@abstraks-dev/ui-library 1.0.1

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 (158) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +708 -0
  3. package/dist/__tests__/Anchor.test.js +145 -0
  4. package/dist/__tests__/ArrowRight.test.js +91 -0
  5. package/dist/__tests__/Avatar.test.js +123 -0
  6. package/dist/__tests__/Button.test.js +82 -0
  7. package/dist/__tests__/Card.test.js +198 -0
  8. package/dist/__tests__/CheckCircle.test.js +98 -0
  9. package/dist/__tests__/Checkbox.test.js +161 -0
  10. package/dist/__tests__/ChevronDown.test.js +73 -0
  11. package/dist/__tests__/Close.test.js +98 -0
  12. package/dist/__tests__/EditSquare.test.js +99 -0
  13. package/dist/__tests__/Error.test.js +74 -0
  14. package/dist/__tests__/Footer.test.js +66 -0
  15. package/dist/__tests__/Heading.test.js +227 -0
  16. package/dist/__tests__/Hero.test.js +74 -0
  17. package/dist/__tests__/Label.test.js +123 -0
  18. package/dist/__tests__/Loader.test.js +115 -0
  19. package/dist/__tests__/MenuHover.test.js +137 -0
  20. package/dist/__tests__/Paragraph.test.js +93 -0
  21. package/dist/__tests__/PlusCircle.test.js +99 -0
  22. package/dist/__tests__/Radio.test.js +153 -0
  23. package/dist/__tests__/Select.test.js +187 -0
  24. package/dist/__tests__/Tabs.test.js +162 -0
  25. package/dist/__tests__/TextArea.test.js +127 -0
  26. package/dist/__tests__/TextInput.test.js +181 -0
  27. package/dist/__tests__/Toggle.test.js +120 -0
  28. package/dist/__tests__/TrashX.test.js +99 -0
  29. package/dist/__tests__/useHeadingAccessibility.test.js +144 -0
  30. package/dist/components/Anchor.js +131 -0
  31. package/dist/components/Animation.js +129 -0
  32. package/dist/components/AnimationGroup.js +207 -0
  33. package/dist/components/AnimationToggle.js +216 -0
  34. package/dist/components/Avatar.js +153 -0
  35. package/dist/components/Button.js +218 -0
  36. package/dist/components/Card.js +222 -0
  37. package/dist/components/Checkbox.js +305 -0
  38. package/dist/components/Crud.js +564 -0
  39. package/dist/components/DragAndDrop.js +337 -0
  40. package/dist/components/Error.js +206 -0
  41. package/dist/components/Footer.js +99 -0
  42. package/dist/components/Form.js +412 -0
  43. package/dist/components/Header.js +372 -0
  44. package/dist/components/Heading.js +134 -0
  45. package/dist/components/Hero.js +181 -0
  46. package/dist/components/Label.js +256 -0
  47. package/dist/components/Loader.js +302 -0
  48. package/dist/components/MenuHover.js +114 -0
  49. package/dist/components/Paragraph.js +128 -0
  50. package/dist/components/Prompt.js +61 -0
  51. package/dist/components/Radio.js +254 -0
  52. package/dist/components/Select.js +422 -0
  53. package/dist/components/SideMenu.js +313 -0
  54. package/dist/components/Tabs.js +297 -0
  55. package/dist/components/TextArea.js +370 -0
  56. package/dist/components/TextInput.js +286 -0
  57. package/dist/components/Toggle.js +186 -0
  58. package/dist/components/crudFiles/CrudEditBase.js +150 -0
  59. package/dist/components/crudFiles/CrudViewBase.js +39 -0
  60. package/dist/components/crudFiles/crudDevelopment.js +118 -0
  61. package/dist/components/crudFiles/crudEditHandlers.js +50 -0
  62. package/dist/constants/animation.js +30 -0
  63. package/dist/icons/ArrowIcon.js +32 -0
  64. package/dist/icons/ArrowRight.js +33 -0
  65. package/dist/icons/CheckCircle.js +33 -0
  66. package/dist/icons/ChevronDown.js +28 -0
  67. package/dist/icons/Close.js +33 -0
  68. package/dist/icons/EditSquare.js +33 -0
  69. package/dist/icons/Ellipses.js +34 -0
  70. package/dist/icons/Hamburger.js +39 -0
  71. package/dist/icons/LoadingSpinner.js +42 -0
  72. package/dist/icons/PlusCircle.js +33 -0
  73. package/dist/icons/SaveIcon.js +32 -0
  74. package/dist/icons/TrashX.js +33 -0
  75. package/dist/icons/__tests__/CheckCircle.test.js +9 -0
  76. package/dist/icons/__tests__/ChevronDown.test.js +9 -0
  77. package/dist/icons/__tests__/Close.test.js +9 -0
  78. package/dist/icons/__tests__/EditSquare.test.js +9 -0
  79. package/dist/icons/__tests__/PlusCircle.test.js +9 -0
  80. package/dist/icons/__tests__/TrashX.test.js +9 -0
  81. package/dist/icons/index.js +89 -0
  82. package/dist/index.js +332 -0
  83. package/dist/setupTests.js +3 -0
  84. package/dist/styles/_variables.scss +286 -0
  85. package/dist/styles/anchor.scss +40 -0
  86. package/dist/styles/animation-accessibility.scss +96 -0
  87. package/dist/styles/animation-toggle.scss +233 -0
  88. package/dist/styles/animation.scss +3781 -0
  89. package/dist/styles/avatar.scss +285 -0
  90. package/dist/styles/button.scss +430 -0
  91. package/dist/styles/card.scss +210 -0
  92. package/dist/styles/checkbox.scss +160 -0
  93. package/dist/styles/crud.scss +474 -0
  94. package/dist/styles/dragAndDrop.scss +312 -0
  95. package/dist/styles/error.scss +232 -0
  96. package/dist/styles/footer.scss +58 -0
  97. package/dist/styles/form.scss +420 -0
  98. package/dist/styles/grid.scss +29 -0
  99. package/dist/styles/header.scss +276 -0
  100. package/dist/styles/heading.scss +118 -0
  101. package/dist/styles/hero.scss +185 -0
  102. package/dist/styles/htmlElements.scss +20 -0
  103. package/dist/styles/image.scss +9 -0
  104. package/dist/styles/label.scss +340 -0
  105. package/dist/styles/list-item.scss +5 -0
  106. package/dist/styles/loader.scss +354 -0
  107. package/dist/styles/logo.scss +19 -0
  108. package/dist/styles/main.css +9056 -0
  109. package/dist/styles/main.css.map +1 -0
  110. package/dist/styles/main.scss +0 -0
  111. package/dist/styles/menu-hover.scss +30 -0
  112. package/dist/styles/paragraph.scss +88 -0
  113. package/dist/styles/prompt.scss +51 -0
  114. package/dist/styles/radio.scss +202 -0
  115. package/dist/styles/select.scss +363 -0
  116. package/dist/styles/side-menu.scss +334 -0
  117. package/dist/styles/tabs.scss +540 -0
  118. package/dist/styles/text-area.scss +388 -0
  119. package/dist/styles/text-input.scss +171 -0
  120. package/dist/styles/toggle.scss +0 -0
  121. package/dist/styles/unordered-list.scss +8 -0
  122. package/dist/utils/ScrollHandler.js +30 -0
  123. package/dist/utils/accessibility.js +128 -0
  124. package/dist/utils/heroUtils.js +316 -0
  125. package/dist/utils/index.js +104 -0
  126. package/dist/utils/inputValidation.js +29 -0
  127. package/dist/utils/keyboardNavigation.js +536 -0
  128. package/dist/utils/labelUtils.js +708 -0
  129. package/dist/utils/loaderUtils.js +387 -0
  130. package/dist/utils/menuUtils.js +575 -0
  131. package/dist/utils/useHeadingAccessibility.js +298 -0
  132. package/dist/utils/useRadioGroup.js +260 -0
  133. package/dist/utils/useSelectAccessibility.js +426 -0
  134. package/dist/utils/useTabsAccessibility.js +278 -0
  135. package/dist/utils/useTextAreaAccessibility.js +255 -0
  136. package/dist/utils/useTextInputAccessibility.js +295 -0
  137. package/dist/utils/useTypographyAccessibility.js +168 -0
  138. package/dist/utils/useWindowSize.js +32 -0
  139. package/dist/utils/utils/ScrollHandler.js +26 -0
  140. package/dist/utils/utils/accessibility.js +133 -0
  141. package/dist/utils/utils/heroUtils.js +348 -0
  142. package/dist/utils/utils/index.js +9 -0
  143. package/dist/utils/utils/inputValidation.js +22 -0
  144. package/dist/utils/utils/keyboardNavigation.js +664 -0
  145. package/dist/utils/utils/labelUtils.js +772 -0
  146. package/dist/utils/utils/loaderUtils.js +436 -0
  147. package/dist/utils/utils/menuUtils.js +651 -0
  148. package/dist/utils/utils/useHeadingAccessibility.js +334 -0
  149. package/dist/utils/utils/useRadioGroup.js +311 -0
  150. package/dist/utils/utils/useSelectAccessibility.js +498 -0
  151. package/dist/utils/utils/useTabsAccessibility.js +316 -0
  152. package/dist/utils/utils/useTextAreaAccessibility.js +303 -0
  153. package/dist/utils/utils/useTextInputAccessibility.js +338 -0
  154. package/dist/utils/utils/useTypographyAccessibility.js +180 -0
  155. package/dist/utils/utils/useWindowSize.js +26 -0
  156. package/dist/utils/utils/validation.js +131 -0
  157. package/dist/utils/validation.js +139 -0
  158. package/package.json +90 -0
