no-frills-ui 0.0.14-alpha.3 → 0.0.14-alpha.4

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 (58) hide show
  1. package/dist/index.js +313 -72
  2. package/dist/index.js.map +1 -1
  3. package/lib-esm/components/Accordion/AccordionStep.d.ts.map +1 -1
  4. package/lib-esm/components/Accordion/AccordionStep.js +18 -11
  5. package/lib-esm/components/Accordion/AccordionStep.js.map +1 -1
  6. package/lib-esm/components/Button/ActionButton.js +2 -2
  7. package/lib-esm/components/Button/ActionButton.js.map +1 -1
  8. package/lib-esm/components/Button/Button.d.ts +2 -2
  9. package/lib-esm/components/Button/Button.d.ts.map +1 -1
  10. package/lib-esm/components/Button/Button.js +6 -2
  11. package/lib-esm/components/Button/Button.js.map +1 -1
  12. package/lib-esm/components/Button/LinkButton.js +1 -1
  13. package/lib-esm/components/Button/LinkButton.js.map +1 -1
  14. package/lib-esm/components/Button/RaisedButton.js +1 -1
  15. package/lib-esm/components/Button/RaisedButton.js.map +1 -1
  16. package/lib-esm/components/Chip/Chip.d.ts +5 -2
  17. package/lib-esm/components/Chip/Chip.d.ts.map +1 -1
  18. package/lib-esm/components/Chip/Chip.js +14 -8
  19. package/lib-esm/components/Chip/Chip.js.map +1 -1
  20. package/lib-esm/components/ChipInput/ChipInput.d.ts +9 -0
  21. package/lib-esm/components/ChipInput/ChipInput.d.ts.map +1 -1
  22. package/lib-esm/components/ChipInput/ChipInput.js +43 -4
  23. package/lib-esm/components/ChipInput/ChipInput.js.map +1 -1
  24. package/lib-esm/components/Dialog/AlertDialog.js +1 -1
  25. package/lib-esm/components/Dialog/AlertDialog.js.map +1 -1
  26. package/lib-esm/components/Dialog/Dialog.d.ts +6 -1
  27. package/lib-esm/components/Dialog/Dialog.d.ts.map +1 -1
  28. package/lib-esm/components/Dialog/Dialog.js.map +1 -1
  29. package/lib-esm/components/DragAndDrop/DragAndDrop.d.ts +24 -0
  30. package/lib-esm/components/DragAndDrop/DragAndDrop.d.ts.map +1 -1
  31. package/lib-esm/components/DragAndDrop/DragAndDrop.js +85 -3
  32. package/lib-esm/components/DragAndDrop/DragAndDrop.js.map +1 -1
  33. package/lib-esm/components/DragAndDrop/DragItem.d.ts +4 -0
  34. package/lib-esm/components/DragAndDrop/DragItem.d.ts.map +1 -1
  35. package/lib-esm/components/DragAndDrop/DragItem.js +86 -6
  36. package/lib-esm/components/DragAndDrop/DragItem.js.map +1 -1
  37. package/lib-esm/components/DragAndDrop/types.d.ts +19 -0
  38. package/lib-esm/components/DragAndDrop/types.d.ts.map +1 -1
  39. package/lib-esm/components/DragAndDrop/types.js.map +1 -1
  40. package/lib-esm/components/Input/Checkbox.d.ts.map +1 -1
  41. package/lib-esm/components/Input/Checkbox.js +1 -1
  42. package/lib-esm/components/Input/Checkbox.js.map +1 -1
  43. package/lib-esm/components/Input/Input.d.ts.map +1 -1
  44. package/lib-esm/components/Input/Input.js +0 -1
  45. package/lib-esm/components/Input/Input.js.map +1 -1
  46. package/lib-esm/components/Input/Select.d.ts.map +1 -1
  47. package/lib-esm/components/Input/Select.js +0 -1
  48. package/lib-esm/components/Input/Select.js.map +1 -1
  49. package/lib-esm/components/Input/TextArea.d.ts.map +1 -1
  50. package/lib-esm/components/Input/TextArea.js +0 -1
  51. package/lib-esm/components/Input/TextArea.js.map +1 -1
  52. package/lib-esm/components/Notification/Notification.d.ts +9 -7
  53. package/lib-esm/components/Notification/Notification.d.ts.map +1 -1
  54. package/lib-esm/components/Notification/Notification.js +51 -24
  55. package/lib-esm/components/Notification/Notification.js.map +1 -1
  56. package/lib-esm/shared/constants.js +7 -7
  57. package/lib-esm/shared/constants.js.map +1 -1
  58. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -75,27 +75,27 @@ function CheckCircle(props) {
75
75
  }
76
76
 
