@wireweave/ux-rules 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -13,7 +13,7 @@ type UXIssueSeverity = 'error' | 'warning' | 'info';
13
13
  /**
14
14
  * Category of UX rule
15
15
  */
16
- type UXRuleCategory = 'accessibility' | 'usability' | 'consistency' | 'touch-target' | 'contrast' | 'navigation' | 'form' | 'feedback';
16
+ type UXRuleCategory = 'accessibility' | 'usability' | 'consistency' | 'touch-target' | 'navigation' | 'form' | 'feedback' | 'content' | 'data-display' | 'interaction';
17
17
  /**
18
18
  * UX validation issue
19
19
  */
@@ -136,12 +136,168 @@ declare const rulesByCategory: {
136
136
  consistency: UXRule[];
137
137
  usability: UXRule[];
138
138
  navigation: UXRule[];
139
+ content: UXRule[];
140
+ 'data-display': UXRule[];
141
+ feedback: UXRule[];
142
+ interaction: UXRule[];
139
143
  };
140
144
  /**
141
145
  * Get rules for specific categories
142
146
  */
143
147
  declare function getRulesForCategories(categories: string[]): UXRule[];
144
148
 
149
+ /**
150
+ * UX Rules Constants
151
+ *
152
+ * Centralized constants for UX validation rules.
153
+ * Based on WCAG, Material Design, Apple HIG, and UX research.
154
+ */
155
+ /** Maximum navigation items (Miller's Law: 7±2) */
156
+ declare const MAX_NAV_ITEMS = 7;
157
+ /** Maximum tab count */
158
+ declare const MAX_TABS = 5;
159
+ /** Maximum nesting depth for layouts */
160
+ declare const MAX_NESTING_DEPTH = 6;
161
+ /** Maximum buttons in a single container (decision fatigue prevention) */
162
+ declare const MAX_BUTTONS = 5;
163
+ /** Maximum form fields before recommending multi-step */
164
+ declare const MAX_FORM_FIELDS = 10;
165
+ /** Maximum elements on a page (cognitive overload prevention) */
166
+ declare const MAX_PAGE_ELEMENTS = 50;
167
+ /** Maximum button text length */
168
+ declare const MAX_BUTTON_TEXT_LENGTH = 25;
169
+ /** Maximum title length */
170
+ declare const MAX_TITLE_LENGTH = 60;
171
+ /** Maximum tooltip content length */
172
+ declare const MAX_TOOLTIP_LENGTH = 100;
173
+ /** Maximum list items before recommending pagination */
174
+ declare const MAX_LIST_ITEMS = 20;
175
+ /** Maximum table columns */
176
+ declare const MAX_TABLE_COLUMNS = 8;
177
+ /** Minimum touch target size (WCAG 2.5.5 AAA: 44x44px) */
178
+ declare const MIN_TOUCH_TARGET = 44;
179
+ /** Recommended touch target size (Material Design: 48x48px) */
180
+ declare const RECOMMENDED_TOUCH_TARGET = 48;
181
+ /** Size presets mapping to pixels */
182
+ declare const SIZE_MAP: Record<string, number>;
183
+ /** Minimum toast duration (ms) */
184
+ declare const MIN_TOAST_DURATION = 2000;
185
+ /** Maximum toast duration (ms) */
186
+ declare const MAX_TOAST_DURATION = 10000;
187
+ /** Generic/non-descriptive link texts that should be avoided */
188
+ declare const GENERIC_LINK_TEXTS: string[];
189
+ /** Words indicating asynchronous/loading actions */
190
+ declare const ASYNC_ACTION_WORDS: string[];
191
+ /** Words indicating destructive/dangerous actions */
192
+ declare const DESTRUCTIVE_WORDS: string[];
193
+ /** Words indicating form submission */
194
+ declare const SUBMIT_WORDS: string[];
195
+ /** Words indicating errors */
196
+ declare const ERROR_WORDS: string[];
197
+ /** Words indicating success */
198
+ declare const SUCCESS_WORDS: string[];
199
+ /** Words indicating warnings */
200
+ declare const WARNING_WORDS: string[];
201
+ /** Words indicating home/root navigation */
202
+ declare const HOME_WORDS: string[];
203
+ /** Words indicating close/dismiss actions */
204
+ declare const CLOSE_WORDS: string[];
205
+ /** Placeholder content patterns that should be replaced */
206
+ declare const PLACEHOLDER_PATTERNS: string[];
207
+ /** Input type suggestions based on keywords */
208
+ declare const INPUT_TYPE_SUGGESTIONS: {
209
+ keywords: string[];
210
+ type: string;
211
+ }[];
212
+ /** Form input node types */
213
+ declare const FORM_INPUT_TYPES: string[];
214
+ /** Container node types */
215
+ declare const CONTAINER_TYPES: string[];
216
+ /** Text content node types */
217
+ declare const TEXT_CONTENT_TYPES: string[];
218
+
219
+ /**
220
+ * UX Rules Utilities
221
+ *
222
+ * Helper functions for common rule patterns.
223
+ */
224
+
225
+ /**
226
+ * Safely get text content from a node.
227
+ * Checks 'content', 'text', and 'label' properties.
228
+ */
229
+ declare function getNodeText(node: AnyNode): string;
230
+ /**
231
+ * Get text content in lowercase for comparison.
232
+ */
233
+ declare function getNodeTextLower(node: AnyNode): string;
234
+ /**
235
+ * Check if node has children array.
236
+ */
237
+ declare function hasChildren(node: AnyNode): node is AnyNode & {
238
+ children: AnyNode[];
239
+ };
240
+ /**
241
+ * Get children array from node (returns empty array if none).
242
+ */
243
+ declare function getChildren(node: AnyNode): AnyNode[];
244
+ /**
245
+ * Find first child matching predicate (recursive).
246
+ */
247
+ declare function findInChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): AnyNode | null;
248
+ /**
249
+ * Check if any child matches predicate (recursive).
250
+ */
251
+ declare function hasChildMatching(node: AnyNode, predicate: (child: AnyNode) => boolean): boolean;
252
+ /**
253
+ * Count children matching predicate (recursive).
254
+ */
255
+ declare function countInChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): number;
256
+ /**
257
+ * Get all children matching predicate (recursive).
258
+ */
259
+ declare function filterChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): AnyNode[];
260
+ /**
261
+ * Get numeric size from size attribute.
262
+ */
263
+ declare function getSizeValue(node: AnyNode): number | null;
264
+ /**
265
+ * Check if text contains any of the given words.
266
+ */
267
+ declare function containsAnyWord(text: string, words: string[]): boolean;
268
+ /**
269
+ * Check if text exactly matches any of the given words.
270
+ */
271
+ declare function matchesAnyWord(text: string, words: string[]): boolean;
272
+ /**
273
+ * Get location info from node for issue reporting.
274
+ */
275
+ declare function getNodeLocation(node: AnyNode): {
276
+ line: number;
277
+ column: number;
278
+ } | undefined;
279
+ /**
280
+ * Check if node is a specific type.
281
+ */
282
+ declare function isNodeType(node: AnyNode, type: string | string[]): boolean;
283
+ /**
284
+ * Get button style from node.
285
+ */
286
+ declare function getButtonStyle(node: AnyNode): string;
287
+ /**
288
+ * Type guard to check if a value is a valid AnyNode.
289
+ */
290
+ declare function isAnyNode(value: unknown): value is AnyNode;
291
+ /**
292
+ * Safely convert an array of unknown values to AnyNode array.
293
+ * Filters out invalid nodes.
294
+ */
295
+ declare function toAnyNodeArray(values: unknown[]): AnyNode[];
296
+ /**
297
+ * Get items array from node (for components like Nav, List, Dropdown, etc.)
298
+ */
299
+ declare function getNodeItems(node: AnyNode): unknown[];
300
+
145
301
  /**
146
302
  * UX Rules Validation Engine
147
303
  *
@@ -184,4 +340,4 @@ declare function getUXScore(ast: WireframeDocument): number;
184
340
  */
