@patternfly/context-for-ai 1.2.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.
Files changed (99) hide show
  1. package/README.md +615 -0
  2. package/codemod/ALL_COMPONENTS_REFERENCE.md +815 -0
  3. package/codemod/ATTRIBUTE_DECISION_LOGIC.md +320 -0
  4. package/codemod/README.md +400 -0
  5. package/codemod/add-semantic-attributes.sh +69 -0
  6. package/codemod/component-attributes-reference.json +129 -0
  7. package/codemod/example-after.tsx +51 -0
  8. package/codemod/example-before.tsx +19 -0
  9. package/codemod/static-inference.js +5015 -0
  10. package/codemod/transform.js +1108 -0
  11. package/dist/components/advanced/index.d.ts +2 -0
  12. package/dist/components/advanced/index.d.ts.map +1 -0
  13. package/dist/components/core/Button.d.ts +14 -0
  14. package/dist/components/core/Button.d.ts.map +1 -0
  15. package/dist/components/core/Link.d.ts +15 -0
  16. package/dist/components/core/Link.d.ts.map +1 -0
  17. package/dist/components/core/StarIcon.d.ts +15 -0
  18. package/dist/components/core/StarIcon.d.ts.map +1 -0
  19. package/dist/components/core/index.d.ts +4 -0
  20. package/dist/components/core/index.d.ts.map +1 -0
  21. package/dist/components/data-display/Card.d.ts +14 -0
  22. package/dist/components/data-display/Card.d.ts.map +1 -0
  23. package/dist/components/data-display/StatusBadge.d.ts +13 -0
  24. package/dist/components/data-display/StatusBadge.d.ts.map +1 -0
  25. package/dist/components/data-display/Tbody.d.ts +12 -0
  26. package/dist/components/data-display/Tbody.d.ts.map +1 -0
  27. package/dist/components/data-display/Td.d.ts +14 -0
  28. package/dist/components/data-display/Td.d.ts.map +1 -0
  29. package/dist/components/data-display/Th.d.ts +14 -0
  30. package/dist/components/data-display/Th.d.ts.map +1 -0
  31. package/dist/components/data-display/Thead.d.ts +12 -0
  32. package/dist/components/data-display/Thead.d.ts.map +1 -0
  33. package/dist/components/data-display/Tr.d.ts +16 -0
  34. package/dist/components/data-display/Tr.d.ts.map +1 -0
  35. package/dist/components/data-display/index.d.ts +8 -0
  36. package/dist/components/data-display/index.d.ts.map +1 -0
  37. package/dist/components/feedback/index.d.ts +2 -0
  38. package/dist/components/feedback/index.d.ts.map +1 -0
  39. package/dist/components/forms/Checkbox.d.ts +16 -0
  40. package/dist/components/forms/Checkbox.d.ts.map +1 -0
  41. package/dist/components/forms/Form.d.ts +12 -0
  42. package/dist/components/forms/Form.d.ts.map +1 -0
  43. package/dist/components/forms/Radio.d.ts +32 -0
  44. package/dist/components/forms/Radio.d.ts.map +1 -0
  45. package/dist/components/forms/Select.d.ts +33 -0
  46. package/dist/components/forms/Select.d.ts.map +1 -0
  47. package/dist/components/forms/Switch.d.ts +31 -0
  48. package/dist/components/forms/Switch.d.ts.map +1 -0
  49. package/dist/components/forms/TextArea.d.ts +29 -0
  50. package/dist/components/forms/TextArea.d.ts.map +1 -0
  51. package/dist/components/forms/TextInput.d.ts +29 -0
  52. package/dist/components/forms/TextInput.d.ts.map +1 -0
  53. package/dist/components/forms/index.d.ts +8 -0
  54. package/dist/components/forms/index.d.ts.map +1 -0
  55. package/dist/components/index.d.ts +9 -0
  56. package/dist/components/index.d.ts.map +1 -0
  57. package/dist/components/layout/Flex.d.ts +16 -0
  58. package/dist/components/layout/Flex.d.ts.map +1 -0
  59. package/dist/components/layout/FlexItem.d.ts +16 -0
  60. package/dist/components/layout/FlexItem.d.ts.map +1 -0
  61. package/dist/components/layout/index.d.ts +3 -0
  62. package/dist/components/layout/index.d.ts.map +1 -0
  63. package/dist/components/navigation/DropdownItem.d.ts +8 -0
  64. package/dist/components/navigation/DropdownItem.d.ts.map +1 -0
  65. package/dist/components/navigation/MenuToggle.d.ts +8 -0
  66. package/dist/components/navigation/MenuToggle.d.ts.map +1 -0
  67. package/dist/components/navigation/index.d.ts +3 -0
  68. package/dist/components/navigation/index.d.ts.map +1 -0
  69. package/dist/components/overlay/Drawer.d.ts +12 -0
  70. package/dist/components/overlay/Drawer.d.ts.map +1 -0
  71. package/dist/components/overlay/Modal.d.ts +16 -0
  72. package/dist/components/overlay/Modal.d.ts.map +1 -0
  73. package/dist/components/overlay/index.d.ts +3 -0
  74. package/dist/components/overlay/index.d.ts.map +1 -0
  75. package/dist/context/SemanticContext.d.ts +28 -0
  76. package/dist/context/SemanticContext.d.ts.map +1 -0
  77. package/dist/hooks/index.d.ts +3 -0
  78. package/dist/hooks/index.d.ts.map +1 -0
  79. package/dist/hooks/useAccessibility.d.ts +13 -0
  80. package/dist/hooks/useAccessibility.d.ts.map +1 -0
  81. package/dist/hooks/useSemanticMetadata.d.ts +9 -0
  82. package/dist/hooks/useSemanticMetadata.d.ts.map +1 -0
  83. package/dist/index.d.ts +574 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.esm.js +1362 -0
  86. package/dist/index.esm.js.map +1 -0
  87. package/dist/index.js +1426 -0
  88. package/dist/index.js.map +1 -0
  89. package/dist/types/index.d.ts +47 -0
  90. package/dist/types/index.d.ts.map +1 -0
  91. package/dist/utils/accessibility.d.ts +16 -0
  92. package/dist/utils/accessibility.d.ts.map +1 -0
  93. package/dist/utils/index.d.ts +4 -0
  94. package/dist/utils/index.d.ts.map +1 -0
  95. package/dist/utils/inference.d.ts +136 -0
  96. package/dist/utils/inference.d.ts.map +1 -0
  97. package/dist/utils/metadata.d.ts +17 -0
  98. package/dist/utils/metadata.d.ts.map +1 -0
  99. package/package.json +104 -0