77
77
  var constants = {
78
- PRIMARY: '#2283d2',
78
+ PRIMARY: '#1f7ac5',
79
79
  PRIMARY_LIGHT: '#64baff',
80
80
  PRIMARY_LIGHTER: '#cfe9ff',
81
81
  BACKDROP_COLOR: '#2681da80',
82
- INFO: '#2283d2',
82
+ INFO: '#1d6eaf',
83
83
  INFO_LIGHT: '#64baff',
84
- SUCCESS: '#22d295',
84
+ SUCCESS: '#1a835f',
85
85
  SUCCESS_LIGHT: '#80eac6',
86
- WARNING: '#cc9500',
86
+ WARNING: '#916b01',
87
87
  WARNING_LIGHT: '#ffba00',
88
- ERROR: '#d63b3b',
88
+ ERROR: '#bb2828',
89
89
  ERROR_LIGHT: '#f1a5a5',
90
90
  BORDER_COLOR: '#555555',
91
91
  TOAST: '#5f5f5f',
92
- TOOLTIP_COLOR: 'rgba(0,0,0,0.5)',
92
+ TOOLTIP_COLOR: 'rgba(0,0,0,0.6)',
93
93
  BORDER_LIGHT_COLOR: '#eeeeee',
94
94
  BACKGROUND: '#ffffff',
95
95
  DISABLED_BACKGROUND: '#fafafa',
96
96
  DISABLED_BORDER: '#aaa',
97
97
  LIGHT_GREY: '#ccc',
98
- DISABLED: '#777',
98
+ DISABLED: '#737373',
99
99
  SHADOW: '0px 1px 3px 0px rgba(0,0,0,0.1), 0px 1px 2px 0px rgba(0,0,0,0.06)',
100
100
  HOVER_SHADOW: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
101
101
  MODAL_SHADOW: '0px 8px 17px 2px rgba(0,0,0,0.14), 0px 3px 14px 2px rgba(0,0,0,0.12), 0px 5px 5px -3px rgba(0,0,0,0.2)',
@@ -193,18 +193,26 @@ const Card = styled.div `
193
193
 
194
194
  const Step$1 = styled(Card) `
195
195
  transition: all 0.6s ease;
196
+ overflow: visible;
196
197
 
197
198
  ${(props) => props.open &&
198
199
  `
199
200
  margin: 20px 5px;
200
201
  `}
201
-
202
- ${(props) => props.focused && `box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});`}
203
202
  `;
204
- const StepHeader = styled.div `
203
+ const StepHeader = styled.button `
205
204
  padding: 20px 15px;
206
205
  display: flex;
207
206
  justify-content: space-between;
207
+ background: none;
208
+ border: none;
209
+ border-radius: 10px;
210
+ width: 100%;
211
+ font-size: inherit;
212
+
213
+ &:focus-visible {
214
+ box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
215
+ }
208
216
 
209
217
  & input {
210
218
  appearance: none;
@@ -219,7 +227,7 @@ const StepHeader = styled.div `
219
227
 
220
228
  ${(props) => props.disabled
221
229
  ? `
222
- color: ${constants.LIGHT_GREY};
230
+ color: ${constants.DISABLED};
223
231
  `
224
232
  : `
225
233
  cursor: pointer;
@@ -278,15 +286,14 @@ const AccordionStepFooter = styled.div `
278
286
  `;
279
287
  function AccordionStep(props) {
280
288
  const [height, setHeight] = React.useState(0);
281
- const [focused, setFocused] = React.useState(false);
282
289
  const { open, disabled, header, errorText, completed, onStepClick } = props;
290
+ // Generate unique IDs for ARIA relationships
291
+ const headerId = React.useId();
292
+ const regionId = React.useId();
283
293
  const ref = (el) => setHeight((el === null || el === void 0 ? void 0 : el.scrollHeight) || 0);
284
- const toggleFocus = () => {
285
- setFocused(!focused);
286
- };
287
- return (jsxRuntime.jsxs(Step$1, Object.assign({}, props, { focused: focused, elevated: props.open, children: [jsxRuntime.jsxs(StepHeader, { open: open, disabled: disabled, onClick: onStepClick, children: [jsxRuntime.jsxs(HeaderContainer, { open: open, completed: completed, children: [jsxRuntime.jsx("input", { type: "checkbox", checked: open, disabled: disabled, onFocus: toggleFocus, onBlur: toggleFocus }), jsxRuntime.jsx(FiberManualRecord, {}), jsxRuntime.jsx(Ellipsis, { children: header })] }), jsxRuntime.jsxs(ExpandContainer, { open: open, children: [errorText && (jsxRuntime.jsx(Badge, { css: react.css `
294
+ return (jsxRuntime.jsxs(Step$1, Object.assign({}, props, { elevated: props.open, children: [jsxRuntime.jsxs(StepHeader, { open: open, disabled: disabled, onClick: onStepClick, "aria-expanded": open ? 'true' : 'false', "aria-controls": regionId, id: headerId, children: [jsxRuntime.jsxs(HeaderContainer, { open: open, completed: completed, children: [jsxRuntime.jsx(FiberManualRecord, { "aria-hidden": "true" }), jsxRuntime.jsx(Ellipsis, { children: header })] }), jsxRuntime.jsxs(ExpandContainer, { open: open, children: [errorText && (jsxRuntime.jsx(Badge, { css: react.css `
288
295
  margin-right: 15px;
289
- `, inline: true, type: exports.BADGE_TYPE.DANGER, children: errorText })), jsxRuntime.jsx(ExpandMore, {})] })] }), jsxRuntime.jsx(StepBody, { ref: ref, height: open ? height : 0, children: open && props.children })] })));
296
+ `, inline: true, type: exports.BADGE_TYPE.DANGER, children: errorText })), jsxRuntime.jsx(ExpandMore, { "aria-hidden": "true" })] })] }), jsxRuntime.jsx(StepBody, { ref: ref, height: open ? height : 0, role: "region", id: regionId, "aria-labelledby": headerId, "aria-hidden": open ? 'false' : 'true', children: open && props.children })] })));
290
297
  }
291
298
  AccordionStep.propTypes = {
292
299
  /** Header text for the step */
@@ -303,7 +310,7 @@ AccordionStep.defaultProps = {
303
310
  disabled: false,
304
311
  };
305
312
 
306
- var Button$2 = styled.button `
313
+ const StyledButton = styled.button `
307
314
  border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
308
315
  border-radius: 5px;
309
316
  height: 32px;
@@ -338,11 +345,14 @@ var Button$2 = styled.button `
338
345
  }
339
346
 
340
347
  &:disabled {
341
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
348
+ background-color: var(--border-light-color, ${constants.DISABLED_BACKGROUND});
342
349
  border-color: var(--light-grey, ${constants.LIGHT_GREY});
343
350
  color: var(--disabled, ${constants.DISABLED});
344
351
  }
345
352
  `;
353
+ StyledButton.defaultProps = {
354
+ type: 'button',
355
+ };
346
356
 
347
357
  var LinkButton = styled.button `
348
358
  min-width: 100px;
@@ -374,7 +384,7 @@ var LinkButton = styled.button `
374
384
 
375
385
  &:disabled {
376
386
  border-color: ${constants.BORDER_COLOR};
377
- color: ${constants.DISABLED_BORDER};
387
+ color: ${constants.DISABLED};
378
388
  }
379
389
  `;
380
390
 
@@ -414,7 +424,7 @@ var RaisedButton = styled.button `
414
424
  }
415
425
 
416
426
  &:disabled {
417
- background-color: ${constants.BORDER_LIGHT_COLOR};
427
+ background-color: ${constants.DISABLED_BACKGROUND};
418
428
  border-color: ${constants.LIGHT_GREY};
419
429
  color: ${constants.DISABLED};
420
430
  }
@@ -458,8 +468,8 @@ var ActionButton = styled.button `
458
468
  }
