@astryxdesign/core 0.4.3 → 0.4.4-canary.0e8af82

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 (254) hide show
  1. package/CHANGELOG.md +60 -0
  2. package/README.md +79 -45
  3. package/dist/Banner/Banner.d.ts +3 -0
  4. package/dist/Banner/Banner.d.ts.map +1 -1
  5. package/dist/Banner/Banner.js +13 -3
  6. package/dist/BottomSheet/BottomSheet.d.ts +75 -0
  7. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -0
  8. package/dist/BottomSheet/BottomSheet.js +396 -0
  9. package/dist/BottomSheet/BottomSheetPanel.d.ts +63 -0
  10. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -0
  11. package/dist/BottomSheet/BottomSheetPanel.js +441 -0
  12. package/dist/BottomSheet/BottomSheetSwitcher.d.ts +61 -0
  13. package/dist/BottomSheet/BottomSheetSwitcher.d.ts.map +1 -0
  14. package/dist/BottomSheet/BottomSheetSwitcher.js +410 -0
  15. package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts +21 -0
  16. package/dist/BottomSheet/BottomSheetSwitcherContext.d.ts.map +1 -0
  17. package/dist/BottomSheet/BottomSheetSwitcherContext.js +13 -0
  18. package/dist/BottomSheet/index.d.ts +11 -0
  19. package/dist/BottomSheet/index.d.ts.map +1 -0
  20. package/dist/BottomSheet/index.js +12 -0
  21. package/dist/BottomSheet/snapOffsets.d.ts +109 -0
  22. package/dist/BottomSheet/snapOffsets.d.ts.map +1 -0
  23. package/dist/BottomSheet/snapOffsets.js +206 -0
  24. package/dist/BottomSheet/useMobileKeyboard.d.ts +35 -0
  25. package/dist/BottomSheet/useMobileKeyboard.d.ts.map +1 -0
  26. package/dist/BottomSheet/useMobileKeyboard.js +373 -0
  27. package/dist/BottomSheet/useSheetGestures.d.ts +185 -0
  28. package/dist/BottomSheet/useSheetGestures.d.ts.map +1 -0
  29. package/dist/BottomSheet/useSheetGestures.js +1038 -0
  30. package/dist/Calendar/Calendar.d.ts +17 -0
  31. package/dist/Calendar/Calendar.d.ts.map +1 -1
  32. package/dist/Calendar/Calendar.js +25 -1
  33. package/dist/Calendar/hooks/useCalendarConstraints.d.ts +22 -1
  34. package/dist/Calendar/hooks/useCalendarConstraints.d.ts.map +1 -1
  35. package/dist/Calendar/hooks/useCalendarConstraints.js +26 -4
  36. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  37. package/dist/Chat/ChatComposerInput.js +3 -4
  38. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  39. package/dist/CheckboxInput/CheckboxInput.js +9 -0
  40. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  41. package/dist/ComplexSelector/ComplexSelector.js +18 -7
  42. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  43. package/dist/ContextMenu/ContextMenu.js +4 -2
  44. package/dist/DateInput/DateInput.d.ts.map +1 -1
  45. package/dist/DateInput/DateInput.js +15 -2
  46. package/dist/DateRangeInput/DateRangeInput.d.ts +23 -1
  47. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  48. package/dist/DateRangeInput/DateRangeInput.js +38 -3
  49. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  50. package/dist/DateTimeInput/DateTimeInput.js +38 -3
  51. package/dist/Dialog/Dialog.d.ts.map +1 -1
  52. package/dist/Dialog/Dialog.js +2 -1
  53. package/dist/Field/FieldLabel.d.ts +2 -1
  54. package/dist/Field/FieldLabel.d.ts.map +1 -1
  55. package/dist/Field/FieldLabel.js +21 -3
  56. package/dist/Field/InputClearButton.d.ts +2 -1
  57. package/dist/Field/InputClearButton.d.ts.map +1 -1
  58. package/dist/Field/InputClearButton.js +6 -1
  59. package/dist/FormLayout/FormLayout.d.ts +24 -2
  60. package/dist/FormLayout/FormLayout.d.ts.map +1 -1
  61. package/dist/FormLayout/FormLayout.js +7 -2
  62. package/dist/FormLayout/FormLayoutContext.d.ts +15 -2
  63. package/dist/FormLayout/FormLayoutContext.d.ts.map +1 -1
  64. package/dist/FormLayout/FormLayoutContext.js +19 -4
  65. package/dist/FormLayout/index.d.ts +1 -1
  66. package/dist/FormLayout/index.d.ts.map +1 -1
  67. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  68. package/dist/Lightbox/Lightbox.js +9 -3
  69. package/dist/MobileNav/MobileNav.d.ts +12 -0
  70. package/dist/MobileNav/MobileNav.d.ts.map +1 -1
  71. package/dist/MobileNav/MobileNav.js +102 -30
  72. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  73. package/dist/MultiSelector/MultiSelector.js +27 -8
  74. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  75. package/dist/NumberInput/NumberInput.js +15 -2
  76. package/dist/PowerSearch/PowerSearchEditPopover.js +1 -1
  77. package/dist/RadioList/RadioList.d.ts.map +1 -1
  78. package/dist/RadioList/RadioList.js +12 -1
  79. package/dist/Selector/Selector.d.ts.map +1 -1
  80. package/dist/Selector/Selector.js +20 -4
  81. package/dist/StatusDot/StatusDot.d.ts +43 -3
  82. package/dist/StatusDot/StatusDot.d.ts.map +1 -1
  83. package/dist/StatusDot/StatusDot.js +42 -5
  84. package/dist/Switch/Switch.d.ts.map +1 -1
  85. package/dist/Switch/Switch.js +14 -1
  86. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  87. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +7 -2
  88. package/dist/TextArea/TextArea.d.ts.map +1 -1
  89. package/dist/TextArea/TextArea.js +6 -1
  90. package/dist/TextInput/TextInput.d.ts.map +1 -1
  91. package/dist/TextInput/TextInput.js +6 -1
  92. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  93. package/dist/TimeInput/TimeInput.js +14 -2
  94. package/dist/Tokenizer/Tokenizer.js +11 -5
  95. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  96. package/dist/Tooltip/useTooltip.js +4 -1
  97. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  98. package/dist/Typeahead/BaseTypeahead.js +5 -3
  99. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  100. package/dist/Typeahead/Typeahead.js +10 -1
  101. package/dist/astryx.css +21 -0
  102. package/dist/hooks/index.d.ts +8 -1
  103. package/dist/hooks/index.d.ts.map +1 -1
  104. package/dist/hooks/index.js +8 -1
  105. package/dist/hooks/useFocusTrap.d.ts +0 -11
  106. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  107. package/dist/hooks/useFocusTrap.js +1 -11
  108. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -1
  109. package/dist/hooks/useInputStatusIcon.js +1 -0
  110. package/dist/hooks/useResolvedRequired.d.ts +19 -0
  111. package/dist/hooks/useResolvedRequired.d.ts.map +1 -0
  112. package/dist/hooks/useResolvedRequired.js +40 -0
  113. package/dist/index.d.ts +1 -0
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.js +1 -0
  116. package/dist/theme/defineTheme.d.ts +22 -4
  117. package/dist/theme/defineTheme.d.ts.map +1 -1
  118. package/dist/theme/expandColorScale.d.ts +17 -2
  119. package/dist/theme/expandColorScale.d.ts.map +1 -1
  120. package/dist/theme/expandColorScale.js +63 -33
  121. package/dist/utils/ime.d.ts +5 -0
  122. package/dist/utils/ime.d.ts.map +1 -0
  123. package/dist/utils/ime.js +63 -0
  124. package/dist/utils/index.d.ts +1 -0
  125. package/dist/utils/index.d.ts.map +1 -1
  126. package/dist/utils/index.js +2 -1
  127. package/dist/utils/plainDate.d.ts +6 -0
  128. package/dist/utils/plainDate.d.ts.map +1 -1
  129. package/dist/utils/plainDate.js +12 -0
  130. package/locales/af-ZA.json +958 -0
  131. package/locales/ar-SA.json +998 -0
  132. package/locales/ca-ES.json +974 -0
  133. package/locales/cs-CZ.json +990 -0
  134. package/locales/da-DK.json +966 -0
  135. package/locales/de-DE.json +966 -0
  136. package/locales/el-GR.json +990 -0
  137. package/locales/en.json +52 -0
  138. package/locales/es-ES.json +978 -0
  139. package/locales/fi-FI.json +990 -0
  140. package/locales/fr-FR.json +928 -0
  141. package/locales/he-IL.json +990 -0
  142. package/locales/hu-HU.json +990 -0
  143. package/locales/it-IT.json +978 -0
  144. package/locales/ja-JP.json +998 -0
  145. package/locales/ko-KR.json +990 -0
  146. package/locales/nl-NL.json +954 -0
  147. package/locales/no-NO.json +978 -0
  148. package/locales/pl-PL.json +982 -0
  149. package/locales/pseudo.json +39 -0
  150. package/locales/pt-BR.json +982 -0
  151. package/locales/pt-PT.json +982 -0
  152. package/locales/ro-RO.json +982 -0
  153. package/locales/ru-RU.json +990 -0
  154. package/locales/sr-SP.json +990 -0
  155. package/locales/sv-SE.json +986 -0
  156. package/locales/tr-TR.json +990 -0
  157. package/locales/uk-UA.json +990 -0
  158. package/locales/vi-VN.json +986 -0
  159. package/locales/zh-CN.json +998 -0
  160. package/locales/zh-TW.json +998 -0
  161. package/package.json +9 -8
  162. package/src/Banner/Banner.doc.mjs +3 -3
  163. package/src/Banner/Banner.test.tsx +40 -0
  164. package/src/Banner/Banner.tsx +27 -2
  165. package/src/BottomSheet/BottomSheet.doc.mjs +299 -0
  166. package/src/BottomSheet/BottomSheet.test.tsx +2265 -0
  167. package/src/BottomSheet/BottomSheet.tsx +559 -0
  168. package/src/BottomSheet/BottomSheetPanel.test.tsx +240 -0
  169. package/src/BottomSheet/BottomSheetPanel.tsx +601 -0
  170. package/src/BottomSheet/BottomSheetSwitcher.doc.mjs +219 -0
  171. package/src/BottomSheet/BottomSheetSwitcher.test.tsx +850 -0
  172. package/src/BottomSheet/BottomSheetSwitcher.tsx +628 -0
  173. package/src/BottomSheet/BottomSheetSwitcherContext.ts +51 -0
  174. package/src/BottomSheet/index.ts +19 -0
  175. package/src/BottomSheet/snapOffsets.test.ts +254 -0
  176. package/src/BottomSheet/snapOffsets.ts +245 -0
  177. package/src/BottomSheet/useMobileKeyboard.ts +499 -0
  178. package/src/BottomSheet/useSheetGestures.test.ts +1112 -0
  179. package/src/BottomSheet/useSheetGestures.ts +1503 -0
  180. package/src/Calendar/Calendar.doc.mjs +16 -0
  181. package/src/Calendar/Calendar.test.tsx +96 -0
  182. package/src/Calendar/Calendar.tsx +55 -0
  183. package/src/Calendar/hooks/useCalendarConstraints.ts +54 -3
  184. package/src/Chat/ChatComposerInput.tsx +3 -4
  185. package/src/CheckboxInput/CheckboxInput.tsx +6 -0
  186. package/src/ComplexSelector/ComplexSelector.tsx +15 -6
  187. package/src/ContextMenu/ContextMenu.tsx +4 -2
  188. package/src/DateInput/DateInput.test.tsx +21 -0
  189. package/src/DateInput/DateInput.tsx +12 -2
  190. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  191. package/src/DateRangeInput/DateRangeInput.test.tsx +81 -1
  192. package/src/DateRangeInput/DateRangeInput.tsx +72 -1
  193. package/src/DateTimeInput/DateTimeInput.doc.mjs +4 -0
  194. package/src/DateTimeInput/DateTimeInput.test.tsx +137 -0
  195. package/src/DateTimeInput/DateTimeInput.tsx +43 -4
  196. package/src/Dialog/Dialog.tsx +2 -1
  197. package/src/Field/Field.doc.mjs +1 -0
  198. package/src/Field/FieldLabel.tsx +20 -4
  199. package/src/Field/InputClearButton.test.tsx +25 -0
  200. package/src/Field/InputClearButton.tsx +4 -1
  201. package/src/FileInput/FileInput.test.tsx +53 -9
  202. package/src/FormLayout/FormLayout.doc.mjs +13 -0
  203. package/src/FormLayout/FormLayout.test.tsx +181 -4
  204. package/src/FormLayout/FormLayout.tsx +33 -2
  205. package/src/FormLayout/FormLayoutContext.ts +22 -7
  206. package/src/FormLayout/index.ts +1 -1
  207. package/src/Lightbox/Lightbox.test.tsx +49 -28
  208. package/src/Lightbox/Lightbox.tsx +7 -3
  209. package/src/MobileNav/MobileNav.tsx +128 -37
  210. package/src/MobileNav/MobileNavCloseEdgeCases.test.tsx +426 -0
  211. package/src/MobileNav/MobileNavCloseTiming.test.ts +58 -0
  212. package/src/MobileNav/MobileNavCloseVisibility.test.tsx +172 -0
  213. package/src/MultiSelector/MultiSelector.test.tsx +195 -51
  214. package/src/MultiSelector/MultiSelector.tsx +25 -9
  215. package/src/NumberInput/NumberInput.test.tsx +18 -0
  216. package/src/NumberInput/NumberInput.tsx +12 -2
  217. package/src/PowerSearch/PowerSearchEditPopover.tsx +1 -1
  218. package/src/RadioList/RadioList.tsx +9 -1
  219. package/src/Selector/Selector.test.tsx +85 -26
  220. package/src/Selector/Selector.tsx +16 -5
  221. package/src/StatusDot/StatusDot.doc.mjs +13 -0
  222. package/src/StatusDot/StatusDot.test.tsx +115 -8
  223. package/src/StatusDot/StatusDot.tsx +74 -9
  224. package/src/Switch/Switch.test.tsx +16 -0
  225. package/src/Switch/Switch.tsx +13 -0
  226. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +20 -2
  227. package/src/TextArea/TextArea.tsx +3 -1
  228. package/src/TextInput/TextInput.tsx +3 -1
  229. package/src/TimeInput/TimeInput.test.tsx +23 -0
  230. package/src/TimeInput/TimeInput.tsx +11 -1
  231. package/src/Tokenizer/Tokenizer.test.tsx +50 -32
  232. package/src/Tokenizer/Tokenizer.tsx +5 -5
  233. package/src/Tooltip/useTooltip.tsx +4 -1
  234. package/src/Typeahead/BaseTypeahead.tsx +10 -3
  235. package/src/Typeahead/Typeahead.test.tsx +116 -7
  236. package/src/Typeahead/Typeahead.tsx +10 -1
  237. package/src/__tests__/stubMatchMedia.test.ts +79 -0
  238. package/src/__tests__/stubMatchMedia.ts +95 -0
  239. package/src/hooks/index.ts +9 -5
  240. package/src/hooks/useFocusTrap.ts +1 -14
  241. package/src/hooks/useInputStatusIcon.test.tsx +19 -0
  242. package/src/hooks/useInputStatusIcon.tsx +7 -0
  243. package/src/hooks/useResolvedRequired.ts +42 -0
  244. package/src/index.ts +1 -0
  245. package/src/theme/defineTheme.ts +22 -4
  246. package/src/theme/expandColorScale.test.ts +138 -0
  247. package/src/theme/expandColorScale.ts +89 -44
  248. package/src/utils/ime.test.ts +32 -0
  249. package/src/utils/ime.ts +69 -0
  250. package/src/utils/index.ts +2 -0
  251. package/src/utils/plainDate.test.ts +50 -0
  252. package/src/utils/plainDate.ts +12 -0
  253. package/dist/astryx.umd.js +0 -147
  254. package/dist/astryx.umd.js.map +0 -7