@@ -0,0 +1,1362 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import React, { createContext, useContext, useState } from 'react';
3
+ import { Button as Button$1, Form as Form$1, Checkbox as Checkbox$1, TextInput as TextInput$1, TextArea as TextArea$1, Select as Select$1, Radio as Radio$1, Switch as Switch$1, Card as Card$1, Flex as Flex$1, FlexItem as FlexItem$1, Modal as Modal$1, Drawer as Drawer$1, MenuToggle as MenuToggle$1, DropdownItem as DropdownItem$1 } from '@patternfly/react-core';
4
+ import { Tbody as Tbody$1, Td as Td$1, Th as Th$1, Thead as Thead$1, Tr as Tr$1 } from '@patternfly/react-table';
5
+
6
+ /**
7
+ * Inference utilities for automatically determining semantic properties
8
+ * from PatternFly component props
9
+ */
10
+ /**
11
+ * Determine if a component is a visual parent (requires user action to see contents)
12
+ * vs a wrapper/structure (always visible)
13
+ */
14
+ const isVisualParent = (componentName) => {
15
+ const visualParents = [
16
+ 'modal', 'drawer', 'popover', 'tooltip', // Overlays
17
+ 'wizardstep', 'wizard', 'tab', 'accordion', // Navigation containers
18
+ 'expandable', 'dropdown', 'menu', 'menutoggle' // Expandable containers
19
+ ];
20
+ return visualParents.includes(componentName.toLowerCase());
21
+ };
22
+ /**
23
+ * Infer button action from PatternFly variant and props
24
+ * Returns both behavior (what it does) and styling (how it looks)
25
+ */
26
+ const inferButtonAction = (variant, href, onClick, target) => {
27
+ // Determine behavior - what the button DOES
28
+ let behaviorType = 'default';
29
+ if (href) {
30
+ // Has href - it's a link
31
+ if (href.startsWith('http'))
32
+ behaviorType = 'external';
33
+ else if (target === '_blank')
34
+ behaviorType = 'external';
35
+ else if (href.startsWith('/'))
36
+ behaviorType = 'navigation';
37
+ else
38
+ behaviorType = 'navigation';
39
+ }
40
+ else if (onClick) {
41
+ // Has onClick but no href - it's an action
42
+ behaviorType = 'action';
43
+ }
44
+ // Determine styling - visual importance/appearance
45
+ let styleVariant = 'secondary';
46
+ switch (variant) {
47
+ case 'primary':
48
+ styleVariant = 'primary';
49
+ break;
50
+ case 'danger':
51
+ styleVariant = 'destructive';
52
+ break;
53
+ case 'control':
54
+ styleVariant = 'toggle';
55
+ break;
56
+ case 'secondary':
57
+ case 'tertiary':
58
+ case 'plain':
59
+ case 'link':
60
+ styleVariant = variant;
61
+ break;
62
+ }
63
+ return {
64
+ type: behaviorType,
65
+ variant: styleVariant
66
+ };
67
+ };
68
+ /**
69
+ * Infer input purpose from type
70
+ */
71
+ const inferInputPurpose = (type) => {
72
+ switch (type) {
73
+ case 'email':
74
+ return 'email-input';
75
+ case 'password':
76
+ return 'password-input';
77
+ case 'search':
78
+ return 'search-input';
79
+ case 'tel':
80
+ return 'phone-input';
81
+ case 'url':
82
+ return 'url-input';
83
+ case 'number':
84
+ return 'numeric-input';
85
+ case 'date':
86
+ case 'datetime-local':
87
+ case 'time':
88
+ return 'date-time-input';
89
+ case 'text':
90
+ default:
91
+ return 'text-input';
92
+ }
93
+ };
94
+ /**
95
+ * Infer alert severity
96
+ */
97
+ const inferAlertSeverity = (variant) => {
98
+ switch (variant) {
99
+ case 'success':
100
+ return 'success';
101
+ case 'danger':
102
+ return 'error';
103
+ case 'warning':
104
+ return 'warning';
105
+ case 'info':
106
+ case 'default':
107
+ default:
108
+ return 'info';
109
+ }
110
+ };
111
+ /**
112
+ * Infer context from parent or usage
113
+ */
114
+ const inferContext = (props) => {
115
+ if (props.onClick || props.onSubmit)
116
+ return 'active';
117
+ if (props.isDisabled)
118
+ return 'disabled';
119
+ if (props.isReadOnly)
120
+ return 'readonly';
121
+ return 'default';
122
+ };
123
+ /**
124
+ * Infer card purpose from PatternFly props
125
+ */
126
+ const inferCardPurpose = (props) => {
127
+ // Interactive cards
128
+ if (props.isSelectable)
129
+ return 'selection-panel';
130
+ if (props.isClickable)
131
+ return 'action-panel';
132
+ if (props.isExpanded !== undefined)
133
+ return 'expandable-content';
134
+ // Layout-based cards
135
+ if (props.isCompact)
136
+ return 'data-summary';
137
+ if (props.isPlain)
138
+ return 'content-display';
139
+ // Content-based cards (based on children analysis)
140
+ if (props.children) {
141
+ const childrenStr = props.children.toString().toLowerCase();
142
+ if (childrenStr.includes('logo') || childrenStr.includes('brand'))
143
+ return 'brand-display';
144
+ if (childrenStr.includes('chart') || childrenStr.includes('graph'))
145
+ return 'data-visualization';
146
+ if (childrenStr.includes('form') || childrenStr.includes('input'))
147
+ return 'form-container';
148
+ if (childrenStr.includes('table') || childrenStr.includes('list'))
149
+ return 'data-display';
150
+ }
151
+ return 'content-display';
152
+ };
153
+ /**
154
+ * Infer modal purpose from props
155
+ */
156
+ const inferModalPurpose = (props) => {
157
+ if (props.variant === 'small')
158
+ return 'confirmation';
159
+ if (props.variant === 'large')
160
+ return 'form';
161
+ return 'information';
162
+ };
163
+ /**
164
+ * Infer accessibility features from props
165
+ */
166
+ const inferAccessibilityFeatures = (props) => {
167
+ const features = ['keyboard-navigable'];
168
+ if (props['aria-label'] || props['aria-labelledby']) {
169
+ features.push('screen-reader-friendly');
170
+ }
171
+ if (props.autoFocus) {
172
+ features.push('auto-focus');
173
+ }
174
+ if (props.role) {
175
+ features.push('semantic-role');
176
+ }
177
+ return features;
178
+ };
179
+ /**
180
+ * Infer usage patterns from component type and props
181
+ */
182
+ const inferUsagePatterns = (componentType, props) => {
183
+ const patterns = ['user-interface'];
184
+ // Component-specific patterns
185
+ switch (componentType.toLowerCase()) {
186
+ case 'button':
187
+ if (props.type === 'submit')
188
+ patterns.push('form-submission');
189
+ if (props.onClick)
190
+ patterns.push('user-interaction');
191
+ break;
192
+ case 'textinput':
193
+ case 'textarea':
194
+ patterns.push('data-entry', 'form-input');
195
+ if (props.validated === 'error')
196
+ patterns.push('validation');
197
+ break;
198
+ case 'select':
199
+ patterns.push('data-entry', 'selection');
200
+ break;
201
+ case 'checkbox':
202
+ case 'radio':
203
+ patterns.push('user-selection', 'form-input');
204
+ break;
205
+ case 'modal':
206
+ patterns.push('user-interaction', 'workflow-step');
207
+ break;
208
+ case 'card':
209
+ patterns.push('content-organization', 'data-presentation');
210
+ break;
211
+ }
212
+ return patterns;
213
+ };
214
+ /**
215
+ * Generate comprehensive metadata from props
216
+ */
217
+ const generateMetadataFromProps = (componentName, props) => {
218
+ return {
219
+ description: `${componentName} component`,
220
+ category: inferCategory(componentName),
221
+ accessibility: inferAccessibilityFeatures(props),
222
+ usage: inferUsagePatterns(componentName, props)
223
+ };
224
+ };
225
+ /**
226
+ * Infer card content type from PatternFly props and children
227
+ */
228
+ const inferCardContentType = (props) => {
229
+ // Interactive states - keep them separate
230
+ if (props.isSelectable)
231
+ return 'selectable';
232
+ if (props.isClickable)
233
+ return 'clickable';
234
+ if (props.isExpanded !== undefined)
235
+ return 'expandable';
236
+ // Content analysis based on children
237
+ if (props.children) {
238
+ const childrenStr = props.children.toString().toLowerCase();
239
+ // Logo content (media cards should only contain logos)
240
+ if (childrenStr.includes('logo') || childrenStr.includes('brand')) {
241
+ return 'logo';
242
+ }
243
+ // Data content
244
+ if (childrenStr.includes('table') || childrenStr.includes('chart') || childrenStr.includes('graph') ||
245
+ childrenStr.includes('metric') || childrenStr.includes('stat')) {
246
+ return 'data';
247
+ }
248
+ // Form content
249
+ if (childrenStr.includes('form') || childrenStr.includes('input') || childrenStr.includes('button')) {
250
+ return 'interactive';
251
+ }
252
+ // Text content
253
+ if (childrenStr.includes('text') || childrenStr.includes('description') || childrenStr.includes('paragraph')) {
254
+ return 'text';
255
+ }
256
+ }
257
+ return 'mixed'; // Default fallback
258
+ };
259
+ /**
260
+ * Infer card interactive state from PatternFly props
261
+ */
262
+ const inferCardInteractiveState = (props) => {
263
+ // Interactive states
264
+ if (props.isSelectable) {
265
+ if (props.isSelected)
266
+ return 'selected';
267
+ return 'selectable';
268
+ }
269
+ if (props.isClickable) {
270
+ if (props.isDisabled)
271
+ return 'disabled-clickable';
272
+ return 'clickable';
273
+ }
274
+ if (props.isExpanded !== undefined) {
275
+ if (props.isExpanded)
276
+ return 'expanded';
277
+ return 'collapsed';
278
+ }
279
+ // Default state
280
+ return 'static';
281
+ };
282
+ /**
283
+ * Infer modal interaction type
284
+ */
285
+ const inferModalInteractionType = (isOpen) => {
286
+ return isOpen ? 'blocking' : 'non-blocking';
287
+ };
288
+ /**
289
+ * Infer select purpose
290
+ */
291
+ const inferSelectPurpose = () => {
292
+ return 'data-entry';
293
+ };
294
+ /**
295
+ * Infer select selection type
296
+ */
297
+ const inferSelectSelectionType = (variant) => {
298
+ return variant === 'typeahead' ? 'typeahead' : 'single';
299
+ };
300
+ /**
301
+ * Infer radio purpose
302
+ */
303
+ const inferRadioPurpose = () => {
304
+ return 'option-selection';
305
+ };
306
+ /**
307
+ * Infer radio group context
308
+ */
309
+ const inferRadioGroupContext = (name) => {
310
+ return name || 'unknown-group';
311
+ };
312
+ /**
313
+ * Infer switch purpose
314
+ */
315
+ const inferSwitchPurpose = () => {
316
+ return 'setting';
317
+ };
318
+ /**
319
+ * Infer switch toggle target
320
+ */
321
+ const inferSwitchToggleTarget = () => {
322
+ return 'feature';
323
+ };
324
+ /**
325
+ * Infer textarea purpose
326
+ */
327
+ const inferTextAreaPurpose = () => {
328
+ return 'content';
329
+ };
330
+ /**
331
+ * Infer textarea content type
332
+ */
333
+ const inferTextAreaContentType = () => {
334
+ return 'plain-text';
335
+ };
336
+ /**
337
+ * Infer checkbox purpose
338
+ */
339
+ const inferCheckboxPurpose = (isChecked) => {
340
+ return isChecked !== undefined ? 'selection' : 'form-input';
341
+ };
342
+ /**
343
+ * Infer link purpose
344
+ */
345
+ const inferLinkPurpose = (href, children) => {
346
+ if (href?.startsWith('http'))
347
+ return 'external';
348
+ if (href === '#')
349
+ return 'action';
350
+ if (href?.includes('download'))
351
+ return 'download';
352
+ if (children?.toString().toLowerCase().includes('launch'))
353
+ return 'launch';
354
+ return 'navigation';
355
+ };
356
+ /**
357
+ * Infer star icon purpose
358
+ */
359
+ const inferStarIconPurpose = (isFavorited) => {
360
+ return isFavorited !== undefined ? 'favorite-toggle' : 'rating';
361
+ };
362
+ /**
363
+ * Infer validation context
364
+ */
365
+ const inferValidationContext = (isRequired) => {
366
+ return isRequired ? 'required' : 'optional';
367
+ };
368
+ /**
369
+ * Infer form context (default for most form components)
370
+ */
371
+ const inferFormContext = () => {
372
+ return 'form';
373
+ };
374
+ /**
375
+ * Infer settings context (default for switches)
376
+ */
377
+ const inferSettingsContext = () => {
378
+ return 'settings';
379
+ };
380
+ /**
381
+ * Infer status badge type from content
382
+ */
383
+ const inferStatusBadgeType = (content) => {
384
+ const lower = content?.toLowerCase() || '';
385
+ if (lower.includes('ready'))
386
+ return 'ready';
387
+ if (lower.includes('success'))
388
+ return 'success';
389
+ if (lower.includes('warning'))
390
+ return 'warning';
391
+ if (lower.includes('error') || lower.includes('fail'))
392
+ return 'error';
393
+ if (lower.includes('pending'))
394
+ return 'pending';
395
+ return 'info';
396
+ };
397
+ /**
398
+ * Infer status badge purpose
399
+ */
400
+ const inferStatusBadgePurpose = () => {
401
+ return 'status-indicator';
402
+ };
403
+ /**
404
+ * Infer category from component name
405
+ * Category describes WHAT the component IS, not what it DOES (that's the action)
406
+ */
407
+ const inferCategory = (componentName) => {
408
+ const name = componentName.toLowerCase();
409
+ // Component type categorization
410
+ if (name === 'button') {
411
+ return 'button';
412
+ }
413
+ if (['textinput', 'textarea', 'select', 'radio', 'checkbox', 'switch'].includes(name)) {
414
+ return 'forms';
415
+ }
416
+ if (['nav', 'breadcrumb', 'tabs', 'pagination', 'masthead'].includes(name)) {
417
+ return 'navigation';
418
+ }
419
+ if (['card', 'table', 'datalist', 'label', 'badge'].includes(name)) {
420
+ return 'data-display';
421
+ }
422
+ if (['alert', 'banner', 'toast', 'progress', 'spinner'].includes(name)) {
423
+ return 'feedback';
424
+ }
425
+ if (['modal', 'drawer', 'popover', 'tooltip'].includes(name)) {
426
+ return 'overlay';
427
+ }
428
+ if (['flex', 'grid', 'stack', 'panel'].includes(name)) {
429
+ return 'layout';
430
+ }
431
+ return 'data-display';
432
+ };
433
+
434
+ const SemanticContext = createContext(undefined);
435
+ const useSemanticContext = () => {
436
+ const context = useContext(SemanticContext);
437
+ if (!context) {
438
+ throw new Error('useSemanticContext must be used within a SemanticProvider');
439
+ }
440
+ return context;
441
+ };
442
+ const SemanticProvider = ({ children }) => {
443
+ const [contextStack, setContextStack] = useState([]);
444
+ const addContext = (context, semanticName, isQualified) => {
445
+ // Auto-detect if not specified
446
+ const qualified = isQualified !== undefined ? isQualified : isVisualParent(context);
447
+ setContextStack(prev => [...prev, {
448
+ name: context,
449
+ semanticName: semanticName || context, // Use semantic name if provided, otherwise fallback to context
450
+ isQualified: qualified
451
+ }]);
452
+ };
453
+ const removeContext = () => {
454
+ setContextStack(prev => prev.slice(0, -1));
455
+ };
456
+ const clearContext = () => {
457
+ setContextStack([]);
458
+ };
459
+ const getHierarchy = () => {
460
+ const allSemanticNames = contextStack.map(c => c.semanticName);
461
+ const qualifiedOnly = contextStack.filter(c => c.isQualified).map(c => c.semanticName);
462
+ const wrappersOnly = contextStack.filter(c => !c.isQualified).map(c => c.semanticName);
463
+ return {
464
+ fullPath: allSemanticNames.length > 0 ? allSemanticNames.join(' > ') : '',
465
+ qualifiedParents: qualifiedOnly,
466
+ wrappers: wrappersOnly,
467
+ immediateParent: qualifiedOnly.length > 0 ? qualifiedOnly[qualifiedOnly.length - 1] : '',
468
+ immediateWrapper: wrappersOnly.length > 0 ? wrappersOnly[wrappersOnly.length - 1] : '',
469
+ depth: qualifiedOnly.length
470
+ };
471
+ };
472
+ return (jsx(SemanticContext.Provider, { value: {
473
+ contextStack,
474
+ addContext,
475
+ removeContext,
476
+ getHierarchy,
477
+ clearContext,
478
+ }, children: children }));
479
+ };
480
+
481
+ /** Button - PatternFly Button wrapper with semantic metadata for AI tooling */
482
+ const Button = ({ semanticRole, aiMetadata: _aiMetadata, action, context, target, semanticName, children, variant, onClick, isDisabled, ...props }) => {
483
+ // Get hierarchy from context (optional - gracefully handles no provider)
484
+ let hierarchy;
485
+ let addContext, removeContext;
486
+ try {
487
+ const semanticContext = useSemanticContext();
488
+ hierarchy = semanticContext.getHierarchy();
489
+ addContext = semanticContext.addContext;
490
+ removeContext = semanticContext.removeContext;
491
+ }
492
+ catch {
493
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
494
+ addContext = () => { };
495
+ removeContext = () => { };
496
+ }
497
+ // Auto-infer semantic properties from PatternFly props
498
+ const inferredAction = inferButtonAction(variant, props.href, onClick, target);
499
+ const actionType = action || inferredAction.type;
500
+ const actionVariant = inferredAction.variant;
501
+ const inferredContext = context || inferContext({ onClick, isDisabled, ...props });
502
+ // Generate semantic role (combines category, action, context into one)
503
+ const role = semanticRole || `button-${actionType}-${inferredContext}`;
504
+ // Generate semantic name: wrapper > parent > action type
505
+ // Button acts on wrapper (if exists), otherwise parent, otherwise standalone
506
+ const componentName = semanticName || (() => {
507
+ // Format action type: "action" → "Action", "navigation" → "Navigation", "external" → "External Link"
508
+ // Treat "default" as "Action"
509
+ let actionLabel;
510
+ if (actionType === 'default') {
511
+ actionLabel = 'Action';
512
+ }
513
+ else if (actionType === 'external') {
514
+ actionLabel = 'External Link';
515
+ }
516
+ else {
517
+ actionLabel = actionType.charAt(0).toUpperCase() + actionType.slice(1);
518
+ }
519
+ // Priority: wrapper (immediate context) > parent > standalone
520
+ if (hierarchy.immediateWrapper) {
521
+ return `${hierarchy.immediateWrapper} ${actionLabel}`;
522
+ }
523
+ else if (hierarchy.immediateParent) {
524
+ return `${hierarchy.immediateParent} ${actionLabel}`;
525
+ }
526
+ // Otherwise just the action label
527
+ return actionLabel;
528
+ })();
529
+ // Register button with its semantic name in context (for modal triggering)
530
+ React.useEffect(() => {
531
+ addContext('Button', componentName, false); // false = not a visual parent
532
+ return () => removeContext();
533
+ }, [addContext, removeContext, componentName]);
534
+ const consequence = actionVariant === 'destructive' ? 'destructive-permanent' : 'safe';
535
+ const affectsParent = target === 'parent-modal' || target === 'parent-form';
536
+ return (jsx(Button$1, { ...props, variant: variant, onClick: onClick, isDisabled: isDisabled, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": role, "data-action-variant": actionVariant, "data-target": target || 'default', "data-consequence": consequence, "data-affects-parent": affectsParent, children: children }));
537
+ };
538
+
539
+ /** Link - HTML anchor wrapper with semantic metadata for AI tooling */
540
+ const Link = ({ semanticName, semanticRole, aiMetadata, purpose, context, target, htmlTarget, children, href, onClick, ...props }) => {
541
+ // Get hierarchy from context (optional - gracefully handles no provider)
542
+ let hierarchy;
543
+ try {
544
+ const semanticContext = useSemanticContext();
545
+ hierarchy = semanticContext.getHierarchy();
546
+ }
547
+ catch {
548
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
549
+ }
550
+ // Auto-infer semantic properties from props
551
+ const inferredPurpose = purpose || inferLinkPurpose(href, children);
552
+ const inferredContext = context || (onClick ? inferContext({ onClick }) : 'content');
553
+ const componentName = semanticName || 'Link';
554
+ // Generate semantic role and AI metadata
555
+ const role = semanticRole || `link-${inferredPurpose}-${inferredContext}`;
556
+ const metadata = aiMetadata || {
557
+ description: `${inferredPurpose} link for ${inferredContext} context`,
558
+ category: inferCategory('Link'),
559
+ usage: [`${inferredContext}-${inferredPurpose}`, 'user-interaction'],
560
+ hierarchy,
561
+ action: {
562
+ type: inferredPurpose,
563
+ target: target || 'default'
564
+ }
565
+ };
566
+ return (jsx("a", { ...props, href: href, onClick: onClick, target: htmlTarget, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-target": target || 'default', "data-context": inferredContext, children: children }));
567
+ };
568
+
569
+ /** StarIcon - HTML span wrapper with semantic metadata for AI tooling */
570
+ const StarIcon = ({ semanticName, semanticRole, aiMetadata, purpose, context, children, isFavorited, onClick, ...props }) => {
571
+ // Auto-infer semantic properties from props
572
+ const inferredPurpose = purpose || inferStarIconPurpose(isFavorited);
573
+ const inferredContext = context || (onClick ? inferContext({ onClick }) : 'display');
574
+ // Generate semantic role and AI metadata
575
+ const role = semanticRole || `star-icon-${inferredPurpose}-${inferredContext}`;
576
+ const metadata = aiMetadata || {
577
+ description: `${inferredPurpose} star icon for ${inferredContext} context`,
578
+ category: 'forms',
579
+ complexity: 'simple',
580
+ usage: [`${inferredContext}-${inferredPurpose}`, 'user-interaction']
581
+ };
582
+ // Default semantic name if not provided
583
+ const defaultSemanticName = semanticName || 'Row Item';
584
+ return (jsx("span", { ...props, onClick: onClick, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-is-favorited": isFavorited, children: children }));
585
+ };
586
+
587
+ /** Form - PatternFly Form wrapper with semantic metadata for AI tooling */
588
+ const Form = ({ semanticName, semanticRole, purpose, children, ...props }) => {
589
+ // Register as wrapper (not a visual parent) in semantic context
590
+ const { addContext, removeContext } = useSemanticContext();
591
+ React.useEffect(() => {
592
+ addContext('Form', undefined, false); // false = wrapper (always visible)
593
+ return () => removeContext();
594
+ }, [addContext, removeContext]);
595
+ // Get hierarchy from context
596
+ let hierarchy;
597
+ try {
598
+ const semanticContext = useSemanticContext();
599
+ hierarchy = semanticContext.getHierarchy();
600
+ }
601
+ catch {
602
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
603
+ }
604
+ // Auto-infer purpose from context if not provided
605
+ const inferredPurpose = purpose || 'edit';
606
+ // Generate semantic role
607
+ const role = semanticRole || `form-${inferredPurpose}`;
608
+ // Default semantic name if not provided
609
+ const componentName = semanticName || 'Form';
610
+ return (jsx(Form$1, { ...props, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": role, "data-purpose": inferredPurpose, children: children }));
611
+ };
612
+
613
+ /** Checkbox - PatternFly Checkbox wrapper with semantic metadata for AI tooling */
614
+ const Checkbox = ({ semanticName, semanticRole, aiMetadata, purpose, context, children, isChecked, onChange, id, ...props }) => {
615
+ // Auto-infer semantic properties from PatternFly props
616
+ const inferredPurpose = purpose || inferCheckboxPurpose(isChecked);
617
+ const inferredContext = context || (onChange ? inferContext({ onChange }) : inferFormContext());
618
+ // Generate semantic role and AI metadata
619
+ const role = semanticRole || `checkbox-${inferredPurpose}-${inferredContext}`;
620
+ const metadata = aiMetadata || {
621
+ description: `${inferredPurpose} checkbox for ${inferredContext} context`,
622
+ category: inferCategory('Checkbox'),
623
+ usage: [`${inferredContext}-${inferredPurpose}`, 'user-interaction']
624
+ };
625
+ // Default semantic name if not provided
626
+ const defaultSemanticName = semanticName || 'Row Item';
627
+ return (jsx(Checkbox$1, { ...props, id: id, isChecked: isChecked, onChange: onChange, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, children: children }));
628
+ };
629
+
630
+ /**
631
+ * TextInput - PatternFly TextInput wrapper with semantic metadata for AI tooling
632
+ *
633
+ * @example
634
+ * ```tsx
635
+ * <TextInput
636
+ * type="email"
637
+ * purpose="email-input"
638
+ * context="form"
639
+ * placeholder="Enter your email"
640
+ * value={email}
641
+ * onChange={handleChange}
642
+ * />
643
+ * ```
644
+ */
645
+ const TextInput = React.forwardRef(({ semanticName, semanticRole, aiMetadata, purpose, context, validationContext, type = 'text', validated, isRequired, ...props }, ref) => {
646
+ // 1. Auto-infer semantic properties from PatternFly props
647
+ const inferredPurpose = purpose || inferInputPurpose(type);
648
+ const inferredContext = context || inferFormContext();
649
+ const inferredValidation = validationContext || inferValidationContext(isRequired);
650
+ // 2. Generate semantic role and AI metadata
651
+ const role = semanticRole || `textinput-${inferredPurpose}-${inferredContext}`;
652
+ const metadata = aiMetadata || {
653
+ ...generateMetadataFromProps('TextInput', { type, validated, isRequired, ...props }),
654
+ description: `${inferredPurpose} for ${inferredContext} context`,
655
+ usage: ['data-entry', 'form-input', 'user-interaction']
656
+ };
657
+ // 3. Default semantic name
658
+ const defaultSemanticName = semanticName || 'TextInput';
659
+ // 4. Render PatternFly component with semantic data attributes
660
+ return (jsx(TextInput$1, { ...props, ref: ref, type: type, validated: validated, isRequired: isRequired, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-validation-context": inferredValidation }));
661
+ });
662
+ TextInput.displayName = 'TextInput';
663
+
664
+ /**
665
+ * TextArea - PatternFly TextArea wrapper with semantic metadata for AI tooling
666
+ *
667
+ * @example
668
+ * ```tsx
669
+ * <TextArea
670
+ * purpose="comment"
671
+ * context="comment-section"
672
+ * placeholder="Add your comment..."
673
+ * value={comment}
674
+ * onChange={handleChange}
675
+ * resizeOrientation="vertical"
676
+ * />
677
+ * ```
678
+ */
679
+ const TextArea = React.forwardRef(({ semanticName, semanticRole, aiMetadata, purpose, context, contentType, validated, isRequired, ...props }, ref) => {
680
+ // 1. Auto-infer semantic properties
681
+ const inferredPurpose = purpose || inferTextAreaPurpose();
682
+ const inferredContext = context || inferFormContext();
683
+ const inferredContentType = contentType || inferTextAreaContentType();
684
+ // 2. Generate semantic role and AI metadata
685
+ const role = semanticRole || `textarea-${inferredPurpose}-${inferredContext}`;
686
+ const metadata = aiMetadata || {
687
+ ...generateMetadataFromProps('TextArea', { validated, isRequired, ...props }),
688
+ description: `${inferredPurpose} textarea for ${inferredContext} containing ${inferredContentType}`,
689
+ usage: ['data-entry', 'long-form-input', 'user-interaction']
690
+ };
691
+ // 3. Default semantic name
692
+ const defaultSemanticName = semanticName || 'TextArea';
693
+ // 4. Render PatternFly component with semantic data attributes
694
+ return (jsx(TextArea$1, { ...props, ref: ref, validated: validated, isRequired: isRequired, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-content-type": inferredContentType }));
695
+ });
696
+ TextArea.displayName = 'TextArea';
697
+
698
+ /**
699
+ * Select - PatternFly Select wrapper with semantic metadata for AI tooling
700
+ *
701
+ * @example
702
+ * ```tsx
703
+ * <Select
704
+ * purpose="category-selection"
705
+ * context="form"
706
+ * isOpen={isOpen}
707
+ * onToggle={handleToggle}
708
+ * selections={selected}
709
+ * onSelect={handleSelect}
710
+ * >
711
+ * <SelectOption value="option1" />
712
+ * <SelectOption value="option2" />
713
+ * </Select>
714
+ * ```
715
+ */
716
+ const Select = ({ semanticName, semanticRole, aiMetadata, purpose, context, selectionType, variant, children, ...props }) => {
717
+ // 1. Auto-infer semantic properties
718
+ const inferredPurpose = purpose || inferSelectPurpose();
719
+ const inferredContext = context || inferFormContext();
720
+ const inferredSelectionType = selectionType || inferSelectSelectionType(variant);
721
+ // 2. Generate semantic role and AI metadata
722
+ const role = semanticRole || `select-${inferredPurpose}-${inferredContext}`;
723
+ const metadata = aiMetadata || {
724
+ ...generateMetadataFromProps('Select', { variant, ...props }),
725
+ description: `${inferredPurpose} select with ${inferredSelectionType} selection for ${inferredContext}`,
726
+ usage: ['data-entry', 'user-selection', 'user-interaction']
727
+ };
728
+ // 3. Default semantic name
729
+ const defaultSemanticName = semanticName || 'Select';
730
+ // 4. Render PatternFly component with semantic data attributes
731
+ return (jsx(Select$1, { ...props, variant: variant, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-selection-type": inferredSelectionType, children: children }));
732
+ };
733
+
734
+ /**
735
+ * Radio - PatternFly Radio wrapper with semantic metadata for AI tooling
736
+ *
737
+ * @example
738
+ * ```tsx
739
+ * <Radio
740
+ * purpose="preference"
741
+ * context="settings"
742
+ * groupContext="theme-selection"
743
+ * name="theme"
744
+ * id="theme-light"
745
+ * label="Light Theme"
746
+ * isChecked={theme === 'light'}
747
+ * onChange={handleChange}
748
+ * />
749
+ * ```
750
+ */
751
+ const Radio = ({ semanticName, semanticRole, aiMetadata, purpose, context, groupContext, name, isChecked, isDisabled, children, ...props }) => {
752
+ // 1. Auto-infer semantic properties
753
+ const inferredPurpose = purpose || inferRadioPurpose();
754
+ const inferredContext = context || inferFormContext();
755
+ const inferredGroupContext = groupContext || inferRadioGroupContext(name);
756
+ // 2. Generate semantic role and AI metadata
757
+ const role = semanticRole || `radio-${inferredPurpose}-${inferredContext}`;
758
+ const metadata = aiMetadata || {
759
+ ...generateMetadataFromProps('Radio', { name, isChecked, isDisabled, ...props }),
760
+ description: `${inferredPurpose} radio button in ${inferredGroupContext} group for ${inferredContext}`,
761
+ usage: ['user-selection', 'form-input', 'user-interaction']
762
+ };
763
+ // 3. Default semantic name
764
+ const defaultSemanticName = semanticName || 'Radio';
765
+ // 4. Render PatternFly component with semantic data attributes
766
+ return (jsx(Radio$1, { ...props, name: name, isChecked: isChecked, isDisabled: isDisabled, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-group-context": inferredGroupContext, children: children }));
767
+ };
768
+
769
+ /**
770
+ * Switch - PatternFly Switch wrapper with semantic metadata for AI tooling
771
+ *
772
+ * @example
773
+ * ```tsx
774
+ * <Switch
775
+ * purpose="feature-toggle"
776
+ * context="settings"
777
+ * toggleTarget="feature"
778
+ * id="notifications"
779
+ * label="Enable notifications"
780
+ * isChecked={notificationsEnabled}
781
+ * onChange={handleToggle}
782
+ * />
783
+ * ```
784
+ */
785
+ const Switch = ({ semanticName, semanticRole, aiMetadata, purpose, context, toggleTarget, isChecked, isDisabled, children, ...props }) => {
786
+ // 1. Auto-infer semantic properties
787
+ const inferredPurpose = purpose || inferSwitchPurpose();
788
+ const inferredContext = context || inferSettingsContext();
789
+ const inferredToggleTarget = toggleTarget || inferSwitchToggleTarget();
790
+ // 2. Generate semantic role and AI metadata
791
+ const role = semanticRole || `switch-${inferredPurpose}-${inferredContext}`;
792
+ const metadata = aiMetadata || {
793
+ ...generateMetadataFromProps('Switch', { isChecked, isDisabled, ...props }),
794
+ description: `${inferredPurpose} switch for toggling ${inferredToggleTarget} in ${inferredContext}`,
795
+ usage: ['user-interaction', 'toggle-control', 'settings-control']
796
+ };
797
+ // 3. Default semantic name
798
+ const defaultSemanticName = semanticName || 'Switch';
799
+ // 4. Render PatternFly component with semantic data attributes
800
+ return (jsx(Switch$1, { ...props, isChecked: isChecked, isDisabled: isDisabled, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-context": inferredContext, "data-toggle-target": inferredToggleTarget, children: children }));
801
+ };
802
+
803
+ /** Card - PatternFly Card wrapper with semantic metadata for AI tooling */
804
+ const Card = ({ semanticName, semanticRole, aiMetadata: _aiMetadata, purpose, contentType, children, isSelectable, isClickable, isExpanded, isCompact, isSelected, isDisabled, ...props }) => {
805
+ // Get hierarchy from context (optional - gracefully handles no provider)
806
+ let hierarchy;
807
+ let addContext, removeContext;
808
+ try {
809
+ const semanticContext = useSemanticContext();
810
+ hierarchy = semanticContext.getHierarchy();
811
+ addContext = semanticContext.addContext;
812
+ removeContext = semanticContext.removeContext;
813
+ }
814
+ catch {
815
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
816
+ addContext = () => { };
817
+ removeContext = () => { };
818
+ }
819
+ // Auto-infer semantic properties from PatternFly props and children
820
+ const inferredPurpose = purpose || inferCardPurpose({ isSelectable, isClickable, isExpanded, isCompact, children });
821
+ const inferredContentType = contentType || inferCardContentType({ isSelectable, isClickable, isExpanded, children });
822
+ const inferredInteractiveState = inferCardInteractiveState({ isSelectable, isClickable, isExpanded, isSelected, isDisabled });
823
+ // Generate semantic role
824
+ const role = semanticRole || `card-${inferredPurpose}-${inferredContentType}`;
825
+ // Generate semantic name: wrapper > parent > standalone
826
+ // Card acts on wrapper (if exists), otherwise parent, otherwise standalone
827
+ const componentName = semanticName || (() => {
828
+ // Priority: wrapper (immediate context) > parent > standalone
829
+ if (hierarchy.immediateWrapper) {
830
+ return `${hierarchy.immediateWrapper} Card`;
831
+ }
832
+ else if (hierarchy.immediateParent) {
833
+ return `${hierarchy.immediateParent} Card`;
834
+ }
835
+ // Otherwise just "Card"
836
+ return 'Card';
837
+ })();
838
+ // Register card with its semantic name in context
839
+ React.useEffect(() => {
840
+ addContext('Card', componentName, false); // false = wrapper (always visible)
841
+ return () => removeContext();
842
+ }, [addContext, removeContext, componentName]);
843
+ return (jsx(Card$1, { ...props, isSelectable: isSelectable, isClickable: isClickable, isExpanded: isExpanded, isCompact: isCompact, isSelected: isSelected, isDisabled: isDisabled, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": role, "data-purpose": inferredPurpose, "data-content-type": inferredContentType, "data-interactive-state": inferredInteractiveState, children: children }));
844
+ };
845
+
846
+ /** StatusBadge - HTML span wrapper with semantic metadata for AI tooling */
847
+ const StatusBadge = ({ semanticName, semanticRole, aiMetadata, purpose, statusType, children, ...props }) => {
848
+ // Auto-infer semantic properties from content
849
+ const content = children?.toString();
850
+ const inferredStatusType = statusType || inferStatusBadgeType(content);
851
+ const inferredPurpose = purpose || inferStatusBadgePurpose();
852
+ // Generate semantic role and AI metadata
853
+ const role = semanticRole || `status-badge-${inferredPurpose}-${inferredStatusType}`;
854
+ const metadata = aiMetadata || {
855
+ description: `${inferredPurpose} showing ${inferredStatusType} status`,
856
+ category: 'data-display',
857
+ complexity: 'simple',
858
+ usage: [`${inferredPurpose}`, 'status-display', 'state-indication']
859
+ };
860
+ // Default semantic name if not provided
861
+ const defaultSemanticName = semanticName || 'Row Item';
862
+ return (jsx("span", { ...props, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-status-type": inferredStatusType, children: children }));
863
+ };
864
+
865
+ /** Tbody - PatternFly Table Body wrapper with semantic metadata for AI tooling */
866
+ const Tbody = ({ semanticName, semanticRole, aiMetadata, purpose, children, ...props }) => {
867
+ // Auto-infer semantic properties from children content
868
+ const inferredPurpose = purpose || (React.Children.toArray(children).some(child => React.isValidElement(child) && React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && cell.props?.children?.toString().toLowerCase().includes('select'))) ? 'selectable-rows' :
869
+ React.Children.toArray(children).some(child => React.isValidElement(child) && React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && cell.props?.children?.toString().toLowerCase().includes('action'))) ? 'action-rows' :
870
+ React.Children.toArray(children).some(child => React.isValidElement(child) && React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && typeof cell.props?.children === 'object')) ? 'mixed-content' : 'data-rows');
871
+ // Generate semantic role and AI metadata
872
+ const role = semanticRole || `table-body-section-${inferredPurpose}`;
873
+ const metadata = aiMetadata || {
874
+ description: `Table body section with ${inferredPurpose}`,
875
+ category: 'data-display',
876
+ complexity: 'moderate',
877
+ usage: [`table-${inferredPurpose}`, 'data-presentation', 'row-content']
878
+ };
879
+ // Default semantic name if not provided
880
+ const defaultSemanticName = semanticName || 'Body Section';
881
+ return (jsx(Tbody$1, { ...props, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, children: children }));
882
+ };
883
+
884
+ /** Td - PatternFly Table Data wrapper with semantic metadata for AI tooling */
885
+ const Td = ({ semanticName, semanticRole, aiMetadata, purpose, dataType, children, ...props }) => {
886
+ // Auto-infer semantic properties from PatternFly props and content
887
+ const inferredPurpose = purpose || (React.Children.toArray(children).some(child => React.isValidElement(child) && child.type?.toString().includes('Button')) ? 'action-cell' :
888
+ React.Children.toArray(children).some(child => React.isValidElement(child) && child.type?.toString().includes('Checkbox')) ? 'selectable-cell' :
889
+ children?.toString().toLowerCase().includes('status') ? 'status-cell' : 'data-cell');
890
+ // Simple data type inference based on content
891
+ const inferredDataType = dataType || (typeof children === 'number' ? 'number' :
892
+ children?.toString().match(/^\d{4}-\d{2}-\d{2}/) ? 'date' :
893
+ children?.toString().toLowerCase() === 'true' ||
894
+ children?.toString().toLowerCase() === 'false' ? 'boolean' :
895
+ React.Children.toArray(children).some(child => React.isValidElement(child) && child.type?.toString().includes('Button')) ? 'action' : 'text');
896
+ // Generate semantic role and AI metadata
897
+ const role = semanticRole || `table-cell-${inferredPurpose}-${inferredDataType}`;
898
+ const metadata = aiMetadata || {
899
+ description: `${inferredPurpose} containing ${inferredDataType} data`,
900
+ category: 'data-display',
901
+ complexity: 'simple',
902
+ usage: [`table-${inferredPurpose}`, 'data-presentation', 'row-content']
903
+ };
904
+ // Default semantic name if not provided
905
+ const defaultSemanticName = semanticName || 'Row Item';
906
+ return (jsx(Td$1, { ...props, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-data-type": inferredDataType, children: children }));
907
+ };
908
+
909
+ /** Th - PatternFly Table Header wrapper with semantic metadata for AI tooling */
910
+ const Th = ({ semanticName, semanticRole, aiMetadata, purpose, dataType, children, sort, ...props }) => {
911
+ // Auto-infer semantic properties from PatternFly props
912
+ const inferredPurpose = purpose || (sort ? 'sortable-header' :
913
+ children?.toString().toLowerCase().includes('select') ? 'selectable-header' :
914
+ children?.toString().toLowerCase().includes('action') ? 'action-header' : 'column-header');
915
+ // Simple data type inference based on content
916
+ const inferredDataType = dataType || (children?.toString().toLowerCase().includes('date') ? 'date' :
917
+ children?.toString().toLowerCase().includes('id') ||
918
+ children?.toString().toLowerCase().includes('count') ? 'number' :
919
+ children?.toString().toLowerCase().includes('action') ? 'action' : 'text');
920
+ // Generate semantic role and AI metadata
921
+ const role = semanticRole || `table-header-${inferredPurpose}-${inferredDataType}`;
922
+ const metadata = aiMetadata || {
923
+ description: `${inferredPurpose} for ${inferredDataType} data`,
924
+ category: 'data-display',
925
+ complexity: 'simple',
926
+ usage: [`table-${inferredPurpose}`, 'data-organization', 'column-definition']
927
+ };
928
+ // Always use 'Th' for component type identification (for validation)
929
+ // Store custom semantic name separately as instance name
930
+ const componentType = 'Th';
931
+ const instanceName = semanticName;
932
+ return (jsx(Th$1, { ...props, sort: sort, "data-semantic-name": componentType, "data-instance-name": instanceName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-data-type": inferredDataType, children: children }));
933
+ };
934
+
935
+ /** Thead - PatternFly Table Header wrapper with semantic metadata for AI tooling */
936
+ const Thead = ({ semanticName, semanticRole, aiMetadata, purpose, children, ...props }) => {
937
+ // Auto-infer semantic properties from children content
938
+ const inferredPurpose = purpose || (React.Children.toArray(children).some(child => React.isValidElement(child) && child.props?.sort) ? 'sortable-headers' :
939
+ React.Children.toArray(children).some(child => React.isValidElement(child) && child.props?.children?.toString().toLowerCase().includes('select')) ? 'selectable-headers' :
940
+ React.Children.toArray(children).some(child => React.isValidElement(child) && child.props?.children?.toString().toLowerCase().includes('action')) ? 'action-headers' : 'column-definition');
941
+ // Generate semantic role and AI metadata
942
+ const role = semanticRole || `table-header-section-${inferredPurpose}`;
943
+ const metadata = aiMetadata || {
944
+ description: `Table header section with ${inferredPurpose}`,
945
+ category: 'data-display',
946
+ complexity: 'moderate',
947
+ usage: [`table-${inferredPurpose}`, 'data-organization', 'column-structure']
948
+ };
949
+ // Default semantic name if not provided
950
+ const defaultSemanticName = semanticName || 'Header Section';
951
+ return (jsx(Thead$1, { ...props, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, children: children }));
952
+ };
953
+
954
+ /** Tr - PatternFly Table Row wrapper with semantic metadata for AI tooling */
955
+ const Tr = ({ semanticName, semanticRole, aiMetadata, purpose, interactionType, rowState, children, isClickable, isSelectable, isExpanded, isStriped, ...props }) => {
956
+ // Auto-infer semantic properties from PatternFly props and content
957
+ const inferredPurpose = purpose || (React.Children.toArray(children).some(child => React.isValidElement(child) &&
958
+ React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && cell.type?.toString().includes('Th'))) ? 'header-row' :
959
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
960
+ React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && cell.type?.toString().includes('Checkbox'))) ? 'selectable-row' :
961
+ isExpanded ? 'expandable-row' :
962
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
963
+ React.Children.toArray(child.props?.children).some(cell => React.isValidElement(cell) && cell.type?.toString().includes('Button'))) ? 'action-row' : 'data-row');
964
+ const inferredInteractionType = interactionType || (isClickable ? 'clickable' :
965
+ isSelectable ? 'selectable' :
966
+ isExpanded !== undefined ? 'expandable' :
967
+ 'static');
968
+ const inferredRowState = rowState || (isExpanded ? 'expanded' :
969
+ isSelectable ? 'selected' :
970
+ isStriped ? 'highlighted' :
971
+ 'normal');
972
+ // Generate semantic role and AI metadata
973
+ const role = semanticRole || `table-row-${inferredPurpose}-${inferredInteractionType}`;
974
+ const metadata = aiMetadata || {
975
+ description: `${inferredPurpose} with ${inferredInteractionType} interaction`,
976
+ category: 'data-display',
977
+ complexity: inferredInteractionType === 'static' ? 'simple' : 'medium',
978
+ usage: [`table-${inferredPurpose}`, 'row-interaction', 'data-presentation'],
979
+ interactionType: inferredInteractionType,
980
+ rowState: inferredRowState,
981
+ isStriped: isStriped || false
982
+ };
983
+ // Default semantic name if not provided
984
+ const defaultSemanticName = semanticName || 'Table Row';
985
+ return (jsx(Tr$1, { ...props, isClickable: isClickable, isSelectable: isSelectable, isExpanded: isExpanded, isStriped: isStriped, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-interaction-type": inferredInteractionType, "data-row-state": inferredRowState, children: children }));
986
+ };
987
+
988
+ /** Flex - PatternFly Flex wrapper with semantic metadata for AI tooling */
989
+ const Flex = ({ semanticName, semanticRole, aiMetadata, purpose, layoutType, alignmentContext, children, direction, justifyContent, alignItems, alignSelf, flex, spaceItems, gap, columnGap, rowGap, order, component, display, ...props }) => {
990
+ // Auto-infer semantic properties from PatternFly props
991
+ const inferredPurpose = purpose || (justifyContent?.default === 'justifyContentSpaceBetween' ? 'toolbar' :
992
+ justifyContent?.default === 'justifyContentCenter' ? 'content' :
993
+ spaceItems ? 'action-group' :
994
+ 'layout');
995
+ const inferredLayoutType = layoutType || (direction?.default === 'column' ? 'column' :
996
+ direction?.lg ? 'responsive' :
997
+ 'row');
998
+ const inferredAlignmentContext = alignmentContext || (alignItems?.default === 'alignItemsCenter' ? 'center' :
999
+ alignItems?.default === 'alignItemsFlexEnd' ? 'end' :
1000
+ alignItems?.default === 'alignItemsFlexStart' ? 'start' :
1001
+ alignItems?.default === 'alignItemsStretch' ? 'stretch' :
1002
+ alignItems?.default === 'alignItemsBaseline' ? 'baseline' :
1003
+ 'start');
1004
+ // Generate semantic role and AI metadata
1005
+ const role = semanticRole || `flex-${inferredPurpose}-${inferredLayoutType}`;
1006
+ const metadata = aiMetadata || {
1007
+ description: `${inferredPurpose} flex container with ${inferredLayoutType} layout`,
1008
+ category: 'layout',
1009
+ complexity: inferredLayoutType === 'responsive' ? 'medium' : 'simple',
1010
+ usage: [`${inferredPurpose}-layout`, `${inferredLayoutType}-container`, 'responsive-design'],
1011
+ alignment: inferredAlignmentContext,
1012
+ layoutDirection: direction?.default || 'row'
1013
+ };
1014
+ // Default semantic name if not provided
1015
+ const defaultSemanticName = semanticName || 'Flex Container';
1016
+ return (jsx(Flex$1, { ...props, direction: direction, justifyContent: justifyContent, alignItems: alignItems, alignSelf: alignSelf, flex: flex, spaceItems: spaceItems, gap: gap, columnGap: columnGap, rowGap: rowGap, order: order, component: component, display: display, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-purpose": inferredPurpose, "data-layout-type": inferredLayoutType, "data-alignment-context": inferredAlignmentContext, children: children }));
1017
+ };
1018
+
1019
+ /** FlexItem - PatternFly FlexItem wrapper with semantic metadata for AI tooling */
1020
+ const FlexItem = ({ semanticName, semanticRole, aiMetadata, contentType, positioningContext, sizingBehavior, children, flex, align, alignSelf, spacer, order, component, ...props }) => {
1021
+ // Auto-infer semantic properties from PatternFly props
1022
+ const inferredContentType = contentType || (React.Children.toArray(children).some(child => React.isValidElement(child) &&
1023
+ (child.type?.toString().includes('Button') ||
1024
+ child.props?.variant === 'primary' ||
1025
+ child.props?.variant === 'secondary')) ? 'button' :
1026
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
1027
+ child.type?.toString().includes('Icon')) ? 'icon' :
1028
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
1029
+ (child.type?.toString().includes('Input') ||
1030
+ child.type?.toString().includes('Select') ||
1031
+ child.type?.toString().includes('Checkbox'))) ? 'form-control' :
1032
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
1033
+ (child.type?.toString().includes('img') ||
1034
+ child.type?.toString().includes('Image'))) ? 'media' :
1035
+ React.Children.toArray(children).some(child => React.isValidElement(child) &&
1036
+ child.type?.toString().includes('Link')) ? 'navigation' :
1037
+ 'text');
1038
+ const inferredPositioningContext = positioningContext || (align?.default === 'alignRight' ? 'end' :
1039
+ align?.default === 'alignLeft' ? 'start' :
1040
+ align?.default === 'alignCenter' ? 'center' :
1041
+ alignSelf?.default === 'alignSelfFlexEnd' ? 'end' :
1042
+ alignSelf?.default === 'alignSelfFlexStart' ? 'start' :
1043
+ alignSelf?.default === 'alignSelfCenter' ? 'center' :
1044
+ alignSelf?.default === 'alignSelfStretch' ? 'stretch' :
1045
+ alignSelf?.default === 'alignSelfBaseline' ? 'baseline' :
1046
+ 'auto');
1047
+ const inferredSizingBehavior = sizingBehavior || (flex?.default === 'flex_1' ? 'flexible' :
1048
+ flex?.default === 'flex_2' ? 'grow' :
1049
+ flex?.default === 'flex_3' ? 'grow' :
1050
+ flex?.default === 'flexNone' ? 'fixed' :
1051
+ flex?.default === 'flexDefault' ? 'auto' :
1052
+ flex?.default === 'flex_4' ? 'auto' :
1053
+ 'auto');
1054
+ // Generate semantic role and AI metadata
1055
+ const role = semanticRole || `flex-item-${inferredContentType}-${inferredSizingBehavior}`;
1056
+ const metadata = aiMetadata || {
1057
+ description: `${inferredContentType} flex item with ${inferredSizingBehavior} sizing`,
1058
+ category: 'layout',
1059
+ complexity: 'simple',
1060
+ usage: [`${inferredContentType}-item`, `${inferredSizingBehavior}-sizing`, 'flex-layout'],
1061
+ positioning: inferredPositioningContext,
1062
+ sizing: inferredSizingBehavior,
1063
+ spacing: spacer?.default || 'none'
1064
+ };
1065
+ // Default semantic name if not provided
1066
+ const defaultSemanticName = semanticName || 'Flex Item';
1067
+ return (jsx(FlexItem$1, { ...props, flex: flex, align: align, alignSelf: alignSelf, spacer: spacer, order: order, component: component, "data-semantic-name": defaultSemanticName, "data-semantic-role": role, "data-ai-metadata": JSON.stringify(metadata), "data-content-type": inferredContentType, "data-positioning-context": inferredPositioningContext, "data-sizing-behavior": inferredSizingBehavior, children: children }));
1068
+ };
1069
+
1070
+ /** Modal - PatternFly Modal wrapper with semantic metadata for AI tooling */
1071
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1072
+ const Modal = React.forwardRef(({ semanticName, semanticRole, aiMetadata: _aiMetadata, purpose, interactionType, triggeredBy, children, variant, isOpen, ...props }, ref) => {
1073
+ // Register as visual parent in semantic context
1074
+ const { addContext, removeContext } = useSemanticContext();
1075
+ React.useEffect(() => {
1076
+ addContext('Modal', undefined, true); // true = qualified visual parent
1077
+ return () => removeContext();
1078
+ }, [addContext, removeContext]);
1079
+ // Get hierarchy from context
1080
+ let hierarchy;
1081
+ try {
1082
+ const semanticContext = useSemanticContext();
1083
+ hierarchy = semanticContext.getHierarchy();
1084
+ }
1085
+ catch {
1086
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
1087
+ }
1088
+ // Auto-infer semantic properties from PatternFly props
1089
+ const inferredPurpose = purpose || inferModalPurpose({ variant });
1090
+ const inferredInteractionType = interactionType || inferModalInteractionType(isOpen);
1091
+ // Auto-infer triggeredBy from current hierarchy context
1092
+ // Extract the semantic name of the last component (usually the triggering button)
1093
+ const inferredTriggeredBy = triggeredBy || (hierarchy.fullPath ?
1094
+ hierarchy.fullPath.split(' > ').pop() || 'unknown' : 'unknown');
1095
+ // Generate semantic role
1096
+ const role = semanticRole || `modal-${inferredPurpose}-${inferredInteractionType}`;
1097
+ // Default semantic name if not provided
1098
+ const componentName = semanticName || 'Modal';
1099
+ return (jsx(Modal$1, { ...props, ref: ref, variant: variant, isOpen: isOpen, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-triggered-by": inferredTriggeredBy, "data-semantic-role": role, "data-purpose": inferredPurpose, "data-interaction-type": inferredInteractionType, children: children }));
1100
+ });
1101
+ Modal.displayName = 'Modal';
1102
+
1103
+ /** Drawer - PatternFly Drawer wrapper with semantic metadata for AI tooling */
1104
+ const Drawer = ({ semanticName, semanticRole, purpose, children, isExpanded, ...props }) => {
1105
+ // Register as visual parent in semantic context
1106
+ const { addContext, removeContext } = useSemanticContext();
1107
+ React.useEffect(() => {
1108
+ addContext('Drawer', undefined, true); // true = qualified visual parent
1109
+ return () => removeContext();
1110
+ }, [addContext, removeContext]);
1111
+ // Get hierarchy from context
1112
+ let hierarchy;
1113
+ try {
1114
+ const semanticContext = useSemanticContext();
1115
+ hierarchy = semanticContext.getHierarchy();
1116
+ }
1117
+ catch {
1118
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
1119
+ }
1120
+ // Auto-infer purpose if not provided
1121
+ const inferredPurpose = purpose || 'details';
1122
+ // Generate semantic role
1123
+ const role = semanticRole || `drawer-${inferredPurpose}`;
1124
+ // Default semantic name if not provided
1125
+ const componentName = semanticName || 'Drawer';
1126
+ return (jsx(Drawer$1, { ...props, isExpanded: isExpanded, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": role, "data-purpose": inferredPurpose, "data-is-expanded": isExpanded, children: children }));
1127
+ };
1128
+
1129
+ const MenuToggle = ({ semanticName, semanticRole, aiMetadata, target, children, ...props }) => {
1130
+ // Get hierarchy from context (optional)
1131
+ let hierarchy;
1132
+ let semanticContext;
1133
+ try {
1134
+ // eslint-disable-next-line react-hooks/rules-of-hooks
1135
+ semanticContext = useSemanticContext();
1136
+ }
1137
+ catch {
1138
+ semanticContext = null;
1139
+ }
1140
+ const { addContext, removeContext, getHierarchy } = semanticContext || {
1141
+ addContext: () => { },
1142
+ removeContext: () => { },
1143
+ getHierarchy: () => ({ fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 })
1144
+ };
1145
+ // Add "menu" context when this component mounts/renders
1146
+ React.useEffect(() => {
1147
+ addContext('Menu'); // Auto-detected as non-qualified (wrapper)
1148
+ return () => removeContext();
1149
+ }, [addContext, removeContext]);
1150
+ hierarchy = getHierarchy();
1151
+ const componentName = semanticName || 'Toggle';
1152
+ const metadata = aiMetadata || {
1153
+ hierarchy,
1154
+ action: {
1155
+ type: 'toggle',
1156
+ target: target || 'menu'
1157
+ }
1158
+ };
1159
+ return (jsx(MenuToggle$1, { ...props, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": semanticRole || 'menu-trigger', "data-ai-metadata": JSON.stringify(metadata), "data-target": target || 'menu', children: children }));
1160
+ };
1161
+
1162
+ const DropdownItem = ({ semanticName, semanticRole, aiMetadata, target, children, ...props }) => {
1163
+ // Get hierarchy from context (optional)
1164
+ let hierarchy;
1165
+ try {
1166
+ const semanticContext = useSemanticContext();
1167
+ hierarchy = semanticContext.getHierarchy();
1168
+ }
1169
+ catch {
1170
+ hierarchy = { fullPath: '', qualifiedParents: [], wrappers: [], immediateParent: '', immediateWrapper: '', depth: 0 };
1171
+ }
1172
+ const componentName = semanticName || 'Action';
1173
+ const metadata = aiMetadata || {
1174
+ hierarchy,
1175
+ action: {
1176
+ type: 'menu-action',
1177
+ target: target || 'default'
1178
+ }
1179
+ };
1180
+ return (jsx(DropdownItem$1, { ...props, "data-semantic-name": componentName, "data-semantic-path": hierarchy.fullPath ? `${hierarchy.fullPath} > ${componentName}` : componentName, "data-parent": hierarchy.immediateParent || 'none', "data-wrapper": hierarchy.immediateWrapper || 'none', "data-num-parents": hierarchy.depth, "data-semantic-role": semanticRole || 'menu-item', "data-ai-metadata": JSON.stringify(metadata), "data-target": target || 'default', children: children }));
1181
+ };
1182
+
1183
+ /**
1184
+ * Utility functions for managing component metadata
1185
+ */
1186
+ /**
1187
+ * Generates default metadata for a component based on its type and props
1188
+ */
1189
+ const generateComponentMetadata = (componentName, props = {}) => {
1190
+ const baseMetadata = {
1191
+ name: componentName,
1192
+ description: `Semantic wrapper for ${componentName}`,
1193
+ category: 'data-display',
1194
+ accessibility: ['keyboard-navigable'],
1195
+ usage: ['user-interface'],
1196
+ props: props
1197
+ };
1198
+ // Customize based on component type
1199
+ switch (componentName.toLowerCase()) {
1200
+ case 'button':
1201
+ return {
1202
+ ...baseMetadata,
1203
+ category: 'forms',
1204
+ description: 'Interactive button with semantic meaning',
1205
+ usage: ['user-interaction', 'form-submission', 'navigation']
1206
+ };
1207
+ case 'card':
1208
+ return {
1209
+ ...baseMetadata,
1210
+ category: 'data-display',
1211
+ description: 'Content container with semantic purpose',
1212
+ usage: ['content-organization', 'data-presentation']
1213
+ };
1214
+ case 'modal':
1215
+ return {
1216
+ ...baseMetadata,
1217
+ category: 'overlay',
1218
+ description: 'Overlay dialog with semantic purpose',
1219
+ accessibility: ['keyboard-navigable', 'focus-management', 'screen-reader-friendly'],
1220
+ usage: ['user-interaction', 'workflow-step', 'confirmation']
1221
+ };
1222
+ default:
1223
+ return baseMetadata;
1224
+ }
1225
+ };
1226
+ /**
1227
+ * Validates component metadata
1228
+ */
1229
+ const validateMetadata = (metadata) => {
1230
+ return !!(metadata.name &&
1231
+ metadata.description &&
1232
+ metadata.category &&
1233
+ Array.isArray(metadata.accessibility) &&
1234
+ Array.isArray(metadata.usage));
1235
+ };
1236
+ /**
1237
+ * Merges user-provided metadata with defaults
1238
+ */
1239
+ const mergeMetadata = (userMetadata, defaultMetadata) => {
1240
+ return {
1241
+ ...defaultMetadata,
1242
+ ...userMetadata,
1243
+ accessibility: [...defaultMetadata.accessibility, ...(userMetadata.accessibility || [])],
1244
+ usage: [...defaultMetadata.usage, ...(userMetadata.usage || [])]
1245
+ };
1246
+ };
1247
+
1248
+ /**
1249
+ * Accessibility utility functions
1250
+ */
1251
+ /**
1252
+ * Generates ARIA attributes based on component context
1253
+ */
1254
+ const generateAriaAttributes = (componentType) => {
1255
+ const baseAttributes = {};
1256
+ switch (componentType.toLowerCase()) {
1257
+ case 'button':
1258
+ return {
1259
+ ...baseAttributes,
1260
+ role: 'button',
1261
+ tabIndex: '0'
1262
+ };
1263
+ case 'card':
1264
+ return {
1265
+ ...baseAttributes,
1266
+ role: 'region',
1267
+ tabIndex: '0'
1268
+ };
1269
+ case 'modal':
1270
+ return {
1271
+ ...baseAttributes,
1272
+ role: 'dialog',
1273
+ 'aria-modal': 'true',
1274
+ tabIndex: '-1'
1275
+ };
1276
+ default:
1277
+ return baseAttributes;
1278
+ }
1279
+ };
1280
+ /**
1281
+ * Validates accessibility requirements
1282
+ */
1283
+ const validateAccessibility = (componentType, props) => {
1284
+ const issues = [];
1285
+ // Check for required ARIA attributes
1286
+ if (componentType === 'button' && !props['aria-label'] && !props.children) {
1287
+ issues.push('Button should have aria-label or visible text content');
1288
+ }
1289
+ if (componentType === 'modal' && !props['aria-labelledby'] && !props.title) {
1290
+ issues.push('Modal should have aria-labelledby or title');
1291
+ }
1292
+ return issues;
1293
+ };
1294
+ /**
1295
+ * Generates keyboard shortcuts metadata
1296
+ */
1297
+ const generateKeyboardShortcuts = (componentType, context = {}) => {
1298
+ const shortcuts = [];
1299
+ switch (componentType.toLowerCase()) {
1300
+ case 'button':
1301
+ shortcuts.push('Enter', 'Space');
1302
+ if (context.action === 'close') {
1303
+ shortcuts.push('Escape');
1304
+ }
1305
+ break;
1306
+ case 'modal':
1307
+ shortcuts.push('Escape', 'Tab', 'Shift+Tab');
1308
+ break;
1309
+ case 'card':
1310
+ if (context.interactive) {
1311
+ shortcuts.push('Enter', 'Space');
1312
+ }
1313
+ break;
1314
+ }
1315
+ return shortcuts;
1316
+ };
1317
+
1318
+ /**
1319
+ * Hook for managing semantic metadata for components
1320
+ */
1321
+ const useSemanticMetadata = (componentName, userMetadata, props = {}) => {
1322
+ const [metadata, setMetadata] = React.useState(() => {
1323
+ const defaultMetadata = generateComponentMetadata(componentName, props);
1324
+ return userMetadata ? mergeMetadata(userMetadata, defaultMetadata) : defaultMetadata;
1325
+ });
1326
+ React.useEffect(() => {
1327
+ const defaultMetadata = generateComponentMetadata(componentName, props);
1328
+ const mergedMetadata = userMetadata ? mergeMetadata(userMetadata, defaultMetadata) : defaultMetadata;
1329
+ setMetadata(mergedMetadata);
1330
+ }, [componentName, userMetadata, props]);
1331
+ const updateMetadata = (updates) => {
1332
+ setMetadata(prev => ({ ...prev, ...updates }));
1333
+ };
1334
+ return {
1335
+ metadata,
1336
+ updateMetadata
1337
+ };
1338
+ };
1339
+
1340
+ /**
1341
+ * Hook for managing accessibility features
1342
+ */
1343
+ const useAccessibility = (componentType, props = {}, context = {}) => {
1344
+ const ariaAttributes = React.useMemo(() => generateAriaAttributes(componentType), [componentType]);
1345
+ const keyboardShortcuts = React.useMemo(() => generateKeyboardShortcuts(componentType, context), [componentType, context]);
1346
+ const accessibilityIssues = React.useMemo(() => validateAccessibility(componentType, props), [componentType, props]);
1347
+ const enhancedProps = React.useMemo(() => ({
1348
+ ...props,
1349
+ ...ariaAttributes,
1350
+ 'data-keyboard-shortcuts': keyboardShortcuts.join(','),
1351
+ 'data-accessibility-issues': accessibilityIssues.join(',')
1352
+ }), [props, ariaAttributes, keyboardShortcuts, accessibilityIssues]);
1353
+ return {
1354
+ ariaAttributes,
1355
+ keyboardShortcuts,
1356
+ accessibilityIssues,
1357
+ enhancedProps
1358
+ };
1359
+ };
1360
+
1361
+ export { Button, Card, Checkbox, Drawer, DropdownItem, Flex, FlexItem, Form, Link, MenuToggle, Modal, Radio, Select, SemanticProvider, StarIcon, StatusBadge, Switch, Tbody, Td, TextArea, TextInput, Th, Thead, Tr, generateAriaAttributes, generateComponentMetadata, generateKeyboardShortcuts, generateMetadataFromProps, inferAccessibilityFeatures, inferAlertSeverity, inferButtonAction, inferCardContentType, inferCardInteractiveState, inferCardPurpose, inferCategory, inferCheckboxPurpose, inferContext, inferFormContext, inferInputPurpose, inferLinkPurpose, inferModalInteractionType, inferModalPurpose, inferRadioGroupContext, inferRadioPurpose, inferSelectPurpose, inferSelectSelectionType, inferSettingsContext, inferStarIconPurpose, inferStatusBadgePurpose, inferStatusBadgeType, inferSwitchPurpose, inferSwitchToggleTarget, inferTextAreaContentType, inferTextAreaPurpose, inferUsagePatterns, inferValidationContext, isVisualParent, mergeMetadata, useAccessibility, useSemanticContext, useSemanticMetadata, validateAccessibility, validateMetadata };
1362
+ //# sourceMappingURL=index.esm.js.map