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

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 (146) hide show
  1. package/dist/index.js +1622 -539
  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 +27 -38
  5. package/lib-esm/components/Accordion/AccordionStep.js.map +1 -1
  6. package/lib-esm/components/Badge/Badge.js +7 -7
  7. package/lib-esm/components/Badge/Badge.js.map +1 -1
  8. package/lib-esm/components/Button/ActionButton.d.ts.map +1 -1
  9. package/lib-esm/components/Button/ActionButton.js +12 -11
  10. package/lib-esm/components/Button/ActionButton.js.map +1 -1
  11. package/lib-esm/components/Button/Button.d.ts +2 -2
  12. package/lib-esm/components/Button/Button.d.ts.map +1 -1
  13. package/lib-esm/components/Button/Button.js +19 -14
  14. package/lib-esm/components/Button/Button.js.map +1 -1
  15. package/lib-esm/components/Button/IconButton.d.ts.map +1 -1
  16. package/lib-esm/components/Button/IconButton.js +15 -14
  17. package/lib-esm/components/Button/IconButton.js.map +1 -1
  18. package/lib-esm/components/Button/LinkButton.d.ts.map +1 -1
  19. package/lib-esm/components/Button/LinkButton.js +7 -6
  20. package/lib-esm/components/Button/LinkButton.js.map +1 -1
  21. package/lib-esm/components/Button/RaisedButton.d.ts.map +1 -1
  22. package/lib-esm/components/Button/RaisedButton.js +15 -14
  23. package/lib-esm/components/Button/RaisedButton.js.map +1 -1
  24. package/lib-esm/components/Card/Card.d.ts.map +1 -1
  25. package/lib-esm/components/Card/Card.js +4 -4
  26. package/lib-esm/components/Card/Card.js.map +1 -1
  27. package/lib-esm/components/Chip/Chip.d.ts +5 -2
  28. package/lib-esm/components/Chip/Chip.d.ts.map +1 -1
  29. package/lib-esm/components/Chip/Chip.js +20 -14
  30. package/lib-esm/components/Chip/Chip.js.map +1 -1
  31. package/lib-esm/components/ChipInput/ChipInput.d.ts +9 -0
  32. package/lib-esm/components/ChipInput/ChipInput.d.ts.map +1 -1
  33. package/lib-esm/components/ChipInput/ChipInput.js +63 -24
  34. package/lib-esm/components/ChipInput/ChipInput.js.map +1 -1
  35. package/lib-esm/components/Dialog/AlertDialog.d.ts.map +1 -1
  36. package/lib-esm/components/Dialog/AlertDialog.js +4 -1
  37. package/lib-esm/components/Dialog/AlertDialog.js.map +1 -1
  38. package/lib-esm/components/Dialog/Dialog.d.ts +32 -2
  39. package/lib-esm/components/Dialog/Dialog.d.ts.map +1 -1
  40. package/lib-esm/components/Dialog/Dialog.js +84 -1
  41. package/lib-esm/components/Dialog/Dialog.js.map +1 -1
  42. package/lib-esm/components/DragAndDrop/DragAndDrop.d.ts +24 -0
  43. package/lib-esm/components/DragAndDrop/DragAndDrop.d.ts.map +1 -1
  44. package/lib-esm/components/DragAndDrop/DragAndDrop.js +85 -3
  45. package/lib-esm/components/DragAndDrop/DragAndDrop.js.map +1 -1
  46. package/lib-esm/components/DragAndDrop/DragItem.d.ts +4 -0
  47. package/lib-esm/components/DragAndDrop/DragItem.d.ts.map +1 -1
  48. package/lib-esm/components/DragAndDrop/DragItem.js +92 -12
  49. package/lib-esm/components/DragAndDrop/DragItem.js.map +1 -1
  50. package/lib-esm/components/DragAndDrop/types.d.ts +19 -0
  51. package/lib-esm/components/DragAndDrop/types.d.ts.map +1 -1
  52. package/lib-esm/components/DragAndDrop/types.js.map +1 -1
  53. package/lib-esm/components/Drawer/Drawer.d.ts +76 -1
  54. package/lib-esm/components/Drawer/Drawer.d.ts.map +1 -1
  55. package/lib-esm/components/Drawer/Drawer.js +158 -24
  56. package/lib-esm/components/Drawer/Drawer.js.map +1 -1
  57. package/lib-esm/components/Groups/Group.d.ts.map +1 -1
  58. package/lib-esm/components/Groups/Group.js +10 -8
  59. package/lib-esm/components/Groups/Group.js.map +1 -1
  60. package/lib-esm/components/Groups/GroupLabel.d.ts.map +1 -1
  61. package/lib-esm/components/Groups/GroupLabel.js +3 -3
  62. package/lib-esm/components/Groups/GroupLabel.js.map +1 -1
  63. package/lib-esm/components/Input/Checkbox.d.ts.map +1 -1
  64. package/lib-esm/components/Input/Checkbox.js +63 -58
  65. package/lib-esm/components/Input/Checkbox.js.map +1 -1
  66. package/lib-esm/components/Input/Dropdown.d.ts +8 -0
  67. package/lib-esm/components/Input/Dropdown.d.ts.map +1 -1
  68. package/lib-esm/components/Input/Dropdown.js +54 -31
  69. package/lib-esm/components/Input/Dropdown.js.map +1 -1
  70. package/lib-esm/components/Input/Input.d.ts.map +1 -1
  71. package/lib-esm/components/Input/Input.js +27 -22
  72. package/lib-esm/components/Input/Input.js.map +1 -1
  73. package/lib-esm/components/Input/Radio.d.ts.map +1 -1
  74. package/lib-esm/components/Input/Radio.js +58 -42
  75. package/lib-esm/components/Input/Radio.js.map +1 -1
  76. package/lib-esm/components/Input/RadioButton.d.ts.map +1 -1
  77. package/lib-esm/components/Input/RadioButton.js +12 -12
  78. package/lib-esm/components/Input/RadioButton.js.map +1 -1
  79. package/lib-esm/components/Input/Select.d.ts.map +1 -1
  80. package/lib-esm/components/Input/Select.js +27 -22
  81. package/lib-esm/components/Input/Select.js.map +1 -1
  82. package/lib-esm/components/Input/TextArea.d.ts.map +1 -1
  83. package/lib-esm/components/Input/TextArea.js +27 -22
  84. package/lib-esm/components/Input/TextArea.js.map +1 -1
  85. package/lib-esm/components/Input/Toggle.d.ts.map +1 -1
  86. package/lib-esm/components/Input/Toggle.js +17 -14
  87. package/lib-esm/components/Input/Toggle.js.map +1 -1
  88. package/lib-esm/components/Menu/Menu.d.ts +13 -1
  89. package/lib-esm/components/Menu/Menu.d.ts.map +1 -1
  90. package/lib-esm/components/Menu/Menu.js +98 -3
  91. package/lib-esm/components/Menu/Menu.js.map +1 -1
  92. package/lib-esm/components/Menu/MenuItem.d.ts +6 -3
  93. package/lib-esm/components/Menu/MenuItem.d.ts.map +1 -1
  94. package/lib-esm/components/Menu/MenuItem.js +10 -10
  95. package/lib-esm/components/Menu/MenuItem.js.map +1 -1
  96. package/lib-esm/components/Modal/Modal.d.ts +70 -1
  97. package/lib-esm/components/Modal/Modal.d.ts.map +1 -1
  98. package/lib-esm/components/Modal/Modal.js +145 -11
  99. package/lib-esm/components/Modal/Modal.js.map +1 -1
  100. package/lib-esm/components/Notification/Notification.d.ts +11 -7
  101. package/lib-esm/components/Notification/Notification.d.ts.map +1 -1
  102. package/lib-esm/components/Notification/Notification.js +54 -25
  103. package/lib-esm/components/Notification/Notification.js.map +1 -1
  104. package/lib-esm/components/Notification/NotificationManager.d.ts +11 -1
  105. package/lib-esm/components/Notification/NotificationManager.d.ts.map +1 -1
  106. package/lib-esm/components/Notification/NotificationManager.js +43 -8
  107. package/lib-esm/components/Notification/NotificationManager.js.map +1 -1
  108. package/lib-esm/components/Notification/style.d.ts +4 -0
  109. package/lib-esm/components/Notification/style.d.ts.map +1 -1
  110. package/lib-esm/components/Notification/style.js +30 -15
  111. package/lib-esm/components/Notification/style.js.map +1 -1
  112. package/lib-esm/components/Notification/types.d.ts +2 -0
  113. package/lib-esm/components/Notification/types.d.ts.map +1 -1
  114. package/lib-esm/components/Notification/types.js.map +1 -1
  115. package/lib-esm/components/Popover/Popover.d.ts.map +1 -1
  116. package/lib-esm/components/Popover/Popover.js +17 -2
  117. package/lib-esm/components/Popover/Popover.js.map +1 -1
  118. package/lib-esm/components/Spinner/Spinner.d.ts +3 -0
  119. package/lib-esm/components/Spinner/Spinner.d.ts.map +1 -1
  120. package/lib-esm/components/Spinner/Spinner.js +19 -4
  121. package/lib-esm/components/Spinner/Spinner.js.map +1 -1
  122. package/lib-esm/components/Stepper/Stepper.d.ts.map +1 -1
  123. package/lib-esm/components/Stepper/Stepper.js +29 -10
  124. package/lib-esm/components/Stepper/Stepper.js.map +1 -1
  125. package/lib-esm/components/Tabs/Tabs.d.ts.map +1 -1
  126. package/lib-esm/components/Tabs/Tabs.js +45 -12
  127. package/lib-esm/components/Tabs/Tabs.js.map +1 -1
  128. package/lib-esm/components/Toast/Toast.d.ts +25 -4
  129. package/lib-esm/components/Toast/Toast.d.ts.map +1 -1
  130. package/lib-esm/components/Toast/Toast.js +114 -18
  131. package/lib-esm/components/Toast/Toast.js.map +1 -1
  132. package/lib-esm/components/Tooltip/Tooltip.d.ts.map +1 -1
  133. package/lib-esm/components/Tooltip/Tooltip.js +16 -5
  134. package/lib-esm/components/Tooltip/Tooltip.js.map +1 -1
  135. package/lib-esm/shared/LayerManager.d.ts.map +1 -1
  136. package/lib-esm/shared/LayerManager.js +63 -1
  137. package/lib-esm/shared/LayerManager.js.map +1 -1
  138. package/lib-esm/shared/constants.d.ts +58 -27
  139. package/lib-esm/shared/constants.d.ts.map +1 -1
  140. package/lib-esm/shared/constants.js +88 -25
  141. package/lib-esm/shared/constants.js.map +1 -1
  142. package/lib-esm/shared/styles.d.ts +1 -1
  143. package/lib-esm/shared/styles.d.ts.map +1 -1
  144. package/lib-esm/shared/styles.js +5 -3
  145. package/lib-esm/shared/styles.js.map +1 -1
  146. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -74,42 +74,106 @@ function CheckCircle(props) {
74
74
  return (jsxRuntime.jsxs("svg", Object.assign({ height: "24", viewBox: "0 0 24 24", width: "24", fill: "currentColor" }, props, { children: [jsxRuntime.jsx("path", { d: "M0 0h24v24H0V0z", fill: "none" }), jsxRuntime.jsx("path", { d: "M11 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm-2-8c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm6 4c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z" })] })));
75
75
  }
76
76
 
77
- var constants = {
78
- PRIMARY: '#2283d2',
79
- PRIMARY_LIGHT: '#64baff',
80
- PRIMARY_LIGHTER: '#cfe9ff',
81
- BACKDROP_COLOR: '#2681da80',
82
- INFO: '#2283d2',
83
- INFO_LIGHT: '#64baff',
84
- SUCCESS: '#22d295',
85
- SUCCESS_LIGHT: '#80eac6',
86
- WARNING: '#cc9500',
87
- WARNING_LIGHT: '#ffba00',
88
- ERROR: '#d63b3b',
89
- ERROR_LIGHT: '#f1a5a5',
90
- BORDER_COLOR: '#555555',
91
- TOAST: '#5f5f5f',
92
- TOOLTIP_COLOR: 'rgba(0,0,0,0.5)',
93
- BORDER_LIGHT_COLOR: '#eeeeee',
94
- BACKGROUND: '#ffffff',
95
- DISABLED_BACKGROUND: '#fafafa',
96
- DISABLED_BORDER: '#aaa',
97
- LIGHT_GREY: '#ccc',
98
- DISABLED: '#777',
99
- SHADOW: '0px 1px 3px 0px rgba(0,0,0,0.1), 0px 1px 2px 0px rgba(0,0,0,0.06)',
100
- HOVER_SHADOW: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
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)',
77
+ var THEME_CONSTANTS;
78
+ (function (THEME_CONSTANTS) {
79
+ THEME_CONSTANTS["PRIMARY"] = "#1f7ac5";
80
+ THEME_CONSTANTS["PRIMARY_LIGHT"] = "#64baff";
81
+ THEME_CONSTANTS["PRIMARY_LIGHTER"] = "#cfe9ff";
82
+ THEME_CONSTANTS["BACKDROP_COLOR"] = "#2681da80";
83
+ THEME_CONSTANTS["INFO"] = "#1f7ac5ff";
84
+ THEME_CONSTANTS["INFO_LIGHT"] = "#64baffff";
85
+ THEME_CONSTANTS["SUCCESS"] = "#1a835f";
86
+ THEME_CONSTANTS["SUCCESS_LIGHT"] = "#80eac6";
87
+ THEME_CONSTANTS["WARNING"] = "#916b01";
88
+ THEME_CONSTANTS["WARNING_LIGHT"] = "#ffba00";
89
+ THEME_CONSTANTS["ERROR"] = "#bb2828";
90
+ THEME_CONSTANTS["ERROR_LIGHT"] = "#f1a5a5";
91
+ THEME_CONSTANTS["BORDER_COLOR"] = "#555555";
92
+ THEME_CONSTANTS["TOAST"] = "#5f5f5f";
93
+ THEME_CONSTANTS["TOOLTIP_COLOR"] = "rgba(0,0,0,0.6)";
94
+ THEME_CONSTANTS["BORDER_LIGHT_COLOR"] = "#eeeeee";
95
+ THEME_CONSTANTS["BACKGROUND"] = "#ffffff";
96
+ THEME_CONSTANTS["DISABLED_BACKGROUND"] = "#fafafa";
97
+ THEME_CONSTANTS["DISABLED_BORDER"] = "#aaa";
98
+ THEME_CONSTANTS["LIGHT_GREY"] = "#ccc";
99
+ THEME_CONSTANTS["DISABLED"] = "#737373";
100
+ THEME_CONSTANTS["TEXT_COLOR_LIGHT"] = "#fff";
101
+ THEME_CONSTANTS["TEXT_COLOR_DARK"] = "#000";
102
+ THEME_CONSTANTS["SHADOW"] = "0px 1px 3px 0px rgba(0,0,0,0.1), 0px 1px 2px 0px rgba(0,0,0,0.06)";
103
+ THEME_CONSTANTS["HOVER_SHADOW"] = "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)";
104
+ THEME_CONSTANTS["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)";
105
+ })(THEME_CONSTANTS || (THEME_CONSTANTS = {}));
106
+ var THEME_NAME;
107
+ (function (THEME_NAME) {
108
+ THEME_NAME["PRIMARY"] = "--nfui-primary";
109
+ THEME_NAME["PRIMARY_LIGHT"] = "--nfui-primary-light";
110
+ THEME_NAME["PRIMARY_LIGHTER"] = "--nfui-primary-lighter";
111
+ THEME_NAME["INFO"] = "--nfui-info";
112
+ THEME_NAME["INFO_LIGHT"] = "--nfui-info-light";
113
+ THEME_NAME["SUCCESS"] = "--nfui-success";
114
+ THEME_NAME["SUCCESS_LIGHT"] = "--nfui-success-light";
115
+ THEME_NAME["WARNING"] = "--nfui-warning";
116
+ THEME_NAME["WARNING_LIGHT"] = "--nfui-warning-light";
117
+ THEME_NAME["ERROR"] = "--nfui-error";
118
+ THEME_NAME["ERROR_LIGHT"] = "--nfui-error-light";
119
+ THEME_NAME["BORDER_COLOR"] = "--nfui-border-color";
120
+ THEME_NAME["TOAST"] = "--nfui-toast";
121
+ THEME_NAME["TOOLTIP_COLOR"] = "--nfui-tooltip-color";
122
+ THEME_NAME["BORDER_LIGHT_COLOR"] = "--nfui-border-light-color";
123
+ THEME_NAME["BACKGROUND"] = "--nfui-background";
124
+ THEME_NAME["DISABLED_BACKGROUND"] = "--nfui-disabled-background";
125
+ THEME_NAME["DISABLED_BORDER"] = "--nfui-disabled-border";
126
+ THEME_NAME["LIGHT_GREY"] = "--nfui-light-grey";
127
+ THEME_NAME["DISABLED"] = "--nfui-disabled";
128
+ THEME_NAME["TEXT_COLOR_LIGHT"] = "--nfui-text-color-light";
129
+ THEME_NAME["TEXT_COLOR_DARK"] = "--nfui-text-color-dark";
130
+ THEME_NAME["SHADOW"] = "--nfui-shadow";
131
+ THEME_NAME["HOVER_SHADOW"] = "--nfui-hover-shadow";
132
+ THEME_NAME["MODAL_SHADOW"] = "--nfui-modal-shadow";
133
+ THEME_NAME["BACKDROP_COLOR"] = "--nfui-backdrop-color";
134
+ })(THEME_NAME || (THEME_NAME = {}));
135
+ const themeNameMap = {
136
+ [THEME_NAME.PRIMARY]: THEME_CONSTANTS.PRIMARY,
137
+ [THEME_NAME.PRIMARY_LIGHT]: THEME_CONSTANTS.PRIMARY_LIGHT,
138
+ [THEME_NAME.PRIMARY_LIGHTER]: THEME_CONSTANTS.PRIMARY_LIGHTER,
139
+ [THEME_NAME.INFO]: THEME_CONSTANTS.INFO,
140
+ [THEME_NAME.INFO_LIGHT]: THEME_CONSTANTS.INFO_LIGHT,
141
+ [THEME_NAME.SUCCESS]: THEME_CONSTANTS.SUCCESS,
142
+ [THEME_NAME.SUCCESS_LIGHT]: THEME_CONSTANTS.SUCCESS_LIGHT,
143
+ [THEME_NAME.WARNING]: THEME_CONSTANTS.WARNING,
144
+ [THEME_NAME.WARNING_LIGHT]: THEME_CONSTANTS.WARNING_LIGHT,
145
+ [THEME_NAME.ERROR]: THEME_CONSTANTS.ERROR,
146
+ [THEME_NAME.ERROR_LIGHT]: THEME_CONSTANTS.ERROR_LIGHT,
147
+ [THEME_NAME.BACKDROP_COLOR]: THEME_CONSTANTS.BACKDROP_COLOR,
148
+ [THEME_NAME.BORDER_COLOR]: THEME_CONSTANTS.BORDER_COLOR,
149
+ [THEME_NAME.TOAST]: THEME_CONSTANTS.TOAST,
150
+ [THEME_NAME.TOOLTIP_COLOR]: THEME_CONSTANTS.TOOLTIP_COLOR,
151
+ [THEME_NAME.BORDER_LIGHT_COLOR]: THEME_CONSTANTS.BORDER_LIGHT_COLOR,
152
+ [THEME_NAME.BACKGROUND]: THEME_CONSTANTS.BACKGROUND,
153
+ [THEME_NAME.DISABLED_BACKGROUND]: THEME_CONSTANTS.DISABLED_BACKGROUND,
154
+ [THEME_NAME.DISABLED_BORDER]: THEME_CONSTANTS.DISABLED_BORDER,
155
+ [THEME_NAME.LIGHT_GREY]: THEME_CONSTANTS.LIGHT_GREY,
156
+ [THEME_NAME.DISABLED]: THEME_CONSTANTS.DISABLED,
157
+ [THEME_NAME.TEXT_COLOR_LIGHT]: THEME_CONSTANTS.TEXT_COLOR_LIGHT,
158
+ [THEME_NAME.TEXT_COLOR_DARK]: THEME_CONSTANTS.TEXT_COLOR_DARK,
159
+ [THEME_NAME.SHADOW]: THEME_CONSTANTS.SHADOW,
160
+ [THEME_NAME.HOVER_SHADOW]: THEME_CONSTANTS.HOVER_SHADOW,
161
+ [THEME_NAME.MODAL_SHADOW]: THEME_CONSTANTS.MODAL_SHADOW,
162
+ };
163
+ const getThemeValue = (key) => {
164
+ return `var(${key}, ${themeNameMap[key]})`;
102
165
  };
103
166
 
104
167
  const Ellipsis = styled.span `
105
168
  white-space: nowrap;
106
169
  text-overflow: ellipsis;
107
170
  overflow: hidden;
171
+ flex: 1;
108
172
  `;
109
- const Header$1 = styled.div `
173
+ const Header$1 = styled.h1 `
110
174
  padding: 10px 15px;
111
175
  line-height: 26px;
112
- border-bottom: 1px solid var(--border-light-color, #eeeeee);
176
+ border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
113
177
  font-size: 16px;
114
178
  font-weight: bold;
115
179
  `;
@@ -120,7 +184,7 @@ const Body$1 = styled.div `
120
184
  `;
121
185
  const Footer$1 = styled.div `
122
186
  padding: 10px 15px;
123
- border-top: 1px solid var(--border-light-color, #eeeeee);
187
+ border-top: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
124
188
  display: flex;
125
189
  justify-content: flex-end;
126
190
  `;
@@ -137,18 +201,18 @@ const BadgeSpan = styled.span `
137
201
  background-color: ${(props) => {
138
202
  switch (props.type) {
139
203
  case exports.BADGE_TYPE.SUCCESS:
140
- return `var(--success, ${constants.SUCCESS})`;
204
+ return getThemeValue(THEME_NAME.SUCCESS);
141
205
  case exports.BADGE_TYPE.WARNING:
142
- return `var(--info, ${constants.WARNING})`;
206
+ return getThemeValue(THEME_NAME.WARNING);
143
207
  case exports.BADGE_TYPE.DANGER:
144
- return `var(--error, ${constants.ERROR})`;
208
+ return getThemeValue(THEME_NAME.ERROR);
145
209
  case exports.BADGE_TYPE.DISABLED:
146
- return `var(--disabled, ${constants.DISABLED})`;
210
+ return getThemeValue(THEME_NAME.DISABLED);
147
211
  default:
148
- return `var(--primary, ${constants.PRIMARY})`;
212
+ return getThemeValue(THEME_NAME.PRIMARY);
149
213
  }
150
214
  }};
151
- color: #fff;
215
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
152
216
  border-radius: 10px;
153
217
  padding: ${(props) => (props.children ? '3px 10px' : '4px')};
154
218
  display: inline-block;
@@ -182,10 +246,10 @@ Badge.defaultProps = {
182
246
 
183
247
  const Card = styled.div `
184
248
  border-radius: 10px;
185
- background-color: var(--background, ${constants.BACKGROUND});
249
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
186
250
  ${(props) => props.elevated
187
- ? `box-shadow: var(--modal-shadow, ${constants.MODAL_SHADOW});`
188
- : `box-shadow: var(--shadow, ${constants.SHADOW});`}
251
+ ? `box-shadow: ${getThemeValue(THEME_NAME.MODAL_SHADOW)};`
252
+ : `box-shadow: ${getThemeValue(THEME_NAME.SHADOW)};`}
189
253
  margin: 5px;
190
254
  overflow: auto;
191
255
  position: relative;
@@ -193,37 +257,33 @@ const Card = styled.div `
193
257
 
194
258
  const Step$1 = styled(Card) `
195
259
  transition: all 0.6s ease;
260
+ overflow: visible;
196
261
 
197
- ${(props) => props.open &&
198
- `
199
- margin: 20px 5px;
200
- `}
201
-
202
- ${(props) => props.focused && `box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});`}
262
+ ${(props) => props.open && `margin: 20px 5px;`}
203
263
  `;
204
- const StepHeader = styled.div `
264
+ const StepHeader = styled.button `
205
265
  padding: 20px 15px;
206
266
  display: flex;
207
267
  justify-content: space-between;
268
+ background: none;
269
+ border: none;
270
+ border-radius: 10px;
271
+ width: 100%;
272
+ font-size: inherit;
273
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
274
+
275
+ &:focus-visible {
276
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
277
+ }
208
278
 
209
279
  & input {
210
280
  appearance: none;
211
281
  margin: 0;
212
282
  }
213
283
 
214
- ${(props) => props.open
215
- ? `
216
- border-bottom: 1px solid var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
217
- `
218
- : ''}
284
+ ${(props) => props.open && `border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};`}
219
285
 
220
- ${(props) => props.disabled
221
- ? `
222
- color: ${constants.LIGHT_GREY};
223
- `
224
- : `
225
- cursor: pointer;
226
- `}
286
+ ${(props) => props.disabled && `color: ${getThemeValue(THEME_NAME.DISABLED)};`}
227
287
  `;
228
288
  const HeaderContainer = styled.div `
229
289
  display: flex;
@@ -234,10 +294,10 @@ const HeaderContainer = styled.div `
234
294
  vertical-align: top;
235
295
  margin-right: 10px;
236
296
  fill: ${(props) => props.open
237
- ? `var(--primary, ${constants.PRIMARY})`
297
+ ? getThemeValue(THEME_NAME.PRIMARY)
238
298
  : props.completed
239
- ? `var(--success, ${constants.SUCCESS})`
240
- : constants.LIGHT_GREY};
299
+ ? getThemeValue(THEME_NAME.SUCCESS)
300
+ : getThemeValue(THEME_NAME.LIGHT_GREY)};
241
301
  transform: ${(props) => (props.open ? 'scale(0.8)' : 'scale(0.6)')};
242
302
  transition: all 0.3s ease;
243
303
  min-width: 24px;
@@ -254,13 +314,7 @@ const ExpandContainer = styled.div `
254
314
  fill: currentColor;
255
315
  }
256
316
 
257
- ${(props) => props.open
258
- ? `
259
- & svg {
260
- transform: rotate(180deg);
261
- }
262
- `
263
- : ''}
317
+ ${(props) => (props.open ? `& svg { transform: rotate(180deg); }` : '')}
264
318
  `;
265
319
  const StepBody = styled.div `
266
320
  transition: all 0.6s ease;
@@ -274,19 +328,18 @@ const AccordionStepFooter = styled.div `
274
328
  display: flex;
275
329
  justify-content: flex-end;
276
330
  padding: 10px 15px;
277
- border-top: 1px solid var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
331
+ border-top: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
278
332
  `;
279
333
  function AccordionStep(props) {
280
334
  const [height, setHeight] = React.useState(0);
281
- const [focused, setFocused] = React.useState(false);
282
335
  const { open, disabled, header, errorText, completed, onStepClick } = props;
336
+ // Generate unique IDs for ARIA relationships
337
+ const headerId = React.useId();
338
+ const regionId = React.useId();
283
339
  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 `
340
+ 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
341
  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 })] })));
342
+ `, 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
343
  }
291
344
  AccordionStep.propTypes = {
292
345
  /** Header text for the step */
@@ -303,8 +356,8 @@ AccordionStep.defaultProps = {
303
356
  disabled: false,
304
357
  };
305
358
 
306
- var Button$2 = styled.button `
307
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
359
+ const StyledButton = styled.button `
360
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
308
361
  border-radius: 5px;
309
362
  height: 32px;
310
363
  min-width: 100px;
@@ -312,12 +365,13 @@ var Button$2 = styled.button `
312
365
  text-align: center;
313
366
  padding: 0 12px;
314
367
  cursor: pointer;
315
- color: inherit;
316
- background-color: var(--background, ${constants.BACKGROUND});
317
- text-overflow: ellipsis;
318
- white-space: nowrap;
368
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
369
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
319
370
  margin: 5px;
320
371
  position: relative;
372
+ display: inline-flex;
373
+ align-items: center;
374
+ justify-content: center;
321
375
 
322
376
  & svg {
323
377
  vertical-align: middle;
@@ -328,21 +382,24 @@ var Button$2 = styled.button `
328
382
  }
329
383
 
330
384
  &:enabled:hover {
331
- border-color: var(--primary, ${constants.PRIMARY});
332
- color: var(--primary, ${constants.PRIMARY});
385
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
386
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
333
387
  }
334
388
 
335
389
  &:focus {
336
- border-color: var(--primary, ${constants.PRIMARY});
337
- box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
390
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
391
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
338
392
  }
339
393
 
340
394
  &:disabled {
341
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
342
- border-color: var(--light-grey, ${constants.LIGHT_GREY});
343
- color: var(--disabled, ${constants.DISABLED});
395
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
396
+ border-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
397
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
344
398
  }
345
399
  `;
400
+ StyledButton.defaultProps = {
401
+ type: 'button',
402
+ };
346
403
 
347
404
  var LinkButton = styled.button `
348
405
  min-width: 100px;
@@ -352,12 +409,13 @@ var LinkButton = styled.button `
352
409
  cursor: pointer;
353
410
  background-color: transparent;
354
411
  border: none;
355
- color: var(--primary, ${constants.PRIMARY});
412
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
356
413
  padding: 0 12px;
357
- text-overflow: ellipsis;
358
- white-space: nowrap;
359
414
  margin: 5px;
360
415
  position: relative;
416
+ display: inline-flex;
417
+ align-items: center;
418
+ justify-content: center;
361
419
 
362
420
  & svg {
363
421
  vertical-align: middle;
@@ -373,28 +431,29 @@ var LinkButton = styled.button `
373
431
  }