459
469
 
460
470
  &:disabled {
461
- border: 1px solid ${constants.LIGHT_GREY};
462
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
471
+ border: 1px solid ${constants.BORDER_LIGHT_COLOR};
472
+ background-color: var(--border-light-color, ${constants.DISABLED_BACKGROUND});
463
473
  color: var(--disabled, ${constants.DISABLED});
464
474
  }
465
475
  `;
@@ -541,7 +551,7 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
541
551
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
542
552
  };
543
553
 
544
- const Container$8 = styled.div `
554
+ const Container$8 = styled.span `
545
555
  padding: 5px;
546
556
  padding-left: 15px;
547
557
  border-radius: 16px;
@@ -556,22 +566,28 @@ const Container$8 = styled.div `
556
566
  }
557
567
  `;
558
568
  const Button$1 = styled.button `
559
- color: #fff;
560
- background-color: var(--disabled-border, ${constants.DISABLED_BORDER});
569
+ color: var(--background-color, ${constants.BACKGROUND});
570
+ background-color: var(--border-color, ${constants.DISABLED});
561
571
  border-radius: 50%;
562
572
  border: none;
563
- padding: 0;
573
+ padding: 4px;
564
574
  display: inline-flex;
565
575
  margin-left: 5px;
566
576
  `;
567
577
  function Chip(props) {
568
- const { label, onCloseClick } = props, rest = __rest(props, ["label", "onCloseClick"]);
578
+ const { label, onCloseClick, closeButtonAriaLabel } = props, rest = __rest(props, ["label", "onCloseClick", "closeButtonAriaLabel"]);
569
579
  const keyUpHandler = (e) => {
570
- if (e.keyCode === 8 || e.keyCode === 46) {
571
- onCloseClick === null || onCloseClick === void 0 ? void 0 : onCloseClick();
580
+ if (e.key === 'Backspace' || e.key === 'Delete') {
581
+ onCloseClick === null || onCloseClick === void 0 ? void 0 : onCloseClick(e);
582
+ }
583
+ };
584
+ const buttonKeyDownHandler = (e) => {
585
+ // Stop propagation to prevent DragAndDrop from capturing Space/Enter
586
+ if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'Enter') {
587
+ e.stopPropagation();
572
588
  }
573
589
  };
574
- return (jsxRuntime.jsxs(Container$8, Object.assign({}, rest, { onKeyUp: keyUpHandler, children: [label, jsxRuntime.jsx(Button$1, { onClick: onCloseClick, "aria-label": `Remove ${label}`, children: jsxRuntime.jsx(Close, { height: 20, width: 20 }) })] })));
590
+ return (jsxRuntime.jsxs(Container$8, Object.assign({}, rest, { onKeyUp: keyUpHandler, children: [label, jsxRuntime.jsx(Button$1, { onClick: onCloseClick, onKeyDown: buttonKeyDownHandler, "aria-label": closeButtonAriaLabel !== null && closeButtonAriaLabel !== void 0 ? closeButtonAriaLabel : `Remove ${label}`, children: jsxRuntime.jsx(Close, { height: 16, width: 16 }) })] })));
575
591
  }
576
592
 
577
593
  exports.ORIENTATION = void 0;
@@ -586,23 +602,36 @@ const Item = styled.div `
586
602
  cursor: ${(props) => (props.showIndicator ? 'default' : 'move')};
587
603
  display: flex;
588
604
  user-select: ${(props) => (props.showIndicator ? 'auto' : 'none')};
589
- border-top: 2px solid
605
+ border-top: 2px dashed
590
606
  ${(props) => props.orientation === exports.ORIENTATION.VERTICAL && props.active > 0
591
607
  ? constants.PRIMARY
592
608
  : 'transparent'};
593
- border-bottom: 2px solid
609
+ border-bottom: 2px dashed
594
610
  ${(props) => props.orientation === exports.ORIENTATION.VERTICAL && props.active < 0
595
611
  ? constants.PRIMARY
596
612
  : 'transparent'};
597
- border-left: 2px solid
613
+ border-left: 2px dashed
598
614
  ${(props) => props.orientation === exports.ORIENTATION.HORIZONTAL && props.active > 0
599
615
  ? constants.PRIMARY
600
616
  : 'transparent'};
601
- border-right: 2px solid
617
+ border-right: 2px dashed
602
618
  ${(props) => props.orientation === exports.ORIENTATION.HORIZONTAL && props.active < 0
603
619
  ? constants.PRIMARY
604
620
  : 'transparent'};
605
621
  opacity: ${(props) => (props.dragging ? 0.5 : 1)};
622
+ border-radius: 10px;
623
+
624
+ &:focus {
625
+ box-shadow: 0 0 0 4px var(--primary, ${constants.PRIMARY_LIGHT});
626
+ }
627
+
628
+ &:focus:not(:focus-visible) {
629
+ box-shadow: none;
630
+ }
631
+
632
+ &:focus-visible {
633
+ box-shadow: 0 0 0 4px var(--primary, ${constants.PRIMARY_LIGHT});
634
+ }
606
635
  `;
607
636
  /** Styled component for the drag handle indicator */
608
637
  const DragKnob = styled.div `
