* Get suggestions with smart defaults based on existing patterns
( fieldName: string, existingValues: string[] )
| 160 | * Get suggestions with smart defaults based on existing patterns |
| 161 | */ |
| 162 | static getSmartDefaults( |
| 163 | fieldName: string, |
| 164 | existingValues: string[] |
| 165 | ): string[] { |
| 166 | const commonDefaults: Record<string, string[]> = { |
| 167 | status: ["To Do", "In Progress", "Done", "Cancelled"], |
| 168 | priority: ["High", "Medium", "Low"], |
| 169 | type: ["Note", "Task", "Project", "Reference"], |
| 170 | category: ["Personal", "Work", "Study"], |
| 171 | mood: ["😊 Good", "😐 Neutral", "😔 Bad"], |
| 172 | rating: ["⭐", "⭐⭐", "⭐⭐⭐", "⭐⭐⭐⭐", "⭐⭐⭐⭐⭐"], |
| 173 | progress: ["0%", "25%", "50%", "75%", "100%"], |
| 174 | difficulty: ["Easy", "Medium", "Hard"], |
| 175 | size: ["Small", "Medium", "Large"], |
| 176 | }; |
| 177 | |
| 178 | const normalizedFieldName = fieldName.toLowerCase(); |
| 179 | |
| 180 | // Check for exact matches. `commonDefaults` is a plain object, so a bare |
| 181 | // `[normalizedFieldName]` lookup resolves inherited members for magic field |
| 182 | // names: `{{FIELD:constructor}}` yields the Object function (truthy, length |
| 183 | // 1) instead of a `string[]`, which then crashes `.slice`/`.map` in |
| 184 | // completeFormatter and aborts the choice. The field name flows unsanitized |
| 185 | // from a `{{FIELD:<name>}}` token (and may come from an imported package |
| 186 | // template), so restrict to own keys. |
| 187 | if ( |
| 188 | Object.prototype.hasOwnProperty.call(commonDefaults, normalizedFieldName) |
| 189 | ) { |
| 190 | return commonDefaults[normalizedFieldName]; |
| 191 | } |
| 192 | |
| 193 | // Check for partial matches |
| 194 | for (const [key, defaults] of Object.entries(commonDefaults)) { |
| 195 | if (normalizedFieldName.includes(key) || key.includes(normalizedFieldName)) { |
| 196 | return defaults; |
| 197 | } |
| 198 | } |
| 199 | |
| 200 | // If we have existing values, suggest the most common ones |
| 201 | if (existingValues.length > 0) { |
| 202 | const valueCounts = new Map<string, number>(); |
| 203 | |
| 204 | for (const value of existingValues) { |
| 205 | valueCounts.set(value, (valueCounts.get(value) || 0) + 1); |
| 206 | } |
| 207 | |
| 208 | return Array.from(valueCounts.entries()) |
| 209 | .sort((a, b) => b[1] - a[1]) |
| 210 | .slice(0, 5) |
| 211 | .map(([value]) => value); |
| 212 | } |
| 213 | |
| 214 | return []; |
| 215 | } |
| 216 | |
| 217 | /** |
| 218 | * Validate default value against existing patterns |
no test coverage detected