374
432
 
375
433
  &:disabled {
376
- border-color: ${constants.BORDER_COLOR};
377
- color: ${constants.DISABLED_BORDER};
434
+ border-color: ${getThemeValue(THEME_NAME.BORDER_COLOR)};
435
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
378
436
  }
379
437
  `;
380
438
 
381
439
  var RaisedButton = styled.button `
382
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
440
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
383
441
  border-radius: 5px;
384
442
  height: 32px;
385
443
  min-width: 100px;
386
444
  font-size: 14px;
387
445
  text-align: center;
388
446
  padding: 0 12px;
389
- cursor: pointer;
447
+ cursor: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
390
448
  color: inherit;
391
- background-color: var(--background, ${constants.BACKGROUND});
449
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
392
450
  transform: translateY(-2px);
393
- box-shadow: var(--hover-shadow, ${constants.HOVER_SHADOW});
394
- text-overflow: ellipsis;
395
- white-space: nowrap;
451
+ box-shadow: ${getThemeValue(THEME_NAME.HOVER_SHADOW)};
396
452
  margin: 5px;
397
453
  position: relative;
454
+ display: inline-flex;
455
+ align-items: center;
456
+ justify-content: center;
398
457
 
399
458
  & svg {
400
459
  vertical-align: middle;
@@ -405,30 +464,30 @@ var RaisedButton = styled.button `
405
464
  }
406
465
 
407
466
  &:enabled:hover {
408
- border-color: var(--primary, ${constants.PRIMARY});
409
- color: var(--primary, ${constants.PRIMARY});
467
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
468
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
410
469
  }
411
470
 
412
471
  &:focus {
413
- border-color: var(--primary, ${constants.PRIMARY});
472
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
414
473
  }
415
474
 
416
475
  &:disabled {
417
- background-color: ${constants.BORDER_LIGHT_COLOR};
418
- border-color: ${constants.LIGHT_GREY};
419
- color: ${constants.DISABLED};
476
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
477
+ border-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
478
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
420
479
  }
421
480
 
422
481
  &:active {
423
482
  transform: translateY(0);
424
- box-shadow: var(--shadow, ${constants.SHADOW});
483
+ box-shadow: ${getThemeValue(THEME_NAME.SHADOW)};
425
484
  }
426
485
  `;
427
486
 
428
487
  var ActionButton = styled.button `
429
- border: 1px solid var(--primary, ${constants.PRIMARY});
430
- background-color: var(--primary, ${constants.PRIMARY});
431
- color: #fff;
488
+ border: 1px solid ${getThemeValue(THEME_NAME.PRIMARY)};
489
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY)};
490
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
432
491
  border-radius: 5px;
433
492
  height: 32px;
434
493
  min-width: 100px;
@@ -436,10 +495,11 @@ var ActionButton = styled.button `
436
495
  text-align: center;
437
496
  padding: 0 12px;
438
497
  cursor: pointer;
439
- text-overflow: ellipsis;
440
- white-space: nowrap;
441
498
  margin: 5px;
442
499
  position: relative;
500
+ display: inline-flex;
501
+ align-items: center;
502
+ justify-content: center;
443
503
 
444
504
  & svg {
445
505
  vertical-align: middle;
@@ -450,34 +510,35 @@ var ActionButton = styled.button `
450
510
  }
451
511
 
452
512
  &:enabled:hover {
453
- box-shadow: var(--hover-shadow, ${constants.HOVER_SHADOW});
513
+ box-shadow: ${getThemeValue(THEME_NAME.HOVER_SHADOW)};
454
514
  }
455
515
 
456
516
  &:focus {
457
- box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
517
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
458
518
  }
459
519
 
460
520
  &:disabled {
461
- border: 1px solid ${constants.LIGHT_GREY};
462
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
463
- color: var(--disabled, ${constants.DISABLED});
521
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
522
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
523
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
464
524
  }
465
525
  `;
466
526
 
467
527
  var IconButton = styled.button `
468
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
528
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
469
529
  border-radius: 5px;
470
530
  height: 32px;
471
531
  font-size: 14px;
472
532
  text-align: center;
473
533
  padding: 0 3px;
474
534
  cursor: pointer;
475
- color: inherit;
476
- background-color: var(--background, ${constants.BACKGROUND});
477
- text-overflow: ellipsis;
478
- white-space: nowrap;
535
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
536
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
479
537
  margin: 5px;
480
538
  position: relative;
539
+ display: inline-flex;
540
+ align-items: center;
541
+ justify-content: center;
481
542
 
482
543
  & svg {
483
544
  vertical-align: middle;
@@ -487,23 +548,23 @@ var IconButton = styled.button `
487
548
  }
488
549
 
489
550
  &:enabled:hover {
490
- border-color: var(--primary, ${constants.PRIMARY});
491
- color: var(--primary, ${constants.PRIMARY});
551
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
552
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
492
553
  }
493
554
 
494
555
  &:focus {
495
- border-color: var(--primary, ${constants.PRIMARY});
496
- box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
556
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
557
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
497
558
  }
498
559
 
499
560
  &:disabled {
500
- background-color: ${constants.BORDER_LIGHT_COLOR};
501
- border-color: ${constants.LIGHT_GREY};
502
- color: ${constants.DISABLED};
561
+ background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
562
+ border-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
563
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
503
564
  }
504
565
 
505
566
  &:disabled > svg {
506
- fill: ${constants.DISABLED};
567
+ fill: ${getThemeValue(THEME_NAME.DISABLED)};
507
568
  }
508
569
  `;
509
570
 
@@ -536,42 +597,58 @@ function __rest(s, e) {
536
597
  return t;
537
598
  }
538
599
 
600
+ function __awaiter(thisArg, _arguments, P, generator) {
601
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
602
+ return new (P || (P = Promise))(function (resolve, reject) {
603
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
604
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
605
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
606
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
607
+ });
608
+ }
609
+
539
610
  typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
540
611
  var e = new Error(message);
541
612
  return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
542
613
  };
543
614
 
544
- const Container$8 = styled.div `
615
+ const Container$8 = styled.span `
545
616
  padding: 5px;
546
617
  padding-left: 15px;
547
618
  border-radius: 16px;
548
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
619
+ background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
549
620
  display: inline-flex;
550
621
  margin: 5px;
551
622
  line-height: 20px;
552
623
  align-items: center;
553
-
554
- &:focus-within {
555
- outline: 2px solid var(--primary-light, ${constants.PRIMARY_LIGHT});
556
- }
557
624
  `;
558
625
  const Button$1 = styled.button `
559
- color: #fff;
560
- background-color: var(--disabled-border, ${constants.DISABLED_BORDER});
626
+ color: ${getThemeValue(THEME_NAME.BACKGROUND)};
627
+ background-color: ${getThemeValue(THEME_NAME.DISABLED)};
561
628
  border-radius: 50%;
562
629
  border: none;
563
- padding: 0;
630
+ padding: 4px;
564
631
  display: inline-flex;
565
632
  margin-left: 5px;
633
+
634
+ &:focus-within {
635
+ outline: 4px solid ${getThemeValue(THEME_NAME.ERROR_LIGHT)};
636
+ }
566
637
  `;
567
638
  function Chip(props) {
568
- const { label, onCloseClick } = props, rest = __rest(props, ["label", "onCloseClick"]);
639
+ const { label, onCloseClick, closeButtonAriaLabel } = props, rest = __rest(props, ["label", "onCloseClick", "closeButtonAriaLabel"]);
569
640
  const keyUpHandler = (e) => {
570
- if (e.keyCode === 8 || e.keyCode === 46) {
571
- onCloseClick === null || onCloseClick === void 0 ? void 0 : onCloseClick();
641
+ if (e.key === 'Backspace' || e.key === 'Delete') {
642
+ onCloseClick === null || onCloseClick === void 0 ? void 0 : onCloseClick(e);
572
643
  }
573
644
  };
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 }) })] })));
645
+ const buttonKeyDownHandler = (e) => {
646
+ // Stop propagation to prevent DragAndDrop from capturing Space/Enter
647
+ if (e.key === ' ' || e.key === 'Spacebar' || e.key === 'Enter') {
648
+ e.stopPropagation();
649
+ }
650
+ };
651
+ 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
652
  }
576
653
 
577
654
  exports.ORIENTATION = void 0;
@@ -586,30 +663,43 @@ const Item = styled.div `
586
663
  cursor: ${(props) => (props.showIndicator ? 'default' : 'move')};
587
664
  display: flex;
588
665
  user-select: ${(props) => (props.showIndicator ? 'auto' : 'none')};
589
- border-top: 2px solid
666
+ border-top: 2px dashed
590
667
  ${(props) => props.orientation === exports.ORIENTATION.VERTICAL && props.active > 0
591
- ? constants.PRIMARY
668
+ ? getThemeValue(THEME_NAME.PRIMARY)
592
669
  : 'transparent'};
593
- border-bottom: 2px solid
670
+ border-bottom: 2px dashed
594
671
  ${(props) => props.orientation === exports.ORIENTATION.VERTICAL && props.active < 0
595
- ? constants.PRIMARY
672
+ ? getThemeValue(THEME_NAME.PRIMARY)
596
673
  : 'transparent'};
597
- border-left: 2px solid
674
+ border-left: 2px dashed
598
675
  ${(props) => props.orientation === exports.ORIENTATION.HORIZONTAL && props.active > 0
599
- ? constants.PRIMARY
676
+ ? getThemeValue(THEME_NAME.PRIMARY)
600
677
  : 'transparent'};
601
- border-right: 2px solid
678
+ border-right: 2px dashed
602
679
  ${(props) => props.orientation === exports.ORIENTATION.HORIZONTAL && props.active < 0
603
- ? constants.PRIMARY
680
+ ? getThemeValue(THEME_NAME.PRIMARY)
604
681
  : 'transparent'};
605
682
  opacity: ${(props) => (props.dragging ? 0.5 : 1)};
683
+ border-radius: 10px;
684
+
685
+ &:focus {
686
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
687
+ }
688
+
689
+ &:focus:not(:focus-visible) {
690
+ box-shadow: none;
691
+ }
692
+
693
+ &:focus-visible {
694
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
695
+ }
606
696
  `;
607
697
  /** Styled component for the drag handle indicator */
608
698
  const DragKnob = styled.div `
609
699
  padding-top: 8px;
610
700
  cursor: move;
611
701
  touch-action: none;
612
- color: var(--disabled, ${constants.DISABLED});
702
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
613
703
  `;
614
704
  /** Container for the children */
615
705
  const Container$7 = styled.div `
@@ -648,7 +738,7 @@ const Container$7 = styled.div `
648
738
  * @returns A draggable item with optional drag indicator and visual feedback
649
739
  */
650
740
  function DragItem(props) {
651
- const { index, orientation, children, showIndicator, dragOver } = props;
741
+ const { index, orientation, children, showIndicator, dragOver, totalItems, setAnnouncement } = props;
652
742
  const [active, setActive] = React.useState(0);
653
743
  const [touchTimer, setTouchTimer] = React.useState(null);
654
744
  const context = React.useContext(DragContext);
@@ -750,6 +840,71 @@ function DragItem(props) {
750
840
  document.body.style.overflow = 'auto';
751
841
  }
752
842
  };
843
+ /**
844
+ * Keyboard navigation handler for reordering items
845
+ * @param e Keyboard event
846
+ */
847
+ const handleKeyDown = (e) => {
848
+ const isVertical = orientation === exports.ORIENTATION.VERTICAL;
849
+ const moveUp = isVertical ? 'ArrowUp' : 'ArrowLeft';
850
+ const moveDown = isVertical ? 'ArrowDown' : 'ArrowRight';
851
+ const isGrabbed = context.isDragging && context.startIndex === index;
852
+ // Space to grab/drop
853
+ if (e.key === ' ' || e.key === 'Spacebar') {
854
+ e.preventDefault();
855
+ if (isGrabbed) {
856
+ // Drop at current position
857
+ context.drop(index);
858
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.droppedAnnouncementTemplate, {
859
+ position: index + 1,
860
+ }));
861
+ }
862
+ else {
863
+ // Grab item
864
+ context.startGrab(index);
865
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.grabbedAnnouncementTemplate, {
866
+ position: index + 1,
867
+ }));
868
+ }
869
+ }
870
+ // Enter to drop
871
+ else if (e.key === 'Enter' && isGrabbed) {
872
+ e.preventDefault();
873
+ context.drop(index);
874
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.droppedAnnouncementTemplate, {
875
+ position: index + 1,
876
+ }));
877
+ }
878
+ // Escape to cancel
879
+ else if (e.key === 'Escape' && isGrabbed) {
880
+ e.preventDefault();
881
+ context.cancel();
882
+ setAnnouncement(context.i18n.cancelledAnnouncementTemplate);
883
+ }
884
+ // Arrow keys to move while grabbed
885
+ else if (isGrabbed) {
886
+ if (e.key === moveUp && index > 0) {
887
+ e.preventDefault();
888
+ // Move without dropping - just reorder and update startIndex
889
+ const newIndex = index - 1;
890
+ context.onDrop(context.startIndex, newIndex);
891
+ context.setStartIndex(newIndex);
892
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.movedAnnouncementTemplate, {
893
+ position: newIndex + 1,
894
+ }));
895
+ }
896
+ else if (e.key === moveDown && index < totalItems - 1) {
897
+ e.preventDefault();
898
+ // Move without dropping - just reorder and update startIndex
899
+ const newIndex = index + 1;
900
+ context.onDrop(context.startIndex, newIndex);
901
+ context.setStartIndex(newIndex);
902
+ setAnnouncement(context.i18n.replacePlaceholders(context.i18n.movedAnnouncementTemplate, {
903
+ position: newIndex + 1,
904
+ }));
905
+ }
906
+ }
907
+ };
753
908
  /** Cleanup touch timer on unmount */
754
909
  React.useEffect(() => {
755
910
  return () => {
@@ -767,7 +922,9 @@ function DragItem(props) {
767
922
  setActive(0);
768
923
  }
769
924
  }, [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 })] }));
925
+ 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, {
926
+ position: index + 1,
927
+ }), "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
928
  }
772
929
 
773
930
  /** Container Component */
@@ -778,6 +935,18 @@ const Container$6 = styled.div `
778
935
  flex-wrap: wrap;
779
936
  flex-direction: ${(props) => (props.orientation === exports.ORIENTATION.HORIZONTAL ? 'row' : 'column')};
780
937
  `;
938
+ /** Visually hidden but accessible to screen readers */
939
+ const VisuallyHidden$2 = styled.div `
940
+ position: absolute;
941
+ width: 1px;
942
+ height: 1px;
943
+ padding: 0;
944
+ margin: -1px;
945
+ overflow: hidden;
946
+ clip: rect(0, 0, 0, 0);
947
+ white-space: nowrap;
948
+ border-width: 0;
949
+ `;
781
950
  /**
782
951
  * A drag and drop container component that enables reordering of child elements.
783
952
  *
@@ -804,10 +973,37 @@ const Container$6 = styled.div `
804
973
  * @returns {JSX.Element} A draggable container with reorderable items
805
974
  */