@@ -648,7 +677,7 @@ const Container$7 = styled.div `
648
677
  * @returns A draggable item with optional drag indicator and visual feedback
649
678
  */
650
679
  function DragItem(props) {
651
- const { index, orientation, children, showIndicator, dragOver } = props;
680
+ const { index, orientation, children, showIndicator, dragOver, totalItems, setAnnouncement } = props;
652
681
  const [active, setActive] = React.useState(0);
653
682
  const [touchTimer, setTouchTimer] = React.useState(null);
654
683
  const context = React.useContext(DragContext);
@@ -750,6 +779,71 @@ function DragItem(props) {
750
779
  document.body.style.overflow = 'auto';
751
780
  }
752
781
  };
782
+ /**
783
+ * Keyboard navigation handler for reordering items
784
+ * @param e Keyboard event
785
+ */
786
+ const handleKeyDown = (e) => {
787
+ const isVertical = orientation === exports.ORIENTATION.VERTICAL;
788
+ const moveUp = isVertical ? 'ArrowUp' : 'ArrowLeft';
789
+ const moveDown = isVertical ? 'ArrowDown' : 'ArrowRight';
790
+ const isGrabbed = context.isDragging && context.startIndex === index;
791
+ // Space to grab/drop
792
+ if (e.key === ' ' || e.key === 'Spacebar') {
793
+ e.preventDefault();
794
+ if (isGrabbed) {
795
+ // Drop at current position
796
+ context.drop(index);
797
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.droppedAnnouncementTemplate, {
798
+ position: index + 1,
799
+ }));
800
+ }
801
+ else {
802
+ // Grab item
803
+ context.startGrab(index);
804
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.grabbedAnnouncementTemplate, {
805
+ position: index + 1,
806
+ }));
807
+ }
808
+ }
809
+ // Enter to drop
810
+ else if (e.key === 'Enter' && isGrabbed) {
811
+ e.preventDefault();
812
+ context.drop(index);
813
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.droppedAnnouncementTemplate, {
814
+ position: index + 1,
815
+ }));
816
+ }
817
+ // Escape to cancel
818
+ else if (e.key === 'Escape' && isGrabbed) {
819
+ e.preventDefault();
820
+ context.cancel();
821
+ setAnnouncement(context.i18n.cancelledAnnouncementTemplate);
822
+ }
823
+ // Arrow keys to move while grabbed
824
+ else if (isGrabbed) {
825
+ if (e.key === moveUp && index > 0) {
826
+ e.preventDefault();
827
+ // Move without dropping - just reorder and update startIndex
828
+ const newIndex = index - 1;
829
+ context.onDrop(context.startIndex, newIndex);
830
+ context.setStartIndex(newIndex);
831
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.movedAnnouncementTemplate, {
832
+ position: newIndex + 1,
833
+ }));
834
+ }
835
+ else if (e.key === moveDown && index < totalItems - 1) {
836
+ e.preventDefault();
837
+ // Move without dropping - just reorder and update startIndex
838
+ const newIndex = index + 1;
839
+ context.onDrop(context.startIndex, newIndex);
840
+ context.setStartIndex(newIndex);
841
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.movedAnnouncementTemplate, {
842
+ position: newIndex + 1,
843
+ }));
844
+ }
845
+ }
846
+ };
753
847
  /** Cleanup touch timer on unmount */
754
848
  React.useEffect(() => {
755
849
  return () => {
@@ -767,7 +861,9 @@ function DragItem(props) {
767
861
  setActive(0);
768
862
  }
769
863
  }, [dragOver, context.startIndex, index, context.isDragging]);
770
- return (jsxRuntime.jsxs(Item, { draggable: !showIndicator, showIndicator: showIndicator, active: active, dragging: context.isDragging && context.startIndex === index, orientation: orientation, "data-drag-index": index, onDragStart: !showIndicator ? dragStartHandler : undefined, onDragOver: dragOverHandler, onDragLeave: dragExitHandler, onDrop: dropHandler, onTouchStart: !showIndicator ? touchStartHandler : undefined, onTouchMove: touchMoveHandler, onTouchEnd: touchEndHandler, onTouchCancel: touchEndHandler, children: [showIndicator && (jsxRuntime.jsx(DragKnob, { draggable: true, onDragStart: dragStartHandler, onTouchStart: touchStartHandler, children: jsxRuntime.jsx(CheckCircle, {}) })), jsxRuntime.jsx(Container$7, { children: children })] }));
864
+ return (jsxRuntime.jsxs(Item, { draggable: !showIndicator, showIndicator: showIndicator, active: active, dragging: context.isDragging && context.startIndex === index, orientation: orientation, "data-drag-index": index, tabIndex: 0, role: "listitem", "aria-label": context.i18n.replacePlaceholders(context.i18n.itemAriaLabelTemplate, {
865
+ position: index + 1,
866
+ }), "aria-grabbed": context.isDragging && context.startIndex === index, onKeyDown: handleKeyDown, onDragStart: !showIndicator ? dragStartHandler : undefined, onDragOver: dragOverHandler, onDragLeave: dragExitHandler, onDrop: dropHandler, onTouchStart: !showIndicator ? touchStartHandler : undefined, onTouchMove: touchMoveHandler, onTouchEnd: touchEndHandler, onTouchCancel: touchEndHandler, children: [showIndicator && (jsxRuntime.jsx(DragKnob, { draggable: true, role: "button", "aria-label": context.i18n.dragHandleAriaLabel, onDragStart: dragStartHandler, onTouchStart: touchStartHandler, onKeyDown: handleKeyDown, tabIndex: -1, children: jsxRuntime.jsx(CheckCircle, {}) })), jsxRuntime.jsx(Container$7, { children: children })] }));
771
867
  }
772
868
 
773
869
  /** Container Component */
@@ -778,6 +874,18 @@ const Container$6 = styled.div `
778
874
  flex-wrap: wrap;
779
875
  flex-direction: ${(props) => (props.orientation === exports.ORIENTATION.HORIZONTAL ? 'row' : 'column')};