@@ -17,7 +17,7 @@
17
17
  */
18
18
  import { useId, useCallback, useMemo, useOptimistic, useTransition } from 'react';
19
19
  import * as stylex from '@stylexjs/stylex';
20
- import { plainDateFromISO, plainDateToday, plainDateFormat, DATE_FORMAT_SHORT, DATE_FORMAT_SHORT_WITH_YEAR } from "../utils/plainDate.js";
20
+ import { plainDateFromISO, plainDateToday, plainDateFormat, plainDateDiffDays, DATE_FORMAT_SHORT, DATE_FORMAT_SHORT_WITH_YEAR } from "../utils/plainDate.js";
21
21
  import "../theme/tokens.stylex.js";
22
22
  import { colorVars, sizeVars, radiusVars, spacingVars, typographyVars, typeScaleVars, borderVars } from "../theme/tokens.stylex.js";
23
23
  import { Field, InputClearButton, inputWrapperStyles, inputStatusBorderStyles, inputStatusHoverShadowStyles, inputStatusFocusWithinStyles } from "../Field/index.js";
@@ -29,6 +29,7 @@ import { useTooltip } from "../Tooltip/index.js";
29
29
  import { mergeProps } from "../utils/index.js";
30
30
  import { useSize } from "../SizeContext/SizeContext.js";