806
975
  function DragAndDrop(props) {
807
- const { orientation, children, onDrop, showIndicator } = props;
976
+ const { orientation, children, onDrop, showIndicator, itemAriaLabelTemplate, dragHandleAriaLabel, grabbedAnnouncementTemplate, movedAnnouncementTemplate, droppedAnnouncementTemplate, cancelledAnnouncementTemplate, } = props;
808
977
  const [startIndex, setStartIndex] = React.useState(null);
978
+ const [originalIndex, setOriginalIndex] = React.useState(null);
809
979
  const [isDragging, setIsDragging] = React.useState(false);
810
980
  const [dragOver, setDragOver] = React.useState(null);
981
+ const [announcement, setAnnouncement] = React.useState('');
982
+ const childrenArray = React.Children.toArray(children);
983
+ const totalItems = childrenArray.length;
984
+ /**
985
+ * Replace placeholders in i18n templates
986
+ */
987
+ const replacePlaceholders = (template, data) => {
988
+ var _a, _b, _c, _d, _e, _f;
989
+ return template
990
+ .replace(/\{:position\}/g, String((_a = data.position) !== null && _a !== void 0 ? _a : ''))
991
+ .replace(/\{:grabKey\}/g, (_b = data.grabKey) !== null && _b !== void 0 ? _b : 'Space')
992
+ .replace(/\{:dropKey\}/g, (_c = data.dropKey) !== null && _c !== void 0 ? _c : 'Space')
993
+ .replace(/\{:altDropKey\}/g, (_d = data.altDropKey) !== null && _d !== void 0 ? _d : 'Enter')
994
+ .replace(/\{:cancelKey\}/g, (_e = data.cancelKey) !== null && _e !== void 0 ? _e : 'Escape')
995
+ .replace(/\{:moveKeys\}/g, (_f = data.moveKeys) !== null && _f !== void 0 ? _f : (orientation === exports.ORIENTATION.VERTICAL ? 'Arrow Up/Down' : 'Arrow Left/Right'));
996
+ };
997
+ // i18n configuration object
998
+ const i18n = {
999
+ itemAriaLabelTemplate: itemAriaLabelTemplate,
1000
+ dragHandleAriaLabel: dragHandleAriaLabel,
1001
+ grabbedAnnouncementTemplate: grabbedAnnouncementTemplate,
1002
+ movedAnnouncementTemplate: movedAnnouncementTemplate,
1003
+ droppedAnnouncementTemplate: droppedAnnouncementTemplate,
1004
+ cancelledAnnouncementTemplate: cancelledAnnouncementTemplate,
1005
+ replacePlaceholders,
1006
+ };
811
1007
  /**
812
1008
  * Drop handler invoked when a draggable item is released.
813
1009
  * @param index
@@ -817,15 +1013,58 @@ function DragAndDrop(props) {
817
1013
  onDrop === null || onDrop === void 0 ? void 0 : onDrop(startIndex, index);
818
1014
  }
819
1015
  setStartIndex(null);
1016
+ setOriginalIndex(null);
1017
+ setIsDragging(false);
1018
+ };
1019
+ /**
1020
+ * Cancel handler to restore item to original position
1021
+ */
1022
+ const cancel = () => {
1023
+ if (originalIndex !== null && startIndex !== null && startIndex !== originalIndex) {
1024
+ onDrop === null || onDrop === void 0 ? void 0 : onDrop(startIndex, originalIndex);
1025
+ }
1026
+ setStartIndex(null);
1027
+ setOriginalIndex(null);
820
1028
  setIsDragging(false);
821
1029
  };
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 }))) }) }));
1030
+ /**
1031
+ * Start grab handler to track original position
1032
+ */
1033
+ const startGrab = (index) => {
1034
+ setStartIndex(index);
1035
+ setOriginalIndex(index);
1036
+ setIsDragging(true);
1037
+ };
1038
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(DragContext.Provider, { value: {
1039
+ startIndex,
1040
+ setStartIndex,
1041
+ drop,
1042
+ onDrop,
1043
+ cancel,
1044
+ startGrab,
1045
+ isDragging,
1046
+ setIsDragging,
1047
+ setDragOver,
1048
+ i18n,
1049
+ }, 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$2, { role: "status", "aria-live": "polite", "aria-atomic": "true", children: announcement })] }));
823
1050
  }
824
1051
  DragAndDrop.defaultProps = {
825
1052
  /** Orientation of the list layout */
826
1053
  orientation: exports.ORIENTATION.VERTICAL,
827
1054
  /** Whether to display drag indicators for each list item */
828
1055
  showIndicator: false,
1056
+ /** Default item aria-label template */
1057
+ itemAriaLabelTemplate: 'Item {:position}. Press {:grabKey} to grab, {:moveKeys} to move, {:dropKey} or {:altDropKey} to drop',
1058
+ /** Default drag handle aria-label */
1059
+ dragHandleAriaLabel: 'Drag to reorder',
1060
+ /** Default grabbed announcement template */
1061
+ grabbedAnnouncementTemplate: 'Item {:position} grabbed. Use {:moveKeys} to move, {:dropKey} or {:altDropKey} to drop, {:cancelKey} to cancel',
1062
+ /** Default moved announcement template */
1063
+ movedAnnouncementTemplate: 'Item moved to position {:position}',
1064
+ /** Default dropped announcement template */
1065
+ droppedAnnouncementTemplate: 'Item dropped at position {:position}',
1066
+ /** Default cancelled announcement template */
1067
+ cancelledAnnouncementTemplate: 'Drag cancelled, item restored to original position',
829
1068
  };
830
1069
 
831
1070
  // Label component for the ChipInput
@@ -839,45 +1078,45 @@ const Label$6 = styled.label `
839
1078
  padding: 0 8px;
840
1079
  width: 250px;
841
1080
  border-radius: 3px;
842
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
843
- background-color: var(--background, ${constants.BACKGROUND});
1081
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
1082
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
844
1083
 
845
1084
  /** Focused */
846
1085
  &:has(:focus),
847
1086
  &:has(:active) {
848
- border-color: var(--primary, ${constants.PRIMARY});
849
- box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
1087
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
1088
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
850
1089
  }
851
1090
 
852
1091
  &:has(:focus) > span,
853
1092
  &:has(:active) > span {
854
- color: var(--primary, ${constants.PRIMARY});
1093
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
855
1094
  }
856
1095
 
857
1096
  /** Disabled */
858
1097
  &:has(:disabled) {
859
- border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
860
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
1098
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
1099
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
861
1100
  }
862
1101
 
863
1102
  &:has(:disabled) > span {
864
- color: #777;
1103
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
865
1104
  }
866
1105
 
867
1106
  /** Invalid */
868
1107
  &:has(:focus:invalid) {
869
- border-color: var(--error, ${constants.ERROR});
870
- box-shadow: 0 0 0 4px var(--error-light, ${constants.ERROR_LIGHT});
1108
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1109
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.ERROR_LIGHT)};
871
1110
  }
872
1111
 
873
1112
  ${(props) => props.touched
874
1113
  ? `
875
1114
  &:has(:invalid) {
876
- border-color: var(--error, ${constants.ERROR});
1115
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
877
1116
  }
878
1117
 
879
1118
  &:has(:invalid) > span {
880
- color: var(--error, ${constants.ERROR});
1119
+ color: ${getThemeValue(THEME_NAME.ERROR)};
881
1120
  }
882
1121
  `
883
1122
  : ''}
@@ -885,10 +1124,10 @@ const Label$6 = styled.label `
885
1124
  /** Error */
886
1125
  ${(props) => props.errorText
887
1126
  ? `
888
- border-color: var(--error, ${constants.ERROR});
1127
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
889
1128
 
890
1129
  & > span {
891
- color: var(--error, ${constants.ERROR});
1130
+ color: ${getThemeValue(THEME_NAME.ERROR)};
892
1131
  }
893
1132
  `
894
1133
  : ''}
@@ -897,15 +1136,15 @@ const Label$6 = styled.label `
897
1136
  &:has(:required) > span:after {
898
1137
  content: '*';
899
1138
  margin-left: 2px;
900
- color: var(--error, ${constants.ERROR});
1139
+ color: ${getThemeValue(THEME_NAME.ERROR)};
901
1140
  }
902
1141
 
903
1142
  & > input {
904
1143
  border: none;
905
1144
  outline: none;
906
- width: 100%;
907
1145
  line-height: 30px;
908
1146
  min-height: 30px;
1147
+ max-width: 95%;
909
1148
  }
910
1149
 
911
1150
  /** Label Animation */
@@ -922,7 +1161,7 @@ const Label$6 = styled.label `
922
1161
  &:has(:focus) > span,
923
1162
  &:has(:placeholder-shown) > span {
924
1163
  top: -8px;
925
- background: var(--background, ${constants.BACKGROUND});
1164
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
926
1165
  font-size: 12px;
927
1166
  line-height: 14px;
928
1167
  }
@@ -931,7 +1170,7 @@ const Label$6 = styled.label `
931
1170
  ? `
932
1171
  & > span {
933
1172
  top: -8px;
934
- background: var(--background, ${constants.BACKGROUND});
1173
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
935
1174
  font-size: 12px;
936
1175
  line-height: 14px;
937
1176
  }
@@ -940,12 +1179,28 @@ const Label$6 = styled.label `
940
1179
  `;
941
1180
  // Error message container
942
1181
  const ErrorContainer$4 = styled.div `
943
- color: var(--error, ${constants.ERROR});
1182
+ color: ${getThemeValue(THEME_NAME.ERROR)};
944
1183
  padding-top: 3px;
945
1184
  font-size: 12px;
946
1185
  line-height: 14px;
947
1186
  margin-left: 3px;
948
1187
  `;
1188
+ // Visually hidden but accessible to screen readers
1189
+ const VisuallyHidden$1 = styled.ul `
1190
+ position: absolute;
1191
+ width: 1px;
1192
+ height: 1px;
1193
+ padding: 0;
1194
+ margin: -1px;
1195
+ overflow: hidden;
1196
+ clip: rect(0, 0, 0, 0);
1197
+ white-space: nowrap;
1198
+ border-width: 0;
1199
+
1200
+ & li {
1201
+ list-style: none;
1202
+ }
1203
+ `;
949
1204
  /**
950
1205
  * A chip input component that allows users to add and remove chips (tags) by typing and pressing Enter.
951
1206
  * @component
@@ -964,9 +1219,21 @@ function ChipInput(props) {
964
1219
  const [touched, setTouched] = React.useState(false);
965
1220
  const [value, setValue] = React.useState(props.value);
966
1221
  const InputRef = React.useRef(null);
1222
+ const [announcement, setAnnouncement] = React.useState('');
1223
+ const errorId = React.useId();
1224
+ /**
1225
+ * Replace {:label} placeholder in template string
1226
+ */
1227
+ const replacePlaceholder = (template, label) => {
1228
+ if (!template)
1229
+ return undefined;
1230
+ return template.replace(/\{:label\}/g, label);
1231
+ };
967
1232
  // Sync internal value with props.value
968
1233
  React.useEffect(() => {
969
- setValue(props.value);
1234
+ if (Array.isArray(props.value)) {
1235
+ setValue(props.value);
1236
+ }
970
1237
  }, [props.value]);
971
1238
  /**
972
1239
  * Update the chip values and notify changes.
@@ -1004,6 +1271,7 @@ function ChipInput(props) {
1004
1271
  const newValue = [...value, text.trim()];
1005
1272
  updateValue(newValue);
1006
1273
  setText('');
1274
+ setAnnouncement(replacePlaceholder(props.addedAnnouncementTemplate, text.trim()));
1007
1275
  }
1008
1276
  };
1009
1277
  /**
@@ -1013,6 +1281,7 @@ function ChipInput(props) {
1013
1281
  const removeChip = (chipToRemove) => {
1014
1282
  const newValue = value.filter((chip) => chip !== chipToRemove);
1015
1283
  updateValue(newValue);
1284
+ setAnnouncement(replacePlaceholder(props.removedAnnouncementTemplate, chipToRemove));
1016
1285
  };
1017
1286
  /**
1018
1287
  * Moves a chip from one position to another.
@@ -1030,7 +1299,7 @@ function ChipInput(props) {
1030
1299
  updateValue(newItems);
1031
1300
  };
1032
1301
  // 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 })] }));
1302
+ 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$1, { "aria-live": "polite", "aria-atomic": "true", children: announcement })] }));
1034
1303
  }
1035
1304
  ChipInput.propTypes = {
1036
1305
  /** Label for the field */
@@ -1041,9 +1310,18 @@ ChipInput.propTypes = {
1041
1310
  value: PropTypes.arrayOf(PropTypes.string),
1042
1311
  /** Callback when chips change */
1043
1312
  onChange: PropTypes.func,
1313
+ /** Aria label for the close button on chip. Defaults to "Remove {label}" */
1314
+ closeButtonAriaLabel: PropTypes.string,
1315
+ /** Announcement text when a chip is added. Defaults to "{label} was added" */
1316
+ addedAnnouncementTemplate: PropTypes.string,
1317
+ /** Announcement text when a chip is removed. Defaults to "{label} was removed" */
1318
+ removedAnnouncementTemplate: PropTypes.string,
1044
1319
  };
1045
1320
  ChipInput.defaultProps = {
1046
1321
  value: [],
1322
+ closeButtonAriaLabel: 'Remove {:label}',
1323
+ addedAnnouncementTemplate: '{:label} was added',
1324
+ removedAnnouncementTemplate: '{:label} was removed',
1047
1325
  };
1048
1326
 
1049
1327
  /** Enums for layer position on screen. */
@@ -1088,7 +1366,7 @@ const Container$5 = styled.div `
1088
1366
  `
1089
1367
  width: 100%;
1090
1368
  height: 100vh;
1091
- background-color: var(--backdrop-color, #2681da80);
1369
+ background-color: ${getThemeValue(THEME_NAME.BACKDROP_COLOR)};
1092
1370
  backdrop-filter: blur(0px);
1093
1371
  pointer-events: all;
1094
1372
  `}
@@ -1188,6 +1466,7 @@ class LayerManager {
1188
1466
  const layerConfig = Object.assign(Object.assign({}, defaultConfig), config);
1189
1467
  // Get the z-index for the new layer
1190
1468
  const currentIndex = layerConfig.alwaysOnTop ? 2147483647 : this.nextIndex++;
1469
+ const className = layerConfig.alwaysOnTop ? 'nf-layer-manager-top' : 'nf-layer-manager';
1191
1470
  // Create a unique ID for tracking this layer
1192
1471
  const layerId = `nf-layer-manager-${currentIndex}`;
1193
1472
  const overlayClickHandler = () => {
@@ -1209,6 +1488,7 @@ class LayerManager {
1209
1488
  React.useEffect(() => {
1210
1489
  // Create the div element only once when component mounts
1211
1490
  const div = document.createElement('div');
1491
+ div.setAttribute('class', className);
1212
1492
  div.setAttribute('id', layerId);
1213
1493
  document.body.appendChild(div);
1214
1494
  // Add layer to stack
@@ -1223,8 +1503,67 @@ class LayerManager {
1223
1503
  setTimeout(() => {
1224
1504
  div.setAttribute('class', 'nf-layer-enter');
1225
1505
  }, 10);
1506
+ // Track elements modified for accessibility
1507
+ const modifiedElements = [];
1508
+ let originalBodyOverflow = null;
1509
+ let originalBodyPosition = null;
1510
+ let originalBodyWidth = null;
1511
+ let originalBodyTop = null;
1512
+ let scrollY = 0;
1513
+ // Apply aria-hidden to siblings and body scroll lock for overlay modals
1514
+ if (layerConfig.overlay) {
1515
+ // Hide all body children except this layer portal, scripts, and styles
1516
+ const bodyChildren = Array.from(document.body.children);
1517
+ bodyChildren.forEach((child) => {
1518
+ if (child !== div &&
1519
+ child.className !== 'nf-layer-manager-top' &&
1520
+ child.tagName !== 'SCRIPT' &&
1521
+ child.tagName !== 'STYLE') {
1522
+ const hadAriaHidden = child.hasAttribute('aria-hidden');
1523
+ const previousValue = child.getAttribute('aria-hidden');
1524
+ // Only set aria-hidden if not already hidden
1525
+ if (previousValue !== 'true') {
1526
+ child.setAttribute('aria-hidden', 'true');
1527
+ modifiedElements.push({
1528
+ element: child,
1529
+ hadAriaHidden,
1530
+ previousValue,
1531
+ });
1532
+ }
1533
+ }
1534
+ });
1535
+ // Prevent body scroll on iOS
1536
+ scrollY = window.scrollY;
1537
+ originalBodyOverflow = document.body.style.overflow;
1538
+ originalBodyPosition = document.body.style.position;
1539
+ originalBodyWidth = document.body.style.width;
1540
+ originalBodyTop = document.body.style.top;
1541
+ document.body.style.overflow = 'hidden';
1542
+ document.body.style.position = 'fixed';
1543
+ document.body.style.width = '100%';
1544
+ document.body.style.top = `-${scrollY}px`;
1545
+ }
1226
1546
  // Cleanup function - remove div when component unmounts
1227
1547
  return () => {
1548
+ // Restore aria-hidden attributes
1549
+ modifiedElements.forEach(({ element, hadAriaHidden, previousValue }) => {
1550
+ if (document.body.contains(element)) {
1551
+ if (hadAriaHidden && previousValue !== null) {
1552
+ element.setAttribute('aria-hidden', previousValue);
1553
+ }
1554
+ else {
1555
+ element.removeAttribute('aria-hidden');
1556
+ }
1557
+ }
1558
+ });
1559
+ // Restore body scroll
1560
+ if (layerConfig.overlay) {
1561
+ document.body.style.overflow = originalBodyOverflow || '';
1562
+ document.body.style.position = originalBodyPosition || '';
1563
+ document.body.style.width = originalBodyWidth || '';
1564
+ document.body.style.top = originalBodyTop || '';
1565
+ window.scrollTo(0, scrollY);
1566
+ }
1228
1567
  if (document.body.contains(div)) {
1229
1568
  document.body.removeChild(div);
1230
1569
  }
@@ -1278,12 +1617,94 @@ const DialogContainer = styled(Card) `
1278
1617
  class Dialog extends React.Component {
1279
1618
  constructor() {
1280
1619
  super(...arguments);
1620
+ this.lastFocusedElement = null;
1621
+ this.dialogRef = React.createRef();
1281
1622
  this.state = {
1282
1623
  show: false,
1283
1624
  LayerComponent: undefined,
1284
1625
  };
1626
+ /**
1627
+ * Retrieves all focusable elements within the dialog.
1628
+ */
1629
+ this.getFocusableElements = () => {
1630
+ if (!this.dialogRef.current)
1631
+ return [];
1632
+ return Array.from(this.dialogRef.current.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'));
1633
+ };
1634
+ /**
1635
+ * Handles keydown events to implement the focus trap.
1636
+ * Traps Tab and Shift+Tab within the dialog.
1637
+ */
1638
+ this.handleKeyDown = (e) => {
1639
+ if (e.key === 'Tab') {
1640
+ const focusableElements = this.getFocusableElements();
1641
+ if (focusableElements.length === 0)
1642
+ return;
1643
+ const firstElement = focusableElements[0];
1644
+ const lastElement = focusableElements[focusableElements.length - 1];
1645
+ if (e.shiftKey) {
1646
+ if (document.activeElement === firstElement) {
1647
+ lastElement.focus();
1648
+ e.preventDefault();
1649
+ }
1650
+ }
1651
+ else {
1652
+ if (document.activeElement === lastElement) {
1653
+ firstElement.focus();
1654
+ e.preventDefault();
1655
+ }
1656
+ }
1657
+ }
1658
+ };
1659
+ /**
1660
+ * Restores focus to the element that was focused before the dialog opened.
1661
+ */
1662
+ this.restoreFocus = () => {
1663
+ if (this.lastFocusedElement) {
1664
+ const elementToBeFocused = this.lastFocusedElement;
1665
+ this.lastFocusedElement = null;
1666
+ setTimeout(() => {
1667
+ if (document.body.contains(elementToBeFocused)) {
1668
+ elementToBeFocused.focus();
1669
+ }
1670
+ }, 100);
1671
+ }
1672
+ };
1673
+ /**
1674
+ * Callback ref to capture the Dialog DOM element.
1675
+ * Triggers initial focus setting when the element mounts.
1676
+ */
1677
+ this.setDialogRef = (node) => {
1678
+ this.dialogRef.current = node;
1679
+ if (node) {
1680
+ this.setInitialFocus(node);
1681
+ }
1682
+ };
1683
+ /**
1684
+ * Sets initial focus within the dialog.
1685
+ * Tries to focus the header first, then the first interactive element, or falls back to the container.
1686
+ */
1687
+ this.setInitialFocus = (root) => {
1688
+ const firstChild = root.firstElementChild;
1689
+ if (firstChild) {
1690
+ if (firstChild.getAttribute('tabindex') === null) {
1691
+ firstChild.setAttribute('tabindex', '-1');
1692
+ }
1693
+ firstChild.focus();
1694
+ return;
1695
+ }
1696
+ const focusableElements = this.getFocusableElements();
1697
+ if (focusableElements.length > 0) {
1698
+ focusableElements[0].focus();
1699
+ }
1700
+ else {
1701
+ root.focus();
1702
+ }
1703
+ };
1285
1704
  this.open = (closeCallback) => {
1286
1705
  const _a = this.props, { closeOnEsc, closeOnOverlayClick, children } = _a, rest = __rest(_a, ["closeOnEsc", "closeOnOverlayClick", "children"]);
1706
+ // Save current focus
1707
+ this.lastFocusedElement = document.activeElement;
1287
1708
  const [Component, closeFn] = LayerManager$1.renderLayer({
1288
1709
  exitDelay: 300,
1289
1710
  overlay: true,
@@ -1291,7 +1712,7 @@ class Dialog extends React.Component {
1291
1712
  closeCallback: this.closeCallback,
1292
1713
  closeOnOverlayClick,
1293
1714
  position: LAYER_POSITION.DIALOG,
1294
- component: (jsxRuntime.jsx(DialogContainer, Object.assign({}, rest, { onClick: (e) => e.stopPropagation(), elevated: true, children: children }))),
1715
+ component: (jsxRuntime.jsx(DialogContainer, Object.assign({}, rest, { ref: this.setDialogRef, role: "dialog", "aria-modal": "true", tabIndex: -1, onKeyDown: this.handleKeyDown, onClick: (e) => e.stopPropagation(), elevated: true, children: children }))),
1295
1716
  });
1296
1717
  this.closeDialog = closeFn;
1297
1718
  this.setState({
@@ -1306,6 +1727,7 @@ class Dialog extends React.Component {
1306
1727
  };
1307
1728
  this.closeCallback = (resp) => {
1308
1729
  var _a;
1730
+ this.restoreFocus();
1309
1731
  this.setState({
1310
1732
  show: false,
1311
1733
  LayerComponent: undefined,
@@ -1337,6 +1759,7 @@ Dialog.defaultProps = {
1337
1759
  closeOnOverlayClick: true,
1338
1760
  };
1339
1761
 
1762
+ let dialogCounter = 0;
1340
1763
  class AlertDialog extends React.Component {
1341
1764
  constructor() {
1342
1765
  super(...arguments);
@@ -1350,7 +1773,9 @@ class AlertDialog extends React.Component {
1350
1773
  this.close = () => this.dialog.current.close();
1351
1774
  }
1352
1775
  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 }) })] })));
1776
+ const titleId = `nfui-alert-dialog-${dialogCounter++}-title`;
1777
+ const descriptionId = `nfui-alert-dialog-${dialogCounter++}-description`;
1778
+ return (jsxRuntime.jsxs(Dialog, Object.assign({}, this.props.dialogProps, { role: "alertdialog", "aria-labelledby": titleId, "aria-describedby": descriptionId, ref: this.dialog, closeOnEsc: false, closeOnOverlayClick: false, children: [this.props.header && jsxRuntime.jsx(Header$1, { id: titleId, children: this.props.header }), jsxRuntime.jsx(Body$1, { id: descriptionId, children: this.props.body }), jsxRuntime.jsx(Footer$1, { children: jsxRuntime.jsx(StyledButton, { onClick: this.close, children: this.props.buttonText }) })] })));
1354
1779
  }
1355
1780
  }
1356
1781
  AlertDialog.propTypes = {
@@ -1389,7 +1814,7 @@ class ConfirmDialog extends React.Component {
1389
1814
  }
1390
1815
  render() {
1391
1816
  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 })] })] })));
1817
+ 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
1818
  }
1394
1819
  }