185
341
  declare function formatUXResult(result: UXValidationResult): string;
186
342
 
187
- export { type UXIssue, type UXIssueSeverity, type UXRule, type UXRuleCategory, type UXRuleContext, type UXValidationOptions, type UXValidationResult, allRules, formatUXResult, getRulesForCategories, getUXIssues, getUXScore, isUXValid, rulesByCategory, validateUX };
343
+ export { ASYNC_ACTION_WORDS, CLOSE_WORDS, CONTAINER_TYPES, DESTRUCTIVE_WORDS, ERROR_WORDS, FORM_INPUT_TYPES, GENERIC_LINK_TEXTS, HOME_WORDS, INPUT_TYPE_SUGGESTIONS, MAX_BUTTONS, MAX_BUTTON_TEXT_LENGTH, MAX_FORM_FIELDS, MAX_LIST_ITEMS, MAX_NAV_ITEMS, MAX_NESTING_DEPTH, MAX_PAGE_ELEMENTS, MAX_TABLE_COLUMNS, MAX_TABS, MAX_TITLE_LENGTH, MAX_TOAST_DURATION, MAX_TOOLTIP_LENGTH, MIN_TOAST_DURATION, MIN_TOUCH_TARGET, PLACEHOLDER_PATTERNS, RECOMMENDED_TOUCH_TARGET, SIZE_MAP, SUBMIT_WORDS, SUCCESS_WORDS, TEXT_CONTENT_TYPES, type UXIssue, type UXIssueSeverity, type UXRule, type UXRuleCategory, type UXRuleContext, type UXValidationOptions, type UXValidationResult, WARNING_WORDS, allRules, containsAnyWord, countInChildren, filterChildren, findInChildren, formatUXResult, getButtonStyle, getChildren, getNodeItems, getNodeLocation, getNodeText, getNodeTextLower, getRulesForCategories, getSizeValue, getUXIssues, getUXScore, hasChildMatching, hasChildren, isAnyNode, isNodeType, isUXValid, matchesAnyWord, rulesByCategory, toAnyNodeArray, validateUX };
package/dist/index.d.ts CHANGED
@@ -13,7 +13,7 @@ type UXIssueSeverity = 'error' | 'warning' | 'info';
13
13
  /**
14
14
  * Category of UX rule
15
15
  */