780
876
  `;
877
+ /** Visually hidden but accessible to screen readers */
878
+ const VisuallyHidden$1 = styled.div `
879
+ position: absolute;
880
+ width: 1px;
881
+ height: 1px;
882
+ padding: 0;
883
+ margin: -1px;
884
+ overflow: hidden;
885
+ clip: rect(0, 0, 0, 0);
886
+ white-space: nowrap;
887
+ border-width: 0;
888
+ `;
781
889
  /**
782
890
  * A drag and drop container component that enables reordering of child elements.
783
891
  *
@@ -804,10 +912,37 @@ const Container$6 = styled.div `
804
912
  * @returns {JSX.Element} A draggable container with reorderable items
805
913
  */
806
914
  function DragAndDrop(props) {
807
- const { orientation, children, onDrop, showIndicator } = props;
915
+ const { orientation, children, onDrop, showIndicator, itemAriaLabelTemplate, dragHandleAriaLabel, grabbedAnnouncementTemplate, movedAnnouncementTemplate, droppedAnnouncementTemplate, cancelledAnnouncementTemplate, } = props;
808
916
  const [startIndex, setStartIndex] = React.useState(null);
917
+ const [originalIndex, setOriginalIndex] = React.useState(null);
809
918
  const [isDragging, setIsDragging] = React.useState(false);
810
919
  const [dragOver, setDragOver] = React.useState(null);
920
+ const [announcement, setAnnouncement] = React.useState('');
921
+ const childrenArray = React.Children.toArray(children);
922
+ const totalItems = childrenArray.length;
923
+ /**
924
+ * Replace placeholders in i18n templates
925
+ */
926
+ const replacePlaceholders = (template, data) => {
927
+ var _a, _b, _c, _d, _e, _f;
928
+ return template
929
+ .replace(/\{:position\}/g, String((_a = data.position) !== null && _a !== void 0 ? _a : ''))
930
+ .replace(/\{:grabKey\}/g, (_b = data.grabKey) !== null && _b !== void 0 ? _b : 'Space')
931
+ .replace(/\{:dropKey\}/g, (_c = data.dropKey) !== null && _c !== void 0 ? _c : 'Space')
932
+ .replace(/\{:altDropKey\}/g, (_d = data.altDropKey) !== null && _d !== void 0 ? _d : 'Enter')
933
+ .replace(/\{:cancelKey\}/g, (_e = data.cancelKey) !== null && _e !== void 0 ? _e : 'Escape')
934
+ .replace(/\{:moveKeys\}/g, (_f = data.moveKeys) !== null && _f !== void 0 ? _f : (orientation === exports.ORIENTATION.VERTICAL ? 'Arrow Up/Down' : 'Arrow Left/Right'));
935
+ };
936
+ // i18n configuration object
937
+ const i18n = {
938
+ itemAriaLabelTemplate: itemAriaLabelTemplate,
939
+ dragHandleAriaLabel: dragHandleAriaLabel,
940
+ grabbedAnnouncementTemplate: grabbedAnnouncementTemplate,
941
+ movedAnnouncementTemplate: movedAnnouncementTemplate,
942
+ droppedAnnouncementTemplate: droppedAnnouncementTemplate,
943
+ cancelledAnnouncementTemplate: cancelledAnnouncementTemplate,
944
+ replacePlaceholders,
945
+ };
811
946
  /**
812
947
  * Drop handler invoked when a draggable item is released.
813
948
  * @param index
@@ -817,15 +952,58 @@ function DragAndDrop(props) {
817
952
  onDrop === null || onDrop === void 0 ? void 0 : onDrop(startIndex, index);
818
953
  }
819
954
  setStartIndex(null);
955
+ setOriginalIndex(null);
820
956
  setIsDragging(false);
821
957
  };
822
- return (jsxRuntime.jsx(DragContext.Provider, { value: { startIndex, setStartIndex, drop, isDragging, setIsDragging, setDragOver }, children: jsxRuntime.jsx(Container$6, { orientation: orientation, children: React.Children.map(children, (child, index) => (jsxRuntime.jsx(DragItem, { index: index, orientation: orientation, showIndicator: showIndicator, dragOver: dragOver, children: child }))) }) }));
958
+ /**
959
+ * Cancel handler to restore item to original position
960
+ */
961
+ const cancel = () => {
962
+ if (originalIndex !== null && startIndex !== null && startIndex !== originalIndex) {
963
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop(startIndex, originalIndex);
964
+ }
965
+ setStartIndex(null);
966
+ setOriginalIndex(null);
967
+ setIsDragging(false);
968
+ };
969
+ /**
970
+ * Start grab handler to track original position
971
+ */
972
+ const startGrab = (index) => {
973
+ setStartIndex(index);
974
+ setOriginalIndex(index);
975
+ setIsDragging(true);
976
+ };
977
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(DragContext.Provider, { value: {
978
+ startIndex,
979
+ setStartIndex,
980
+ drop,
981
+ onDrop,
982
+ cancel,
983
+ startGrab,
984
+ isDragging,
985
+ setIsDragging,
986
+ setDragOver,
987
+ i18n,
988
+ }, children: jsxRuntime.jsx(Container$6, { orientation: orientation, role: "list", children: React.Children.map(childrenArray, (child, index) => (jsxRuntime.jsx(DragItem, { index: index, orientation: orientation, showIndicator: showIndicator, dragOver: dragOver, totalItems: totalItems, setAnnouncement: setAnnouncement, children: child }))) }) }), jsxRuntime.jsx(VisuallyHidden$1, { role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement })] }));
823
989
  }