1395
1820
  ConfirmDialog.propTypes = {
@@ -1412,7 +1837,6 @@ ConfirmDialog.defaultProps = {
1412
1837
  const Label$5 = styled.label `
1413
1838
  display: inline-flex;
1414
1839
  flex-direction: column;
1415
- flex: 1;
1416
1840
  position: relative;
1417
1841
  margin: 10px 5px;
1418
1842
  `;
@@ -1424,46 +1848,46 @@ const TextField$1 = styled.input `
1424
1848
  min-height: 30px;
1425
1849
  width: 250px;
1426
1850
  border-radius: 3px;
1427
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
1851
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
1428
1852
  display: inline-block;
1429
- background-color: var(--background, ${constants.BACKGROUND});
1853
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
1430
1854
 
1431
1855
  /** Focused */
1432
1856
  &:focus,
1433
1857
  &:active {
1434
- border-color: var(--primary, ${constants.PRIMARY});
1435
- box-shadow: 0 0 0 4px var(--primary-light, ${constants.PRIMARY_LIGHT});
1858
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
1859
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
1436
1860
  }
1437
1861
 
1438
1862
  &:focus + span,
1439
1863
  &:active + span {
1440
- color: var(--primary, ${constants.PRIMARY});
1864
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
1441
1865
  }
1442
1866
 
1443
1867
  /** Disabled */
1444
1868
  &:disabled {
1445
- border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
1446
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
1869
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
1870
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
1447
1871
  }
1448
1872
 
1449
1873
  &:disabled + span {
1450
- color: #777;
1874
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
1451
1875
  }
1452
1876
 
1453
1877
  /** Invalid */
1454
1878
  &:focus:invalid {
1455
- border-color: var(--error, ${constants.ERROR});
1456
- box-shadow: 0 0 0 4px var(--error-light, ${constants.ERROR_LIGHT});
1879
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1880
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.ERROR_LIGHT)};
1457
1881
  }
1458
1882
 
1459
1883
  ${(props) => props.touched
1460
1884
  ? `
1461
1885
  &:invalid {
1462
- border-color: var(--error, ${constants.ERROR});
1886
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1463
1887
  }
1464
1888
 
1465
1889
  &:invalid + span {
1466
- color: var(--error, ${constants.ERROR});
1890
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1467
1891
  }
1468
1892
  `
1469
1893
  : ''}
@@ -1471,10 +1895,10 @@ const TextField$1 = styled.input `
1471
1895
  /** Error */
1472
1896
  ${(props) => props.errorText
1473
1897
  ? `
1474
- border-color: var(--error, ${constants.ERROR});
1898
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1475
1899
 
1476
1900
  & + span {
1477
- color: var(--error, ${constants.ERROR});
1901
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1478
1902
  }
1479
1903
  `
1480
1904
  : ''}
@@ -1483,7 +1907,7 @@ const TextField$1 = styled.input `
1483
1907
  &:required + span:after {
1484
1908
  content: '*';
1485
1909
  margin-left: 2px;
1486
- color: var(--error, ${constants.ERROR});
1910
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1487
1911
  }
1488
1912
 
1489
1913
  /** Label Animation */
@@ -1501,7 +1925,7 @@ const TextField$1 = styled.input `
1501
1925
  ? `
1502
1926
  & + span {
1503
1927
  top: -8px;
1504
- background: var(--background, ${constants.BACKGROUND});
1928
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1505
1929
  font-size: 12px;
1506
1930
  line-height: 14px;
1507
1931
  }
@@ -1510,21 +1934,27 @@ const TextField$1 = styled.input `
1510
1934
 
1511
1935
  &:focus + span, &:placeholder-shown + span {
1512
1936
  top: -8px;
1513
- background: var(--background, ${constants.BACKGROUND});
1937
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1514
1938
  font-size: 12px;
1515
1939
  line-height: 14px;
1516
1940
  }
1517
1941
  `;
1518
1942
  const ErrorContainer$3 = styled.div `
1519
- color: var(--error, ${constants.ERROR});
1943
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1520
1944
  padding-top: 3px;
1521
1945
  font-size: 12px;
1522
1946
  line-height: 14px;
1523
1947
  margin-left: 3px;
1524
1948
  `;
1525
- const Input$4 = React.forwardRef((props, ref) => {
1949
+ const Input$2 = React.forwardRef((props, ref) => {
1526
1950
  const [touched, setTouched] = React.useState(false);
1527
1951
  const [value, setValue] = React.useState(props.value || '');
1952
+ const errorId = React.useId();
1953
+ React.useEffect(() => {
1954
+ if (props.value !== undefined) {
1955
+ setValue(props.value);
1956
+ }
1957
+ }, [props.value]);
1528
1958
  const handleFocus = (e) => {
1529
1959
  setTouched(true);
1530
1960
  if (props.onFocus) {
@@ -1540,10 +1970,10 @@ const Input$4 = React.forwardRef((props, ref) => {
1540
1970
  setValue(e.target.value);
1541
1971
  }
1542
1972
  };
1543
- return (jsxRuntime.jsxs(Label$5, { children: [jsxRuntime.jsx(TextField$1, Object.assign({}, props, { ref: ref, value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched })), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$3, { children: props.errorText })] }));
1973
+ return (jsxRuntime.jsxs(Label$5, { children: [jsxRuntime.jsx(TextField$1, Object.assign({}, props, { ref: ref, value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched, "aria-invalid": !!props.errorText, "aria-required": props.required, "aria-describedby": props.errorText ? errorId : undefined })), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$3, { id: errorId, children: props.errorText })] }));
1544
1974
  });
1545
- Input$4.displayName = 'Input';
1546
- Input$4.propTypes = {
1975
+ Input$2.displayName = 'Input';
1976
+ Input$2.propTypes = {
1547
1977
  /** Label for the field */
1548
1978
  label: PropTypes.string,
1549
1979
  /** Error text to be shown below the field */
@@ -1553,7 +1983,6 @@ Input$4.propTypes = {
1553
1983
  const Label$4 = styled.label `
1554
1984
  display: inline-flex;
1555
1985
  flex-direction: column;
1556
- flex: 1;
1557
1986
  position: relative;
1558
1987
  margin: 10px 5px;
1559
1988
  `;
@@ -1564,46 +1993,46 @@ const TextField = styled.textarea `
1564
1993
  min-height: 150px;
1565
1994
  min-width: 250px;
1566
1995
  border-radius: 3px;
1567
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
1996
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
1568
1997
  display: inline-block;
1569
- background-color: var(--background, ${constants.BACKGROUND});
1998
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
1570
1999
 
1571
2000
  /** Focused */
1572
2001
  &:focus,
1573
2002
  &:active {
1574
- border-color: var(--primary, ${constants.PRIMARY});
1575
- box-shadow: 0 0 0 4px var(--primary, ${constants.PRIMARY_LIGHT});
2003
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2004
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
1576
2005
  }
1577
2006
 
1578
2007
  &:focus + span,
1579
2008
  &:active + span {
1580
- color: var(--primary, ${constants.PRIMARY});
2009
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
1581
2010
  }
1582
2011
 
1583
2012
  /** Disabled */
1584
2013
  &:disabled {
1585
- border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
1586
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
2014
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2015
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
1587
2016
  }
1588
2017
 
1589
2018
  &:disabled + span {
1590
- color: var(--disabled, ${constants.DISABLED});
2019
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
1591
2020
  }
1592
2021
 
1593
2022
  /** Invalid */
1594
2023
  &:focus:invalid {
1595
- border-color: var(--error, ${constants.ERROR});
1596
- box-shadow: 0 0 0 4px var(--error-light, ${constants.ERROR_LIGHT});
2024
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
2025
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.ERROR_LIGHT)};
1597
2026
  }
1598
2027
 
1599
2028
  ${(props) => props.touched
1600
2029
  ? `
1601
2030
  &:invalid {
1602
- border-color: var(--error, ${constants.ERROR});
2031
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1603
2032
  }
1604
2033
 
1605
2034
  &:invalid + span {
1606
- color: var(--error, ${constants.ERROR});
2035
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1607
2036
  }
1608
2037
  `
1609
2038
  : ''}
@@ -1611,10 +2040,10 @@ const TextField = styled.textarea `
1611
2040
  /** Error */
1612
2041
  ${(props) => props.errorText
1613
2042
  ? `
1614
- border-color: var(--error, ${constants.ERROR});
2043
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1615
2044
 
1616
2045
  & + span {
1617
- color: var(--error, ${constants.ERROR});
2046
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1618
2047
  }
1619
2048
  `
1620
2049
  : ''}
@@ -1623,7 +2052,7 @@ const TextField = styled.textarea `
1623
2052
  &:required + span:after {
1624
2053
  content: '*';
1625
2054
  margin-left: 2px;
1626
- color: var(--error, ${constants.ERROR});
2055
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1627
2056
  }
1628
2057
 
1629
2058
  /** Label Animation */
@@ -1641,7 +2070,7 @@ const TextField = styled.textarea `
1641
2070
  ? `
1642
2071
  & + span {
1643
2072
  top: -8px;
1644
- background: var(--background, ${constants.BACKGROUND});
2073
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1645
2074
  font-size: 12px;
1646
2075
  line-height: 14px;
1647
2076
  }
@@ -1650,13 +2079,13 @@ const TextField = styled.textarea `
1650
2079
 
1651
2080
  &:focus + span, &:placeholder-shown + span {
1652
2081
  top: -8px;
1653
- background: var(--background, ${constants.BACKGROUND});
2082
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1654
2083
  font-size: 12px;
1655
2084
  line-height: 14px;
1656
2085
  }
1657
2086
  `;
1658
2087
  const ErrorContainer$2 = styled.div `
1659
- color: var(--error, ${constants.ERROR});
2088
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1660
2089
  padding-top: 3px;
1661
2090
  font-size: 12px;
1662
2091
  line-height: 14px;
@@ -1665,6 +2094,12 @@ const ErrorContainer$2 = styled.div `
1665
2094
  function TextArea(props) {
1666
2095
  const [touched, setTouched] = React.useState(false);
1667
2096
  const [value, setValue] = React.useState(props.value || '');
2097
+ const errorId = React.useId();
2098
+ React.useEffect(() => {
2099
+ if (props.value !== undefined) {
2100
+ setValue(props.value);
2101
+ }
2102
+ }, [props.value]);
1668
2103
  const handleFocus = (e) => {
1669
2104
  setTouched(true);
1670
2105
  if (props.onFocus) {
@@ -1680,7 +2115,7 @@ function TextArea(props) {
1680
2115
  setValue(e.target.value);
1681
2116
  }
1682
2117
  };
1683
- return (jsxRuntime.jsxs(Label$4, { children: [jsxRuntime.jsx(TextField, Object.assign({}, props, { value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched })), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$2, { children: props.errorText })] }));
2118
+ return (jsxRuntime.jsxs(Label$4, { children: [jsxRuntime.jsx(TextField, Object.assign({}, props, { value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched, "aria-invalid": !!props.errorText, "aria-required": props.required, "aria-describedby": props.errorText ? errorId : undefined })), jsxRuntime.jsx("span", { children: props.label }), props.errorText && jsxRuntime.jsx(ErrorContainer$2, { id: errorId, children: props.errorText })] }));
1684
2119
  }
1685
2120
  TextArea.propTypes = {
1686
2121
  /** Label for the field */
@@ -1692,7 +2127,6 @@ TextArea.propTypes = {
1692
2127
  const Label$3 = styled.label `
1693
2128
  display: inline-flex;
1694
2129
  flex-direction: column;
1695
- flex: 1;
1696
2130
  position: relative;
1697
2131
  margin: 10px 5px;
1698
2132
  pointer-events: none;
@@ -1710,48 +2144,48 @@ const SelectField = styled.select `
1710
2144
  min-height: 32px;
1711
2145
  width: 268px;
1712
2146
  border-radius: 3px;
1713
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
2147
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
1714
2148
  display: inline-block;
1715
- background-color: var(--background, ${constants.BACKGROUND});
2149
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
1716
2150
  pointer-events: auto;
1717
2151
  appearance: none;
1718
2152
 
1719
2153
  /** Focused */
1720
2154
  &:focus,
1721
2155
  &:active {
1722
- border-color: var(--primary, ${constants.PRIMARY});
1723
- box-shadow: 0 0 0 4px var(--primary, ${constants.PRIMARY_LIGHT});
2156
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2157
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
1724
2158
  }
1725
2159
 
1726
2160
  &:focus ~ span,
1727
2161
  &:active ~ span {
1728
- color: var(--primary, ${constants.PRIMARY});
2162
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
1729
2163
  }
1730
2164
 
1731
2165
  /** Disabled */
1732
2166
  &:disabled {
1733
- border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
1734
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
2167
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2168
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
1735
2169
  }
1736
2170
 
1737
2171
  &:disabled ~ span {
1738
- color: var(--disabled, ${constants.DISABLED});
2172
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
1739
2173
  }
1740
2174
 
1741
2175
  /** Invalid */
1742
2176
  &:focus:invalid {
1743
- border-color: var(--error, ${constants.ERROR});
1744
- box-shadow: 0 0 0 4px var(--error-light, ${constants.ERROR_LIGHT});
2177
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
2178
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.ERROR_LIGHT)};
1745
2179
  }
1746
2180
 
1747
2181
  ${(props) => props.touched
1748
2182
  ? `
1749
2183
  &:invalid {
1750
- border-color: var(--error, ${constants.ERROR});
2184
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1751
2185
  }
1752
2186
 
1753
2187
  &:invalid ~ span {
1754
- color: var(--error, ${constants.ERROR});
2188
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1755
2189
  }
1756
2190
  `
1757
2191
  : ''}
@@ -1759,10 +2193,10 @@ const SelectField = styled.select `
1759
2193
  /** Error */
1760
2194
  ${(props) => props.errorText
1761
2195
  ? `
1762
- border-color: var(--error, ${constants.ERROR});
2196
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
1763
2197
 
1764
2198
  & ~ span {
1765
- color: var(--error, ${constants.ERROR});
2199
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1766
2200
  }
1767
2201
  `
1768
2202
  : ''}
@@ -1771,7 +2205,7 @@ const SelectField = styled.select `
1771
2205
  &:required + span:after {
1772
2206
  content: '*';
1773
2207
  margin-left: 2px;
1774
- color: var(--error, ${constants.ERROR});
2208
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1775
2209
  }
1776
2210
 
1777
2211
  /** Label Animation */
@@ -1789,7 +2223,7 @@ const SelectField = styled.select `
1789
2223
  ? `
1790
2224
  & + span {
1791
2225
  top: -8px;
1792
- background: var(--background, ${constants.BACKGROUND});
2226
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1793
2227
  font-size: 12px;
1794
2228
  line-height: 14px;
1795
2229
  }
@@ -1798,13 +2232,13 @@ const SelectField = styled.select `
1798
2232
 
1799
2233
  &:focus + span, &:placeholder-shown + span {
1800
2234
  top: -8px;
1801
- background: var(--background, ${constants.BACKGROUND});
2235
+ background: ${getThemeValue(THEME_NAME.BACKGROUND)};
1802
2236
  font-size: 12px;
1803
2237
  line-height: 14px;
1804
2238
  }
1805
2239
  `;