16
- type UXRuleCategory = 'accessibility' | 'usability' | 'consistency' | 'touch-target' | 'contrast' | 'navigation' | 'form' | 'feedback';
16
+ type UXRuleCategory = 'accessibility' | 'usability' | 'consistency' | 'touch-target' | 'navigation' | 'form' | 'feedback' | 'content' | 'data-display' | 'interaction';
17
17
  /**
18
18
  * UX validation issue
19
19
  */
@@ -136,12 +136,168 @@ declare const rulesByCategory: {
136
136
  consistency: UXRule[];
137
137
  usability: UXRule[];
138
138
  navigation: UXRule[];
139
+ content: UXRule[];
140
+ 'data-display': UXRule[];
141
+ feedback: UXRule[];
142
+ interaction: UXRule[];
139
143
  };
140
144
  /**
141
145
  * Get rules for specific categories
142
146
  */
143
147
  declare function getRulesForCategories(categories: string[]): UXRule[];
144
148
 
149
+ /**
150
+ * UX Rules Constants
151
+ *
152
+ * Centralized constants for UX validation rules.
153
+ * Based on WCAG, Material Design, Apple HIG, and UX research.
154
+ */
155
+ /** Maximum navigation items (Miller's Law: 7±2) */
156
+ declare const MAX_NAV_ITEMS = 7;
157
+ /** Maximum tab count */
158
+ declare const MAX_TABS = 5;
159
+ /** Maximum nesting depth for layouts */
160
+ declare const MAX_NESTING_DEPTH = 6;
161
+ /** Maximum buttons in a single container (decision fatigue prevention) */
162
+ declare const MAX_BUTTONS = 5;
163
+ /** Maximum form fields before recommending multi-step */
164
+ declare const MAX_FORM_FIELDS = 10;
165
+ /** Maximum elements on a page (cognitive overload prevention) */
166
+ declare const MAX_PAGE_ELEMENTS = 50;
167
+ /** Maximum button text length */
168
+ declare const MAX_BUTTON_TEXT_LENGTH = 25;
169
+ /** Maximum title length */
170
+ declare const MAX_TITLE_LENGTH = 60;
171
+ /** Maximum tooltip content length */
172
+ declare const MAX_TOOLTIP_LENGTH = 100;
173
+ /** Maximum list items before recommending pagination */
174
+ declare const MAX_LIST_ITEMS = 20;
175
+ /** Maximum table columns */
176
+ declare const MAX_TABLE_COLUMNS = 8;
177
+ /** Minimum touch target size (WCAG 2.5.5 AAA: 44x44px) */
178
+ declare const MIN_TOUCH_TARGET = 44;
179
+ /** Recommended touch target size (Material Design: 48x48px) */
180
+ declare const RECOMMENDED_TOUCH_TARGET = 48;
181
+ /** Size presets mapping to pixels */
182
+ declare const SIZE_MAP: Record<string, number>;
183
+ /** Minimum toast duration (ms) */
184
+ declare const MIN_TOAST_DURATION = 2000;
185
+ /** Maximum toast duration (ms) */
186
+ declare const MAX_TOAST_DURATION = 10000;
187
+ /** Generic/non-descriptive link texts that should be avoided */
188
+ declare const GENERIC_LINK_TEXTS: string[];
189
+ /** Words indicating asynchronous/loading actions */
190
+ declare const ASYNC_ACTION_WORDS: string[];
191
+ /** Words indicating destructive/dangerous actions */
192
+ declare const DESTRUCTIVE_WORDS: string[];
193
+ /** Words indicating form submission */
194
+ declare const SUBMIT_WORDS: string[];
195
+ /** Words indicating errors */
196
+ declare const ERROR_WORDS: string[];
197
+ /** Words indicating success */
198
+ declare const SUCCESS_WORDS: string[];
199
+ /** Words indicating warnings */
200
+ declare const WARNING_WORDS: string[];
201
+ /** Words indicating home/root navigation */
202
+ declare const HOME_WORDS: string[];
203
+ /** Words indicating close/dismiss actions */
204
+ declare const CLOSE_WORDS: string[];
205
+ /** Placeholder content patterns that should be replaced */
206
+ declare const PLACEHOLDER_PATTERNS: string[];
207
+ /** Input type suggestions based on keywords */
208
+ declare const INPUT_TYPE_SUGGESTIONS: {
209
+ keywords: string[];
210
+ type: string;
211
+ }[];
212
+ /** Form input node types */
213
+ declare const FORM_INPUT_TYPES: string[];
214
+ /** Container node types */
215
+ declare const CONTAINER_TYPES: string[];
216
+ /** Text content node types */
217
+ declare const TEXT_CONTENT_TYPES: string[];
218
+
219
+ /**
220
+ * UX Rules Utilities
221
+ *
222
+ * Helper functions for common rule patterns.
223
+ */
224
+
225
+ /**
226
+ * Safely get text content from a node.
227
+ * Checks 'content', 'text', and 'label' properties.
228
+ */
229
+ declare function getNodeText(node: AnyNode): string;
230
+ /**
231
+ * Get text content in lowercase for comparison.
232
+ */
233
+ declare function getNodeTextLower(node: AnyNode): string;
234
+ /**
235
+ * Check if node has children array.
236
+ */
237
+ declare function hasChildren(node: AnyNode): node is AnyNode & {
238
+ children: AnyNode[];
239
+ };
240
+ /**
241
+ * Get children array from node (returns empty array if none).
242
+ */
243
+ declare function getChildren(node: AnyNode): AnyNode[];
244
+ /**
245
+ * Find first child matching predicate (recursive).
246
+ */
247
+ declare function findInChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): AnyNode | null;
248
+ /**
249
+ * Check if any child matches predicate (recursive).
250
+ */
251
+ declare function hasChildMatching(node: AnyNode, predicate: (child: AnyNode) => boolean): boolean;
252
+ /**
253
+ * Count children matching predicate (recursive).
254
+ */
255
+ declare function countInChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): number;
256
+ /**
257
+ * Get all children matching predicate (recursive).
258
+ */
259
+ declare function filterChildren(node: AnyNode, predicate: (child: AnyNode) => boolean): AnyNode[];
260
+ /**
261
+ * Get numeric size from size attribute.
262
+ */
263
+ declare function getSizeValue(node: AnyNode): number | null;
264
+ /**
265
+ * Check if text contains any of the given words.
266
+ */
267
+ declare function containsAnyWord(text: string, words: string[]): boolean;
268
+ /**
269
+ * Check if text exactly matches any of the given words.
270
+ */
271
+ declare function matchesAnyWord(text: string, words: string[]): boolean;
272
+ /**
273
+ * Get location info from node for issue reporting.
274
+ */
275
+ declare function getNodeLocation(node: AnyNode): {
276
+ line: number;
277
+ column: number;
278
+ } | undefined;
279
+ /**
280
+ * Check if node is a specific type.
281
+ */
282
+ declare function isNodeType(node: AnyNode, type: string | string[]): boolean;
283
+ /**
284
+ * Get button style from node.
285
+ */
286
+ declare function getButtonStyle(node: AnyNode): string;
287
+ /**
288
+ * Type guard to check if a value is a valid AnyNode.
289
+ */
290
+ declare function isAnyNode(value: unknown): value is AnyNode;
291
+ /**
292
+ * Safely convert an array of unknown values to AnyNode array.
293
+ * Filters out invalid nodes.
294
+ */
295
+ declare function toAnyNodeArray(values: unknown[]): AnyNode[];
296
+ /**
297
+ * Get items array from node (for components like Nav, List, Dropdown, etc.)
298
+ */
299
+ declare function getNodeItems(node: AnyNode): unknown[];
300
+
145
301
  /**
146
302
  * UX Rules Validation Engine
147
303
  *
@@ -184,4 +340,4 @@ declare function getUXScore(ast: WireframeDocument): number;
184
340
  */