824
990
  DragAndDrop.defaultProps = {
825
991
  /** Orientation of the list layout */
826
992
  orientation: exports.ORIENTATION.VERTICAL,
827
993
  /** Whether to display drag indicators for each list item */
828
994
  showIndicator: false,
995
+ /** Default item aria-label template */
996
+ itemAriaLabelTemplate: 'Item {:position}. Press {:grabKey} to grab, {:moveKeys} to move, {:dropKey} or {:altDropKey} to drop',
997
+ /** Default drag handle aria-label */
998
+ dragHandleAriaLabel: 'Drag to reorder',
999
+ /** Default grabbed announcement template */
1000
+ grabbedAnnouncementTemplate: 'Item {:position} grabbed. Use {:moveKeys} to move, {:dropKey} or {:altDropKey} to drop, {:cancelKey} to cancel',
1001
+ /** Default moved announcement template */
1002
+ movedAnnouncementTemplate: 'Item moved to position {:position}',
1003
+ /** Default dropped announcement template */
1004
+ droppedAnnouncementTemplate: 'Item dropped at position {:position}',
1005
+ /** Default cancelled announcement template */
1006
+ cancelledAnnouncementTemplate: 'Drag cancelled, item restored to original position',
829
1007
  };
830
1008
 
831
1009
  // Label component for the ChipInput
@@ -946,6 +1124,22 @@ const ErrorContainer$4 = styled.div `
946
1124
  line-height: 14px;
947
1125
  margin-left: 3px;
948
1126
  `;
1127
+ // Visually hidden but accessible to screen readers
1128
+ const VisuallyHidden = styled.ul `
1129
+ position: absolute;
1130
+ width: 1px;
1131
+ height: 1px;
1132
+ padding: 0;
1133
+ margin: -1px;
1134
+ overflow: hidden;
1135
+ clip: rect(0, 0, 0, 0);
1136
+ white-space: nowrap;
1137
+ border-width: 0;
1138
+
1139
+ & li {
1140
+ list-style: none;
1141
+ }
1142
+ `;
949
1143
  /**
950
1144
  * A chip input component that allows users to add and remove chips (tags) by typing and pressing Enter.
951
1145
  * @component
@@ -964,9 +1158,21 @@ function ChipInput(props) {
964
1158
  const [touched, setTouched] = React.useState(false);
965
1159
  const [value, setValue] = React.useState(props.value);
966
1160
  const InputRef = React.useRef(null);
1161
+ const [announcement, setAnnouncement] = React.useState('');
1162
+ const errorId = React.useId();
1163
+ /**
1164
+ * Replace {:label} placeholder in template string
1165
+ */
1166
+ const replacePlaceholder = (template, label) => {
1167
+ if (!template)
1168
+ return undefined;
1169
+ return template.replace(/\{:label\}/g, label);
1170
+ };
967
1171
  // Sync internal value with props.value
968
1172
  React.useEffect(() => {
969
- setValue(props.value);
1173
+ if (Array.isArray(props.value)) {
1174
+ setValue(props.value);
1175
+ }
970
1176
  }, [props.value]);
971
1177
  /**
972
1178
  * Update the chip values and notify changes.
@@ -1004,6 +1210,7 @@ function ChipInput(props) {
1004
1210
  const newValue = [...value, text.trim()];
1005
1211
  updateValue(newValue);
1006
1212
  setText('');
1213
+ setAnnouncement(replacePlaceholder(props.addedAnnouncementTemplate, text.trim()));
1007
1214
  }
1008
1215
  };
1009
1216
  /**
@@ -1013,6 +1220,7 @@ function ChipInput(props) {
1013
1220
  const removeChip = (chipToRemove) => {
1014
1221
  const newValue = value.filter((chip) => chip !== chipToRemove);
1015
1222
  updateValue(newValue);
1223
+ setAnnouncement(replacePlaceholder(props.removedAnnouncementTemplate, chipToRemove));
1016
1224
  };
1017
1225
  /**
1018
1226
  * Moves a chip from one position to another.
@@ -1030,7 +1238,7 @@ function ChipInput(props) {
1030
1238
  updateValue(newItems);
1031
1239
  };
1032
1240
  // Render the component
1033
- return (jsxRuntime.jsxs(Label$6, { text: text, touched: touched, errorText: props.errorText, children: [jsxRuntime.jsx("input", Object.assign({}, props, { ref: InputRef, type: "text", value: text, onChange: handleChange, onFocus: handleFocus, onKeyUp: handleKeyUp, required: props.required && value.length === 0 })), jsxRuntime.jsx("div", { children: (value === null || value === void 0 ? void 0 : value.length) > 0 && (jsxRuntime.jsx(DragAndDrop, { orientation: exports.ORIENTATION.HORIZONTAL, onDrop: onDrop, children: value.map((chip) => (jsxRuntime.jsx(Chip, { label: chip, onCloseClick: () => removeChip(chip) }, chip))) })) }), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$4, { children: props.errorText })] }));
1241
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsxs(Label$6, { text: text, touched: touched, errorText: props.errorText, children: [jsxRuntime.jsx("input", Object.assign({}, props, { ref: InputRef, value: text, onChange: handleChange, onFocus: handleFocus, onKeyUp: handleKeyUp, required: props.required && value.length === 0, "aria-required": props.required, "aria-invalid": !!props.errorText, "aria-describedby": props.errorText ? errorId : undefined })), jsxRuntime.jsx("div", { children: (value === null || value === void 0 ? void 0 : value.length) > 0 && (jsxRuntime.jsx(DragAndDrop, { orientation: exports.ORIENTATION.HORIZONTAL, onDrop: onDrop, children: value.map((chip) => (jsxRuntime.jsx(Chip, { label: chip, onCloseClick: () => removeChip(chip), closeButtonAriaLabel: replacePlaceholder(props.closeButtonAriaLabel, chip) }, chip))) })) }), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$4, { id: errorId, children: props.errorText })] }), jsxRuntime.jsx(VisuallyHidden, { "aria-live": "polite", "aria-atomic": "true", children: announcement })] }));
1034
1242
  }
1035
1243
  ChipInput.propTypes = {
1036
1244
  /** Label for the field */