31
31
  import { useInputStatusIcon } from "../hooks/useInputStatusIcon.js";
32
+ import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
32
33
  import { themeProps } from "../utils/themeProps.js";
33
34
  import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
34
35
  import { stableClassName } from "../naming.js";
@@ -73,6 +74,12 @@ const styles = {
73
74
  kWkggS: "xgcxg3y",
74
75
  kMwMTN: "xqwr325",
75
76
  $$css: true
77
+ },
78
+ presetButtonDisabled: {
79
+ kMwMTN: "xnbbluu",
80
+ kkrTdU: "x1h6gzvc",
81
+ kWkggS: "xjbqb8w",
82
+ $$css: true
76
83
  }
77
84
  };
78
85
  const sizeStyles = {
@@ -112,6 +119,24 @@ function isRangeEqual(a, b) {
112
119
  }
113
120
  return a.start === b.start && a.end === b.end;
114
121
  }
122
+
123
+ // A preset that would land outside the span bounds is disabled rather than
124
+ // allowed to override them: the cap is authoritative, so an out-of-window
125
+ // preset stays visible (discoverable) but non-committable, mirroring how the
126
+ // calendar disables out-of-window days. Spans count both endpoints.
127
+ function isRangeWithinSpan(range, maxRangeSpan, minRangeSpan) {
128
+ if (maxRangeSpan == null && minRangeSpan == null) {
129
+ return true;
130
+ }
131
+ const span = Math.abs(plainDateDiffDays(plainDateFromISO(range.start), plainDateFromISO(range.end))) + 1;
132
+ if (maxRangeSpan != null && span > maxRangeSpan) {
133
+ return false;
134
+ }
135
+ if (minRangeSpan != null && span < minRangeSpan) {
136
+ return false;
137
+ }
138
+ return true;
139
+ }
115
140
  /**
116
141
  * A date range picker with a button trigger that opens a popover
117
142
  * containing a dual-month calendar and optional preset ranges.
@@ -143,6 +168,8 @@ export function DateRangeInput({
143
168
  min,
144
169
  max,
145
170
  dateConstraints,
171
+ maxRangeSpan,
172
+ minRangeSpan,
146
173
  presets,
147
174
  hasClear = true,
148
175
  placeholder: placeholderFromProps,
@@ -160,6 +187,10 @@ export function DateRangeInput({
160
187
  ...rest
161
188
  }) {
162
189
  const t = useTranslator();
190
+ const isEffectivelyRequired = useResolvedRequired({
191
+ isRequired,
192
+ isOptional
193
+ });
163
194
  const placeholder = placeholderFromProps ?? t('@astryx.dateRangeInput.placeholder');
164
195
  const size = useSize(sizeProp, 'md');
165
196
  const id = useId();
@@ -293,7 +324,7 @@ export function DateRangeInput({
293
324
  "aria-disabled": showsDisabledMessage ? 'true' : undefined,
294
325
  "aria-label": triggerAriaLabel,
295
326
  "aria-describedby": ariaDescribedBy,
296
- "aria-required": isRequired === true ? 'true' : undefined,
327
+ "aria-required": isEffectivelyRequired ? 'true' : undefined,
297
328
  "aria-invalid": status?.type === 'error' ? 'true' : undefined,
298
329
  "aria-busy": isBusy || undefined,
299
330
  "aria-expanded": popover.isOpen,
@@ -336,6 +367,7 @@ export function DateRangeInput({
336
367
  children: presets.map(preset => {
337
368
  const presetRange = preset.getRange();
338
369
  const isActive = isRangeEqual(value, presetRange);
370
+ const isPresetDisabled = !isRangeWithinSpan(presetRange, maxRangeSpan, minRangeSpan);
339
371
  return /*#__PURE__*/_jsx("button", {
340
372
  type: "button"
341
373
  // These presets are independent action buttons navigated by
@@ -345,8 +377,9 @@ export function DateRangeInput({
345
377
  // concept that contradicted the Tab interaction) (forms-5).
346
378
  ,
347
379
  "aria-current": isActive ? 'true' : undefined,
380
+ disabled: isPresetDisabled,
348
381
  onClick: () => handlePresetClick(preset),
349
- ...stylex.props(focusOutlineStyles.focusVisible, styles.presetButton, isActive && styles.presetButtonActive),
382
+ ...stylex.props(focusOutlineStyles.focusVisible, styles.presetButton, isActive && styles.presetButtonActive, isPresetDisabled && styles.presetButtonDisabled),
350
383
  children: preset.label
351
384
  }, preset.label);
352
385
  })