185
341
  declare function formatUXResult(result: UXValidationResult): string;
186
342
 
187
- export { type UXIssue, type UXIssueSeverity, type UXRule, type UXRuleCategory, type UXRuleContext, type UXValidationOptions, type UXValidationResult, allRules, formatUXResult, getRulesForCategories, getUXIssues, getUXScore, isUXValid, rulesByCategory, validateUX };
343
+ export { ASYNC_ACTION_WORDS, CLOSE_WORDS, CONTAINER_TYPES, DESTRUCTIVE_WORDS, ERROR_WORDS, FORM_INPUT_TYPES, GENERIC_LINK_TEXTS, HOME_WORDS, INPUT_TYPE_SUGGESTIONS, MAX_BUTTONS, MAX_BUTTON_TEXT_LENGTH, MAX_FORM_FIELDS, MAX_LIST_ITEMS, MAX_NAV_ITEMS, MAX_NESTING_DEPTH, MAX_PAGE_ELEMENTS, MAX_TABLE_COLUMNS, MAX_TABS, MAX_TITLE_LENGTH, MAX_TOAST_DURATION, MAX_TOOLTIP_LENGTH, MIN_TOAST_DURATION, MIN_TOUCH_TARGET, PLACEHOLDER_PATTERNS, RECOMMENDED_TOUCH_TARGET, SIZE_MAP, SUBMIT_WORDS, SUCCESS_WORDS, TEXT_CONTENT_TYPES, type UXIssue, type UXIssueSeverity, type UXRule, type UXRuleCategory, type UXRuleContext, type UXValidationOptions, type UXValidationResult, WARNING_WORDS, allRules, containsAnyWord, countInChildren, filterChildren, findInChildren, formatUXResult, getButtonStyle, getChildren, getNodeItems, getNodeLocation, getNodeText, getNodeTextLower, getRulesForCategories, getSizeValue, getUXIssues, getUXScore, hasChildMatching, hasChildren, isAnyNode, isNodeType, isUXValid, matchesAnyWord, rulesByCategory, toAnyNodeArray, validateUX };