@@ -0,0 +1,256 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Label = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = require("prop-types");
9
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
10
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
11
+ /**
12
+ * Label - Accessible form label component with validation and help text support
13
+ *
14
+ * Features:
15
+ * - Semantic HTML label element with proper form association
16
+ * - Required field indicators with multiple display options
17
+ * - Validation states with contextual messaging
18
+ * - Help text support for user guidance
19
+ * - Multiple size and weight variants
20
+ * - Full ARIA support for screen readers
21
+ * - Error, success, and warning state handling
22
+ *
23
+ * Accessibility:
24
+ * - Uses semantic <label> element with htmlFor association
25
+ * - Proper ARIA attributes for form control relationships
26
+ * - Screen reader announcements for validation states
27
+ * - Required field indicators with semantic meaning
28
+ * - Help text and error messages properly associated
29
+ * - Focus management and keyboard navigation support
30
+ *
31
+ * @component
32
+ * @example
33
+ * // Basic form label
34
+ * <Label labelFor="email" labelText="Email Address">
35
+ * <input id="email" type="email" />
36
+ * </Label>
37
+ *
38
+ * @example
39
+ * // Required field with validation
40
+ * <Label
41
+ * labelFor="password"
42
+ * labelText="Password"
43
+ * required={true}
44
+ * validationState="error"
45
+ * errorText="Password must be at least 8 characters"
46
+ * >
47
+ * <input id="password" type="password" />
48
+ * </Label>
49
+ *
50
+ * @example
51
+ * // With help text and custom styling
52
+ * <Label
53
+ * labelFor="username"
54
+ * labelText="Username"
55
+ * helpText="Choose a unique username"
56
+ * size="large"
57
+ * weight="bold"
58
+ * className="custom-label"
59
+ * >
60
+ * <input id="username" type="text" />
61
+ * </Label>
62
+ */
63
+ const Label = exports.Label = /*#__PURE__*/(0, _react.forwardRef)(({
64
+ // Core props
65
+ labelFor = '',
66
+ labelText = '',
67
+ children = null,
68
+ required = false,
69
+ // Layout props
70
+ className = '',
71
+ size = 'medium',
72
+ weight = 'medium',
73
+ disabled = false,
74
+ // Validation props
75
+ validationState = 'default',
76
+ requiredIndicator = 'asterisk',
77
+ helpText = '',
78
+ errorText = '',
79
+ successText = '',
80
+ // Accessibility props
81
+ ariaDescribedBy = '',
82
+ // Legacy props (for backward compatibility - internal use only)
83
+ additionalClassName = '',
84
+ componentName = 'label',
85
+ testId = 'label',
86
+ ...restProps
87
+ }, ref) => {
88
+ // Handle legacy prop mapping
89
+ const finalClassName = className || additionalClassName;
90
+
91
+ // Generate unique IDs for accessibility
92
+ const helpId = helpText ? `${testId}-help` : '';
93
+ const errorId = errorText ? `${testId}-error` : '';
94
+ const successId = successText ? `${testId}-success` : '';
95
+
96
+ // Build aria-describedby attribute
97
+ const describedBy = [ariaDescribedBy, helpId, errorId, successId].filter(Boolean).join(' ');
98
+
99
+ // Build CSS classes
100
+ const labelClasses = [componentName, finalClassName, `${componentName}--${size}`, `${componentName}--${weight}`, validationState !== 'default' && `${componentName}--${validationState}`, disabled && `${componentName}--disabled`, required && `${componentName}--required`].filter(Boolean).join(' ');
101
+
102
+ // Required indicator rendering
103
+ const renderRequiredIndicator = () => {
104
+ if (!required) return null;
105
+ switch (requiredIndicator) {
106
+ case 'asterisk':
107
+ return /*#__PURE__*/_react.default.createElement("span", {
108
+ className: "required",
109
+ "aria-label": "required"
110
+ }, "*");
111
+ case 'text':
112
+ return /*#__PURE__*/_react.default.createElement("span", {
113
+ className: "required-text"
114
+ }, "(required)");
115
+ case 'none':
116
+ return null;
117
+ default:
118
+ return /*#__PURE__*/_react.default.createElement("span", {
119
+ className: `${componentName}__required`,
120
+ "aria-label": "required"
121
+ }, "*");
122
+ }
123
+ };
124
+
125
+ // Validation message rendering
126
+ const renderValidationMessage = () => {
127
+ if (validationState === 'error' && errorText) {
128
+ return /*#__PURE__*/_react.default.createElement("div", {
129
+ id: errorId,
130
+ className: `${componentName}__message ${componentName}__message--error`,
131
+ role: "alert",
132
+ "aria-live": "polite"
133
+ }, errorText);
134
+ }
135
+ if (validationState === 'success' && successText) {
136
+ return /*#__PURE__*/_react.default.createElement("div", {
137
+ id: successId,
138
+ className: `${componentName}__message ${componentName}__message--success`,
139
+ role: "status",
140
+ "aria-live": "polite"
141
+ }, successText);
142
+ }
143
+ return null;
144
+ };
145
+
146
+ // Help text rendering
147
+ const renderHelpText = () => {
148
+ if (!helpText) return null;
149
+ return /*#__PURE__*/_react.default.createElement("div", {
150
+ id: helpId,
151
+ className: `${componentName}__help`
152
+ }, helpText);
153
+ };
154
+ return /*#__PURE__*/_react.default.createElement("div", {
155
+ className: `${componentName}-wrapper`,
156
+ "data-testid": testId
157
+ }, /*#__PURE__*/_react.default.createElement("label", _extends({
158
+ ref: ref,
159
+ className: labelClasses,
160
+ htmlFor: labelFor,
161
+ "aria-describedby": describedBy || undefined
162
+ }, restProps), /*#__PURE__*/_react.default.createElement("span", {
163
+ className: "label-text"
164
+ }, labelText && labelText, required && renderRequiredIndicator())), renderHelpText(), children, renderValidationMessage());
165
+ });
166
+ Label.propTypes = {
167
+ // ===========================================
168
+ // Core Props
169
+ // ===========================================
170
+ /**
171
+ * ID of the form control this label is associated with (required for accessibility)
172
+ */
173
+ labelFor: _propTypes.string,
174
+ /**
175
+ * The text content of the label (required)
176
+ */
177
+ labelText: _propTypes.string,
178
+ // ===========================================
179
+ // Content Props
180
+ // ===========================================
181
+ /**
182
+ * Form control element(s) to be labeled
183
+ */
184
+ children: _propTypes.node,
185
+ // ===========================================
186
+ // Appearance Props
187
+ // ===========================================
188
+ /**
189
+ * Additional CSS classes to apply to the label wrapper
190
+ */
191
+ className: _propTypes.string,
192
+ /**
193
+ * Size variant of the label
194
+ */
195
+ size: (0, _propTypes.oneOf)(['small', 'medium', 'large']),
196
+ /**
197
+ * Font weight of the label text
198
+ */
199
+ weight: (0, _propTypes.oneOf)(['light', 'normal', 'medium', 'bold']),
200
+ // ===========================================
201
+ // Behavior Props
202
+ // ===========================================
203
+ /**
204
+ * Whether the associated form control is required
205
+ */
206
+ required: _propTypes.bool,
207
+ /**
208
+ * Whether the associated form control is disabled
209
+ */
210
+ disabled: _propTypes.bool,
211
+ // ===========================================
212
+ // Validation Props
213
+ // ===========================================
214
+ /**
215
+ * Validation state of the associated form control
216
+ */
217
+ validationState: (0, _propTypes.oneOf)(['default', 'success', 'warning', 'error']),
218
+ /**
219
+ * How to display the required indicator
220
+ */
221
+ requiredIndicator: (0, _propTypes.oneOf)(['asterisk', 'text', 'none']),
222
+ /**
223
+ * Helpful text to display below the label
224
+ */
225
+ helpText: _propTypes.string,
226
+ /**
227
+ * Error message to display when validationState is 'error'
228
+ */
229
+ errorText: _propTypes.string,
230
+ /**
231
+ * Success message to display when validationState is 'success'
232
+ */
233
+ successText: _propTypes.string,
234
+ // ===========================================
235
+ // Accessibility Props
236
+ // ===========================================
237
+ /**
238
+ * Space-separated list of element IDs that describe the label
239
+ */
240
+ ariaDescribedBy: _propTypes.string,
241
+ /**
242
+ * Use className instead
243
+ */
244
+ additionalClassName: _propTypes.string,
245
+ /**
246
+ * Use labelFor/id for identification
247
+ * Base CSS class name for the component
248
+ */
249
+ componentName: _propTypes.string,
250
+ /**
251
+ * Test ID for testing and automation
252
+ */
253
+ testId: _propTypes.string
254
+ };
255
+ Label.displayName = 'Label';
256
+ var _default = exports.default = Label;
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Loader = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _Animation = _interopRequireDefault(require("./Animation"));
9
+ var _propTypes = require("prop-types");
10
+ var _Heading = _interopRequireDefault(require("./Heading"));
11
+ var _icons = require("../icons");
12
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
14
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
15
+ /**
16
+ * Loader - Accessible loading component for full-page or section loading states
17
+ *
18
+ * Features:
19
+ * - Multiple size variants with responsive design (sm, md, lg, xl)
20
+ * - Multiple animation variants (svg, spinner, dots, pulse)
21
+ * - Optional heading text with customizable size
22
+ * - Comprehensive ARIA labeling and screen reader support
23
+ * - Respects prefers-reduced-motion for accessibility
24
+ * - High contrast mode support
25
+ * - Keyboard navigation friendly
26
+ * - Semantic HTML structure with proper loading states
27
+ *
28
+ * Accessibility:
29
+ * - Uses proper ARIA roles (status) and labels
30
+ * - Announces loading state to screen readers with aria-live
31
+ * - Respects user motion preferences
32
+ * - High contrast mode compatible
33
+ * - Focus management ready
34
+ * - Screen reader friendly announcements
35
+ *
36
+ * @component
37
+ * @example
38
+ * // Basic usage
39
+ * <Loader />
40
+ *
41
+ * @example
42
+ * // With custom text and variant
43
+ * <Loader
44
+ * size="lg"
45
+ * variant="pulse"
46
+ * headerText="Loading your dashboard..."
47
+ * aria-label="Dashboard loading in progress"
48
+ * />
49
+ *
50
+ * @example
51
+ * // Minimal loader without header
52
+ * <Loader
53
+ * size="sm"
54
+ * showHeader={false}
55
+ * variant="dots"
56
+ * className="custom-loader"
57
+ * />
58
+ */
59
+ // Helper functions moved outside for clarity and performance
60
+ const sizeMap = {
61
+ sm: {
62
+ container: '150px',
63
+ spinner: 24,
64
+ dots: 6
65
+ },
66
+ md: {
67
+ container: '200px',
68
+ spinner: 32,
69
+ dots: 8
70
+ },
71
+ lg: {
72
+ container: '250px',
73
+ spinner: 40,
74
+ dots: 10
75
+ },
76
+ xl: {
77
+ container: '300px',
78
+ spinner: 48,
79
+ dots: 12
80
+ }
81
+ };
82
+ function getClassNames(componentName, size, variant, finalClassName) {
83
+ const classes = [componentName, `${componentName}--${size}`, `${componentName}--${variant}`, finalClassName].filter(Boolean);
84
+ return classes.join(' ');
85
+ }
86
+ function renderDots(componentName, currentSize, fill) {
87
+ return /*#__PURE__*/_react.default.createElement("div", {
88
+ className: `${componentName}__dots`,
89
+ "aria-hidden": "true"
90
+ }, [...Array(3)].map((_, index) => /*#__PURE__*/_react.default.createElement("div", {
91
+ key: index,
92
+ className: `${componentName}__dot`,
93
+ style: {
94
+ width: currentSize.dots,
95
+ height: currentSize.dots,
96
+ backgroundColor: fill,
97
+ animationDelay: `${index * 0.2}s`
98
+ }
99
+ })));
100
+ }
101
+ function renderPulse(componentName, currentSize, fill) {
102
+ return /*#__PURE__*/_react.default.createElement("div", {
103
+ className: `${componentName}__pulse`,
104
+ style: {
105
+ width: currentSize.container,
106
+ height: currentSize.container,
107
+ backgroundColor: fill
108
+ },
109
+ "aria-hidden": "true"
110
+ });
111
+ }
112
+ function renderSpinner(variant, componentName, currentSize, fill) {
113
+ switch (variant) {
114
+ case 'spinner':
115
+ return /*#__PURE__*/_react.default.createElement(_icons.LoadingSpinner, {
116
+ componentName: `${componentName}__spinner`,
117
+ dimensions: currentSize.spinner,
118
+ fill: fill
119
+ });
120
+ case 'dots':
121
+ return renderDots(componentName, currentSize, fill);
122
+ case 'pulse':
123
+ return renderPulse(componentName, currentSize, fill);
124
+ case 'svg':
125
+ default:
126
+ // Default SVG animation variant
127
+ return /*#__PURE__*/_react.default.createElement("svg", {
128
+ className: `${componentName}__svg`,
129
+ version: "1.1",
130
+ x: "0px",
131
+ y: "0px",
132
+ viewBox: "0 0 100 100",
133
+ enableBackground: "new 0 0 0 0",
134
+ width: currentSize.container,
135
+ height: currentSize.container,
136
+ "aria-hidden": "true",
137
+ role: "img",
138
+ focusable: "false"
139
+ }, /*#__PURE__*/_react.default.createElement("path", {
140
+ className: `${componentName}__path`,
141
+ fill: fill,
142
+ d: "M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50"
143
+ }, /*#__PURE__*/_react.default.createElement("animateTransform", {
144
+ attributeName: "transform",
145
+ attributeType: "XML",
146
+ type: "rotate",
147
+ dur: "1s",
148
+ from: "0 50 50",
149
+ to: "360 50 50",
150
+ repeatCount: "indefinite"
151
+ })));
152
+ }
153
+ }
154
+ const Loader = exports.Loader = /*#__PURE__*/(0, _react.forwardRef)(function Loader({
155
+ headerText,
156
+ children,
157
+ className,
158
+ size = 'md',
159
+ variant = 'svg',
160
+ fill = '#333',
161
+ showHeader = true,
162
+ titleSize = 3,
163
+ ariaLabel,
164
+ additionalClassName,
165
+ componentName = 'ui-loader',
166
+ testId,
167
+ ...props
168
+ }, ref) {
169
+ // Remove svgSize from props before spreading onto the root div
170
+ const {
171
+ svgSize,
172
+ ...restProps
173
+ } = props;
174
+ const finalClassName = className || additionalClassName;
175
+ const currentSize = sizeMap[size] || sizeMap.md;
176
+
177
+ // Always show a heading, defaulting to 'Loading...' if headerText is not provided
178
+ const headingText = showHeader ? headerText || 'Loading...' : null;
179
+ function renderSpinnerWithSvgSize(variant, componentName, currentSize, fill, svgSize) {
180
+ if (variant === 'svg' && svgSize) {
181
+ return /*#__PURE__*/_react.default.createElement("svg", {
182
+ className: `${componentName}__svg`,
183
+ version: "1.1",
184
+ x: "0px",
185
+ y: "0px",
186
+ viewBox: "0 0 100 100",
187
+ enableBackground: "new 0 0 0 0",
188
+ width: svgSize,
189
+ height: svgSize,
190
+ "aria-hidden": "true",
191
+ role: "img",
192
+ focusable: "false"
193
+ }, /*#__PURE__*/_react.default.createElement("path", {
194
+ className: `${componentName}__path`,
195
+ fill: fill,
196
+ d: "M73,50c0-12.7-10.3-23-23-23S27,37.3,27,50 M30.9,50c0-10.5,8.5-19.1,19.1-19.1S69.1,39.5,69.1,50"
197
+ }, /*#__PURE__*/_react.default.createElement("animateTransform", {
198
+ attributeName: "transform",
199
+ attributeType: "XML",
200
+ type: "rotate",
201
+ dur: "1s",
202
+ from: "0 50 50",
203
+ to: "360 50 50",
204
+ repeatCount: "indefinite"
205
+ })));
206
+ }
207
+ return renderSpinner(variant, componentName, currentSize, fill);
208
+ }
209
+ const loaderContent = /*#__PURE__*/_react.default.createElement("div", _extends({
210
+ ref: ref,
211
+ className: getClassNames(componentName, size, variant, finalClassName),
212
+ "data-testid": testId || componentName,
213
+ role: "status",
214
+ "aria-label": ariaLabel || headingText,
215
+ "aria-live": "polite",
216
+ "aria-busy": "true"
217
+ }, restProps), showHeader && /*#__PURE__*/_react.default.createElement(_Heading.default, {
218
+ variant: titleSize,
219
+ componentName: `${componentName}__heading`,
220
+ id: `${componentName}-heading`
221
+ }, headingText), /*#__PURE__*/_react.default.createElement("div", {
222
+ className: `${componentName}__wrapper`,
223
+ "aria-describedby": showHeader ? `${componentName}-heading` : undefined
224
+ }, renderSpinnerWithSvgSize(variant, componentName, currentSize, fill, svgSize)), children && /*#__PURE__*/_react.default.createElement("div", {
225
+ className: `${componentName}__content`
226
+ }, children));
227
+
228
+ // Animation wrapper for entrance effect
229
+ return /*#__PURE__*/_react.default.createElement(_Animation.default, {
230
+ fadingEntrances: "fadeIn",
231
+ duration: "faster"
232
+ }, loaderContent);
233
+ });
234
+ Loader.propTypes = {
235
+ // ===========================================
236
+ // Core Props
237
+ // ===========================================
238
+ /**
239
+ * Header text to display above the loader
240
+ * @required Recommended for screen reader accessibility
241
+ */
242
+ headerText: _propTypes.string,
243
+ // ===========================================
244
+ // Content Props
245
+ // ===========================================
246
+ /**
247
+ * Additional content to display below the loader
248
+ */
249
+ children: _propTypes.node,
250
+ // ===========================================
251
+ // Appearance Props
252
+ // ===========================================
253
+ /**
254
+ * Additional CSS classes to apply to the loader wrapper
255
+ */
256
+ className: _propTypes.string,
257
+ /**
258
+ * Size variant for the loader - affects overall dimensions and spacing
259
+ * @required Recommended to be explicit about sizing for consistent UX
260
+ */
261
+ size: (0, _propTypes.oneOf)(['sm', 'md', 'lg', 'xl']),
262
+ /**
263
+ * Loader animation variant - different visual styles for various contexts
264
+ * @required Recommended for intentional animation choice
265
+ */
266
+ variant: (0, _propTypes.oneOf)(['svg', 'spinner', 'dots', 'pulse']),
267
+ /**
268
+ * Fill color for the loader animations - should match design system
269
+ */
270
+ fill: _propTypes.string,
271
+ /**
272
+ * Whether to show the header text - should be true for accessibility unless redundant
273
+ */
274
+ showHeader: _propTypes.bool,
275
+ /**
276
+ * Heading size variant (1-6) - semantic heading level
277
+ */
278
+ titleSize: (0, _propTypes.oneOf)([1, 2, 3, 4, 5, 6]),
279
+ // ===========================================
280
+ // Accessibility Props
281
+ // ===========================================
282
+ /**
283
+ * Accessible label for the loader - overrides headerText for ARIA
284
+ */
285
+ // aria-label is used as a prop, not ariaLabel
286
+
287
+ /**
288
+ * Use className instead
289
+ */
290
+ additionalClassName: _propTypes.string,
291
+ /**
292
+ * Use className/id for identification
293
+ * Base CSS class name for the component
294
+ */
295
+ componentName: _propTypes.string,
296
+ /**
297
+ * Custom test ID for automated testing
298
+ */
299
+ testId: _propTypes.string
300
+ };
301
+ Loader.displayName = 'Loader';
302
+ var _default = exports.default = Loader;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.MenuHover = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = require("prop-types");
9
+ var _uuid = require("uuid");
10
+ var _ChevronDown = require("../icons/ChevronDown");
11
+ var _ArrowRight = require("../icons/ArrowRight");
12
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
13
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
14
+ /**
15
+ * MenuHover Component
16
+ *
17
+ * A stateless toggle component that displays different content based on its open/closed state.
18
+ * Features keyboard navigation and accessibility support.
19
+ *
20
+ * @component
21
+ * @example
22
+ * ```jsx
23
+ * <MenuHover
24
+ * isOpen={isMenuOpen}
25
+ * onToggle={(isOpen) => setMenuOpen(isOpen)}
26
+ * isOpenChildren={<div>Open menu content</div>}
27
+ * isClosedChildren={<div>Closed menu content</div>}
28
+ * ariaLabel="Navigation menu"
29
+ * />
30
+ * ```
31
+ *
32
+ * @param {object} props - Component props
33
+ * @param {React.ReactNode} props.isOpenChildren - Content to display when menu is open
34
+ * @param {React.ReactNode} props.isClosedChildren - Content to display when menu is closed
35
+ * @param {boolean} props.isOpen - Whether the menu is currently open (controlled state)
36
+ * @param {function} props.onToggle - Callback when menu toggle is triggered
37
+ * @param {string} [props.className=''] - Additional CSS classes to apply
38
+ * @param {string} [props.id] - Unique identifier for the component
39
+ * @param {string} [props.ariaLabel] - Accessible label for the menu
40
+ * @returns {JSX.Element} The MenuHover component
41
+ */
42
+ const MenuHover = exports.MenuHover = /*#__PURE__*/(0, _react.forwardRef)(({
43
+ // Core props
44
+ id,
45
+ className = '',
46
+ // Content props
47
+ isOpenChildren,
48
+ isClosedChildren,
49
+ // Behavior props
50
+ isOpen = false,
51
+ // Event props
52
+ onToggle = () => {},
53
+ // Accessibility props
54
+ 'aria-label': ariaLabel = 'Menu',
55
+ // Legacy props (for backward compatibility - internal use only)
56
+ componentName = 'menu-hover',
57
+ additionalClassName = '',
58
+ ...restProps
59
+ }, ref) => {
60
+ // Handle legacy prop mapping
61
+ const finalId = id || `menu-hover-${Math.random().toString(36).substr(2, 9)}`;
62
+ const finalClassName = className || additionalClassName;
63
+
64
+ // Handle click and keyboard interactions
65
+ const handleToggle = () => {
66
+ onToggle(!isOpen);
67
+ };
68
+ const handleKeyDown = event => {
69
+ if (event.key === 'Enter' || event.key === ' ') {
70
+ event.preventDefault();
71
+ handleToggle();
72
+ }
73
+ };
74
+ return /*#__PURE__*/_react.default.createElement("div", _extends({
75
+ ref: ref,
76
+ id: finalId,
77
+ className: `${componentName} ${isOpen ? 'open' : ''} ${finalClassName}`,
78
+ "data-testid": componentName,
79
+ role: "button",
80
+ tabIndex: 0,
81
+ "aria-label": ariaLabel,
82
+ "aria-expanded": isOpen,
83
+ onClick: handleToggle,
84
+ onKeyDown: handleKeyDown
85
+ }, restProps), isOpen ? isOpenChildren : isClosedChildren);
86
+ });
87
+
88
+ // Configure component PropTypes
89
+ MenuHover.propTypes = {
90
+ // Core props
91
+ /** Unique identifier for the component */
92
+ id: _propTypes.string,
93
+ /** Additional CSS classes to apply */
94
+ className: _propTypes.string,
95
+ // Content props
96
+ /** Content to display when menu is open */
97
+ isOpenChildren: _propTypes.node,
98
+ /** Content to display when menu is closed */
99
+ isClosedChildren: _propTypes.node,
100
+ // Behavior props
101
+ /** Whether the menu is currently open (controlled state) */
102
+ isOpen: _propTypes.bool,
103
+ // Event props
104
+ /** Callback when menu toggle is triggered */
105
+ onToggle: _propTypes.func,
106
+ // Accessibility props
107
+ /** Accessible label for the menu */
108
+ 'aria-label': _propTypes.string,
109
+ // Legacy props (for backward compatibility - internal use only)
110
+ /** Base component name for CSS classes and data attributes */
111
+ componentName: _propTypes.string,
112
+ /** Additional CSS class name for custom styling */
113
+ additionalClassName: _propTypes.string
114
+ };