1806
2240
  const ErrorContainer$1 = styled.div `
1807
- color: var(--error, ${constants.ERROR});
2241
+ color: ${getThemeValue(THEME_NAME.ERROR)};
1808
2242
  padding-top: 3px;
1809
2243
  font-size: 12px;
1810
2244
  line-height: 14px;
@@ -1818,6 +2252,12 @@ const ArrowContainer$1 = styled.span `
1818
2252
  function Select(props) {
1819
2253
  const [touched, setTouched] = React.useState(false);
1820
2254
  const [value, setValue] = React.useState(props.value || '');
2255
+ const errorId = React.useId();
2256
+ React.useEffect(() => {
2257
+ if (props.value !== undefined) {
2258
+ setValue(props.value);
2259
+ }
2260
+ }, [props.value]);
1821
2261
  const handleFocus = (e) => {
1822
2262
  setTouched(true);
1823
2263
  if (props.onFocus) {
@@ -1833,7 +2273,7 @@ function Select(props) {
1833
2273
  setValue(e.target.value);
1834
2274
  }
1835
2275
  };
1836
- return (jsxRuntime.jsxs(Label$3, { children: [jsxRuntime.jsxs(SelectField, Object.assign({}, props, { multiple: false, value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched, children: [jsxRuntime.jsx("option", {}), props.children] })), jsxRuntime.jsx("span", { children: props.label }), jsxRuntime.jsx(ArrowContainer$1, { children: jsxRuntime.jsx(ExpandMore, {}) }), props.errorText && jsxRuntime.jsx(ErrorContainer$1, { children: props.errorText })] }));
2276
+ return (jsxRuntime.jsxs(Label$3, { children: [jsxRuntime.jsxs(SelectField, Object.assign({}, props, { multiple: false, value: value, onChange: onChangeHandler, onFocus: handleFocus, touched: touched, "aria-invalid": !!props.errorText, "aria-required": props.required, "aria-describedby": props.errorText ? errorId : undefined, children: [jsxRuntime.jsx("option", {}), props.children] })), jsxRuntime.jsx("span", { children: props.label }), jsxRuntime.jsx(ArrowContainer$1, { "aria-hidden": "true", children: jsxRuntime.jsx(ExpandMore, {}) }), props.errorText && jsxRuntime.jsx(ErrorContainer$1, { id: errorId, children: props.errorText })] }));
1837
2277
  }
1838
2278
  Select.propTypes = {
1839
2279
  /** Label for the field */
@@ -1845,99 +2285,104 @@ Select.propTypes = {
1845
2285
  const Label$2 = styled.label `
1846
2286
  margin: 5px 0;
1847
2287
  position: relative;
2288
+ display: inline-flex;
2289
+ align-items: center;
2290
+ cursor: pointer;
1848
2291
  `;
1849
- const Input$3 = styled.input `
1850
- appearance: none;
2292
+ const StyledCheckmark = styled.span `
2293
+ width: 16px;
2294
+ height: 16px;
2295
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
2296
+ display: inline-block;
2297
+ border-radius: 3px;
2298
+ margin-right: 5px;
2299
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
2300
+ transition: all 0.3s ease;
1851
2301
  position: relative;
1852
- margin: 0;
1853
-
1854
- &::before {
1855
- content: '';
1856
- width: 16px;
1857
- height: 16px;
1858
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
1859
- display: inline-block;
1860
- border-radius: 3px;
1861
- vertical-align: bottom;
1862
- margin: 0 5px;
1863
- text-align: center;
1864
- line-height: 16px;
1865
- background-color: var(--background, ${constants.BACKGROUND});
1866
- transition: background-color 0.3s ease;
1867
- }
2302
+ flex-shrink: 0;
1868
2303
 
1869
2304
  &::after {
1870
2305
  content: '';
1871
2306
  width: 3px;
1872
2307
  height: 10px;
1873
- border-right: 2px solid #fff;
1874
- border-bottom: 2px solid #fff;
1875
- transform: translate(-16px, 1px);
1876
- opacity: 0;
1877
- transition: transform 0.3s ease;
2308
+ border-right: 2px solid ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
2309
+ border-bottom: 2px solid ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
1878
2310
  position: absolute;
2311
+ top: 1px;
2312
+ left: 6px;
2313
+ opacity: 0;
2314
+ transform: rotate(45deg) scale(0);
2315
+ transition: all 0.2s ease;
1879
2316
  }
2317
+ `;
2318
+ const HiddenInput$1 = styled.input `
2319
+ opacity: 0;
2320
+ width: 0;
2321
+ height: 0;
2322
+ position: absolute;
2323
+ margin: 0;
1880
2324
 
1881
2325
  /** checked */
1882
- &:checked::before {
1883
- content: '';
1884
- background-color: var(--primary, ${constants.PRIMARY});
1885
- border-color: var(--primary, ${constants.PRIMARY});
1886
- color: #fff;
2326
+ &:checked + ${StyledCheckmark} {
2327
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2328
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
1887
2329
  }
1888
2330
 
1889
- &:checked::after {
2331
+ &:checked + ${StyledCheckmark}::after {
1890
2332
  opacity: 1;
1891
- transform: translate(-16px, 2px) rotate(45deg);
2333
+ transform: rotate(45deg) scale(1);
1892
2334
  }
1893
2335
 
1894
2336
  /** indeterminate */
1895
- &:indeterminate::before {
1896
- content: '';
1897
- background-color: var(--primary, ${constants.PRIMARY});
1898
- border-color: var(--primary, ${constants});
1899
- color: #fff;
2337
+ &:indeterminate + ${StyledCheckmark} {
2338
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2339
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
1900
2340
  }
1901
2341
 
1902
- &:indeterminate::after {
1903
- width: 0;
2342
+ &:indeterminate + ${StyledCheckmark}::after {
1904
2343
  opacity: 1;
1905
- transform: translate(-15px, 3px) rotate(90deg);
2344
+ height: 0;
2345
+ width: 8px;
2346
+ border-right: none;
2347
+ border-bottom: 2px solid ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
2348
+ transform: rotate(0deg) scale(1);
2349
+ top: 7px;
2350
+ left: 4px;
1906
2351
  }
1907
2352
 
1908
2353
  /** active and focus */
1909
- &:enabled:active::before,
1910
- &:focus::before {
1911
- border-color: var(--primary, ${constants.PRIMARY});
1912
- box-shadow: 0 0 0 3px var(--primary, ${constants.PRIMARY_LIGHT});
2354
+ &:enabled:active + ${StyledCheckmark}, &:focus + ${StyledCheckmark} {
2355
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2356
+ box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
1913
2357
  }
1914
2358
 
1915
- &:enabled:active + span,
1916
- &:focus + span {
1917
- color: var(--primary, ${constants.PRIMARY});
2359
+ &:enabled:active ~ span,
2360
+ &:focus ~ span {
2361
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
1918
2362
  }
1919
2363
 
1920
2364
  /** hover */
1921
- &:enabled:hover::before {
1922
- border-color: var(--primary, ${constants.PRIMARY});
2365
+ &:enabled:hover + ${StyledCheckmark} {
2366
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
1923
2367
  }
1924
2368
 
1925
- &:enabled:hover + span {
1926
- color: var(--primary, ${constants.PRIMARY});
2369
+ &:enabled:hover ~ span {
2370
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
1927
2371
  }
1928
2372
 
1929
2373
  /** disabled */
1930
- &:disabled::before {
1931
- border-color: #aaa;
2374
+ &:disabled + ${StyledCheckmark} {
2375
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2376
+ cursor: not-allowed;
1932
2377
  }
1933
2378
 
1934
- &:disabled + span {
1935
- color: #aaa;
2379
+ &:disabled ~ span {
2380
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
2381
+ cursor: not-allowed;
1936
2382
  }
1937
2383
 
1938
- &:checked:disabled::before,
1939
- &:indeterminate:disabled::before {
1940
- background-color: #aaa;
2384
+ &:checked:disabled + ${StyledCheckmark}, &:indeterminate:disabled + ${StyledCheckmark} {
2385
+ background-color: ${getThemeValue(THEME_NAME.DISABLED)};
1941
2386
  }
1942
2387
  `;
1943
2388
  function Checkbox(props) {
@@ -1948,7 +2393,7 @@ function Checkbox(props) {
1948
2393
  }
1949
2394
  }
1950
2395
  }, [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 })] }));
2396
+ return (jsxRuntime.jsxs(Label$2, { children: [jsxRuntime.jsx(HiddenInput$1, Object.assign({}, props, { ref: ref, type: "checkbox", "aria-checked": props.indeterminate ? 'mixed' : props.checked })), jsxRuntime.jsx(StyledCheckmark, {}), jsxRuntime.jsx("span", { children: props.label })] }));
1952
2397
  }
1953
2398
  Checkbox.propTypes = {
1954
2399
  /** Label for the field */
@@ -1966,7 +2411,10 @@ const Switch = styled.label `
1966
2411
  display: inline-flex;
1967
2412
  margin: 5px 0;
1968
2413
  `;
1969
- const Input$2 = styled.input `
2414
+ const Input$1 = styled.input `
2415
+ position: absolute;
2416
+ width: 0;
2417
+ height: 0;
1970
2418
  appearance: none;
1971
2419
  margin: 0;
1972
2420
 
@@ -1975,7 +2423,7 @@ const Input$2 = styled.input `
1975
2423
  cursor: pointer;
1976
2424
  width: 30px;
1977
2425
  height: 18px;
1978
- background-color: ${constants.LIGHT_GREY};
2426
+ background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
1979
2427
  transition: 0.4s;
1980
2428
  border-radius: 10px;
1981
2429
  padding: 0 3px;
@@ -1988,51 +2436,51 @@ const Input$2 = styled.input `
1988
2436
  width: 14px;
1989
2437
  left: 1px;
1990
2438
  top: 1px;
1991
- border: 1px solid var(--disabled-border, ${constants.DISABLED_BORDER});
2439
+ border: 1px solid ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
1992
2440
  border-radius: 50%;
1993
- background-color: var(--background, ${constants.BACKGROUND});
2441
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
1994
2442
  transition: 0.4s;
1995
2443
  }
1996
2444
 
1997
2445
  /* checked */
1998
2446
  &:checked + span {
1999
- background-color: var(--primary, ${constants.PRIMARY_LIGHT});
2447
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2000
2448
  }
2001
2449
 
2002
2450
  &:checked + span:before {
2003
2451
  transform: translateX(18px);
2004
- border-color: var(--primary, ${constants.PRIMARY});
2452
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2005
2453
  }
2006
2454
 
2007
2455
  /* focus */
2008
2456
  &:enabled:focus + span:before {
2009
- box-shadow: 0 0 0 3px var(--primary, ${constants.PRIMARY_LIGHT});
2010
- border-color: var(--primary, ${constants.PRIMARY});
2457
+ box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2458
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2011
2459
  }
2012
2460
 
2013
2461
  /* hover */
2014
2462
  &:enabled:hover ~ span {
2015
2463
  cursor: pointer;
2016
- color: var(--primary, ${constants.PRIMARY});
2464
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
2017
2465
  }
2018
2466
 
2019
2467
  /* disabled */
2020
2468
  &:disabled ~ span {
2021
- color: var(--disabled-border, ${constants.DISABLED_BORDER});
2469
+ color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2022
2470
  }
2023
2471
 
2024
2472
  &:disabled + span {
2025
- background-color: ${constants.LIGHT_GREY};
2473
+ background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
2026
2474
  cursor: not-allowed;
2027
2475
  }
2028
2476
 
2029
2477
  &:disabled + span:before {
2030
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
2031
- border-color: var(--disabled-border, ${constants.DISABLED_BORDER});
2478
+ background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
2479
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2032
2480
  }
2033
2481
  `;
2034
2482
  function Toggle(props) {
2035
- return (jsxRuntime.jsxs(Switch, { children: [jsxRuntime.jsx(Input$2, Object.assign({}, props, { type: "checkbox" })), jsxRuntime.jsx("span", {}), jsxRuntime.jsx("span", { children: props.label })] }));
2483
+ return (jsxRuntime.jsxs(Switch, { children: [jsxRuntime.jsx(Input$1, Object.assign({}, props, { type: "checkbox", role: "switch", "aria-checked": props.checked })), jsxRuntime.jsx("span", {}), jsxRuntime.jsx("span", { children: props.label })] }));
2036
2484
  }
2037
2485
  Toggle.propTypes = {
2038
2486
  /** Label for the field */
@@ -2043,73 +2491,89 @@ const Label$1 = styled.label `
2043
2491
  display: inline-flex;
2044
2492
  align-items: center;
2045
2493
  margin: 5px 0;
2494
+ cursor: pointer;
2495
+ position: relative;
2046
2496
  `;
2047
- const Input$1 = styled.input `
2048
- appearance: none;
2049
- margin: 0;
2497
+ const StyledRadio = styled.span `
2498
+ width: 16px;
2499
+ height: 16px;
2500
+ margin-right: 5px;
2501
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
2502
+ border-radius: 50%;
2503
+ display: block;
2504
+ transition: background-color 0.3s ease;
2505
+ position: relative;
2506
+ flex-shrink: 0;
2050
2507
 
2051
- &::before {
2052
- content: ' ';
2053
- width: 16px;
2054
- height: 16px;
2055
- margin: 0 5px;
2056
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
2508
+ &::after {
2509
+ content: '';
2510
+ width: 100%;
2511
+ height: 100%;
2057
2512
  border-radius: 50%;
2058
- display: block;
2059
- transition: background-color 0.3s ease;
2513
+ position: absolute;
2514
+ top: 0;
2515
+ left: 0;
2516
+ box-shadow: inset 0 0 0 3px ${getThemeValue(THEME_NAME.BACKGROUND)};
2517
+ opacity: 0;
2518
+ transition: opacity 0.2s ease;
2060
2519
  }
2520
+ `;
2521
+ const HiddenInput = styled.input `
2522
+ opacity: 0;
2523
+ width: 0;
2524
+ height: 0;
2525
+ position: absolute;
2526
+ margin: 0;
2061
2527
 
2062
2528
  /* checked */
2063
- &:checked::before {
2064
- border: 1px solid var(--primary, ${constants.PRIMARY});
2065
- background-color: var(--primary, ${constants.PRIMARY});
2066
- box-shadow: inset 0 0 0 3px var(--background, ${constants.BACKGROUND});
2529
+ &:checked + ${StyledRadio} {
2530
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2531
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2532
+ }
2533
+
2534
+ &:checked + ${StyledRadio}::after {
2535
+ opacity: 1;
2067
2536
  }
2068
2537
 
2069
2538
  /* focus */
2070
- &:enabled:focus::before {
2071
- border: 1px solid var(--primary, ${constants.PRIMARY});
2072
- box-shadow: 0 0 0 3px var(--primary, ${constants.PRIMARY_LIGHT});
2073
- cursor: pointer;
2539
+ &:enabled:focus + ${StyledRadio} {
2540
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2541
+ box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2074
2542
  }
2075
2543
 
2076
- &:enabled:checked:focus::before {
2077
- border: 1px solid var(--primary, ${constants.PRIMARY});
2078
- box-shadow:
2079
- 0 0 0 3px var(--primary, ${constants.PRIMARY_LIGHT}),
2080
- inset 0 0 0 3px var(--background, ${constants.BACKGROUND});
2081
- cursor: pointer;
2544
+ &:enabled:checked:focus + ${StyledRadio} {
2545
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2546
+ box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2082
2547
  }
2083
2548
 
2084
2549
  /* hover */
2085
- &:enabled:hover::before {
2086
- border: 1px solid var(--primary, ${constants.PRIMARY});
2087
- cursor: pointer;
2550
+ &:enabled:hover + ${StyledRadio} {
2551
+ border-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2088
2552
  }
2089
2553
 
2090
- &:enabled:hover + span {
2091
- color: var(--primary, ${constants.PRIMARY});
2092
- cursor: pointer;
2554
+ &:enabled:hover ~ span {
2555
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
2093
2556
  }
2094
2557
 
2095
2558
  /* disabled */
2096
- &:disabled::before {
2097
- border: 1px solid var(--disabled-border, ${constants.DISABLED_BORDER});
2098
- background-color: var(--light-grey, ${constants.LIGHT_GREY});
2559
+ &:disabled + ${StyledRadio} {
2560
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2561
+ background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
2562
+ cursor: not-allowed;
2099
2563
  }
2100
2564
 
2101
- &:disabled:checked::before {
2102
- border: 1px solid var(--disabled-border, ${constants.DISABLED_BORDER});
2103
- background-color: var(--disabled-border, ${constants.DISABLED_BORDER});
2104
- box-shadow: inset 0 0 0 3px var(--background, ${constants.BACKGROUND});
2565
+ &:disabled:checked + ${StyledRadio} {
2566
+ border-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2567
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2105
2568
  }
2106
2569
 
2107
- &:disabled + span {
2108
- color: var(--disabled-border, ${constants.DISABLED_BORDER});
2570
+ &:disabled ~ span {
2571
+ color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2572
+ cursor: not-allowed;
2109
2573
  }
2110
2574
  `;
2111
2575
  function Radio(props) {
2112
- return (jsxRuntime.jsxs(Label$1, { children: [jsxRuntime.jsx(Input$1, Object.assign({}, props, { type: "radio" })), jsxRuntime.jsx("span", { children: props.label })] }));
2576
+ return (jsxRuntime.jsxs(Label$1, { children: [jsxRuntime.jsx(HiddenInput, Object.assign({}, props, { type: "radio" })), jsxRuntime.jsx(StyledRadio, {}), jsxRuntime.jsx("span", { children: props.label })] }));
2113
2577
  }
2114
2578
  Radio.propTypes = {
2115
2579
  /** Label for the field */
@@ -2122,37 +2586,37 @@ const Input = styled.input `
2122
2586
  width: 0;
2123
2587
 
2124
2588
  & + span {
2125
- color: var(--primary, ${constants.PRIMARY});
2589
+ color: ${getThemeValue(THEME_NAME.PRIMARY)};
2126
2590
  padding: 6px 12px;
2127
2591
  border: none;
2128
- border: 1px solid var(--primary, ${constants.PRIMARY});
2592
+ border: 1px solid ${getThemeValue(THEME_NAME.PRIMARY)};
2129
2593
  cursor: pointer;
2130
2594
  margin-right: -1px;
2131
2595
  line-height: 18px;
2132
2596
  }
2133
2597
 
2134
2598
  &:enabled:focus + span {
2135
- box-shadow: 0 0 0 4px var(--primary, ${constants.PRIMARY_LIGHT});
2599
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2136
2600
  }
2137
2601
 
2138
2602
  &:enabled:hover + span {
2139
- background-color: var(--primary, ${constants.PRIMARY_LIGHT});
2140
- color: #fff;
2603
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2604
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
2141
2605
  }
2142
2606
 
2143
2607
  &:enabled:checked + span {
2144
- background-color: var(--primary, ${constants.PRIMARY});
2145
- color: #fff;
2608
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY)};
2609
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
2146
2610
  }
2147
2611
 
2148
2612
  &:disabled + span {
2149
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
2150
- color: var(--disabled-border, ${constants.DISABLED_BORDER});
2613
+ background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
2614
+ color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2151
2615
  }
2152
2616
 
2153
2617
  &:disabled:checked + span {
2154
- background-color: var(--disabled-border, ${constants.DISABLED_BORDER});
2155
- color: #fff;
2618
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
2619
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
2156
2620
  }
2157
2621
  `;
2158
2622
  const Label = styled.label `
@@ -2194,10 +2658,28 @@ const MenuContainer = styled.div `
2194
2658
  & div:last-child {
2195
2659
  border-bottom: none;
2196
2660
  }
2661
+
2662
+ &:focus-within {
2663
+ box-shadow: 0 0 0 4px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
2664
+ }
2197
2665
  `;
2666
+ /**
2667
+ * Menu component that allows selection of items from a list.
2668
+ * Supports single and multi-select modes and keyboard navigation.
2669
+ *
2670
+ * @template T - The type of value(s) in the menu.
2671
+ * @param {MenuProps<T> & Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange'>} props - The menu properties.
2672
+ * @param {ForwardedRef<HTMLDivElement>} ref - The ref forwarded to the menu container.
2673
+ */
2198
2674
  const Menu = React.forwardRef(function (props, ref) {
2199
- const { multiSelect, onChange } = props;
2200
- const [value, setValue] = React.useState(props.value || (multiSelect ? [] : ''));
2675
+ const { multiSelect, onChange, value: propValue } = props, rest = __rest(props, ["multiSelect", "onChange", "value"]);
2676
+ const [value, setValue] = React.useState(propValue || (multiSelect ? [] : ''));
2677
+ /**
2678
+ * Updates the selected value(s).
2679
+ * Handles both single and multi-select logic.
2680
+ *
2681
+ * @param {T} val - The value to select or deselect.
2682
+ */
2201
2683
  const updateValue = (val) => {
2202
2684
  let newVal;
2203
2685
  if (multiSelect) {
@@ -2216,11 +2698,74 @@ const Menu = React.forwardRef(function (props, ref) {
2216
2698
  setValue(newVal);
2217
2699
  onChange === null || onChange === void 0 ? void 0 : onChange(newVal);
2218
2700
  };
2701
+ /**
2702
+ * Handles keyboard navigation within the menu.
2703
+ * Supports Arrow keys for navigation, and Enter/Space for selection.
2704
+ *
2705
+ * @param {React.KeyboardEvent} e - The keyboard event.
2706
+ */
2707
+ const handleKeyDown = (e) => {
2708
+ var _a, _b, _c, _d;
2709
+ const target = e.target;
2710
+ const container = e.currentTarget;
2711
+ const items = Array.from(container.querySelectorAll('[role="option"]'));
2712
+ const currentIndex = items.indexOf(target);
2713
+ let nextIndex;
2714
+ switch (e.key) {
2715
+ case 'ArrowDown':
2716
+ e.preventDefault();
2717
+ nextIndex = currentIndex + 1;
2718
+ if (nextIndex >= items.length)
2719
+ nextIndex = 0;
2720
+ (_a = items[nextIndex]) === null || _a === void 0 ? void 0 : _a.focus();
2721
+ break;
2722
+ case 'ArrowUp':
2723
+ e.preventDefault();
2724
+ nextIndex = currentIndex - 1;
2725
+ if (nextIndex < 0)
2726
+ nextIndex = items.length - 1;
2727
+ (_b = items[nextIndex]) === null || _b === void 0 ? void 0 : _b.focus();
2728
+ break;
2729
+ case 'Home':
2730
+ e.preventDefault();
2731
+ (_c = items[0]) === null || _c === void 0 ? void 0 : _c.focus();
2732
+ break;
2733
+ case 'End':
2734
+ e.preventDefault();
2735
+ (_d = items[items.length - 1]) === null || _d === void 0 ? void 0 : _d.focus();
2736
+ break;
2737
+ case 'Enter':
2738
+ case ' ': // Space
2739
+ e.preventDefault();
2740
+ target.click();
2741
+ break;
2742
+ }
2743
+ };
2744
+ /**
2745
+ * Handles focus events on the menu container.
2746
+ * Delegates focus to the first item if the container itself receives focus.
2747
+ *
2748
+ * @param {React.FocusEvent} e - The focus event.
2749
+ */
2750
+ const focusHandler = (e) => {
2751
+ // Prevent trap: If focus came from inside (Shift+Tab), do NOT auto-focus again.
2752
+ // This allows focus to land on the container, and the next Shift+Tab will exit.
2753
+ if (e.currentTarget.contains(e.relatedTarget)) {
2754
+ return;
2755
+ }
2756
+ // Only if focus is actually on the container (e.g. tabbing into it)
2757
+ // and not bubbling up from a child
2758
+ if (e.target === e.currentTarget) {
2759
+ // Prevent the container from holding focus; delegate to first item
2760
+ const firstItem = e.currentTarget.querySelector('[role="option"]');
2761
+ firstItem === null || firstItem === void 0 ? void 0 : firstItem.focus();
2762
+ }
2763
+ };
2219
2764
  return (jsxRuntime.jsx(MenuContext.Provider, { value: {
2220
2765
  value,
2221
2766
  multiSelect,
2222
2767
  updateValue,
2223
- }, children: jsxRuntime.jsx(MenuContainer, { ref: ref, children: props.children }) }));
2768
+ }, children: jsxRuntime.jsx(MenuContainer, Object.assign({}, rest, { ref: ref, role: "listbox", "aria-multiselectable": multiSelect, tabIndex: 0, onKeyDown: handleKeyDown, onFocus: focusHandler, children: props.children })) }));
2224
2769
  });
2225
2770
  Menu.displayName = 'Menu';
2226
2771
  Menu.defaultProps = {
@@ -2233,39 +2778,38 @@ const Container$4 = styled.button `
2233
2778
  border: none;
2234
2779
  background-color: transparent;
2235
2780
  font-size: 16px;
2236
- border-bottom: 1px solid var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
2781
+ border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
2237
2782
  min-height: 41px;
2238
2783
  display: flex;
2239
2784
  align-items: center;
2240
2785
  cursor: pointer;
2241
2786
  position: relative;
2787
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
2242
2788
 
2243
2789
  &:hover,
2244
2790
  &:focus,
2245
2791
  &:focus-within {
2246
- background-color: var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
2792
+ background-color: ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
2247
2793
  }
2248
2794
 
2249
2795
  & > label {
2250
2796
  margin: 0 4px 0 0;
2251
2797
  }
2252
2798
  `;
2253
- function MenuItem(props) {
2799
+ const MenuItemInner = (props, ref) => {
2254
2800
  var _a, _b;
2255
2801
  const context = React.useContext(MenuContext);
2256
2802
  const { value, children } = props, rest = __rest(props, ["value", "children"]);
2257
2803
  const clickHandler = (e) => {
2258
2804
  e.stopPropagation();
2259
- if (context.multiSelect) {
2260
- e.nativeEvent.stopImmediatePropagation();
2261
- }
2262
2805
  context.updateValue(value);
2263
2806
  };
2264
2807
  const selected = context.multiSelect
2265
2808
  ? (_b = (_a = context.value) === null || _a === void 0 ? void 0 : _a.includes) === null || _b === void 0 ? void 0 : _b.call(_a, value)
2266
2809
  : context.value === value;
2267
- return (jsxRuntime.jsxs(Container$4, Object.assign({}, rest, { type: "button", tabIndex: context.multiSelect ? -1 : 0, selected: selected, onClick: clickHandler, children: [context.multiSelect && jsxRuntime.jsx(Checkbox, { checked: selected }), children] })));
2268
- }
2810
+ return (jsxRuntime.jsxs(Container$4, Object.assign({}, rest, { ref: ref, type: "button", role: "option", "aria-selected": selected, selected: selected, onClick: clickHandler, children: [context.multiSelect && (jsxRuntime.jsx(Checkbox, { checked: selected, readOnly: true, tabIndex: -1, onClick: (e) => e.stopPropagation() })), children] })));
2811
+ };
2812
+ const MenuItem = React.forwardRef(MenuItemInner);
2269
2813
 
2270
2814
  exports.POPOVER_POSITION = void 0;
2271
2815
  (function (POPOVER_POSITION) {
@@ -2349,6 +2893,9 @@ function Popover(props) {
2349
2893
  const [translate, setTranslate] = React.useState({ x: 0, y: 0 });
2350
2894
  const popperRef = React.useRef();
2351
2895
  const containerRef = React.useRef();
2896
+ const triggerRef = React.useRef(null);
2897
+ const popperId = React.useId();
2898
+ const triggerId = React.useId();
2352
2899
  const close = React.useCallback(() => {
2353
2900
  setClosing(true);
2354
2901
  setTimeout(() => {
@@ -2358,6 +2905,12 @@ function Popover(props) {
2358
2905
  props.onClose();
2359
2906
  }
2360
2907
  setClosing(false);
2908
+ // Restore focus to the trigger element after animation completes
2909
+ setTimeout(() => {
2910
+ if (triggerRef.current) {
2911
+ triggerRef.current.focus();
2912
+ }
2913
+ }, 50);
2361
2914
  }, 280);
2362
2915
  }, [props]);
2363
2916
  const keyupEventHandler = React.useCallback((e) => {
@@ -2446,7 +2999,13 @@ function Popover(props) {
2446
2999
  popperRef.current.focus();
2447
3000
  }
2448
3001
  }, [open, props.position]);
2449
- return (jsxRuntime.jsxs(PopoverDiv, { ref: containerRef, children: [jsxRuntime.jsx(props.element, {}), open && (jsxRuntime.jsx(Popper, { elevated: true, tabIndex: 0, position: props.position, translateX: translate.x, translateY: translate.y, className: closing && 'closing', ref: popperRef, onClick: (e) => {
3002
+ return (jsxRuntime.jsxs(PopoverDiv, { ref: containerRef, children: [React.createElement(props.element, {
3003
+ ref: triggerRef,
3004
+ id: triggerId,
3005
+ 'aria-expanded': open,
3006
+ 'aria-haspopup': 'dialog',
3007
+ 'aria-controls': popperId,
3008
+ }), open && (jsxRuntime.jsx(Popper, { elevated: true, tabIndex: 0, role: "dialog", "aria-labelledby": triggerId, id: popperId, position: props.position, translateX: translate.x, translateY: translate.y, className: closing && 'closing', ref: popperRef, onClick: (e) => {
2450
3009
  e.stopPropagation();
2451
3010
  e.nativeEvent.stopImmediatePropagation();
2452
3011
  }, children: props.children }))] }));
@@ -2479,54 +3038,77 @@ const ArrowContainer = styled.span `
2479
3038
  top: 16px;
2480
3039
  pointer-events: none;
2481
3040
  `;
3041
+ /**
3042
+ * Dropdown component that allows selection from a list of options.
3043
+ * Supports single and multi-select modes.
3044
+ *
3045
+ * @template T - The type of the value(s) in the dropdown.
3046
+ * @param {DropdownProps<T>} props - The properties for the Dropdown component.
3047
+ * @returns {JSX.Element} The rendered Dropdown component.
3048
+ */
2482
3049
  function Dropdown(props) {
2483
3050
  const { multiSelect, onChange } = props;
2484
3051
  const [open, setOpen] = React.useState(false);
2485
3052
  const [value, setValue] = React.useState(props.value);
3053
+ const id = React.useId();
3054
+ const menuId = `${id}-menu`;
3055
+ const menuRef = React.useRef(null);
3056
+ const triggerRef = React.useRef(null);
3057
+ // Focus menu when opened
2486
3058
  React.useEffect(() => {
2487
- const focusHandler = (e) => {
2488
- var _a, _b;
2489
- if (open && (e.keyCode === 38 || e.keyCode === 40)) {
2490
- e.preventDefault();
2491
- const current = document.querySelector(':focus');
2492
- if (current.tagName === 'DIV') {
2493
- const firstBtn = current.querySelector('button');
2494
- firstBtn === null || firstBtn === void 0 ? void 0 : firstBtn.focus();
2495
- }
2496
- else {
2497
- const currentBtn = current.closest('button');
2498
- if (e.keyCode === 38) {
2499
- const prev = (_a = currentBtn === null || currentBtn === void 0 ? void 0 : currentBtn.previousElementSibling) === null || _a === void 0 ? void 0 : _a.closest('button');
2500
- prev === null || prev === void 0 ? void 0 : prev.focus();
2501
- }
2502
- else {
2503
- const next = (_b = currentBtn === null || currentBtn === void 0 ? void 0 : currentBtn.nextElementSibling) === null || _b === void 0 ? void 0 : _b.closest('button');
2504
- next === null || next === void 0 ? void 0 : next.focus();
2505
- }
3059
+ if (open) {
3060
+ // Wait for Popover to fully open and focus itself first
3061
+ // Then move focus to the first menu item
3062
+ const timer = setTimeout(() => {
3063
+ var _a;
3064
+ const firstItem = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('[role="option"]');
3065
+ if (firstItem) {
3066
+ firstItem.focus();
2506
3067
  }
2507
- return false;
2508
- }
2509
- };
2510
- document.addEventListener('keydown', focusHandler);
2511
- return () => {
2512
- document.removeEventListener('keydown', focusHandler);
2513
- };
3068
+ }, 100); // Wait after Popover has set initial focus
3069
+ return () => clearTimeout(timer);
3070
+ }
2514
3071
  }, [open]);
2515
- const clickHandler = () => setOpen(true);
2516
- const keyUp = (e) => {
2517
- if (e.keyCode === 40) {
3072
+ /**
3073
+ * Handles keydown events on the input trigger.
3074
+ * Opens the menu on 'Enter', 'Space', 'ArrowDown', or 'ArrowUp'.
3075
+ *
3076
+ * @param {React.KeyboardEvent<HTMLInputElement>} e - The keyboard event.
3077
+ */
3078
+ const onKeyDown = (e) => {
3079
+ if (['ArrowDown', 'ArrowUp', 'Enter', ' '].includes(e.key)) {
3080
+ e.preventDefault();
2518
3081
  setOpen(true);
2519
3082
  }
2520
3083
  };
3084
+ /**
3085
+ * Handles changes to the dropdown value.
3086
+ * Updates local state and calls the external onChange handler.
3087
+ * Closes the dropdown if not in multi-select mode.
3088
+ *
3089
+ * @param {T | T[]} val - The new value(s).
3090
+ */
2521
3091
  const changeHandler = (val) => {
3092
+ var _a;
2522
3093
  setValue(val);
2523
3094
  onChange === null || onChange === void 0 ? void 0 : onChange(val);
2524
3095
  // Close dropdown after selection if not multiSelect
2525
3096
  if (!multiSelect) {
2526
3097
  setOpen(false);
3098
+ (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
2527
3099
  }
2528
3100
  };
2529
- return (jsxRuntime.jsx(Popover, { position: exports.POPOVER_POSITION.BOTTOM_LEFT, open: open, element: () => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Input$4, { type: "text", value: value && String(value), label: props.label, errorText: props.errorText, onClick: clickHandler, onKeyUp: keyUp, required: props.required, disabled: props.disabled }), jsxRuntime.jsx(ArrowContainer, { children: jsxRuntime.jsx(ExpandMore, {}) })] })), onClose: () => setOpen(false), children: jsxRuntime.jsx(Menu, { value: value, multiSelect: multiSelect, onChange: changeHandler, children: props.children }) }));
3101
+ /**
3102
+ * Toggles the dropdown open state on click.
3103
+ */
3104
+ const clickHandler = () => setOpen(true);
3105
+ const TriggerElement = React.forwardRef((passedProps, ref) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Input$2, Object.assign({}, passedProps, { ref: ref, type: "text", value: value && String(value), label: props.label, errorText: props.errorText, onClick: clickHandler, onKeyDown: onKeyDown, required: props.required, disabled: props.disabled, readOnly: true, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": open, "aria-controls": menuId })), jsxRuntime.jsx(ArrowContainer, { "aria-hidden": "true", children: jsxRuntime.jsx(ExpandMore, {}) })] })));
3106
+ TriggerElement.displayName = 'DropdownTrigger';
3107
+ return (jsxRuntime.jsx(Popover, { position: exports.POPOVER_POSITION.BOTTOM_LEFT, open: open, element: TriggerElement, onClose: () => {
3108
+ var _a;
3109
+ setOpen(false);
3110
+ (_a = triggerRef.current) === null || _a === void 0 ? void 0 : _a.focus();
3111
+ }, children: jsxRuntime.jsx(Menu, { ref: menuRef, id: menuId, value: value, multiSelect: multiSelect, onChange: changeHandler, children: props.children }) }));
2530
3112
  }
2531
3113
  Dropdown.defaultProps = {
2532
3114
  multiSelect: false,
@@ -2571,7 +3153,7 @@ class PromptDialog extends React.Component {
2571
3153
  }
2572
3154
  render() {
2573
3155
  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 })] })] }) })));
3156
+ 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$2, 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
3157
  }
2576
3158
  }
2577
3159
  PromptDialog.propTypes = {
@@ -2626,9 +3208,9 @@ const positionStyle$1 = (size) => ({
2626
3208
  const DrawerDiv = styled.div `
2627
3209
  display: flex;
2628
3210
  flex-direction: column;
2629
- background-color: #fff;
3211
+ background-color: ${getThemeValue(THEME_NAME.BACKGROUND)};
2630
3212
  transition: transform 0.3s ease;
2631
- box-shadow: var(--modal-shadow, ${constants.MODAL_SHADOW});
3213
+ box-shadow: ${getThemeValue(THEME_NAME.MODAL_SHADOW)};
2632
3214
  ${(props) => positionStyle$1(props.size)[props.position].before}
2633
3215
 
2634
3216
  .nf-layer-enter & {
@@ -2636,19 +3218,56 @@ const DrawerDiv = styled.div `
2636
3218
  ${(props) => positionStyle$1(props.size)[props.position].after}
2637
3219
  }
2638
3220
  `;
3221
+ const drawerPropTypes = {
3222
+ /** Opens the drawer */
3223
+ open: PropTypes.bool.isRequired,
3224
+ /** position of the drawer */
3225
+ position: PropTypes.oneOf([
3226
+ exports.DRAWER_POSITION.LEFT,
3227
+ exports.DRAWER_POSITION.RIGHT,
3228
+ exports.DRAWER_POSITION.BOTTOM,
3229
+ ]),
3230
+ /** size of the drawer */
3231
+ size: PropTypes.string,
3232
+ /** Shows an overlay behind the drawer. */
3233
+ overlay: PropTypes.bool,
3234
+ /** Closes the drawer on esc */
3235
+ closeOnEsc: PropTypes.bool,
3236
+ /** Closes the drawer on overlay click */
3237
+ closeOnOverlayClick: PropTypes.bool,
3238
+ /** Call back function called when the drawer closes. */
3239
+ onClose: PropTypes.func,
3240
+ };
2639
3241
  const positionMap$1 = {
2640
3242
  [exports.DRAWER_POSITION.LEFT]: LAYER_POSITION.TOP_LEFT,
2641
3243
  [exports.DRAWER_POSITION.RIGHT]: LAYER_POSITION.TOP_RIGHT,
2642
3244
  [exports.DRAWER_POSITION.BOTTOM]: LAYER_POSITION.BOTTOM_LEFT,
2643
3245
  };
3246
+ /**
3247
+ * Drawer component
3248
+ *
3249
+ * A panel that slides in from the edge of the screen.
3250
+ * It sits on top of the application content and is often used for navigation or details.
3251
+ *
3252
+ * Accessibility:
3253
+ * - Implements ARIA `role="dialog"` and `aria-modal="true"`.
3254
+ * - Traps focus effectively within the drawer while open.
3255
+ * - Restores focus to the triggering element upon closure.
3256
+ * - Supports closing via ESC key and overlay click.
3257
+ */
2644
3258
  class Drawer extends React.Component {
2645
3259
  constructor() {
2646
3260
  super(...arguments);
2647
3261
  this.state = {
2648
3262
  open: false,
2649
3263
  };
3264
+ /**
3265
+ * Internal close handler.
3266
+ * Restores focus and calls the external onClose callback.
3267
+ */
2650
3268
  this.onClose = () => {
2651
3269
  var _a, _b;
3270
+ this.restoreFocus();
2652
3271
  this.setState({
2653
3272
  open: false,
2654
3273
  });
@@ -2656,7 +3275,97 @@ class Drawer extends React.Component {
2656
3275
  this.closeCallback = null;
2657
3276
  this.layer = null;
2658
3277
  };
3278
+ this.lastFocusedElement = null;
3279
+ this.drawerRef = React.createRef();
3280
+ /**
3281
+ * Retrieves all focusable elements within the drawer.
3282
+ */
3283
+ this.getFocusableElements = () => {
3284
+ if (!this.drawerRef.current)
3285
+ return [];
3286
+ return Array.from(this.drawerRef.current.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'));
3287
+ };
3288
+ /**
3289
+ * Handles keydown events to implement the focus trap.
3290
+ * Traps Tab and Shift+Tab within the drawer.
3291
+ */
3292
+ this.handleKeyDown = (e) => {
3293
+ if (e.key === 'Tab') {
3294
+ const focusableElements = this.getFocusableElements();
3295
+ if (focusableElements.length === 0)
3296
+ return;
3297
+ const firstElement = focusableElements[0];
3298
+ const lastElement = focusableElements[focusableElements.length - 1];
3299
+ if (e.shiftKey) {
3300
+ if (document.activeElement === firstElement) {
3301
+ lastElement.focus();
3302
+ e.preventDefault();
3303
+ }
3304
+ }
3305
+ else {
3306
+ if (document.activeElement === lastElement) {
3307
+ firstElement.focus();
3308
+ e.preventDefault();
3309
+ }
3310
+ }
3311
+ }
3312
+ };
3313
+ /**
3314
+ * Restores focus to the element that was focused before the drawer opened.
3315
+ */
3316
+ this.restoreFocus = () => {
3317
+ if (this.lastFocusedElement) {
3318
+ // Check if the element is still in the document
3319
+ const elementToBeFocused = this.lastFocusedElement;
3320
+ this.lastFocusedElement = null;
3321
+ setTimeout(() => {
3322
+ if (document.body.contains(elementToBeFocused)) {
3323
+ elementToBeFocused.focus();
3324
+ }
3325
+ }, 100);
3326
+ }
3327
+ };
3328
+ /**
3329
+ * Callback ref to capture the Drawer DOM element.
3330
+ * Triggers initial focus setting when the element mounts.
3331
+ */
3332
+ this.setDrawerRef = (node) => {
3333
+ // Update ref
3334
+ this.drawerRef.current = node;
3335
+ if (node) {
3336
+ // Set initial focus when the node is mounted
3337
+ this.setInitialFocus(node);
3338
+ }
3339
+ };
3340
+ /**
3341
+ * Sets initial focus within the drawer.
3342
+ * Tries to focus the header first, then the first interactive element, or falls back to the container.
3343
+ */
3344
+ this.setInitialFocus = (root) => {
3345
+ // Try to find the header (assumed to be the first child)
3346
+ const firstChild = root.firstElementChild;
3347
+ if (firstChild) {
3348
+ // Ensure it's focusable
3349
+ if (firstChild.getAttribute('tabindex') === null) {
3350
+ firstChild.setAttribute('tabindex', '-1');
3351
+ }
3352
+ firstChild.focus();
3353
+ return;
3354
+ }
3355
+ // Fallback to focusable elements
3356
+ const focusableElements = this.getFocusableElements();
3357
+ if (focusableElements.length > 0) {
3358
+ focusableElements[0].focus();
3359
+ }
3360
+ else {
3361
+ // Fallback to container
3362
+ root.focus();
3363
+ }
3364
+ };
2659
3365
  }
3366
+ /**
3367
+ * Syncs state with props.
3368
+ */
2660
3369
  static getDerivedStateFromProps(props) {
2661
3370
  if (props.open) {
2662
3371
  return {
@@ -2665,13 +3374,36 @@ class Drawer extends React.Component {
2665
3374
  }
2666
3375
  return null;
2667
3376
  }
3377
+ /**
3378
+ * Lifecycle method to save the currently focused element when the drawer mounts while open.
3379
+ */
3380
+ componentDidMount() {
3381
+ if (this.props.open) {
3382
+ this.lastFocusedElement = document.activeElement;
3383
+ }
3384
+ }
3385
+ /**
3386
+ * Lifecycle method to restore focus when the drawer unmounts.
3387
+ */
3388
+ componentWillUnmount() {
3389
+ if (this.props.open) {
3390
+ this.restoreFocus();
3391
+ }
3392
+ }
3393
+ /**
3394
+ * Lifecycle method to handle Drawer updates.
3395
+ * Manages opening/closing logic via LayerManager and focus preservation.
3396
+ */
2668
3397
  getSnapshotBeforeUpdate(prevProps) {
2669
3398
  var _a;
2670
3399
  const _b = this.props, { open, closeOnEsc, closeOnOverlayClick, overlay, position, children, size } = _b, rest = __rest(_b, ["open", "closeOnEsc", "closeOnOverlayClick", "overlay", "position", "children", "size"]);
2671
3400
  if (prevProps.open && !open) {
2672
3401
  (_a = this.closeCallback) === null || _a === void 0 ? void 0 : _a.call(this);
3402
+ this.restoreFocus();
2673
3403
  }
2674
3404
  if (!prevProps.open && open) {
3405
+ // Save current focus
3406
+ this.lastFocusedElement = document.activeElement;
2675
3407
  this.layer = LayerManager$1.renderLayer({
2676
3408
  overlay,
2677
3409
  exitDelay: 300,
@@ -2679,12 +3411,15 @@ class Drawer extends React.Component {
2679
3411
  closeCallback: this.onClose,
2680
3412
  closeOnEsc,
2681
3413
  closeOnOverlayClick,
2682
- component: (jsxRuntime.jsx(DrawerDiv, Object.assign({}, rest, { position: position, size: size, onClick: (e) => e.stopPropagation(), children: children }))),
3414
+ component: (jsxRuntime.jsx(DrawerDiv, Object.assign({}, rest, { ref: this.setDrawerRef, role: "dialog", "aria-modal": "true", tabIndex: -1, onKeyDown: this.handleKeyDown, position: position, size: size, onClick: (e) => e.stopPropagation(), children: children }))),
2683
3415
  });
2684
3416
  this.closeCallback = this.layer[1];
2685
3417
  this.forceUpdate();
2686
3418
  }
2687
3419
  }
3420
+ /**
3421
+ * Renders the Drawer component via the LayerManager portal.
3422
+ */
2688
3423
  render() {
2689
3424
  if (this.state.open && this.layer) {
2690
3425
  const [Component] = this.layer;
@@ -2693,26 +3428,7 @@ class Drawer extends React.Component {
2693
3428
  return null;
2694
3429
  }
2695
3430
  }
2696
- Drawer.propTypes = {
2697
- /** Opens the drawer */
2698
- open: PropTypes.bool.isRequired,
2699
- /** position of the drawer */
2700
- position: PropTypes.oneOf([
2701
- exports.DRAWER_POSITION.LEFT,
2702
- exports.DRAWER_POSITION.RIGHT,
2703
- exports.DRAWER_POSITION.BOTTOM,
2704
- ]),
2705
- /** size of the drawer */
2706
- size: PropTypes.string,
2707
- /** Shows an overlay behind the drawer. */
2708
- overlay: PropTypes.bool,
2709
- /** Closes the drawer on esc */
2710
- closeOnEsc: PropTypes.bool,
2711
- /** Closes the drawer on overlay click */
2712
- closeOnOverlayClick: PropTypes.bool,
2713
- /** Call back function called when the drawer closes. */
2714
- onClose: PropTypes.func,
2715
- };
3431
+ Drawer.propTypes = drawerPropTypes;
2716
3432
  Drawer.defaultProps = {
2717
3433
  overlay: true,
2718
3434
  position: exports.DRAWER_POSITION.LEFT,
@@ -2722,7 +3438,7 @@ Drawer.defaultProps = {
2722
3438
 
2723
3439
  const Container$3 = styled.div `
2724
3440
  display: inline-flex;
2725
- border: 1px solid var(--border-color, ${constants.BORDER_COLOR});
3441
+ border: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
2726
3442
  border-radius: 3px;
2727
3443
  margin: 5px;
2728
3444
 
@@ -2732,7 +3448,7 @@ const Container$3 = styled.div `
2732
3448
  margin: 0;
2733
3449
  border: none;
2734
3450
  border-radius: 0;
2735
- border-left: 1px solid var(--border-color, ${constants.BORDER_COLOR});
3451
+ border-left: 1px solid ${getThemeValue(THEME_NAME.BORDER_COLOR)};
2736
3452
  box-shadow: none;
2737
3453
  height: 32px;
2738
3454
  }
@@ -2787,26 +3503,27 @@ const Container$3 = styled.div `
2787
3503
 
2788
3504
  &:focus-within,
2789
3505
  &:hover {
2790
- box-shadow: var(--hover-shadow, ${constants.HOVER_SHADOW});
3506
+ box-shadow: ${getThemeValue(THEME_NAME.HOVER_SHADOW)};
2791
3507
  }
2792
3508
 
2793
3509
  ${(props) => props.errorText
2794
3510
  ? `
2795
- border-color: var(--error, ${constants.ERROR});
3511
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
2796
3512
 
2797
3513
  & > button, & > label {
2798
- border-color: var(--error, ${constants.ERROR});
3514
+ border-color: ${getThemeValue(THEME_NAME.ERROR)};
2799
3515
  }
2800
3516
  `
2801
3517
  : ''}
2802
3518
  `;
2803
3519
  const ErrorContainer = styled.div `
2804
- color: var(--error, ${constants.ERROR});
3520
+ color: ${getThemeValue(THEME_NAME.ERROR)};
2805
3521
  margin-left: 8px;
2806
3522
  font-size: 12px;
2807
3523
  `;
2808
3524
  function Group(props) {
2809
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Container$3, Object.assign({}, props, { children: props.children })), props.errorText && jsxRuntime.jsx(ErrorContainer, { children: props.errorText })] }));
3525
+ const errorId = React.useId();
3526
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(Container$3, Object.assign({}, props, { "aria-describedby": props.errorText ? errorId : undefined, children: props.children })), props.errorText && jsxRuntime.jsx(ErrorContainer, { id: errorId, children: props.errorText })] }));
2810
3527
  }
2811
3528
  Group.propTypes = {
2812
3529
  /** Error Message for the group */
@@ -2815,12 +3532,12 @@ Group.propTypes = {
2815
3532
 
2816
3533
  var GroupLabel = styled.label `
2817
3534
  height: 32px;
2818
- background-color: ${constants.DISABLED_BACKGROUND};
3535
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
2819
3536
  padding: 0 4px;
2820
3537
  line-height: 32px;
2821
3538
  min-width: 24px;
2822
3539
  text-align: center;
2823
- color: ${constants.BORDER_COLOR};
3540
+ color: ${getThemeValue(THEME_NAME.BORDER_COLOR)};
2824
3541
 
2825
3542
  & > svg {
2826
3543
  height: 24px;
@@ -2830,14 +3547,41 @@ var GroupLabel = styled.label `
2830
3547
  }
2831
3548
  `;
2832
3549
 
3550
+ const modalPropTypes = {
3551
+ /** Opens the modal */
3552
+ open: PropTypes.bool.isRequired,
3553
+ /** Closes the modal on esc */
3554
+ closeOnEsc: PropTypes.bool,
3555
+ /** Closes the modal on overlay click */
3556
+ closeOnOverlayClick: PropTypes.bool,
3557
+ /** Call back function called when the modal closes. */
3558
+ onClose: PropTypes.func,
3559
+ };
3560
+ /**
3561
+ * Modal component
3562
+ *
3563
+ * A dialog window that sits on top of the main application content.
3564
+ * It disrupts the user's workflow to demand attention for a critical task or decision.
3565
+ *
3566
+ * Accessibility:
3567
+ * - Implements ARIA `role="dialog"` and `aria-modal="true"`.
3568
+ * - Traps focus effectively within the modal while open.
3569
+ * - Restores focus to the triggering element upon closure.
3570
+ * - Supports closing via ESC key and overlay click.
3571
+ */
2833
3572
  class Modal extends React.Component {
2834
3573
  constructor() {
2835
3574
  super(...arguments);
2836
3575
  this.state = {
2837
3576
  open: false,
2838
3577
  };
3578
+ /**
3579
+ * Internal close handler.
3580
+ * Restores focus and calls the external onClose callback.
3581
+ */
2839
3582
  this.onClose = () => {
2840
3583
  var _a, _b;
3584
+ this.restoreFocus();
2841
3585
  this.setState({
2842
3586
  open: false,
2843
3587
  });
@@ -2845,7 +3589,97 @@ class Modal extends React.Component {
2845
3589
  this.closeCallback = null;
2846
3590
  this.layer = null;
2847
3591
  };
3592
+ this.lastFocusedElement = null;
3593
+ this.modalRef = React.createRef();
3594
+ /**
3595
+ * Retrieves all focusable elements within the modal.
3596
+ */
3597
+ this.getFocusableElements = () => {
3598
+ if (!this.modalRef.current)
3599
+ return [];
3600
+ return Array.from(this.modalRef.current.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'));
3601
+ };
3602
+ /**
3603
+ * Handles keydown events to implement the focus trap.
3604
+ * Traps Tab and Shift+Tab within the modal.
3605
+ */
3606
+ this.handleKeyDown = (e) => {
3607
+ if (e.key === 'Tab') {
3608
+ const focusableElements = this.getFocusableElements();
3609
+ if (focusableElements.length === 0)
3610
+ return;
3611
+ const firstElement = focusableElements[0];
3612
+ const lastElement = focusableElements[focusableElements.length - 1];
3613
+ if (e.shiftKey) {
3614
+ if (document.activeElement === firstElement) {
3615
+ lastElement.focus();
3616
+ e.preventDefault();
3617
+ }
3618
+ }
3619
+ else {
3620
+ if (document.activeElement === lastElement) {
3621
+ firstElement.focus();
3622
+ e.preventDefault();
3623
+ }
3624
+ }
3625
+ }
3626
+ };
3627
+ /**
3628
+ * Restores focus to the element that was focused before the modal opened.
3629
+ */
3630
+ this.restoreFocus = () => {
3631
+ if (this.lastFocusedElement) {
3632
+ // Check if the element is still in the document
3633
+ const elementToBeFocused = this.lastFocusedElement;
3634
+ this.lastFocusedElement = null;
3635
+ setTimeout(() => {
3636
+ if (document.body.contains(elementToBeFocused)) {
3637
+ elementToBeFocused.focus();
3638
+ }
3639
+ }, 100);
3640
+ }
3641
+ };
3642
+ /**
3643
+ * Callback ref to capture the Modal DOM element.
3644
+ * Triggers initial focus setting when the element mounts.
3645
+ */
3646
+ this.setModalRef = (node) => {
3647
+ // Update ref
3648
+ this.modalRef.current = node;
3649
+ if (node) {
3650
+ // Set initial focus when the node is mounted
3651
+ this.setInitialFocus(node);
3652
+ }
3653
+ };
3654
+ /**
3655
+ * Sets initial focus within the modal.
3656
+ * Tries to focus the header (first child) first, then the first interactive element, or falls back to the container.
3657
+ */
3658
+ this.setInitialFocus = (root) => {
3659
+ // Try to find the header (assumed to be the first child)
3660
+ const firstChild = root.firstElementChild;
3661
+ if (firstChild) {
3662
+ // Ensure it's focusable
3663
+ if (firstChild.getAttribute('tabindex') === null) {
3664
+ firstChild.setAttribute('tabindex', '-1');
3665
+ }
3666
+ firstChild.focus();
3667
+ return;
3668
+ }
3669
+ // Fallback to focusable elements
3670
+ const focusableElements = this.getFocusableElements();
3671
+ if (focusableElements.length > 0) {
3672
+ focusableElements[0].focus();
3673
+ }
3674
+ else {
3675
+ // Fallback to container
3676
+ root.focus();
3677
+ }
3678
+ };
2848
3679
  }
3680
+ /**
3681
+ * Syncs state with props.
3682
+ */
2849
3683
  static getDerivedStateFromProps(props) {
2850
3684
  if (props.open) {
2851
3685
  return {
@@ -2854,13 +3688,36 @@ class Modal extends React.Component {
2854
3688
  }
2855
3689
  return null;
2856
3690
  }
3691
+ /**
3692
+ * Lifecycle method to save the currently focused element when the modal mounts while open.
3693
+ */
3694
+ componentDidMount() {
3695
+ if (this.props.open) {
3696
+ this.lastFocusedElement = document.activeElement;
3697
+ }
3698
+ }
3699
+ /**
3700
+ * Lifecycle method to restore focus when the modal unmounts.
3701
+ */
3702
+ componentWillUnmount() {
3703
+ if (this.props.open) {
3704
+ this.restoreFocus();
3705
+ }
3706
+ }
3707
+ /**
3708
+ * Lifecycle method to handle Modal updates.
3709
+ * Manages opening/closing logic via LayerManager and focus preservation.
3710
+ */
2857
3711
  getSnapshotBeforeUpdate(prevProps) {
2858
3712
  var _a;
2859
3713
  const _b = this.props, { open, closeOnEsc, closeOnOverlayClick, children } = _b, rest = __rest(_b, ["open", "closeOnEsc", "closeOnOverlayClick", "children"]);
2860
3714
  if (prevProps.open && !open) {
2861
3715
  (_a = this.closeCallback) === null || _a === void 0 ? void 0 : _a.call(this);
3716
+ this.restoreFocus();
2862
3717
  }
2863
3718
  if (!prevProps.open && open) {
3719
+ // Save current focus
3720
+ this.lastFocusedElement = document.activeElement;
2864
3721
  this.layer = LayerManager$1.renderLayer({
2865
3722
  overlay: true,
2866
3723
  exitDelay: 300,
@@ -2868,12 +3725,15 @@ class Modal extends React.Component {
2868
3725
  closeCallback: this.onClose,
2869
3726
  closeOnEsc: closeOnEsc,
2870
3727
  closeOnOverlayClick: closeOnOverlayClick,
2871
- component: (jsxRuntime.jsx(DialogContainer, Object.assign({}, rest, { onClick: (e) => e.stopPropagation(), elevated: true, children: children }))),
3728
+ component: (jsxRuntime.jsx(DialogContainer, Object.assign({}, rest, { ref: this.setModalRef, role: "dialog", "aria-modal": "true", tabIndex: -1, onKeyDown: this.handleKeyDown, onClick: (e) => e.stopPropagation(), elevated: true, children: children }))),
2872
3729
  });
2873
3730
  this.closeCallback = this.layer[1];
2874
3731
  this.forceUpdate();
2875
3732
  }
2876
3733
  }
3734
+ /**
3735
+ * Renders the Modal component via the LayerManager portal.
3736
+ */
2877
3737
  render() {
2878
3738
  if (this.state.open && this.layer) {
2879
3739
  const [Component] = this.layer;
@@ -2882,16 +3742,7 @@ class Modal extends React.Component {
2882
3742
  return null;
2883
3743
  }
2884
3744
  }
2885
- Modal.propTypes = {
2886
- /** Opens the modal */
2887
- open: PropTypes.bool.isRequired,
2888
- /** Closes the modal on esc */
2889
- closeOnEsc: PropTypes.bool,
2890
- /** Closes the modal on overlay click */
2891
- closeOnOverlayClick: PropTypes.bool,
2892
- /** Call back function called when the modal closes. */
2893
- onClose: PropTypes.func,
2894
- };
3745
+ Modal.propTypes = modalPropTypes;
2895
3746
  Modal.defaultProps = {
2896
3747
  closeOnEsc: true,
2897
3748
  closeOnOverlayClick: true,
@@ -2935,37 +3786,37 @@ const getExitAnimation = (position) => {
2935
3786
  const getBorderColor = (type) => {
2936
3787
  switch (type) {
2937
3788
  case exports.NOTIFICATION_TYPE.SUCCESS:
2938
- return `var(--success-light, ${constants.SUCCESS_LIGHT})`;
3789
+ return getThemeValue(THEME_NAME.SUCCESS_LIGHT);
2939
3790
  case exports.NOTIFICATION_TYPE.DANGER:
2940
- return `var(--error-light, ${constants.ERROR_LIGHT})`;
3791
+ return getThemeValue(THEME_NAME.ERROR_LIGHT);
2941
3792
  case exports.NOTIFICATION_TYPE.WARNING:
2942
- return `var(--warning-light, ${constants.WARNING_LIGHT})`;
3793
+ return getThemeValue(THEME_NAME.WARNING_LIGHT);
2943
3794
  default:
2944
- return `var(--info-light, ${constants.INFO_LIGHT})`;
3795
+ return getThemeValue(THEME_NAME.INFO_LIGHT);
2945
3796
  }
2946
3797
  };
2947
3798
  const getTitleColor = (type) => {
2948
3799
  switch (type) {
2949
3800
  case exports.NOTIFICATION_TYPE.SUCCESS:
2950
- return `var(--success, ${constants.SUCCESS})`;
3801
+ return getThemeValue(THEME_NAME.SUCCESS);
2951
3802
  case exports.NOTIFICATION_TYPE.DANGER:
2952
- return `var(--error, ${constants.ERROR})`;
3803
+ return getThemeValue(THEME_NAME.ERROR);
2953
3804
  case exports.NOTIFICATION_TYPE.WARNING:
2954
- return `var(--warning, ${constants.WARNING})`;
3805
+ return getThemeValue(THEME_NAME.WARNING);
2955
3806
  case exports.NOTIFICATION_TYPE.INFO:
2956
- return `var(--info, ${constants.INFO})`;
3807
+ return getThemeValue(THEME_NAME.INFO);
2957
3808
  }
2958
3809
  };
2959
3810
  const getTypeStyle = (type) => {
2960
3811
  switch (type) {
2961
3812
  case exports.NOTIFICATION_TYPE.INFO:
2962
- return `color: var(--info, ${constants.INFO})`;
3813
+ return `color: ${getThemeValue(THEME_NAME.INFO)}`;
2963
3814
  case exports.NOTIFICATION_TYPE.SUCCESS:
2964
- return `color: var(--success, ${constants.SUCCESS})`;
3815
+ return `color: ${getThemeValue(THEME_NAME.SUCCESS)}`;
2965
3816
  case exports.NOTIFICATION_TYPE.DANGER:
2966
- return `color: var(--error, ${constants.ERROR})`;
3817
+ return `color: ${getThemeValue(THEME_NAME.ERROR)}`;
2967
3818
  case exports.NOTIFICATION_TYPE.WARNING:
2968
- return `color: var(--warning, ${constants.WARNING})`;
3819
+ return `color: ${getThemeValue(THEME_NAME.WARNING)}`;
2969
3820
  }
2970
3821
  };
2971
3822
  const Container$2 = styled.div `
@@ -2976,6 +3827,7 @@ const Container$2 = styled.div `
2976
3827
  : 'column-reverse'};
2977
3828
  `;
2978
3829
  const Notice = styled(Card) `
3830
+ position: relative;
2979
3831
  border-radius: 3px;
2980
3832
  border-left: 4px solid ${(props) => getBorderColor(props.type)};
2981
3833
  width: 300px;
@@ -3062,13 +3914,16 @@ const FillParent = styled.div `
3062
3914
  flex: 1;
3063
3915
  `;
3064
3916
  const CloseButton = styled.button `
3917
+ position: absolute;
3065
3918
  background-color: transparent;
3066
3919
  border: none;
3067
- padding: none;
3920
+ padding: 0;
3921
+ top: 4px;
3922
+ right: 4px;
3068
3923
  cursor: pointer;
3069
3924
 
3070
3925
  &:focus {
3071
- box-shadow: 0 0 0 3px var(--primary, ${constants.PRIMARY_LIGHT});
3926
+ box-shadow: 0 0 0 3px ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
3072
3927
  border-radius: 3px;
3073
3928
  }
3074
3929
  `;
@@ -3085,6 +3940,17 @@ const Footer = styled.div `
3085
3940
  justify-content: flex-end;
3086
3941
  padding: 0 5px;
3087
3942
  `;
3943
+ const VisuallyHidden = styled.span `
3944
+ position: absolute;
3945
+ width: 1px;
3946
+ height: 1px;
3947
+ padding: 0;
3948
+ margin: -1px;
3949
+ overflow: hidden;
3950
+ clip: rect(0, 0, 0, 0);
3951
+ white-space: nowrap;
3952
+ border: 0;
3953
+ `;
3088
3954
 
3089
3955
  const DEFAULT_DURATION$1 = 5000;
3090
3956
  /**
@@ -3100,6 +3966,9 @@ class NotificationManager extends React.Component {
3100
3966
  this.timeouts = {};
3101
3967
  // Set of notification ids
3102
3968
  this.set = new Set();
3969
+ // Refs for live regions to ensure they exist before updates
3970
+ this.politeRegionRef = React.createRef();
3971
+ this.assertiveRegionRef = React.createRef();
3103
3972
  /**
3104
3973
  * Removes a notification from stack if the notification with the given id is found.
3105
3974
  *
@@ -3142,17 +4011,23 @@ class NotificationManager extends React.Component {
3142
4011
  *
3143
4012
  * @param notice
3144
4013
  */
3145
- this.add = (notice) => {
4014
+ this.add = (notice) => __awaiter(this, void 0, void 0, function* () {
3146
4015
  // Generate unique id if not provided.
3147
4016
  const id = notice.id || (Math.random() * Math.pow(10, 7)).toFixed(0);
3148
4017
  // De-dupe on id
3149
4018
  if (!this.set.has(id)) {
4019
+ const type = notice.type || exports.NOTIFICATION_TYPE.INFO;
4020
+ const isUrgent = type === exports.NOTIFICATION_TYPE.WARNING || type === exports.NOTIFICATION_TYPE.DANGER;
3150
4021
  // Add notice to the top of stack.
3151
4022
  this.setState({
3152
4023
  notices: [
3153
4024
  Object.assign(Object.assign({}, notice), { id }),
3154
4025
  ...this.state.notices,
3155
4026
  ],
4027
+ }, () => {
4028
+ // Update live region after state update
4029
+ const announcement = `${notice.title} ${notice.description}`;
4030
+ this.updateLiveRegion(announcement, isUrgent);
3156
4031
  });
3157
4032
  // set timeout for closing the notification.
3158
4033
  if (!notice.sticky) {
@@ -3162,6 +4037,23 @@ class NotificationManager extends React.Component {
3162
4037
  this.set.add(id);
3163
4038
  }
3164
4039
  return id;
4040
+ });
4041
+ /**
4042
+ * Update live region content with clear-then-set pattern for reliable VoiceOver announcements.
4043
+ *
4044
+ * @param content - The text content to announce
4045
+ * @param isAssertive - Whether to use assertive (alert) or polite (log) live region
4046
+ */
4047
+ this.updateLiveRegion = (content, isAssertive) => {
4048
+ const region = isAssertive ? this.assertiveRegionRef.current : this.politeRegionRef.current;
4049
+ if (region) {
4050
+ // Add content after delay
4051
+ setTimeout(() => {
4052
+ if (region) {
4053
+ region.textContent = content;
4054
+ }
4055
+ }, 150);
4056
+ }
3165
4057
  };
3166
4058
  /**
3167
4059
  * Handler for close button click.
@@ -3192,12 +4084,12 @@ class NotificationManager extends React.Component {
3192
4084
  };
3193
4085
  }
3194
4086
  render() {
3195
- return (jsxRuntime.jsx(Container$2, { position: this.props.position, children: this.state.notices.map((notice) => {
3196
- const { id, title, description, leaving, type = exports.NOTIFICATION_TYPE.INFO, buttonText, buttonClick, } = notice;
3197
- return (jsxRuntime.jsxs(Notice, Object.assign({}, notice, { position: this.props.position, className: leaving ? 'leave' : '', onMouseEnter: this.pause(id), onMouseLeave: this.resume(id), children: [jsxRuntime.jsxs(IconContainer, { type: type, children: [type === exports.NOTIFICATION_TYPE.INFO && jsxRuntime.jsx(CheckCircle$3, {}), type === exports.NOTIFICATION_TYPE.SUCCESS && jsxRuntime.jsx(CheckCircle$4, {}), type === exports.NOTIFICATION_TYPE.WARNING && jsxRuntime.jsx(CheckCircle$2, {}), type === exports.NOTIFICATION_TYPE.DANGER && jsxRuntime.jsx(CheckCircle$1, {})] }), jsxRuntime.jsxs(FillParent, { children: [jsxRuntime.jsxs(Title, { type: type, children: [jsxRuntime.jsx(FillParent, { children: title }), jsxRuntime.jsx(CloseButton, { onClick: this.closeClickHandler(id), children: jsxRuntime.jsx(Close, {}) })] }), jsxRuntime.jsx(Body, { children: description }), buttonText && (jsxRuntime.jsx(Footer, { children: jsxRuntime.jsx(ActionButton, { onClick: () => {
3198
- buttonClick === null || buttonClick === void 0 ? void 0 : buttonClick();
3199
- }, children: buttonText }) }))] })] }), id));
3200
- }) }));
4087
+ return (jsxRuntime.jsxs(Container$2, { position: this.props.position, children: [jsxRuntime.jsx(VisuallyHidden, { ref: this.politeRegionRef, role: "log", "aria-live": "polite", "aria-atomic": "false", "aria-relevant": "additions text" }), jsxRuntime.jsx(VisuallyHidden, { ref: this.assertiveRegionRef, role: "alert", "aria-live": "assertive", "aria-atomic": "true" }), jsxRuntime.jsx("div", { role: "list", "aria-label": this.props.ariaLabel, children: this.state.notices.map((notice) => {
4088
+ const { id, title, description, leaving, type = exports.NOTIFICATION_TYPE.INFO, buttonText, buttonClick, closeButtonAriaLabel, } = notice;
4089
+ return (jsxRuntime.jsxs(Notice, Object.assign({}, notice, { position: this.props.position, className: leaving ? 'leave' : '', onMouseEnter: this.pause(id), onMouseLeave: this.resume(id), role: "listitem", children: [jsxRuntime.jsxs(IconContainer, { type: type, "aria-hidden": "true", children: [type === exports.NOTIFICATION_TYPE.INFO && jsxRuntime.jsx(CheckCircle$3, {}), type === exports.NOTIFICATION_TYPE.SUCCESS && jsxRuntime.jsx(CheckCircle$4, {}), type === exports.NOTIFICATION_TYPE.WARNING && jsxRuntime.jsx(CheckCircle$2, {}), type === exports.NOTIFICATION_TYPE.DANGER && jsxRuntime.jsx(CheckCircle$1, {})] }), jsxRuntime.jsxs(FillParent, { children: [jsxRuntime.jsx(Title, { type: type, children: title }), jsxRuntime.jsx(Body, { children: description }), buttonText && (jsxRuntime.jsx(Footer, { children: jsxRuntime.jsx(ActionButton, { onClick: () => {
4090
+ buttonClick === null || buttonClick === void 0 ? void 0 : buttonClick();
4091
+ }, children: buttonText }) }))] }), jsxRuntime.jsx(CloseButton, { onClick: this.closeClickHandler(id), "aria-label": closeButtonAriaLabel || 'Close notification', tabIndex: 0, children: jsxRuntime.jsx(Close, {}) })] }), id));
4092
+ }) })] }));
3201
4093
  }
3202
4094
  }
3203
4095
 
@@ -3231,6 +4123,8 @@ StoryProps.propTypes = {
3231
4123
  buttonClick: PropTypes.func,
3232
4124
  /** Notification close callback. */
3233
4125
  onClose: PropTypes.func,
4126
+ /** Aria label for the close button on the notification. Defaults to "Close notification" */
4127
+ closeButtonAriaLabel: PropTypes.string,
3234
4128
  };
3235
4129
  StoryProps.defaultProps = {
3236
4130
  duration: 5000,
@@ -3252,56 +4146,83 @@ class Notification {
3252
4146
  /**
3253
4147
  * Adds a notification
3254
4148
  *
3255
- * @param position
3256
- * @param options
4149
+ * @param position - The position where the notification should appear
4150
+ * @param options - Configuration options for the notification
4151
+ * @returns The notification ID or a promise that resolves to the notification ID
3257
4152
  */
3258
- this.add = (position, options) => {
3259
- let notification;
4153
+ this.add = (position, options, ariaLabel = 'Notifications') => {
3260
4154
  if (!this.containers.has(position)) {
3261
- const div = document === null || document === void 0 ? void 0 : document.createElement('div');
3262
- const ref = React.createRef();
4155
+ /** Callback ref to capture the NotificationManager instance when it mounts */
4156
+ const refCallback = (instance) => {
4157
+ if (instance) {
4158
+ const container = this.containers.get(position);
4159
+ if (container) {
4160
+ container.manager = instance;
4161
+ }
4162
+ }
4163
+ };
3263
4164
  const [Component] = LayerManager$1.renderLayer({
3264
4165
  closeOnEsc: false,
3265
4166
  closeOnOverlayClick: false,
3266
4167
  position: positionMap[position],
3267
4168
  alwaysOnTop: true,
3268
- component: (jsxRuntime.jsx(NotificationManager, { ref: ref, position: position, onEmpty: () => this.destroy(position) })),
4169
+ component: (jsxRuntime.jsx(NotificationManager, { ref: refCallback, position: position, onEmpty: () => this.destroy(position), ariaLabel: ariaLabel })),
3269
4170
  });
4171
+ // Create a div to mount the Component
4172
+ const div = document.createElement('div');
4173
+ document.body.appendChild(div);
4174
+ const root = client.createRoot(div);
3270
4175
  this.containers.set(position, {
3271
- ref,
3272
- element: div,
3273
- root: client.createRoot(div),
4176
+ manager: null,
4177
+ root,
4178
+ div,
3274
4179
  });
4180
+ // Render the Component which will trigger the LayerManager's useEffect
3275
4181
  ReactDOM.flushSync(() => {
3276
- this.containers.get(position).root.render(jsxRuntime.jsx(Component, {}));
4182
+ root.render(jsxRuntime.jsx(Component, {}));
3277
4183
  });
3278
- notification = ref;
3279
4184
  }
3280
- else {
3281
- notification = this.containers.get(position).ref;
4185
+ const container = this.containers.get(position);
4186
+ if (container && container.manager) {
4187
+ return container.manager.add(options);
3282
4188
  }
3283
- return notification.current.add(options);
4189
+ // If manager is not ready yet, wait a bit and retry
4190
+ return new Promise((resolve) => {
4191
+ setTimeout(() => {
4192
+ const container = this.containers.get(position);
4193
+ if (container && container.manager) {
4194
+ resolve(container.manager.add(options));
4195
+ }
4196
+ }, 10);
4197
+ });
3284
4198
  };
3285
4199
  /**
3286
4200
  * Removes a notification
3287
4201
  *
3288
- * @param position
3289
- * @param id
4202
+ * @param position - The position of the notification container
4203
+ * @param id - The unique ID of the notification to remove
3290
4204
  */
3291
4205
  this.remove = (position, id) => {
3292
- if (this.containers.has(position)) {
3293
- this.containers.get(position).ref.current.remove(id);
4206
+ const container = this.containers.get(position);
4207
+ if (container && container.manager) {
4208
+ container.manager.remove(id);
3294
4209
  }
3295
4210
  };
3296
4211
  /**
3297
- * Destroys entire stack of notifications.
4212
+ * Destroys entire stack of notifications at a position.
4213
+ * Unmounts the React root and cleans up DOM elements.
3298
4214
  *
3299
- * @param position
4215
+ * @param position - The position of the notification container to destroy
3300
4216
  */
3301
4217
  this.destroy = (position) => {
3302
- const notification = this.containers.get(position);
3303
- notification.root.unmount();
3304
- this.containers.delete(position);
4218
+ const container = this.containers.get(position);
4219
+ if (container) {
4220
+ container.root.unmount();
4221
+ if (document.body.contains(container.div)) {
4222
+ document.body.removeChild(container.div);
4223
+ }
4224
+ this.containers.delete(position);
4225
+ }
3305
4226
  };
3306
4227
  }
3307
4228
  }
@@ -3309,8 +4230,8 @@ class Notification {
3309
4230
  var Notification$1 = new Notification();
3310
4231
 
3311
4232
  const SpinnerDiv = styled.div `
3312
- border: 4px solid var(--primary, ${constants.PRIMARY});
3313
- border-top: 4px solid var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
4233
+ border: 4px solid ${getThemeValue(THEME_NAME.PRIMARY)};
4234
+ border-top: 4px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
3314
4235
  border-radius: 50%;
3315
4236
  width: ${(props) => props.size}px;
3316
4237
  height: ${(props) => props.size}px;
@@ -3327,14 +4248,18 @@ const SpinnerDiv = styled.div `
3327
4248
  }
3328
4249
  `;
3329
4250
  function Spinner(props) {
3330
- return jsxRuntime.jsx(SpinnerDiv, Object.assign({}, props));
4251
+ const { label } = props, rest = __rest(props, ["label"]);
4252
+ return (jsxRuntime.jsx(SpinnerDiv, Object.assign({}, rest, { role: "status", "aria-label": label, "aria-live": "polite", "aria-busy": "true" })));
3331
4253
  }
3332
4254
  Spinner.propTypes = {
3333
4255
  /** Spinner's size */
3334
4256
  size: PropTypes.number,
4257
+ /** Accessible label for screen readers */
4258
+ label: PropTypes.string,
3335
4259
  };
3336
4260
  Spinner.defaultProps = {
3337
4261
  size: 30,
4262
+ label: 'Loading',
3338
4263
  };
3339
4264
 
3340
4265
  const Container$1 = styled.div `
@@ -3347,7 +4272,7 @@ const Header = styled.div `
3347
4272
  display: flex;
3348
4273
  flex-direction: row;
3349
4274
  justify-content: space-between;
3350
- border-bottom: 1px solid var(--border-light-color, ${constants.BORDER_LIGHT_COLOR});
4275
+ border-bottom: 1px solid ${getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)};
3351
4276
 
3352
4277
  @media (min-width: 601px) {
3353
4278
  &::before {
@@ -3356,7 +4281,7 @@ const Header = styled.div `
3356
4281
  left: 0;
3357
4282
  right: 0;
3358
4283
  height: 2px;
3359
- background-color: var(--light-grey, ${constants.LIGHT_GREY});
4284
+ background-color: ${getThemeValue(THEME_NAME.LIGHT_GREY)};
3360
4285
  content: ' ';
3361
4286
  z-index: 0;
3362
4287
  }
@@ -3372,21 +4297,22 @@ const HeaderButton = styled.button `
3372
4297
  font-size: 16px;
3373
4298
  cursor: pointer;
3374
4299
  background-color: ${(props) => props.active
3375
- ? `var(--border-light-color, ${constants.BORDER_LIGHT_COLOR})`
3376
- : `var(--background, ${constants.BACKGROUND})`};
4300
+ ? getThemeValue(THEME_NAME.BORDER_LIGHT_COLOR)
4301
+ : getThemeValue(THEME_NAME.BACKGROUND)};
3377
4302
  font-weight: ${(props) => (props.active ? 'bold' : 'normal')};
3378
4303
  overflow: hidden;
3379
4304
  display: flex;
3380
4305
  align-items: center;
4306
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
3381
4307
 
3382
4308
  &:disabled {
3383
4309
  cursor: not-allowed;
3384
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
4310
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
3385
4311
  }
3386
4312
 
3387
4313
  &:enabled:hover,
3388
4314
  &:focus {
3389
- background-color: var(--primary-light, ${constants.PRIMARY_LIGHTER});
4315
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHTER)};
3390
4316
  }
3391
4317
 
3392
4318
  @media (max-width: 600px) {
@@ -3416,9 +4342,13 @@ function Stepper(props) {
3416
4342
  const [active, setActive] = React.useState(props.active);
3417
4343
  const { children, onStepClick } = props;
3418
4344
  const childrenArray = React.Children.toArray(children);
4345
+ const stepRefs = [];
3419
4346
  const stepClickHandler = (index) => () => {
4347
+ var _a;
3420
4348
  setActive(index);
3421
4349
  onStepClick === null || onStepClick === void 0 ? void 0 : onStepClick(index);
4350
+ // Move focus to the active step
4351
+ (_a = stepRefs[index]) === null || _a === void 0 ? void 0 : _a.focus();
3422
4352
  };
3423
4353
  const getBadgeType = (index, completed, disabled) => {
3424
4354
  if (disabled) {
@@ -3432,10 +4362,24 @@ function Stepper(props) {
3432
4362
  }
3433
4363
  return exports.BADGE_TYPE.DISABLED;
3434
4364
  };
3435
- return (jsxRuntime.jsxs(Container$1, { children: [jsxRuntime.jsxs(Header, { children: [React.Children.map(children, (child, index) => {
4365
+ // Keyboard navigation for step buttons
4366
+ const onStepKeyDown = (index) => (e) => {
4367
+ var _a, _b;
4368
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
4369
+ e.preventDefault();
4370
+ const next = (index + 1) % childrenArray.length;
4371
+ (_a = stepRefs[next]) === null || _a === void 0 ? void 0 : _a.focus();
4372
+ }
4373
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
4374
+ e.preventDefault();
4375
+ const prev = (index - 1 + childrenArray.length) % childrenArray.length;
4376
+ (_b = stepRefs[prev]) === null || _b === void 0 ? void 0 : _b.focus();
4377
+ }
4378
+ };
4379
+ return (jsxRuntime.jsxs(Container$1, { children: [jsxRuntime.jsxs(Header, { role: "tablist", "aria-label": "Stepper Steps", children: [React.Children.map(children, (child, index) => {
3436
4380
  if (!React.isValidElement(child))
3437
4381
  return null;
3438
- return (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(HeaderButton, { active: index === active, type: "button", disabled: child.props.disabled, onClick: stepClickHandler(index), children: [jsxRuntime.jsx(Badge, { inline: true, type: getBadgeType(index, child.props.completed, child.props.disabled) }), jsxRuntime.jsx(Ellipsis, { children: child.props.name })] }) }));
4382
+ return (jsxRuntime.jsxs(HeaderButton, { ref: (el) => (stepRefs[index] = el), active: index === active, type: "button", role: "tab", "aria-selected": index === active, "aria-disabled": !!child.props.disabled, tabIndex: index === active ? 0 : -1, disabled: child.props.disabled, onClick: stepClickHandler(index), onKeyDown: onStepKeyDown(index), children: [jsxRuntime.jsx(Badge, { inline: true, type: getBadgeType(index, child.props.completed, child.props.disabled) }), jsxRuntime.jsx(Ellipsis, { children: child.props.name })] }));
3439
4383
  }), jsxRuntime.jsxs(MobileHeader, { children: [jsxRuntime.jsx("span", { children: React.isValidElement(childrenArray[active])
3440
4384
  ? childrenArray[active].props.name
3441
4385
  : '' }), jsxRuntime.jsxs(Badge, { inline: true, type: exports.BADGE_TYPE.PRIMARY, children: [active + 1, " of ", React.Children.count(children)] })] })] }), childrenArray[active]] }));
@@ -3471,26 +4415,28 @@ const Button = styled.button `
3471
4415
  padding: 8px 12px;
3472
4416
  font-size: 14px;
3473
4417
  border-radius: 3px 3px 0 0;
3474
- border-bottom: ${(props) => props.active ? `3px solid var(--primary, ${constants.PRIMARY})` : 'none'};
3475
- color: ${(props) => (props.active ? `var(--primary, ${constants.PRIMARY})` : '#000')};
4418
+ border-bottom: ${(props) => props.active ? `3px solid ${getThemeValue(THEME_NAME.PRIMARY)}` : 'none'};
4419
+ color: ${(props) => props.active
4420
+ ? getThemeValue(THEME_NAME.PRIMARY)
4421
+ : getThemeValue(THEME_NAME.TEXT_COLOR_DARK)};
3476
4422
  cursor: pointer;
3477
4423
 
3478
4424
  &:hover,
3479
4425
  &:focus {
3480
- background-color: var(--primary-lighter, #cfe9ff);
4426
+ background-color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHTER)};
3481
4427
  border-bottom: ${(props) => props.active
3482
- ? `3px solid var(--primary, ${constants.PRIMARY})`
3483
- : `3px solid var(--primary, ${constants.PRIMARY})`};
4428
+ ? `3px solid ${getThemeValue(THEME_NAME.PRIMARY)}`
4429
+ : `3px solid ${getThemeValue(THEME_NAME.PRIMARY)}`};
3484
4430
  }
3485
4431
 
3486
4432
  &[disabled] {
3487
- background-color: var(--disabled-background, ${constants.DISABLED_BACKGROUND});
3488
- color: var(--disabled, ${constants.DISABLED});
3489
- border-bottom: 3px solid var(--disabled-border, ${constants.DISABLED_BORDER});
4433
+ background-color: ${getThemeValue(THEME_NAME.DISABLED_BACKGROUND)};
4434
+ color: ${getThemeValue(THEME_NAME.DISABLED)};
4435
+ border-bottom: 3px solid ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
3490
4436
  }
3491
4437
  `;
3492
4438
  const ButtonContainer = styled.div `
3493
- border-bottom: 1px solid var(--disabled-border, ${constants.DISABLED_BORDER});
4439
+ border-bottom: 1px solid ${getThemeValue(THEME_NAME.DISABLED_BORDER)};
3494
4440
  margin-bottom: 5px;
3495
4441
  position: relative;
3496
4442
  `;
@@ -3499,14 +4445,45 @@ const TabBody = styled.div `
3499
4445
  `;
3500
4446
  function Tabs(props) {
3501
4447
  const [active, setActive] = React.useState(props.active);
3502
- const switchTab = (index) => () => setActive(index);
3503
4448
  const { children } = props;
4449
+ const tabRefs = [];
4450
+ const childrenArray = React.Children.toArray(children);
4451
+ const switchTab = (index) => () => {
4452
+ var _a, _b;
4453
+ setActive(index);
4454
+ (_a = tabRefs[index]) === null || _a === void 0 ? void 0 : _a.focus();
4455
+ (_b = props.onChange) === null || _b === void 0 ? void 0 : _b.call(props, index);
4456
+ };
4457
+ // Keyboard navigation for tab buttons
4458
+ const onTabKeyDown = (index) => (e) => {
4459
+ var _a, _b;
4460
+ if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {
4461
+ e.preventDefault();
4462
+ const next = (index + 1) % childrenArray.length;
4463
+ (_a = tabRefs[next]) === null || _a === void 0 ? void 0 : _a.focus();
4464
+ }
4465
+ else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {
4466
+ e.preventDefault();
4467
+ const prev = (index - 1 + childrenArray.length) % childrenArray.length;
4468
+ (_b = tabRefs[prev]) === null || _b === void 0 ? void 0 : _b.focus();
4469
+ }
4470
+ };
3504
4471
  React.useEffect(() => {
3505
4472
  var _a;
3506
4473
  setActive(props.active);
3507
4474
  (_a = props.onChange) === null || _a === void 0 ? void 0 : _a.call(props, props.active);
3508
4475
  }, [props]);
3509
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ButtonContainer, Object.assign({}, props.props, { children: React.Children.map(children, (child, index) => (jsxRuntime.jsx(Button, { type: "button", active: active === index, onClick: switchTab(index), disabled: React.isValidElement(child) ? child.props.disabled : false, children: React.isValidElement(child) ? child.props.name : '' }))) })), jsxRuntime.jsx(TabBody, Object.assign({}, props.bodyProps, { children: React.Children.toArray(children)[active] }))] }));
4476
+ // Generate unique IDs for tabs and panels using sanitized tab name and index
4477
+ const sanitize = (str) => str.replace(/[^a-zA-Z0-9_-]/g, '').toLowerCase();
4478
+ const tabIds = childrenArray.map((child, i) => {
4479
+ const name = React.isValidElement(child) && child.props.name ? child.props.name : `tab${i}`;
4480
+ return `nfui-tab-${sanitize(name)}-${i}`;
4481
+ });
4482
+ const panelIds = childrenArray.map((child, i) => {
4483
+ const name = React.isValidElement(child) && child.props.name ? child.props.name : `tab${i}`;
4484
+ return `nfui-tabpanel-${sanitize(name)}-${i}`;
4485
+ });
4486
+ return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [jsxRuntime.jsx(ButtonContainer, Object.assign({ role: "tablist", "aria-label": "Tabs" }, props.props, { children: childrenArray.map((child, index) => (jsxRuntime.jsx(Button, { ref: (el) => (tabRefs[index] = el), id: tabIds[index], type: "button", role: "tab", "aria-selected": active === index, "aria-controls": panelIds[index], tabIndex: active === index ? 0 : -1, active: active === index, onClick: switchTab(index), onKeyDown: onTabKeyDown(index), disabled: React.isValidElement(child) ? child.props.disabled : false, "aria-disabled": React.isValidElement(child) ? child.props.disabled : false, children: React.isValidElement(child) ? child.props.name : '' }, tabIds[index]))) })), jsxRuntime.jsx(TabBody, Object.assign({ id: panelIds[active], role: "tabpanel", "aria-labelledby": tabIds[active], tabIndex: 0 }, props.bodyProps, { children: childrenArray[active] }))] }));
3510
4487
  }
3511
4488
  Tabs.propTypes = {
3512
4489
  /** Active Tab Index */
@@ -3547,15 +4524,15 @@ exports.TOAST_TYPE = void 0;
3547
4524
  const getBackgroundColor = (type) => {
3548
4525
  switch (type) {
3549
4526
  case exports.TOAST_TYPE.INFO:
3550
- return `var(--info, ${constants.INFO})`;
4527
+ return getThemeValue(THEME_NAME.INFO);
3551
4528
  case exports.TOAST_TYPE.SUCCESS:
3552
- return `var(--success, ${constants.SUCCESS})`;
4529
+ return getThemeValue(THEME_NAME.SUCCESS);
3553
4530
  case exports.TOAST_TYPE.WARNING:
3554
- return `var(--warning, ${constants.WARNING})`;
4531
+ return getThemeValue(THEME_NAME.WARNING);
3555
4532
  case exports.TOAST_TYPE.DANGER:
3556
- return `var(--error, ${constants.ERROR})`;
4533
+ return getThemeValue(THEME_NAME.ERROR);
3557
4534
  case exports.TOAST_TYPE.NORMAL:
3558
- return `var(--toast, ${constants.TOAST})`;
4535
+ return getThemeValue(THEME_NAME.TOAST);
3559
4536
  }
3560
4537
  };
3561
4538
  const ToastContainer = styled(Card) `
@@ -3563,7 +4540,7 @@ const ToastContainer = styled(Card) `
3563
4540
  border-radius: 3px;
3564
4541
  padding: 12px;
3565
4542
  background-color: ${(props) => getBackgroundColor(props.type)};
3566
- color: #fff;
4543
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
3567
4544
  margin: 20px;
3568
4545
  font-size: 14px;
3569
4546
  line-height: 20px;
@@ -3572,6 +4549,7 @@ const ToastContainer = styled(Card) `
3572
4549
  width: 344px;
3573
4550
  display: flex;
3574
4551
  align-items: center;
4552
+ position: relative;
3575
4553
 
3576
4554
  & svg {
3577
4555
  width: 20px;
@@ -3596,7 +4574,7 @@ const TextContainer = styled.div `
3596
4574
  `;
3597
4575
  const CloseContainer = styled.button `
3598
4576
  background-color: transparent;
3599
- color: var(--primary, ${constants.PRIMARY_LIGHT});
4577
+ color: ${getThemeValue(THEME_NAME.PRIMARY_LIGHT)};
3600
4578
  padding: 6px 10px;
3601
4579
  border: none;
3602
4580
  border-radius: 3px;
@@ -3608,8 +4586,71 @@ const CloseContainer = styled.button `
3608
4586
  }
3609
4587
  `;
3610
4588
  const DEFAULT_DURATION = 2000;
4589
+ const createAriaLiveRegion = (id, ariaLive) => {
4590
+ const region = document.createElement('div');
4591
+ region.id = id;
4592
+ region.style.position = 'absolute';
4593
+ region.style.width = '1px';
4594
+ region.style.height = '1px';
4595
+ region.style.padding = '0';
4596
+ region.style.margin = '-1px';
4597
+ region.style.overflow = 'hidden';
4598
+ region.style.clip = 'rect(0, 0, 0, 0)';
4599
+ region.style.whiteSpace = 'nowrap';
4600
+ region.style.borderWidth = '0';
4601
+ region.setAttribute('role', ariaLive === 'assertive' ? 'alert' : 'log');
4602
+ region.setAttribute('aria-live', ariaLive);
4603
+ region.setAttribute('aria-atomic', 'true');
4604
+ return region;
4605
+ };
3611
4606
  class Toast {
3612
4607
  constructor() {
4608
+ this.isPaused = false;
4609
+ this.currentOptions = null;
4610
+ /**
4611
+ * Set up keyboard listener for dismissing toast with Escape key
4612
+ */
4613
+ this.setupKeyboardListeners = () => {
4614
+ if (typeof document !== 'undefined') {
4615
+ document.addEventListener('keydown', this.handleKeyDown);
4616
+ }
4617
+ };
4618
+ /**
4619
+ * Handle keyboard events for toast interaction
4620
+ */
4621
+ this.handleKeyDown = (event) => {
4622
+ if (!this.toast)
4623
+ return;
4624
+ // Escape key dismisses the toast
4625
+ if (event.key === 'Escape') {
4626
+ this.remove();
4627
+ }
4628
+ // Space key pauses/resumes auto-dismiss
4629
+ else if (event.key === ' ' && this.currentOptions) {
4630
+ event.preventDefault();
4631
+ if (this.isPaused) {
4632
+ this.resumeTimeout();
4633
+ }
4634
+ else {
4635
+ this.pauseTimeout();
4636
+ }
4637
+ }
4638
+ };
4639
+ /**
4640
+ * Update the appropriate live region with toast content
4641
+ */
4642
+ this.updateLiveRegion = (content, isAssertive) => {
4643
+ const region = isAssertive ? this.assertiveRegion : this.politeRegion;
4644
+ region.textContent = '';
4645
+ if (region) {
4646
+ // Add content after delay
4647
+ setTimeout(() => {
4648
+ if (region) {
4649
+ region.textContent = content;
4650
+ }
4651
+ }, 200);
4652
+ }
4653
+ };
3613
4654
  this.remove = () => {
3614
4655
  if (this.toast) {
3615
4656
  this.toast[1]();
@@ -3623,36 +4664,68 @@ class Toast {
3623
4664
  }
3624
4665
  }, 300);
3625
4666
  };
4667
+ /**
4668
+ * Pause toast auto-dismiss
4669
+ */
4670
+ this.pauseTimeout = () => {
4671
+ if (this.timeout) {
4672
+ clearTimeout(this.timeout);
4673
+ this.isPaused = true;
4674
+ }
4675
+ };
4676
+ /**
4677
+ * Resume toast auto-dismiss
4678
+ */
4679
+ this.resumeTimeout = () => {
4680
+ if (this.currentOptions && this.isPaused) {
4681
+ this.timeout = setTimeout(() => {
4682
+ this.remove();
4683
+ }, this.currentOptions.duration || DEFAULT_DURATION);
4684
+ this.isPaused = false;
4685
+ }
4686
+ };
3626
4687
  /**
3627
4688
  * Pause toast when user is hovering over it.
3628
- *
3629
- * @param id
3630
4689
  */
3631
4690
  this.pause = () => {
3632
- clearTimeout(this.timeout);
4691
+ this.pauseTimeout();
3633
4692
  };
3634
4693
  /**
3635
4694
  * Restart the removal of toast.
3636
- *
3637
- * @param id
3638
4695
  */
3639
4696
  this.resume = (options) => () => {
3640
- this.timeout = setTimeout(() => {
3641
- this.remove();
3642
- }, options.duration || DEFAULT_DURATION);
4697
+ this.currentOptions = options;
4698
+ this.resumeTimeout();
3643
4699
  };
4700
+ if (typeof document === 'undefined')
4701
+ return;
3644
4702
  this.element = document === null || document === void 0 ? void 0 : document.createElement('div');
4703
+ this.ariaLiveContainer = document === null || document === void 0 ? void 0 : document.createElement('div');
4704
+ this.ariaLiveContainer.id = 'nf-toast-container';
4705
+ document.body.appendChild(this.ariaLiveContainer);
4706
+ this.politeRegion = createAriaLiveRegion('nf-toast-polite-region', 'polite');
4707
+ this.assertiveRegion = createAriaLiveRegion('nf-toast-assertive-region', 'assertive');
4708
+ this.ariaLiveContainer.appendChild(this.politeRegion);
4709
+ this.ariaLiveContainer.appendChild(this.assertiveRegion);
4710
+ this.setupKeyboardListeners();
3645
4711
  }
3646
4712
  add(options) {
3647
4713
  const { text, buttonText, buttonClick, duration, type = exports.TOAST_TYPE.NORMAL } = options;
4714
+ this.currentOptions = options;
4715
+ this.isPaused = false;
3648
4716
  this.remove();
4717
+ // Determine if this is an assertive message (warning/danger)
4718
+ const isAssertive = type === exports.TOAST_TYPE.WARNING || type === exports.TOAST_TYPE.DANGER;
4719
+ // Announce to screen readers
4720
+ const announcement = buttonText ? `${text} ${buttonText} button available` : text;
4721
+ this.updateLiveRegion(announcement, isAssertive);
3649
4722
  this.toast = LayerManager$1.renderLayer({
3650
4723
  exitDelay: 300,
3651
4724
  closeOnEsc: false,
3652
4725
  closeOnOverlayClick: false,
3653
4726
  alwaysOnTop: true,
3654
4727
  position: LAYER_POSITION.BOTTOM_LEFT,
3655
- component: (jsxRuntime.jsxs(ToastContainer, Object.assign({}, options, { type: type, elevated: true, onMouseEnter: this.pause, onMouseLeave: this.resume(options), children: [jsxRuntime.jsx(TextContainer, { children: text }), buttonText && (jsxRuntime.jsx(CloseContainer, { onClick: buttonClick, type: "button", children: buttonText }))] }))),
4728
+ component: (jsxRuntime.jsx(jsxRuntime.Fragment, { children: jsxRuntime.jsxs(ToastContainer, Object.assign({}, options, { type: type, elevated: true, onMouseEnter: this.pause, onMouseLeave: this.resume(options), "aria-hidden": "true", children: [jsxRuntime.jsx(TextContainer, { children: text }), buttonText && (jsxRuntime.jsx(CloseContainer, { onClick: buttonClick, type: "button", "aria-label": `${buttonText} - Press Space to pause auto-dismiss, Escape to close`, children: buttonText }))] })) })),
3656
4729
  });
3657
4730
  const Component = this.toast[0];
3658
4731
  this.root = client.createRoot(this.element);
@@ -3705,9 +4778,9 @@ const positionHoverStyle = {
3705
4778
  };
3706
4779
  const TooltipDiv = styled.div `
3707
4780
  position: absolute;
3708
- background-color: var(--tooltip-color, ${constants.TOOLTIP_COLOR});
4781
+ background-color: ${getThemeValue(THEME_NAME.TOOLTIP_COLOR)};
3709
4782
  padding: 5px;
3710
- color: #fff;
4783
+ color: ${getThemeValue(THEME_NAME.TEXT_COLOR_LIGHT)};
3711
4784
  border-radius: 3px;
3712
4785
  transition: transform 0.3s ease;
3713
4786
  font-size: 12px;
@@ -3720,13 +4793,23 @@ const TooltipContainer = styled.div `
3720
4793
  justify-content: center;
3721
4794
  align-items: center;
3722
4795
 
3723
- &:hover ${TooltipDiv} {
4796
+ &:hover ${TooltipDiv}, &:focus-within ${TooltipDiv} {
3724
4797
  ${(props) => positionHoverStyle[props.position]}
3725
4798
  }
3726
4799
  `;
3727
4800
  function Tooltip(props) {
3728
4801
  const { children, position } = props, rest = __rest(props, ["children", "position"]);
3729
- return (jsxRuntime.jsxs(TooltipContainer, Object.assign({ position: position }, rest, { children: [children, jsxRuntime.jsx(TooltipDiv, { position: position, children: rest.tooltipText })] })));
4802
+ const tooltipId = React.useId();
4803
+ // Clone the child to inject aria-describedby and tabIndex if possible
4804
+ const trigger = React.isValidElement(children)
4805
+ ? React.cloneElement(children, {
4806
+ 'aria-describedby': tooltipId,
4807
+ tabIndex: children.props && typeof children.props.tabIndex !== 'undefined'
4808
+ ? children.props.tabIndex
4809
+ : 0,
4810
+ })
4811
+ : children;
4812
+ return (jsxRuntime.jsxs(TooltipContainer, Object.assign({ position: position }, rest, { children: [trigger, jsxRuntime.jsx(TooltipDiv, { id: tooltipId, "aria-hidden": "true", role: "tooltip", position: position, children: rest.tooltipText })] })));
3730
4813
  }
3731
4814
  Tooltip.propTypes = {
3732
4815
  /** Text to show in the tooltip */
@@ -3750,7 +4833,7 @@ exports.AccordionStepFooter = AccordionStepFooter;
3750
4833
  exports.ActionButton = ActionButton;
3751
4834
  exports.AlertDialog = AlertDialog;
3752
4835
  exports.Badge = Badge;
3753
- exports.Button = Button$2;
4836
+ exports.Button = StyledButton;
3754
4837
  exports.Card = Card;
3755
4838
  exports.CardBody = Body$1;
3756
4839
  exports.CardFooter = Footer$1;
@@ -3772,7 +4855,7 @@ exports.Dropdown = Dropdown;
3772
4855
  exports.Group = Group;
3773
4856
  exports.GroupLabel = GroupLabel;
3774
4857
  exports.IconButton = IconButton;
3775
- exports.Input = Input$4;
4858
+ exports.Input = Input$2;
3776
4859
  exports.LinkButton = LinkButton;
3777
4860
  exports.Menu = Menu;
3778
4861
  exports.MenuItem = MenuItem;