@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,337 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.DragAndDrop = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = require("prop-types");
9
+ var _accessibility = require("../utils/accessibility.js");
10
+ 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); }
11
+ /**
12
+ * DragAndDrop Component - A completely stateless, accessible drag-and-drop list component
13
+ *
14
+ * This component provides drag-and-drop functionality with:
15
+ * - Full accessibility support (ARIA, keyboard navigation, screen reader announcements)
16
+ * - Customizable item rendering and styling
17
+ * - Proper event handling for all drag operations
18
+ * - Focus management and keyboard interactions
19
+ * - High contrast and reduced motion support
20
+ * - Screen reader announcements for all drag operations
21
+ *
22
+ * All state management and business logic should be handled by parent components.
23
+ * This ensures maximum flexibility and reusability across different use cases.
24
+ *
25
+ * ## Accessibility Features
26
+ * - Full keyboard navigation with Tab, Arrow keys, Space, Enter
27
+ * - Screen reader announcements for drag operations and state changes
28
+ * - Proper ARIA labeling and live regions
29
+ * - Focus indicators and management
30
+ * - High contrast mode support
31
+ * - Reduced motion preferences respected
32
+ * - Semantic HTML structure
33
+ *
34
+ * ## Technical Implementation
35
+ * - Uses HTML5 drag and drop API with proper event handling
36
+ * - Provides callbacks for all drag events (start, over, enter, leave, drop)
37
+ * - Supports custom drag state management from parent
38
+ * - Handles keyboard interactions for accessibility
39
+ *
40
+ * @component
41
+ * @example
42
+ * // Basic usage (stateless)
43
+ * <DragAndDrop
44
+ * items={items}
45
+ * onDragStart={handleDragStart}
46
+ * onDragOver={handleDragOver}
47
+ * onDrop={handleDrop}
48
+ * dragState={dragState}
49
+ * ariaLabel="Reorderable task list"
50
+ * />
51
+ *
52
+ * @param {Object} props - Component props
53
+ * @param {string} [props.componentName='drag-and-drop'] - Base CSS class name
54
+ * @param {string} [props.additionalClassName=''] - Additional CSS classes
55
+ * @param {Array} props.items - Array of items to display and make draggable (required)
56
+ * @param {Function} props.onDragStart - Callback for drag start events (required)
57
+ * @param {Function} props.onDragOver - Callback for drag over events (required)
58
+ * @param {Function} props.onDragEnter - Callback for drag enter events
59
+ * @param {Function} props.onDragLeave - Callback for drag leave events (required)
60
+ * @param {Function} props.onDrop - Callback for drop events (required)
61
+ * @param {Function} [props.onKeyDown] - Callback for keyboard events
62
+ * @param {Object} [props.dragState] - Current drag and drop state
63
+ * @param {boolean} [props.dragState.isDragging=false] - Whether an item is being dragged
64
+ * @param {number|string} [props.dragState.draggedFrom] - Index of item being dragged
65
+ * @param {number|string} [props.dragState.draggedTo] - Index of drop target
66
+ * @param {boolean} [props.enableKeyboardNavigation=true] - Enable keyboard navigation
67
+ * @param {string} [props.ariaLabel='Draggable list'] - Accessible label for the component
68
+ * @param {string} [props.ariaDescribedBy] - ID of element describing the component
69
+ * @param {Function} [props.renderItem] - Custom item renderer function
70
+ * @param {string} [props.itemIdKey='id'] - Key to use for item IDs
71
+ * @param {string} [props.itemContentKey='title'] - Key to use for item content
72
+ * @param {string} [props.itemNumberKey='number'] - Key to use for item numbers
73
+ */
74
+
75
+ const DragAndDrop = exports.DragAndDrop = /*#__PURE__*/(0, _react.forwardRef)(({
76
+ componentName = 'drag-and-drop',
77
+ additionalClassName = '',
78
+ items = [],
79
+ onDragStart,
80
+ onDragOver,
81
+ onDragEnter = null,
82
+ onDragLeave,
83
+ onDrop,
84
+ onKeyDown = null,
85
+ dragState = {
86
+ isDragging: false,
87
+ draggedFrom: null,
88
+ draggedTo: null,
89
+ originalOrder: [],
90
+ updatedOrder: []
91
+ },
92
+ enableKeyboardNavigation = true,
93
+ ariaLabel = 'Draggable list',
94
+ ariaDescribedBy = null,
95
+ renderItem = null,
96
+ itemIdKey = 'id',
97
+ itemContentKey = 'title',
98
+ itemNumberKey = 'number'
99
+ }, ref) => {
100
+ const {
101
+ isDragging = false,
102
+ draggedFrom = null,
103
+ draggedTo = null
104
+ } = dragState;
105
+
106
+ /**
107
+ * Handles drag start events with accessibility announcements
108
+ */
109
+ const handleDragStart = (event, item, index) => {
110
+ // Call parent callback
111
+ onDragStart?.(event, item, index);
112
+
113
+ // Set data for Firefox compatibility
114
+ event.dataTransfer.setData('text/html', '');
115
+
116
+ // Focus management for accessibility
117
+ (0, _accessibility.safeFocus)(event.currentTarget);
118
+ };
119
+
120
+ /**
121
+ * Handles drag over events
122
+ */
123
+ const handleDragOver = (event, item, index) => {
124
+ event.preventDefault();
125
+ onDragOver?.(event, item, index);
126
+ };
127
+
128
+ /**
129
+ * Handles drag enter events
130
+ */
131
+ const handleDragEnter = (event, item, index) => {
132
+ onDragEnter?.(event, item, index);
133
+ };
134
+
135
+ /**
136
+ * Handles drag leave events
137
+ */
138
+ const handleDragLeave = (event, item, index) => {
139
+ onDragLeave?.(event, item, index);
140
+ };
141
+
142
+ /**
143
+ * Handles drop events
144
+ */
145
+ const handleDrop = (event, item, index) => {
146
+ event.preventDefault();
147
+ onDrop?.(event, item, index);
148
+ };
149
+
150
+ /**
151
+ * Handles keyboard navigation for accessibility
152
+ */
153
+ const handleKeyDown = (event, item, index) => {
154
+ if (!enableKeyboardNavigation) return;
155
+
156
+ // Let parent handle any custom keyboard logic
157
+ onKeyDown?.(event, item, index);
158
+
159
+ // Basic keyboard navigation
160
+ switch (event.key) {
161
+ case 'ArrowUp':
162
+ event.preventDefault();
163
+ if (index > 0) {
164
+ const prevItem = event.currentTarget.parentElement?.previousElementSibling?.querySelector('[draggable]');
165
+ (0, _accessibility.safeFocus)(prevItem);
166
+ }
167
+ break;
168
+ case 'ArrowDown':
169
+ event.preventDefault();
170
+ if (index < items.length - 1) {
171
+ const nextItem = event.currentTarget.parentElement?.nextElementSibling?.querySelector('[draggable]');
172
+ (0, _accessibility.safeFocus)(nextItem);
173
+ }
174
+ break;
175
+ case 'Space':
176
+ case 'Enter':
177
+ // Parent can handle drag simulation for keyboard users
178
+ break;
179
+ default:
180
+ break;
181
+ }
182
+ };
183
+
184
+ /**
185
+ * Default item renderer
186
+ */
187
+ const defaultRenderItem = (item, index) => /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
188
+ "aria-hidden": "true"
189
+ }, item[itemNumberKey] || index + 1), /*#__PURE__*/_react.default.createElement("p", null, item[itemContentKey] || item.title || `Item ${index + 1}`));
190
+ const itemRenderer = renderItem || defaultRenderItem;
191
+ return /*#__PURE__*/_react.default.createElement("div", {
192
+ ref: ref,
193
+ className: `${componentName} ${additionalClassName}`.trim(),
194
+ "data-testid": componentName,
195
+ role: "application",
196
+ "aria-label": ariaLabel,
197
+ "aria-describedby": ariaDescribedBy
198
+ }, /*#__PURE__*/_react.default.createElement("ul", {
199
+ className: "unordered-list",
200
+ role: "list",
201
+ "aria-label": "Reorderable items"
202
+ }, items.map((item, index) => {
203
+ const isDropTarget = draggedTo === index;
204
+ const isBeingDragged = draggedFrom === index && isDragging;
205
+ const itemId = item[itemIdKey] || item.id || `item-${index}`;
206
+ return /*#__PURE__*/_react.default.createElement("li", {
207
+ key: itemId,
208
+ "data-position": index,
209
+ draggable: true,
210
+ onDragStart: e => handleDragStart(e, item, index),
211
+ onDragOver: e => handleDragOver(e, item, index),
212
+ onDragEnter: e => handleDragEnter(e, item, index),
213
+ onDrop: e => handleDrop(e, item, index),
214
+ onDragLeave: e => handleDragLeave(e, item, index),
215
+ onKeyDown: e => handleKeyDown(e, item, index),
216
+ className: `list-item ${isDropTarget ? 'dropArea' : ''} ${isBeingDragged ? 'being-dragged' : ''}`,
217
+ role: "listitem",
218
+ tabIndex: 0,
219
+ "aria-label": `${item[itemContentKey] || item.title}, position ${index + 1} of ${items.length}. Press space to start dragging.`,
220
+ "aria-describedby": `drag-instructions-${index}`,
221
+ "aria-grabbed": isBeingDragged,
222
+ "aria-dropeffect": isDropTarget ? 'move' : 'none'
223
+ }, itemRenderer(item, index), /*#__PURE__*/_react.default.createElement("div", {
224
+ id: `drag-instructions-${index}`,
225
+ className: "sr-only",
226
+ "aria-live": "polite"
227
+ }, isBeingDragged && 'Currently dragging this item', isDropTarget && 'Drop target area', !isBeingDragged && !isDropTarget && 'Use arrow keys to navigate, space to drag'));
228
+ })), /*#__PURE__*/_react.default.createElement("div", {
229
+ "aria-live": "assertive",
230
+ "aria-atomic": "true",
231
+ className: "sr-only",
232
+ role: "status"
233
+ }, isDragging && draggedFrom !== null && `Item ${draggedFrom + 1} is being dragged`));
234
+ });
235
+
236
+ // Set display name for better debugging
237
+ DragAndDrop.displayName = 'DragAndDrop';
238
+
239
+ // PropTypes definition with proper required fields
240
+ DragAndDrop.propTypes = {
241
+ /**
242
+ * Base CSS class name for the component
243
+ */
244
+ componentName: _propTypes.string,
245
+ /**
246
+ * Additional CSS classes to apply
247
+ */
248
+ additionalClassName: _propTypes.string,
249
+ /**
250
+ * Array of items to display and make draggable (REQUIRED)
251
+ * Each item should have at least a title/content property
252
+ */
253
+ items: _propTypes.array.isRequired,
254
+ /**
255
+ * Callback function for drag start events (REQUIRED)
256
+ * @param {Event} event - The drag event
257
+ * @param {Object} item - The item being dragged
258
+ * @param {number} index - The index of the item
259
+ */
260
+ onDragStart: _propTypes.func.isRequired,
261
+ /**
262
+ * Callback function for drag over events (REQUIRED)
263
+ * @param {Event} event - The drag event
264
+ * @param {Object} item - The item being dragged over
265
+ * @param {number} index - The index of the drop target
266
+ */
267
+ onDragOver: _propTypes.func.isRequired,
268
+ /**
269
+ * Callback function for drag enter events
270
+ * @param {Event} event - The drag event
271
+ * @param {Object} item - The item being entered
272
+ * @param {number} index - The index of the item
273
+ */
274
+ onDragEnter: _propTypes.func,
275
+ /**
276
+ * Callback function for drag leave events (REQUIRED)
277
+ * @param {Event} event - The drag event
278
+ * @param {Object} item - The item being left
279
+ * @param {number} index - The index of the item
280
+ */
281
+ onDragLeave: _propTypes.func.isRequired,
282
+ /**
283
+ * Callback function for drop events (REQUIRED)
284
+ * @param {Event} event - The drop event
285
+ * @param {Object} item - The item being dropped on
286
+ * @param {number} index - The index of the drop target
287
+ */
288
+ onDrop: _propTypes.func.isRequired,
289
+ /**
290
+ * Callback function for keyboard events
291
+ * @param {Event} event - The keyboard event
292
+ * @param {Object} item - The focused item
293
+ * @param {number} index - The index of the focused item
294
+ */
295
+ onKeyDown: _propTypes.func,
296
+ /**
297
+ * Current drag and drop state object
298
+ */
299
+ dragState: (0, _propTypes.shape)({
300
+ isDragging: _propTypes.bool,
301
+ draggedFrom: (0, _propTypes.oneOfType)([_propTypes.number, _propTypes.string]),
302
+ draggedTo: (0, _propTypes.oneOfType)([_propTypes.number, _propTypes.string]),
303
+ originalOrder: _propTypes.array,
304
+ updatedOrder: _propTypes.array
305
+ }),
306
+ /**
307
+ * Enable/disable keyboard navigation
308
+ */
309
+ enableKeyboardNavigation: _propTypes.bool,
310
+ /**
311
+ * Accessible label for the entire component
312
+ */
313
+ ariaLabel: _propTypes.string,
314
+ /**
315
+ * ID of element that describes the component
316
+ */
317
+ ariaDescribedBy: _propTypes.string,
318
+ /**
319
+ * Custom item renderer function
320
+ * @param {Object} item - The item to render
321
+ * @param {number} index - The index of the item
322
+ * @returns {React.ReactNode} The rendered item content
323
+ */
324
+ renderItem: _propTypes.func,
325
+ /**
326
+ * Key to use for item IDs (for React keys)
327
+ */
328
+ itemIdKey: _propTypes.string,
329
+ /**
330
+ * Key to use for item content/title
331
+ */
332
+ itemContentKey: _propTypes.string,
333
+ /**
334
+ * Key to use for item numbers/positions
335
+ */
336
+ itemNumberKey: _propTypes.string
337
+ };
@@ -0,0 +1,206 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Error = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = require("prop-types");
9
+ require("../styles/error.scss");
10
+ 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); }
11
+ 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); }
12
+ /**
13
+ * Error Component
14
+ *
15
+ * Displays error messages with proper accessibility support and multiple severity levels.
16
+ * Features ARIA live regions, keyboard navigation, and customizable styling.
17
+ *
18
+ * @component
19
+ * @example
20
+ * ```jsx
21
+ * <Error
22
+ * severity="error"
23
+ * size="medium"
24
+ * dismissible={true}
25
+ * onDismiss={() => setShowError(false)}
26
+ * aria-label="Form validation error"
27
+ * >
28
+ * Please fill in all required fields
29
+ * </Error>
30
+ * ```
31
+ *
32
+ * @param {object} props - Component props
33
+ * @param {React.ReactNode} props.children - The error message content to display
34
+ * @param {string} [props.className=''] - Additional CSS classes to apply
35
+ * @param {string} [props.id] - Unique identifier for the component
36
+ * @param {string} [props.severity='error'] - Error severity level
37
+ * @param {string} [props.size='medium'] - Size variant
38
+ * @param {boolean} [props.dismissible=false] - Whether the error can be dismissed
39
+ * @param {function} [props.onDismiss] - Callback when error is dismissed
40
+ * @returns {JSX.Element} The Error component
41
+ */
42
+ const Error = exports.Error = /*#__PURE__*/(0, _react.forwardRef)(({
43
+ // Core props
44
+ id,
45
+ className = '',
46
+ // Content props
47
+ children = '',
48
+ // Appearance props
49
+ severity = 'error',
50
+ size = 'medium',
51
+ // Behavior props
52
+ dismissible = false,
53
+ isLive = true,
54
+ // Event props
55
+ onDismiss = null,
56
+ // Accessibility props
57
+ 'aria-label': ariaLabel = '',
58
+ role = '',
59
+ // Legacy props (for backward compatibility - internal use only)
60
+ componentName = 'error',
61
+ additionalClassName = '',
62
+ ...restProps
63
+ }, ref) => {
64
+ // Handle legacy prop mapping
65
+ const finalId = id || `error-${Math.random().toString(36).substr(2, 9)}`;
66
+ const finalClassName = className || additionalClassName;
67
+
68
+ // Determine the appropriate ARIA role based on severity
69
+ const getAriaRole = () => {
70
+ if (role) return role;
71
+ switch (severity) {
72
+ case 'error':
73
+ return 'alert';
74
+ case 'warning':
75
+ return 'alert';
76
+ case 'info':
77
+ return 'status';
78
+ case 'success':
79
+ return 'status';
80
+ default:
81
+ return 'alert';
82
+ }
83
+ };
84
+
85
+ // Determine aria-live setting based on severity and isLive prop
86
+ const getAriaLive = () => {
87
+ if (!isLive) return 'off';
88
+ switch (severity) {
89
+ case 'error':
90
+ return 'assertive';
91
+ case 'warning':
92
+ return 'assertive';
93
+ case 'info':
94
+ return 'polite';
95
+ case 'success':
96
+ return 'polite';
97
+ default:
98
+ return 'assertive';
99
+ }
100
+ };
101
+
102
+ // Generate comprehensive class names
103
+ const classNames = [componentName, `${componentName}--${severity}`, `${componentName}--${size}`, finalClassName].filter(Boolean).join(' ');
104
+ return /*#__PURE__*/_react.default.createElement("div", _extends({
105
+ ref: ref,
106
+ className: classNames,
107
+ "data-testid": componentName,
108
+ id: finalId,
109
+ role: getAriaRole(),
110
+ "aria-live": getAriaLive(),
111
+ "aria-atomic": "true",
112
+ "aria-label": ariaLabel || undefined
113
+ }, restProps), /*#__PURE__*/_react.default.createElement("span", {
114
+ className: `${componentName}__icon`,
115
+ "aria-hidden": "true"
116
+ }, severity === 'error' && '⚠️', severity === 'warning' && '⚠️', severity === 'info' && 'ℹ️', severity === 'success' && '✅'), /*#__PURE__*/_react.default.createElement("span", {
117
+ className: `${componentName}__text`
118
+ }, children), dismissible && /*#__PURE__*/_react.default.createElement("button", {
119
+ type: "button",
120
+ className: `${componentName}__dismiss`,
121
+ onClick: onDismiss,
122
+ "aria-label": "Dismiss message"
123
+ }, "\xD7"));
124
+ });
125
+ Error.propTypes = {
126
+ // ====================
127
+ // Core Props
128
+ // ====================
129
+
130
+ /**
131
+ * Unique identifier for the component
132
+ */
133
+ id: _propTypes.string,
134
+ /**
135
+ * Additional CSS classes to apply to the component
136
+ */
137
+ className: _propTypes.string,
138
+ // ====================
139
+ // Content Props
140
+ // ====================
141
+
142
+ /**
143
+ * The error message content to display
144
+ * @required for meaningful error messages
145
+ */
146
+ children: _propTypes.node.isRequired,
147
+ // ====================
148
+ // Appearance Props
149
+ // ====================
150
+
151
+ /**
152
+ * Error severity level affecting styling and ARIA behavior
153
+ * @default 'error'
154
+ */
155
+ severity: (0, _propTypes.oneOf)(['error', 'warning', 'info', 'success']),
156
+ /**
157
+ * Size variant for responsive display
158
+ * @default 'medium'
159
+ */
160
+ size: (0, _propTypes.oneOf)(['small', 'medium', 'large']),
161
+ // ====================
162
+ // Behavior Props
163
+ // ====================
164
+
165
+ /**
166
+ * Whether the error can be dismissed by the user
167
+ * @default false
168
+ */
169
+ dismissible: _propTypes.bool,
170
+ /**
171
+ * Whether to use aria-live for real-time announcements
172
+ * @default true
173
+ */
174
+ isLive: _propTypes.bool,
175
+ // ====================
176
+ // Event Props
177
+ // ====================
178
+
179
+ /**
180
+ * Callback function when error is dismissed
181
+ */
182
+ onDismiss: _propTypes.func,
183
+ // ====================
184
+ // Accessibility Props
185
+ // ====================
186
+
187
+ /**
188
+ * ARIA label for screen readers (optional, uses children if not provided)
189
+ */
190
+ 'aria-label': _propTypes.string,
191
+ /**
192
+ * ARIA role override (auto-determined from severity if not provided)
193
+ */
194
+ role: _propTypes.string,
195
+ /**
196
+ * Use `className` instead
197
+ * Additional CSS class names to apply
198
+ */
199
+ additionalClassName: _propTypes.string,
200
+ /**
201
+ * Internal prop for CSS class generation
202
+ * The base component name for CSS classes
203
+ */
204
+ componentName: _propTypes.string
205
+ };
206
+ var _default = exports.default = Error;
@@ -0,0 +1,99 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = exports.Footer = void 0;
7
+ var _react = _interopRequireWildcard(require("react"));
8
+ var _propTypes = require("prop-types");
9
+ var _useWindowSize = require("../utils/useWindowSize");
10
+ var _Animation = require("./Animation");
11
+ 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); }
12
+ 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); }
13
+ /**
14
+ * Footer Component
15
+ *
16
+ * A responsive footer component that adapts between desktop and mobile layouts.
17
+ * Features navigation display and optional authentication links.
18
+ */
19
+ const Footer = exports.Footer = /*#__PURE__*/(0, _react.forwardRef)(({
20
+ id,
21
+ className = '',
22
+ navigation = null,
23
+ signInLink = null,
24
+ signUpLink = null,
25
+ avatarSrc = null,
26
+ ellipsesList = [],
27
+ hasAuth = false,
28
+ 'aria-label': ariaLabel = 'Footer',
29
+ componentName = 'footer',
30
+ additionalClassName = '',
31
+ ...restProps
32
+ }, ref) => {
33
+ const size = (0, _useWindowSize.useWindowSize)();
34
+ const finalId = id || `footer-${Math.random().toString(36).substr(2, 9)}`;
35
+ const finalClassName = className || additionalClassName;
36
+ return /*#__PURE__*/_react.default.createElement("footer", _extends({
37
+ ref: ref,
38
+ id: finalId,
39
+ className: `${componentName} ${finalClassName}`,
40
+ "data-testid": componentName,
41
+ role: "contentinfo",
42
+ "aria-label": ariaLabel
43
+ }, restProps), /*#__PURE__*/_react.default.createElement(_Animation.AnimatedDiv, {
44
+ fadingEntrances: "fadeIn",
45
+ duration: "faster"
46
+ }, size.width < 768 ?
47
+ /*#__PURE__*/
48
+ // mobile
49
+ _react.default.createElement("div", {
50
+ className: "navigation",
51
+ role: "navigation",
52
+ "aria-label": "Mobile footer navigation"
53
+ }, !hasAuth ? /*#__PURE__*/_react.default.createElement("ul", {
54
+ className: "unordered-list",
55
+ role: "list"
56
+ }, navigation) : /*#__PURE__*/_react.default.createElement("ul", {
57
+ className: "unordered-list auth-menu",
58
+ role: "list",
59
+ "aria-label": "User navigation"
60
+ }, /*#__PURE__*/_react.default.createElement("li", {
61
+ className: "list-item",
62
+ role: "listitem"
63
+ }, "Home"), /*#__PURE__*/_react.default.createElement("li", {
64
+ className: "list-item",
65
+ role: "listitem"
66
+ }, "Search"), /*#__PURE__*/_react.default.createElement("li", {
67
+ className: "list-item",
68
+ role: "listitem"
69
+ }, "Add"), /*#__PURE__*/_react.default.createElement("li", {
70
+ className: "list-item",
71
+ role: "listitem"
72
+ }, "Profile"))) :
73
+ /*#__PURE__*/
74
+ // desktop
75
+ _react.default.createElement("div", {
76
+ className: "navigation",
77
+ "data-testid": "navigation",
78
+ role: "navigation",
79
+ "aria-label": "Desktop footer navigation"
80
+ }, /*#__PURE__*/_react.default.createElement("ul", {
81
+ className: "unordered-list",
82
+ role: "list"
83
+ }, navigation))));
84
+ });
85
+ Footer.displayName = 'Footer';
86
+ Footer.propTypes = {
87
+ id: _propTypes.string,
88
+ className: _propTypes.string,
89
+ navigation: _propTypes.node,
90
+ signInLink: _propTypes.node,
91
+ signUpLink: _propTypes.node,
92
+ avatarSrc: _propTypes.string,
93
+ ellipsesList: (0, _propTypes.arrayOf)(_propTypes.node),
94
+ hasAuth: _propTypes.bool,
95
+ 'aria-label': _propTypes.string,
96
+ componentName: _propTypes.string,
97
+ additionalClassName: _propTypes.string
98
+ };
99
+ var _default = exports.default = Footer;