@@ -1041,9 +1249,18 @@ ChipInput.propTypes = {
1041
1249
  value: PropTypes.arrayOf(PropTypes.string),
1042
1250
  /** Callback when chips change */
1043
1251
  onChange: PropTypes.func,
1252
+ /** Aria label for the close button on chip. Defaults to "Remove {label}" */
1253
+ closeButtonAriaLabel: PropTypes.string,
1254
+ /** Announcement text when a chip is added. Defaults to "{label} was added" */
1255
+ addedAnnouncementTemplate: PropTypes.string,
1256
+ /** Announcement text when a chip is removed. Defaults to "{label} was removed" */
1257
+ removedAnnouncementTemplate: PropTypes.string,
1044
1258
  };
1045
1259
  ChipInput.defaultProps = {
1046
1260
  value: [],
1261
+ closeButtonAriaLabel: 'Remove {:label}',
1262
+ addedAnnouncementTemplate: '{:label} was added',
1263
+ removedAnnouncementTemplate: '{:label} was removed',
1047
1264
  };
1048
1265
 
1049
1266
  /** Enums for layer position on screen. */
@@ -1350,7 +1567,7 @@ class AlertDialog extends React.Component {
1350
1567
  this.close = () => this.dialog.current.close();
1351
1568
  }
1352
1569
  render() {
1353
- return (jsxRuntime.jsxs(Dialog, Object.assign({}, this.props.dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: true, children: [this.props.header && jsxRuntime.jsx(Header$1, { children: this.props.header }), jsxRuntime.jsx(Body$1, { children: this.props.body }), jsxRuntime.jsx(Footer$1, { children: jsxRuntime.jsx(Button$2, { onClick: this.close, children: this.props.buttonText }) })] })));
1570
+ return (jsxRuntime.jsxs(Dialog, Object.assign({}, this.props.dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: [this.props.header && jsxRuntime.jsx(Header$1, { children: this.props.header }), jsxRuntime.jsx(Body$1, { children: this.props.body }), jsxRuntime.jsx(Footer$1, { children: jsxRuntime.jsx(StyledButton, { onClick: this.close, children: this.props.buttonText }) })] })));
1354
1571
  }
1355
1572
  }
1356
1573
  AlertDialog.propTypes = {
@@ -1389,7 +1606,7 @@ class ConfirmDialog extends React.Component {
1389
1606
  }
1390
1607
  render() {
1391
1608
  const { header, body, yesText, noText, dialogProps } = this.props;
1392
- return (jsxRuntime.jsxs(Dialog, Object.assign({}, dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: [header && jsxRuntime.jsx(Header$1, { children: header }), jsxRuntime.jsx(Body$1, { children: body }), jsxRuntime.jsxs(Footer$1, { children: [jsxRuntime.jsx(Button$2, { onClick: this.cancel, children: noText }), jsxRuntime.jsx(ActionButton, { onClick: this.confirm, children: yesText })] })] })));
1609
+ return (jsxRuntime.jsxs(Dialog, Object.assign({}, dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: [header && jsxRuntime.jsx(Header$1, { children: header }), jsxRuntime.jsx(Body$1, { children: body }), jsxRuntime.jsxs(Footer$1, { children: [jsxRuntime.jsx(StyledButton, { onClick: this.cancel, children: noText }), jsxRuntime.jsx(ActionButton, { onClick: this.confirm, children: yesText })] })] })));
1393
1610
  }
1394
1611
  }