@@ -357,6 +390,8 @@ export function DateRangeInput({
357
390
  min: min,
358
391
  max: max,
359
392
  dateConstraints: dateConstraints,
393
+ maxRangeSpan: maxRangeSpan,
394
+ minRangeSpan: minRangeSpan,
360
395
  numberOfMonths: numberOfMonths,
361
396
  weekStartsOn: weekStartsOn
362
397
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DateTimeInput.d.ts","sourceRoot":"","sources":["../../src/DateTimeInput/DateTimeInput.tsx"],"names":[],"mappings":"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"}
@@ -29,9 +29,10 @@ import { usePopover } from "../Popover/index.js";
29
29
  import { useTooltip } from "../Tooltip/index.js";
30
30
  import { useInputContainer } from "../hooks/useInputContainer.js";
31
31
  import { useInputStatusIcon } from "../hooks/useInputStatusIcon.js";
32
- import { parseDateInput, parseTimeInput, formatDisplayTime12h, formatDisplayTime24h, formatISOTime, isTimeInRange, adjustTime, mergeProps, mergeRefs, isFocusDetached } from "../utils/index.js";
32
+ import { parseDateInput, parseTimeInput, formatDisplayTime12h, formatDisplayTime24h, formatISOTime, isTimeInRange, adjustTime, isImeKeyEvent, mergeProps, mergeRefs, isFocusDetached } from "../utils/index.js";
33
33
  import { plainDateFromISO, plainDateToISO, plainDateFormat, DATE_FORMAT_LONG } from "../utils/plainDate.js";
34
34
  import { useAnnounce } from "../hooks/useAnnounce.js";
35
+ import { useResolvedRequired } from "../hooks/useResolvedRequired.js";
35
36
  import { useSize } from "../SizeContext/SizeContext.js";
36
37
  import { themeProps } from "../utils/themeProps.js";
37
38
  import { focusOutlineStyles } from "../utils/focusOutline.stylex.js";
@@ -170,6 +171,10 @@ export function DateTimeInput({
170
171
  ...rest
171
172
  }) {
172
173
  const t = useTranslator();
174
+ const isEffectivelyRequired = useResolvedRequired({
175
+ isRequired,
176
+ isOptional
177
+ });
173
178
  // Speaks arrow-key stepping results through the persistent live regions:
174
179
  // stepping programmatically rewrites a plain textbox's value, which screen
175
180
  // readers do not announce on their own (WCAG 4.1.2).
@@ -403,6 +408,13 @@ export function DateTimeInput({
403
408
  commitDatePendingInput();
404
409
  }, [commitDatePendingInput]);
405
410
  const handleDateKeyDown = useCallback(e => {
411
+ // Guard the composing keydown (fires before compositionend): an IME uses
412
+ // Enter to commit the candidate and Escape to cancel it, so without this
413
+ // a CJK user committing a syllable with Enter would commit the pending
414
+ // date instead. See utils/ime.ts.
415
+ if (isImeKeyEvent(e.nativeEvent)) {
416
+ return;
417
+ }
406
418
  if (e.key === 'Escape' && popover.isOpen) {
407
419
  e.preventDefault();
408
420
  popover.hide();
@@ -471,6 +483,13 @@ export function DateTimeInput({
471
483
  setTimePendingInput(null);
472
484
  }, [timePendingInput, hasSeconds, timeMin, timeMax, valueParts, fireChange]);
473
485
  const handleTimeKeyDown = useCallback(e => {
486
+ // ArrowUp/ArrowDown step the time and preventDefault; an IME candidate
487
+ // window uses those same arrows to navigate candidates, so guard the
488
+ // composing keydown (fires before compositionend) to avoid stealing them
489
+ // mid-composition. See utils/ime.ts.
490
+ if (isImeKeyEvent(e.nativeEvent)) {
491
+ return;
492
+ }
474
493
  if (e.key === 'ArrowUp' || e.key === 'ArrowDown') {
475
494
  e.preventDefault();
476
495
  let currentTime = valueParts.time;
@@ -552,6 +571,16 @@ export function DateTimeInput({
552
571
  icon: "calendar",
553
572
  size: "sm",
554
573
  color: "secondary"
574
+ // Stable theme target on the calendar toggle glyph, so a theme
575
+ // can restyle just this icon (color, size, hover) — and each
576
+ // open/closed state — via `defineTheme`, mirroring
577
+ // `date-input-toggle-icon`. Same-element rules in
578
+ // @layer astryx-theme win over the icon's own base color/size,
579
+ // which a segment-level target could not reach.
580
+ ,
581
+ ...themeProps('date-time-input-toggle-icon', {
582
+ state: popover.isOpen ? 'expanded' : 'collapsed'
583
+ })
555
584
  })
556
585
  }), /*#__PURE__*/_jsx("input", {
557
586
  ref: mergeRefs(ref, dateInputRef),
@@ -573,7 +602,7 @@ export function DateTimeInput({
573
602
  "aria-disabled": showsDisabledMessage ? 'true' : undefined,
574
603
  readOnly: showsDisabledMessage || undefined,
575
604
  "aria-describedby": ariaDescribedBy,
576
- "aria-required": isRequired === true ? 'true' : undefined,
605
+ "aria-required": isEffectivelyRequired ? 'true' : undefined,
577
606
  "aria-invalid": status?.type === 'error' || !isDateInputValid ? 'true' : undefined,
578
607
  "aria-busy": isBusy || undefined,
579
608
  "aria-expanded": popover.isOpen,
@@ -624,6 +653,12 @@ export function DateTimeInput({
624
653
  icon: "clock",
625
654
  size: "sm",
626
655
  color: "secondary"
656
+ // Stable theme target on the leading clock glyph, so a theme can
657
+ // restyle just this icon (color, size) via `defineTheme`. The
658
+ // time segment has no toggle button — the clock is a static
659
+ // leading affordance — so this carries no interactive state.
660
+ ,
661
+ ...themeProps('date-time-input-clock-icon')
627
662
  })
628
663
  }), /*#__PURE__*/_jsx("input", {
629
664
  ref: timeInputRef,
@@ -646,7 +681,7 @@ export function DateTimeInput({
646
681
  label
647
682
  }),
648
683
  "aria-describedby": ariaDescribedBy,
649
- "aria-required": isRequired === true ? 'true' : undefined,
684
+ "aria-required": isEffectivelyRequired ? 'true' : undefined,
650
685
  "aria-invalid": status?.type === 'error' || !isTimeInputValid ? 'true' : undefined,
651
686
  "aria-busy": isBusy || undefined,
652
687
  ...{
@@ -1 +1 @@
1
- {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAoB5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAKhD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAsB9C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,4EAA4E;AAC5E,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAuHD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;EAUpE;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAgB,EAChB,YAAY,EACZ,KAAW,EACX,SAAkB,EAClB,QAAQ,EACR,OAAoB,EACpB,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,sCA2Sb;yBA3Te,MAAM"}
1
+ {"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../../src/Dialog/Dialog.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAqB5C,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gBAAgB,CAAC;AAKhD,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,SAAS,CAAC;AAsB9C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,gBAAgB,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzD,4EAA4E;AAC5E,UAAU,mBAAmB;IAC3B,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,mBAAmB;IACzD,6EAA6E;IAC7E,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACxB,yEAAyE;IACzE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAuHD;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,cAAc;;;;;EAUpE;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IAC/D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAEhB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;;OAOG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;IAE3C;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,QAAQ,CAAC,cAAc,CAAC,CAAC;IAEpC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC;IAExB;;;;OAIG;IACH,OAAO,CAAC,EAAE,WAAW,CAAC;IAEtB;;;OAGG;IACH,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,MAAM,CAAC,EACrB,MAAM,EACN,QAAgB,EAChB,YAAY,EACZ,KAAW,EACX,SAAkB,EAClB,QAAQ,EACR,OAAoB,EACpB,OAAgB,EAChB,OAAO,EACP,QAAQ,EACR,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,sCA2Sb;yBA3Te,MAAM"}
@@ -18,7 +18,8 @@
18
18
  import { useCallback, useEffect, useId, useMemo, useRef } from 'react';
19
19
  import * as stylex from '@stylexjs/stylex';
20
20
  import { useScrollLock } from "../hooks/useScrollLock.js";
21
- import { hasActiveFocusTrapEscape, isImeKeyEvent } from "../hooks/useFocusTrap.js";
21
+ import { hasActiveFocusTrapEscape } from "../hooks/useFocusTrap.js";
22
+ import { isImeKeyEvent } from "../utils/ime.js";
22
23
  import "../theme/tokens.stylex.js";
23
24
  import { colorVars, radiusVars, durationVars, easeVars, shadowVars } from "../theme/tokens.stylex.js";
24
25
  import { container } from "../Layout/container.stylex.js";
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * @file FieldLabel.tsx
3
- * @input Uses React, Icon, IconType, useTranslator
3
+ * @input Uses React, Icon, IconType, useTranslator, FormLayoutContext
4
4
  * @output Exports FieldLabel component, FieldLabelProps
5
5
  * @position Core label implementation; used by Field, CheckboxInput, Switch
6
6
  *
7
7
  * SYNC: When modified, update these files to stay in sync:
8
8
  * - /packages/core/src/Field/Field.doc.mjs (props table, features, implementation notes)
9
9
  * - /packages/core/src/Field/index.ts (exports if types change)
10
+ * - /packages/core/src/FormLayout/FormLayoutContext.ts (defaultOptionality drives the indicator)
10
11
  * - /packages/cli/assets/templates/blocks/components/Field/ (showcase blocks)
11
12
  * - /packages/core/locales/en.json (@astryx.field.required / @astryx.field.optional)
12
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"FieldLabel.d.ts","sourceRoot":"","sources":["../../src/Field/FieldLabel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAkB,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AAEtE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAU5C,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AAyD5D,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,gBAAgB,CAAC;IAClE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,OAAO,EACP,YAAoB,EACpB,aAAqB,EACrB,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,EACT,KAAK,EACL,MAAM,EACN,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BAwGjB;yBA1He,UAAU"}
1
+ {"version":3,"file":"FieldLabel.d.ts","sourceRoot":"","sources":["../../src/Field/FieldLabel.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAuB,KAAK,SAAS,EAAiB,MAAM,OAAO,CAAC;AAE3E,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAU5C,OAAO,EAAuB,KAAK,QAAQ,EAAC,MAAM,SAAS,CAAC;AA0D5D,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,gBAAgB,CAAC;IAClE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACjC;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,OAAO,EACP,OAAO,EACP,YAAoB,EACpB,aAAqB,EACrB,UAAkB,EAClB,UAAkB,EAClB,UAAkB,EAClB,SAAS,EACT,YAAY,EACZ,WAAW,EACX,aAAa,EACb,SAAS,EACT,KAAK,EACL,MAAM,EACN,GAAG,EACH,GAAG,IAAI,EACR,EAAE,eAAe,+BAsHjB;yBAxIe,UAAU"}
@@ -4,17 +4,18 @@
4
4
 
5
5
  /**
6
6
  * @file FieldLabel.tsx
7
- * @input Uses React, Icon, IconType, useTranslator
7
+ * @input Uses React, Icon, IconType, useTranslator, FormLayoutContext
8
8
  * @output Exports FieldLabel component, FieldLabelProps
9
9
  * @position Core label implementation; used by Field, CheckboxInput, Switch
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
12
  * - /packages/core/src/Field/Field.doc.mjs (props table, features, implementation notes)
13
13
  * - /packages/core/src/Field/index.ts (exports if types change)
14
+ * - /packages/core/src/FormLayout/FormLayoutContext.ts (defaultOptionality drives the indicator)
14
15
  * - /packages/cli/assets/templates/blocks/components/Field/ (showcase blocks)
15
16
  * - /packages/core/locales/en.json (@astryx.field.required / @astryx.field.optional)
16
17
  */
17
- import { useMemo, useRef } from 'react';
18
+ import { use, useMemo, useRef } from 'react';
18
19
  import * as stylex from '@stylexjs/stylex';
19
20
  import { mergeProps } from "../utils/index.js";
20
21
  import "../theme/tokens.stylex.js";
@@ -24,6 +25,7 @@ import { Tooltip } from "../Tooltip/index.js";
24
25
  import { useTranslator } from "../i18n/index.js";
25
26
  import { themeProps } from "../utils/themeProps.js";
26
27
  import { useInputContainer } from "../hooks/index.js";
28
+ import { FormLayoutContext } from "../FormLayout/FormLayoutContext.js";
27
29
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
28
30
  const styles = {
29
31
  label: {
@@ -93,7 +95,23 @@ export function FieldLabel({
93
95
  ...rest
94
96
  }) {
95
97
  const t = useTranslator();
96
- const statusText = isOptional ? t('@astryx.field.optional') : isRequired ? t('@astryx.field.required') : null;
98
+ const {
99
+ defaultOptionality
100
+ } = use(FormLayoutContext);
101
+
102
+ // A form-level `defaultOptionality` means "only the exception is marked": a
103
+ // field that merely restates the form's default shows no indicator, and only
104
+ // a deviation from it does. This is the *visible indicator* only; the
105
+ // matching `aria-required` is resolved on each control (see
106
+ // useResolvedRequired) so the unmarked majority is still announced.
107
+ //
108
+ // defaultOptionality isRequired isOptional
109
+ // 'optional' → required indicator → (matches default, hidden)
110
+ // 'required' → (matches, hidden) → optional indicator
111
+ // unset → required indicator → optional indicator
112
+ const showRequired = isRequired && defaultOptionality !== 'required';
113
+ const showOptional = isOptional && defaultOptionality !== 'optional';
114
+ const statusText = showOptional ? t('@astryx.field.optional') : showRequired ? t('@astryx.field.required') : null;
97
115
 
98
116
  // A group label (e.g. for a radiogroup) must not be a literal `<label>`
99
117
  // element: a `<label>` semantically names a single form control and can't be
@@ -7,7 +7,8 @@
7
7
  * TextInput, NumberInput, TimeInput, DateInput, DateTimeInput,
8
8
  * DateRangeInput, Selector, MultiSelector, Typeahead, Tokenizer, FileInput —
9
9
  * routes it through here, so the glyph is themed in one place via the
10
- * `astryx-input-clear-icon` target.
10
+ * `astryx-input-clear-icon` target and the button wrapper is themed via the
11
+ * `astryx-input-clear-button` target.
11
12
  */
12
13
  import type { ReactNode } from 'react';
13
14
  import * as stylex from '@stylexjs/stylex';
@@ -1 +1 @@
1
- {"version":3,"file":"InputClearButton.d.ts","sourceRoot":"","sources":["../../src/Field/InputClearButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAY3C,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC;IAC7B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,MAAM,EACN,aAAa,GACd,EAAE,qBAAqB,GAAG,SAAS,CAwBnC;yBA7Be,gBAAgB"}
1
+ {"version":3,"file":"InputClearButton.d.ts","sourceRoot":"","sources":["../../src/Field/InputClearButton.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,OAAO,CAAC;AACrC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC;AAY3C,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,iBAAiB,CAAC,KAAK,IAAI,CAAC;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC;IAC7B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,OAAO,EACP,MAAM,EACN,aAAa,GACd,EAAE,qBAAqB,GAAG,SAAS,CA0BnC;yBA/Be,gBAAgB"}
@@ -11,7 +11,8 @@
11
11
  * TextInput, NumberInput, TimeInput, DateInput, DateTimeInput,
12
12
  * DateRangeInput, Selector, MultiSelector, Typeahead, Tokenizer, FileInput —
13
13
  * routes it through here, so the glyph is themed in one place via the
14
- * `astryx-input-clear-icon` target.
14
+ * `astryx-input-clear-icon` target and the button wrapper is themed via the
15
+ * `astryx-input-clear-button` target.
15
16
  */
16
17
  import * as stylex from '@stylexjs/stylex';
17
18
  import { Button } from "../Button/index.js";
@@ -34,10 +35,14 @@ export function InputClearButton({
34
35
  const {
35
36
  className: iconTargetClassName
36
37
  } = themeProps('input-clear-icon');
38
+ const {
39
+ className: buttonTargetClassName
40
+ } = themeProps('input-clear-button');
37
41
  return /*#__PURE__*/_jsx(Button, {
38
42
  variant: "ghost",
39
43
  size: "sm",
40
44
  label: label,
45
+ className: buttonTargetClassName,
41
46
  icon: /*#__PURE__*/_jsx(Icon, {
42
47
  icon: "close",
43
48
  size: "sm",
@@ -6,13 +6,16 @@
6
6
  *
7
7
  * SYNC: When modified, update these files to stay in sync:
8
8
  * - /packages/core/src/FormLayout/FormLayout.test.tsx (tests for new/changed behavior)
9
+ * - /packages/core/src/FormLayout/FormLayoutContext.ts (context value shape)
10
+ * - /packages/core/src/FormLayout/FormLayout.doc.mjs (props table)
9
11
  * - /packages/core/src/FormLayout/index.ts (exports if types change)
12
+ * - /packages/core/src/Field/FieldLabel.tsx (defaultOptionality indicator resolution)
10
13
  * - /apps/storybook/stories/FormLayout.stories.tsx (storybook stories)
11
14
  * - /packages/cli/assets/templates/blocks/components/FormLayout/ (showcase blocks)
12
15
  */
13
16
  import { type ReactNode } from 'react';
14
17
  import type { BaseProps } from '../BaseProps';
15
- import { type FormLayoutDirection } from './FormLayoutContext';
18
+ import { type FormLayoutDirection, type FormOptionality } from './FormLayoutContext';
16
19
  export interface FormLayoutProps extends BaseProps<HTMLDivElement> {
17
20
  /** Ref forwarded to the root element */
18
21
  ref?: React.Ref<HTMLDivElement>;
@@ -33,6 +36,25 @@ export interface FormLayoutProps extends BaseProps<HTMLDivElement> {
33
36
  * @default 'vertical'
34
37
  */
35
38
  direction?: FormLayoutDirection;
39
+ /**
40
+ * Which state the form treats as its default, so only the *exception*
41
+ * carries a visible optional/required indicator. It also resolves each
42
+ * field's `aria-required` so the unmarked majority is still announced
43
+ * correctly — but only `aria-required`, never the native `required`
44
+ * attribute, so a layout default can't switch on browser validation.
45
+ *
46
+ * - `'optional'` — fields read as optional; only a field with `isRequired`
47
+ * shows an indicator (the "required" one).
48
+ * - `'required'` — fields read as required; only a field with `isOptional`
49
+ * shows an indicator (the "optional" one). Fields without `isOptional`
50
+ * expose `aria-required` even though they show no indicator.
51
+ * - unset — today's behavior: `isRequired` and `isOptional` each show their
52
+ * own indicator independently.
53
+ *
54
+ * A field that merely restates the default (e.g. `isOptional` under
55
+ * `'optional'`) shows nothing. An inner `FormLayout` shadows an outer one.
56
+ */
57
+ defaultOptionality?: FormOptionality;
36
58
  }
37
59
  /**
38
60
  * Spatial layout container for form fields.
@@ -52,7 +74,7 @@ export interface FormLayoutProps extends BaseProps<HTMLDivElement> {
52
74
  * </FormLayout>
53
75
  * ```
54
76
  */
55
- export declare function FormLayout({ children, direction, xstyle, className, style, ref, ...props }: FormLayoutProps): import("react").JSX.Element;
77
+ export declare function FormLayout({ children, direction, defaultOptionality, xstyle, className, style, ref, ...props }: FormLayoutProps): import("react").JSX.Element;
56
78
  export declare namespace FormLayout {
57
79
  var displayName: string;
58
80
  }
@@ -1 +1 @@
1
- {"version":3,"file":"FormLayout.d.ts","sourceRoot":"","sources":["../../src/FormLayout/FormLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAU,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,OAAO,EAAoB,KAAK,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AA0ChF,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;CACjC;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAsB,EACtB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,eAAe,+BAuBjB;yBA/Be,UAAU"}
1
+ {"version":3,"file":"FormLayout.d.ts","sourceRoot":"","sources":["../../src/FormLayout/FormLayout.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAU,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AAC9C,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAG5C,OAAO,EAEL,KAAK,mBAAmB,EACxB,KAAK,eAAe,EACrB,MAAM,qBAAqB,CAAC;AA0C7B,MAAM,WAAW,eAAgB,SAAQ,SAAS,CAAC,cAAc,CAAC;IAChE,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IAErB;;;;;;;;;;OAUG;IACH,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAEhC;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,eAAe,CAAC;CACtC;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,SAAsB,EACtB,kBAAkB,EAClB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,eAAe,+BA0BjB;yBAnCe,UAAU"}
@@ -10,7 +10,10 @@
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
12
  * - /packages/core/src/FormLayout/FormLayout.test.tsx (tests for new/changed behavior)
13
+ * - /packages/core/src/FormLayout/FormLayoutContext.ts (context value shape)
14
+ * - /packages/core/src/FormLayout/FormLayout.doc.mjs (props table)
13
15
  * - /packages/core/src/FormLayout/index.ts (exports if types change)
16
+ * - /packages/core/src/Field/FieldLabel.tsx (defaultOptionality indicator resolution)
14
17
  * - /apps/storybook/stories/FormLayout.stories.tsx (storybook stories)
15
18
  * - /packages/cli/assets/templates/blocks/components/FormLayout/ (showcase blocks)
16
19
  */
@@ -86,6 +89,7 @@ const styles = {
86
89
  export function FormLayout({
87
90
  children,
88
91
  direction = 'vertical',
92
+ defaultOptionality,
89
93
  xstyle,
90
94
  className,
91
95
  style,
@@ -93,8 +97,9 @@ export function FormLayout({
93
97
  ...props
94
98
  }) {
95
99
  const contextValue = useMemo(() => ({
96
- direction
97
- }), [direction]);
100
+ direction,
101
+ defaultOptionality
102
+ }), [direction, defaultOptionality]);
98
103
  return /*#__PURE__*/_jsx(FormLayoutContext, {
99
104
  value: contextValue,
100
105
  children: /*#__PURE__*/_jsx("div", {
@@ -8,10 +8,23 @@
8
8
  */
9
9
  export type FormLayoutDirection = 'vertical' | 'horizontal' | 'horizontal-labels';
10
10
  /**
11
- * Context for detecting which form layout direction a component is rendered in.
12
- * Children can use this to adapt their rendering based on the parent layout.
11
+ * Which state a form treats as its default, so only the *exception* carries a
12
+ * visible optional/required indicator.
13
+ *
14
+ * - `'optional'` — fields are optional unless a field opts into `isRequired`;
15
+ * only required fields show an indicator.
16
+ * - `'required'` — fields are required unless a field opts into `isOptional`;
17
+ * only optional fields show an indicator.
18
+ */
19
+ export type FormOptionality = 'optional' | 'required';
20
+ /**
21
+ * Context for detecting which form layout a component is rendered in. Children
22
+ * can use this to adapt their rendering based on the parent layout — direction
23
+ * for spatial arrangement, and `defaultOptionality` so a field can suppress the
24
+ * indicator that merely restates the form-wide default.
13
25
  */
14
26
  export declare const FormLayoutContext: import("react").Context<{
15
27
  direction: FormLayoutDirection;
28
+ defaultOptionality?: FormOptionality;
16
29
  }>;
17
30
  //# sourceMappingURL=FormLayoutContext.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormLayoutContext.d.ts","sourceRoot":"","sources":["../../src/FormLayout/FormLayoutContext.ts"],"names":[],"mappings":"AAeA;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAC3B,UAAU,GACV,YAAY,GACZ,mBAAmB,CAAC;AAExB;;;GAGG;AACH,eAAO,MAAM,iBAAiB;eACjB,mBAAmB;EACL,CAAC"}
1
+ {"version":3,"file":"FormLayoutContext.d.ts","sourceRoot":"","sources":["../../src/FormLayout/FormLayoutContext.ts"],"names":[],"mappings":"AAkBA;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAC7B,UAAU,GAAG,YAAY,GAAG,mBAAmB,CAAC;AAElD;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,CAAC;AAEtD;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB;eACjB,mBAAmB;yBACT,eAAe;EACX,CAAC"}
@@ -5,10 +5,13 @@
5
5
  /**
6
6
  * @file FormLayoutContext.ts
7
7
  * @input Uses React createContext
8
- * @output Exports FormLayoutContext and FormLayoutDirection type
9
- * @position Context for form layout direction detection
8
+ * @output Exports FormLayoutContext, FormLayoutDirection, and FormOptionality types
9
+ * @position Context for form layout direction + default-optionality detection
10
10
  *
11
11
  * SYNC: When modified, update these files to stay in sync:
12
+ * - /packages/core/src/FormLayout/FormLayout.tsx (prop + context value)
13
+ * - /packages/core/src/Field/FieldLabel.tsx (indicator resolution)
14
+ * - /packages/core/src/FormLayout/index.ts (exports if types change)
12
15
  */
13
16
  import { createContext } from 'react';
14
17
 
@@ -22,8 +25,20 @@ import { createContext } from 'react';
22
25
  */
23
26
 
24
27
  /**
25
- * Context for detecting which form layout direction a component is rendered in.
26
- * Children can use this to adapt their rendering based on the parent layout.
28
+ * Which state a form treats as its default, so only the *exception* carries a
29
+ * visible optional/required indicator.
30
+ *
31
+ * - `'optional'` — fields are optional unless a field opts into `isRequired`;
32
+ * only required fields show an indicator.
33
+ * - `'required'` — fields are required unless a field opts into `isOptional`;
34
+ * only optional fields show an indicator.
35
+ */
36
+
37
+ /**
38
+ * Context for detecting which form layout a component is rendered in. Children
39
+ * can use this to adapt their rendering based on the parent layout — direction
40
+ * for spatial arrangement, and `defaultOptionality` so a field can suppress the
41
+ * indicator that merely restates the form-wide default.
27
42
  */
28
43
  export const FormLayoutContext = /*#__PURE__*/createContext({
29
44
  direction: 'vertical'
@@ -8,6 +8,6 @@
8
8
  */
9
9
  export { FormLayout } from './FormLayout';
10
10
  export type { FormLayoutProps } from './FormLayout';
11
- export type { FormLayoutDirection } from './FormLayoutContext';
11
+ export type { FormLayoutDirection, FormOptionality } from './FormLayoutContext';
12
12
  export { FormLayoutContext } from './FormLayoutContext';
13
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FormLayout/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAClD,YAAY,EAAC,mBAAmB,EAAC,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/FormLayout/index.ts"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AAEH,OAAO,EAAC,UAAU,EAAC,MAAM,cAAc,CAAC;AACxC,YAAY,EAAC,eAAe,EAAC,MAAM,cAAc,CAAC;AAClD,YAAY,EAAC,mBAAmB,EAAE,eAAe,EAAC,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EAAC,iBAAiB,EAAC,MAAM,qBAAqB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Lightbox.d.ts","sourceRoot":"","sources":["../../src/Lightbox/Lightbox.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAK5C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACjE,+CAA+C;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,KAAK,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAwJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,YAAY,EACZ,KAAK,EACL,KAAK,EAAE,eAAe,EACtB,YAAgB,EAChB,aAAa,EACb,OAAe,EACf,WAAmB,EACnB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,GAAG,KAAK,EACT,EAAE,aAAa,sCAyYf;yBAzZe,QAAQ"}
1
+ {"version":3,"file":"Lightbox.d.ts","sourceRoot":"","sources":["../../src/Lightbox/Lightbox.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AASf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAK5C;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,OAAO,GAAG,OAAO,CAAC;AAElD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAC;IACZ,iDAAiD;IACjD,OAAO,CAAC,EAAE,SAAS,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,aAAc,SAAQ,SAAS,CAAC,iBAAiB,CAAC;IACjE,+CAA+C;IAC/C,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;OAEG;IACH,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,KAAK,EAAE,aAAa,GAAG,aAAa,EAAE,CAAC;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAwJD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,QAAQ,CAAC,EACvB,MAAM,EACN,YAAY,EACZ,KAAK,EACL,KAAK,EAAE,eAAe,EACtB,YAAgB,EAChB,aAAa,EACb,OAAe,EACf,WAAmB,EACnB,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,GAAG,KAAK,EACT,EAAE,aAAa,sCA6Yf;yBA7Ze,QAAQ"}
@@ -269,9 +269,15 @@ export function Lightbox({
269
269
  return;
270
270
  }
271
271
  const item = mediaArray[Math.min(index, mediaArray.length - 1)];
272
- const position = `${index + 1} of ${mediaArray.length}`;
273
- announce(item?.alt ? `${item.alt}, ${position}` : `Image ${position}`);
274
- }, [index, isOpen, announce, mediaArray]);
272
+ const position = {
273
+ index: index + 1,
274
+ total: mediaArray.length
275
+ };
276
+ announce(item?.alt ? t('@astryx.lightbox.mediaPosition', {
277
+ alt: item.alt,
278
+ ...position
279
+ }) : t('@astryx.lightbox.imagePosition', position));
280
+ }, [index, isOpen, announce, mediaArray, t]);
275
281
 
276
282
  // Open/close dialog
277
283
  useIsomorphicLayoutEffect(() => {
@@ -23,6 +23,18 @@
23
23
  */
24
24
  import { type ReactNode } from 'react';
25
25
  import type { BaseProps } from '../BaseProps';
26
+ /**
27
+ * Shortest duration in a `transition-duration` list, in ms; null if unreadable.
28
+ *
29
+ * Browsers serialise computed `<time>` values in seconds — an authored `410ms`
30
+ * reads back as `"0.41s"` and a list as `"0.41s, 0.12s"` — so the seconds branch
31
+ * is the one that runs outside tests. jsdom echoes an inline `250ms` back as-is
32
+ * and never resolves `var()`, so both units and the unreadable case are covered
33
+ * directly in MobileNavCloseTiming.test.ts rather than through the component.
34
+ *
35
+ * @internal Exported for unit tests.
36
+ */
37
+ export declare function parseShortestDurationMs(value: string): number | null;
26
38
  export interface MobileNavProps extends Omit<BaseProps, 'title'> {
27
39
  /** Ref forwarded to the root element */
28
40
  ref?: React.Ref<HTMLDialogElement>;
@@ -1 +1 @@
1
- {"version":3,"file":"MobileNav.d.ts","sourceRoot":"","sources":["../../src/MobileNav/MobileNav.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAcf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA2I5C,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,EACxB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EACR,MAAM,EACN,KAAW,EACX,IAAa,EACb,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,+BAsLhB;yBArMe,SAAS"}
1
+ {"version":3,"file":"MobileNav.d.ts","sourceRoot":"","sources":["../../src/MobileNav/MobileNav.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAcf,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AA4J5C;;;;;;;;;;GAUG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBpE;AAmCD,MAAM,WAAW,cAAe,SAAQ,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC;IAC9D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IACnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;IAEzC;;OAEG;IACH,QAAQ,EAAE,SAAS,CAAC;IAEpB;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;IAEhC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAMD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,SAAS,CAAC,EACxB,MAAM,EAAE,UAAU,EAClB,YAAY,EAAE,gBAAgB,EAC9B,QAAQ,EACR,MAAM,EACN,KAAW,EACX,IAAa,EACb,KAAK,EACL,aAAa,EAAE,MAAM,EACrB,MAAM,EACN,SAAS,EACT,KAAK,EACL,OAAO,EAAE,WAAW,EACpB,GAAG,EACH,GAAG,IAAI,EACR,EAAE,cAAc,+BAgMhB;yBA/Me,SAAS"}