1395
1612
  ConfirmDialog.propTypes = {
@@ -1412,7 +1629,6 @@ ConfirmDialog.defaultProps = {
1412
1629
  const Label$5 = styled.label `
1413
1630
  display: inline-flex;
1414
1631
  flex-direction: column;
1415
- flex: 1;
1416
1632
  position: relative;
1417
1633
  margin: 10px 5px;
1418
1634
  `;
@@ -1553,7 +1769,6 @@ Input$4.propTypes = {
1553
1769
  const Label$4 = styled.label `
1554
1770
  display: inline-flex;
1555
1771
  flex-direction: column;
1556
- flex: 1;
1557
1772
  position: relative;
1558
1773
  margin: 10px 5px;
1559
1774
  `;
@@ -1692,7 +1907,6 @@ TextArea.propTypes = {
1692
1907
  const Label$3 = styled.label `
1693
1908
  display: inline-flex;
1694
1909
  flex-direction: column;
1695
- flex: 1;
1696
1910
  position: relative;
1697
1911
  margin: 10px 5px;
1698
1912
  pointer-events: none;
@@ -1948,7 +2162,7 @@ function Checkbox(props) {
1948
2162
  }
1949
2163
  }
1950
2164
  }, [props.indeterminate]);
1951
- return (jsxRuntime.jsxs(Label$2, { children: [jsxRuntime.jsx(Input$3, Object.assign({}, props, { ref: ref, type: "checkbox" })), jsxRuntime.jsx("span", { children: props.label })] }));
2165
+ return (jsxRuntime.jsxs(Label$2, { children: [jsxRuntime.jsx(Input$3, Object.assign({}, props, { ref: ref, type: "checkbox", "aria-checked": props.indeterminate ? 'mixed' : props.checked })), jsxRuntime.jsx("span", { children: props.label })] }));
1952
2166
  }
1953
2167
  Checkbox.propTypes = {
1954
2168
  /** Label for the field */
@@ -2571,7 +2785,7 @@ class PromptDialog extends React.Component {
2571
2785
  }
2572
2786
  render() {
2573
2787
  const { header, body, inputProps, submitText, cancelText, dialogProps } = this.props;
2574
- return (jsxRuntime.jsx(Dialog, Object.assign({}, dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: jsxRuntime.jsxs("form", { onSubmit: this.submit, children: [header && jsxRuntime.jsx(Header$1, { children: header }), jsxRuntime.jsxs(Body$1, { children: [jsxRuntime.jsx(BodyText, { children: body }), jsxRuntime.jsx("div", { style: { display: 'flex' }, children: jsxRuntime.jsx(Input$4, Object.assign({ style: { width: 'auto', flex: '1' }, value: this.state.value, onChange: this.valueChange }, inputProps)) })] }), jsxRuntime.jsxs(Footer$1, { children: [jsxRuntime.jsx(Button$2, { type: "button", onClick: this.cancel, children: cancelText }), jsxRuntime.jsx(ActionButton, { children: submitText })] })] }) })));
2788
+ return (jsxRuntime.jsx(Dialog, Object.assign({}, dialogProps, { ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: jsxRuntime.jsxs("form", { onSubmit: this.submit, children: [header && jsxRuntime.jsx(Header$1, { children: header }), jsxRuntime.jsxs(Body$1, { children: [jsxRuntime.jsx(BodyText, { children: body }), jsxRuntime.jsx("div", { style: { display: 'flex' }, children: jsxRuntime.jsx(Input$4, Object.assign({ style: { width: 'auto', flex: '1' }, value: this.state.value, onChange: this.valueChange }, inputProps)) })] }), jsxRuntime.jsxs(Footer$1, { children: [jsxRuntime.jsx(StyledButton, { type: "button", onClick: this.cancel, children: cancelText }), jsxRuntime.jsx(ActionButton, { children: submitText })] })] }) })));
2575
2789
  }
2576
2790
  }
2577
2791
  PromptDialog.propTypes = {
@@ -3252,56 +3466,83 @@ class Notification {
3252
3466
  /**
3253
3467
  * Adds a notification
3254
3468
  *
3255
- * @param position
3256
- * @param options
3469
+ * @param position - The position where the notification should appear
3470
+ * @param options - Configuration options for the notification
3471
+ * @returns The notification ID or a promise that resolves to the notification ID
3257
3472
  */
3258
3473
  this.add = (position, options) => {
3259
- let notification;
3260
3474
  if (!this.containers.has(position)) {
3261
- const div = document === null || document === void 0 ? void 0 : document.createElement('div');
3262
- const ref = React.createRef();
3475
+ /** Callback ref to capture the NotificationManager instance when it mounts */
3476
+ const refCallback = (instance) => {
3477
+ if (instance) {
3478
+ const container = this.containers.get(position);
3479
+ if (container) {
3480
+ container.manager = instance;
3481
+ }
3482
+ }
3483
+ };
3263
3484
  const [Component] = LayerManager$1.renderLayer({
3264
3485
  closeOnEsc: false,
3265
3486
  closeOnOverlayClick: false,
3266
3487
  position: positionMap[position],
3267
3488
  alwaysOnTop: true,
3268
- component: (jsxRuntime.jsx(NotificationManager, { ref: ref, position: position, onEmpty: () => this.destroy(position) })),
3489
+ component: (jsxRuntime.jsx(NotificationManager, { ref: refCallback, position: position, onEmpty: () => this.destroy(position) })),
3269
3490
  });
3491
+ // Create a div to mount the Component
3492
+ const div = document.createElement('div');
3493
+ document.body.appendChild(div);
3494
+ const root = client.createRoot(div);
3270
3495
  this.containers.set(position, {
3271
- ref,
3272
- element: div,
3273
- root: client.createRoot(div),
3496
+ manager: null,
3497
+ root,
3498
+ div,
3274
3499
  });
3500
+ // Render the Component which will trigger the LayerManager's useEffect
3275
3501
  ReactDOM.flushSync(() => {
3276
- this.containers.get(position).root.render(jsxRuntime.jsx(Component, {}));
3502
+ root.render(jsxRuntime.jsx(Component, {}));
3277
3503
  });
3278
- notification = ref;
3279
3504
  }
3280
- else {
3281
- notification = this.containers.get(position).ref;
3505
+ const container = this.containers.get(position);
3506
+ if (container && container.manager) {
3507
+ return container.manager.add(options);
3282
3508
  }
3283
- return notification.current.add(options);
3509
+ // If manager is not ready yet, wait a bit and retry
3510
+ return new Promise((resolve) => {
3511
+ setTimeout(() => {
3512
+ const container = this.containers.get(position);
3513
+ if (container && container.manager) {
3514
+ resolve(container.manager.add(options));
3515
+ }
3516
+ }, 10);
3517
+ });
3284
3518
  };
3285
3519
  /**
3286
3520
  * Removes a notification
3287
3521
  *
3288
- * @param position
3289
- * @param id
3522
+ * @param position - The position of the notification container
3523
+ * @param id - The unique ID of the notification to remove
3290
3524
  */
3291
3525
  this.remove = (position, id) => {
3292
- if (this.containers.has(position)) {
3293
- this.containers.get(position).ref.current.remove(id);
3526
+ const container = this.containers.get(position);
3527
+ if (container && container.manager) {
3528
+ container.manager.remove(id);
3294
3529
  }
3295
3530
  };
3296
3531
  /**
3297
- * Destroys entire stack of notifications.
3532
+ * Destroys entire stack of notifications at a position.
3533
+ * Unmounts the React root and cleans up DOM elements.
3298
3534
  *
3299
- * @param position
3535
+ * @param position - The position of the notification container to destroy
3300
3536
  */
3301
3537
  this.destroy = (position) => {
3302
- const notification = this.containers.get(position);
3303
- notification.root.unmount();
3304
- this.containers.delete(position);
3538
+ const container = this.containers.get(position);
3539
+ if (container) {
3540
+ container.root.unmount();
3541
+ if (document.body.contains(container.div)) {
3542
+ document.body.removeChild(container.div);
3543
+ }
3544
+ this.containers.delete(position);
3545
+ }
3305
3546
  };
3306
3547
  }
3307
3548
  }
@@ -3750,7 +3991,7 @@ exports.AccordionStepFooter = AccordionStepFooter;
3750
3991
  exports.ActionButton = ActionButton;
3751
3992
  exports.AlertDialog = AlertDialog;
3752
3993
  exports.Badge = Badge;
3753
- exports.Button = Button$2;
3994
+ exports.Button = StyledButton;
3754
3995
  exports.Card = Card;
3755
3996
  exports.CardBody = Body$1;
3756
3997
  exports.CardFooter = Footer$1;