@dashforge/tw 1.6.0 → 1.7.0

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 (25) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/index.esm.js +167 -10
  3. package/dist/src/components/Autocomplete/Autocomplete.d.ts.map +1 -1
  4. package/dist/src/components/Checkbox/Checkbox.d.ts.map +1 -1
  5. package/dist/src/components/Checkbox/checkbox.types.d.ts +16 -0
  6. package/dist/src/components/Checkbox/checkbox.types.d.ts.map +1 -1
  7. package/dist/src/components/Checkbox/checkbox.variants.d.ts +3 -0
  8. package/dist/src/components/Checkbox/checkbox.variants.d.ts.map +1 -1
  9. package/dist/src/components/DatePicker/DatePicker.d.ts.map +1 -1
  10. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  11. package/dist/src/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  12. package/dist/src/components/NumberField/NumberField.d.ts.map +1 -1
  13. package/dist/src/components/OTPField/OTPField.d.ts.map +1 -1
  14. package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  15. package/dist/src/components/Select/Select.d.ts.map +1 -1
  16. package/dist/src/components/Slider/Slider.d.ts.map +1 -1
  17. package/dist/src/components/Switch/Switch.d.ts.map +1 -1
  18. package/dist/src/components/Switch/switch.types.d.ts +15 -0
  19. package/dist/src/components/Switch/switch.types.d.ts.map +1 -1
  20. package/dist/src/components/Switch/switch.variants.d.ts +3 -0
  21. package/dist/src/components/Switch/switch.variants.d.ts.map +1 -1
  22. package/dist/src/components/TextField/TextField.d.ts.map +1 -1
  23. package/dist/src/components/Textarea/Textarea.d.ts.map +1 -1
  24. package/dist/src/components/TimePicker/TimePicker.d.ts.map +1 -1
  25. package/package.json +4 -4
package/CHANGELOG.md CHANGED
@@ -12,6 +12,53 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
12
12
  > duplicated intentionally — no shared "lowest common denominator" headless
13
13
  > layer.
14
14
 
15
+ ## [1.7.0] — 2026-09-22
16
+
17
+ ### Added
18
+
19
+ - **`<Checkbox required>` and `<Switch required>`** — the last two
20
+ bridge-integrated field components in the package that did not
21
+ accept `required` (the other twelve — Autocomplete, DatePicker,
22
+ DateRangePicker, DateTimePicker, NumberField, OTPField, RadioGroup,
23
+ Select, Slider, TextField, Textarea, TimePicker — already did).
24
+ Fixes BUG 21 in `libs/dashforge/README-BUG.md`. Both components now
25
+ render a `*` marker at the end of the label (styled via a new
26
+ `requiredMark` slot in the variants recipe, colour tokens matching
27
+ `textField.variants.ts` `requiredMark`) and set `aria-required="true"`
28
+ on the underlying Radix Root button via a **ref + `useEffect`
29
+ post-mount DOM setter** (Radix v1.3.3's own internal
30
+ context-then-re-emit path for `aria-required` was verified to strip
31
+ the attribute in production browser builds, though jsdom did not
32
+ catch that; the ref-based fallback is Radix-version-agnostic). HTML5
33
+ `required` is still passed through to Radix so
34
+ `Radix.CheckboxBubbleInput` picks it up for native form validation.
35
+ The `requiredMark` slot accepts a `className` via `slotProps` for
36
+ per-instance overrides, and via `theme.components.<Name>.slotProps`
37
+ for design-system-wide overrides. Presentational only, per the
38
+ library-wide convention: form-submit enforcement still requires
39
+ `rules={{ required: … }}` or a resolver rule. Seven regression tests
40
+ in `src/components/_shared/checkboxSwitchRequired.test.tsx` pin the
41
+ marker, the aria-required attribute, the no-render-when-omitted
42
+ invariant, and the slot override plumbing.
43
+
44
+ ### Fixed
45
+
46
+ - **14 field components now honour `bridge.shouldUnregister`** (BUG 22
47
+ cross-package fix). Autocomplete, Checkbox, DatePicker,
48
+ DateRangePicker, DateTimePicker, NumberField, OTPField, RadioGroup,
49
+ Select, Slider, Switch, TextField, Textarea, TimePicker — the
50
+ unmount cleanup that previously ran unconditionally
51
+ (`queueMicrotask` schedule of `bridge.unregister(name)`) now bails
52
+ out first with `if (!cap?.shouldUnregister) return;`. When
53
+ `bridge.shouldUnregister` is `false` (the new Dashforge default,
54
+ set in `DashFormProvider`) the field's row in `formState.values`
55
+ survives the unmount, which is what `<Stepper>` and tab-swap
56
+ patterns need. Requires `@dashforge/ui-core@≥1.2.0` (new bridge
57
+ field) and `@dashforge/forms@≥1.2.0` (bridge population). The
58
+ StrictMode-safe `queueMicrotask` + `isMountedRef` pattern is
59
+ preserved verbatim; the change only decides *whether* to run the
60
+ scheduled cleanup.
61
+
15
62
  ## [1.6.0] — 2026-09-15
16
63
 
17
64
  Minor release: three bug fixes (BUG 6 Dialog `actions` slot,
package/dist/index.esm.js CHANGED
@@ -1095,6 +1095,11 @@ const tooltipVariants = tv({
1095
1095
  return ()=>{
1096
1096
  isMountedRef.current = false;
1097
1097
  const { bridge: cap, name: capName } = unregisterRef.current;
1098
+ // BUG 22: only release bridge state on unmount if the form
1099
+ // is configured to forget unmounted fields. Default `false`
1100
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
1101
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
1102
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
1098
1103
  queueMicrotask(()=>{
1099
1104
  var _cap_unregister;
1100
1105
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -1257,6 +1262,10 @@ const tooltipVariants = tv({
1257
1262
  ],
1258
1263
  indicator: 'flex items-center justify-center text-white',
1259
1264
  label: 'select-none cursor-pointer text-neutral-900',
1265
+ // BUG 21: `*` marker after the label, matching the `textField.variants.ts`
1266
+ // `requiredMark` slot so a consent box aligns visually with sibling
1267
+ // required fields in a form.
1268
+ requiredMark: 'text-danger-500 ml-0.5',
1260
1269
  helperText: 'text-sm text-neutral-600 mt-1',
1261
1270
  errorText: 'text-sm text-danger-600 mt-1'
1262
1271
  },
@@ -1365,13 +1374,13 @@ const tooltipVariants = tv({
1365
1374
  * rather than MUI slot components.
1366
1375
  */ function Checkbox(props) {
1367
1376
  var _ref;
1368
- var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_indicator, _slotProps_indicator, _themeSlotProps_label, _slotProps_label, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1377
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_indicator, _slotProps_indicator, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1369
1378
  const themeDefaults = useComponentDefaults('Checkbox');
1370
1379
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1371
1380
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1372
1381
  // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1373
1382
  const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1374
- const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1383
+ const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, required, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1375
1384
  // ───── Hooks (always called, unconditional) ─────
1376
1385
  const bridge = useContext(DashFormContext);
1377
1386
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
@@ -1381,6 +1390,32 @@ const tooltipVariants = tv({
1381
1390
  const fieldMeta = useDashFieldMeta(name);
1382
1391
  const accessState = useAccessState(access);
1383
1392
  const controlId = useId();
1393
+ // BUG 21 v2: local ref for the Radix Root DOM button. We use this to
1394
+ // set `aria-required` post-mount because setting the attribute via a
1395
+ // JSX prop on `RadixCheckbox.Root` does not reach the browser DOM in
1396
+ // production builds (verified empirically in urbango on Radix v1.3.3;
1397
+ // jsdom does not surface the same gap).
1398
+ const buttonRef = useRef(null);
1399
+ const setControlRef = (node)=>{
1400
+ buttonRef.current = node;
1401
+ const regRef = registration == null ? void 0 : registration.ref;
1402
+ if (typeof regRef === 'function') {
1403
+ regRef(node);
1404
+ } else if (regRef && typeof regRef === 'object') {
1405
+ regRef.current = node;
1406
+ }
1407
+ };
1408
+ useEffect(()=>{
1409
+ const node = buttonRef.current;
1410
+ if (!node) return;
1411
+ if (required) {
1412
+ node.setAttribute('aria-required', 'true');
1413
+ } else {
1414
+ node.removeAttribute('aria-required');
1415
+ }
1416
+ }, [
1417
+ required
1418
+ ]);
1384
1419
  // StrictMode-safe unregister-on-unmount — mirrors MUI Checkbox.tsx
1385
1420
  // (the bridge identity changes on every keystroke, so we MUST NOT
1386
1421
  // re-run cleanup on deps changes — empty deps + ref pattern).
@@ -1398,6 +1433,11 @@ const tooltipVariants = tv({
1398
1433
  return ()=>{
1399
1434
  isMountedRef.current = false;
1400
1435
  const { bridge: cap, name: capName } = unregisterRef.current;
1436
+ // BUG 22: only release bridge state on unmount if the form
1437
+ // is configured to forget unmounted fields. Default `false`
1438
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
1439
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
1440
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
1401
1441
  queueMicrotask(()=>{
1402
1442
  var _cap_unregister;
1403
1443
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -1486,9 +1526,19 @@ const tooltipVariants = tv({
1486
1526
  name: name
1487
1527
  }, radixStateProps, {
1488
1528
  disabled: effectiveDisabled,
1529
+ required: required,
1489
1530
  onCheckedChange: handleCheckedChange,
1490
1531
  onBlur: handleBlur,
1491
- ref: registration == null ? void 0 : registration.ref,
1532
+ // BUG 21 v2: compose our own ref with `registration.ref` so we can
1533
+ // ALSO set `aria-required` post-mount via a `useEffect` below. The
1534
+ // JSX-level `aria-required` prop was verified empirically not to
1535
+ // reach the DOM in a real browser (Radix v1.3.3 reads its own
1536
+ // `required` prop into context and re-emits `aria-required` from
1537
+ // the internal trigger, but the attribute is stripped somewhere
1538
+ // in the production path — jsdom does not catch it). Post-mount
1539
+ // ref-based setter is Radix-version-agnostic and lands on the
1540
+ // element the browser actually shows.
1541
+ ref: setControlRef,
1492
1542
  className: cn(v.control(), themeSlotProps == null ? void 0 : (_themeSlotProps_control = themeSlotProps.control) == null ? void 0 : _themeSlotProps_control.className, slotProps == null ? void 0 : (_slotProps_control = slotProps.control) == null ? void 0 : _slotProps_control.className),
1493
1543
  children: jsxs(RadixCheckbox.Indicator, {
1494
1544
  className: cn(v.indicator(), 'group', themeSlotProps == null ? void 0 : (_themeSlotProps_indicator = themeSlotProps.indicator) == null ? void 0 : _themeSlotProps_indicator.className, slotProps == null ? void 0 : (_slotProps_indicator = slotProps.indicator) == null ? void 0 : _slotProps_indicator.className),
@@ -1505,10 +1555,17 @@ const tooltipVariants = tv({
1505
1555
  jsxs("div", {
1506
1556
  className: "flex flex-col",
1507
1557
  children: [
1508
- label && jsx("label", {
1558
+ label && jsxs("label", {
1509
1559
  htmlFor: controlId,
1510
1560
  className: cn(v.label(), themeSlotProps == null ? void 0 : (_themeSlotProps_label = themeSlotProps.label) == null ? void 0 : _themeSlotProps_label.className, slotProps == null ? void 0 : (_slotProps_label = slotProps.label) == null ? void 0 : _slotProps_label.className),
1511
- children: renderLabelWithTooltip(label, tooltipConfig)
1561
+ children: [
1562
+ renderLabelWithTooltip(label, tooltipConfig),
1563
+ required && jsx("span", {
1564
+ "aria-hidden": "true",
1565
+ className: cn(v.requiredMark(), themeSlotProps == null ? void 0 : (_themeSlotProps_requiredMark = themeSlotProps.requiredMark) == null ? void 0 : _themeSlotProps_requiredMark.className, slotProps == null ? void 0 : (_slotProps_requiredMark = slotProps.requiredMark) == null ? void 0 : _slotProps_requiredMark.className),
1566
+ children: "*"
1567
+ })
1568
+ ]
1512
1569
  }),
1513
1570
  resolvedHelperText && jsx("p", {
1514
1571
  className: cn(resolvedError ? v.errorText() : v.helperText(), resolvedError ? [
@@ -1559,6 +1616,9 @@ const tooltipVariants = tv({
1559
1616
  'data-[state=unchecked]:translate-x-0'
1560
1617
  ],
1561
1618
  label: 'select-none cursor-pointer text-neutral-900',
1619
+ // BUG 21: `*` marker after the label, same tokens as
1620
+ // `checkboxVariants.requiredMark` for visual parity.
1621
+ requiredMark: 'text-danger-500 ml-0.5',
1562
1622
  helperText: 'text-sm text-neutral-600 mt-1',
1563
1623
  errorText: 'text-sm text-danger-600 mt-1'
1564
1624
  },
@@ -1605,19 +1665,45 @@ const tooltipVariants = tv({
1605
1665
  * translate-x distance so the knob lands flush at each end.
1606
1666
  */ function Switch(props) {
1607
1667
  var _ref;
1608
- var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_thumb, _slotProps_thumb, _themeSlotProps_label, _slotProps_label, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1668
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_thumb, _slotProps_thumb, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1609
1669
  const themeDefaults = useComponentDefaults('Switch');
1610
1670
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1611
1671
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1612
1672
  // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1613
1673
  const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1614
- const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1674
+ const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, required, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1615
1675
  const bridge = useContext(DashFormContext);
1616
1676
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
1617
1677
  // Reactive snapshot — see Checkbox.tsx for the same rationale.
1618
1678
  const fieldMeta = useDashFieldMeta(name);
1619
1679
  const accessState = useAccessState(access);
1620
1680
  const controlId = useId();
1681
+ // BUG 21 v2: local ref + post-mount `aria-required` setter — same
1682
+ // pattern as Checkbox.tsx. Radix.Switch.Root reads `required` prop
1683
+ // into context but the JSX `aria-required` attribute does not reach
1684
+ // the browser DOM in production builds. Setting via ref is
1685
+ // Radix-version-agnostic. See README-BUG.md § BUG 21.
1686
+ const buttonRef = useRef(null);
1687
+ const setControlRef = (node)=>{
1688
+ buttonRef.current = node;
1689
+ const regRef = registration == null ? void 0 : registration.ref;
1690
+ if (typeof regRef === 'function') {
1691
+ regRef(node);
1692
+ } else if (regRef && typeof regRef === 'object') {
1693
+ regRef.current = node;
1694
+ }
1695
+ };
1696
+ useEffect(()=>{
1697
+ const node = buttonRef.current;
1698
+ if (!node) return;
1699
+ if (required) {
1700
+ node.setAttribute('aria-required', 'true');
1701
+ } else {
1702
+ node.removeAttribute('aria-required');
1703
+ }
1704
+ }, [
1705
+ required
1706
+ ]);
1621
1707
  // StrictMode-safe unregister-on-unmount
1622
1708
  const unregisterRef = useRef({
1623
1709
  bridge,
@@ -1633,6 +1719,11 @@ const tooltipVariants = tv({
1633
1719
  return ()=>{
1634
1720
  isMountedRef.current = false;
1635
1721
  const { bridge: cap, name: capName } = unregisterRef.current;
1722
+ // BUG 22: only release bridge state on unmount if the form
1723
+ // is configured to forget unmounted fields. Default `false`
1724
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
1725
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
1726
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
1636
1727
  queueMicrotask(()=>{
1637
1728
  var _cap_unregister;
1638
1729
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -1708,9 +1799,13 @@ const tooltipVariants = tv({
1708
1799
  name: name
1709
1800
  }, radixStateProps, {
1710
1801
  disabled: effectiveDisabled,
1802
+ required: required,
1711
1803
  onCheckedChange: handleCheckedChange,
1712
1804
  onBlur: handleBlur,
1713
- ref: registration == null ? void 0 : registration.ref,
1805
+ // BUG 21 v2: `aria-required` set via `setControlRef` + `useEffect`
1806
+ // above, not via JSX prop. See Checkbox.tsx for the same pattern
1807
+ // and the reasoning.
1808
+ ref: setControlRef,
1714
1809
  className: cn(v.control(), themeSlotProps == null ? void 0 : (_themeSlotProps_control = themeSlotProps.control) == null ? void 0 : _themeSlotProps_control.className, slotProps == null ? void 0 : (_slotProps_control = slotProps.control) == null ? void 0 : _slotProps_control.className),
1715
1810
  children: jsx(RadixSwitch.Thumb, {
1716
1811
  className: cn(v.thumb(), themeSlotProps == null ? void 0 : (_themeSlotProps_thumb = themeSlotProps.thumb) == null ? void 0 : _themeSlotProps_thumb.className, slotProps == null ? void 0 : (_slotProps_thumb = slotProps.thumb) == null ? void 0 : _slotProps_thumb.className)
@@ -1719,10 +1814,17 @@ const tooltipVariants = tv({
1719
1814
  jsxs("div", {
1720
1815
  className: "flex flex-col",
1721
1816
  children: [
1722
- label && jsx("label", {
1817
+ label && jsxs("label", {
1723
1818
  htmlFor: controlId,
1724
1819
  className: cn(v.label(), themeSlotProps == null ? void 0 : (_themeSlotProps_label = themeSlotProps.label) == null ? void 0 : _themeSlotProps_label.className, slotProps == null ? void 0 : (_slotProps_label = slotProps.label) == null ? void 0 : _slotProps_label.className),
1725
- children: renderLabelWithTooltip(label, tooltipConfig)
1820
+ children: [
1821
+ renderLabelWithTooltip(label, tooltipConfig),
1822
+ required && jsx("span", {
1823
+ "aria-hidden": "true",
1824
+ className: cn(v.requiredMark(), themeSlotProps == null ? void 0 : (_themeSlotProps_requiredMark = themeSlotProps.requiredMark) == null ? void 0 : _themeSlotProps_requiredMark.className, slotProps == null ? void 0 : (_slotProps_requiredMark = slotProps.requiredMark) == null ? void 0 : _slotProps_requiredMark.className),
1825
+ children: "*"
1826
+ })
1827
+ ]
1726
1828
  }),
1727
1829
  resolvedHelperText && jsx("p", {
1728
1830
  className: cn(resolvedError ? v.errorText() : v.helperText(), resolvedError ? [
@@ -1903,6 +2005,11 @@ const tooltipVariants = tv({
1903
2005
  return ()=>{
1904
2006
  isMountedRef.current = false;
1905
2007
  const { bridge: cap, name: capName } = unregisterRef.current;
2008
+ // BUG 22: only release bridge state on unmount if the form
2009
+ // is configured to forget unmounted fields. Default `false`
2010
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
2011
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
2012
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
1906
2013
  queueMicrotask(()=>{
1907
2014
  var _cap_unregister;
1908
2015
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -2219,6 +2326,11 @@ const tooltipVariants = tv({
2219
2326
  return ()=>{
2220
2327
  isMountedRef.current = false;
2221
2328
  const { bridge: cap, name: capName } = unregisterRef.current;
2329
+ // BUG 22: only release bridge state on unmount if the form
2330
+ // is configured to forget unmounted fields. Default `false`
2331
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
2332
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
2333
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
2222
2334
  queueMicrotask(()=>{
2223
2335
  var _cap_unregister;
2224
2336
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -2541,6 +2653,11 @@ const tooltipVariants = tv({
2541
2653
  return ()=>{
2542
2654
  isMountedRef.current = false;
2543
2655
  const { bridge: cap, name: capName } = unregisterRef.current;
2656
+ // BUG 22: only release bridge state on unmount if the form
2657
+ // is configured to forget unmounted fields. Default `false`
2658
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
2659
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
2660
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
2544
2661
  queueMicrotask(()=>{
2545
2662
  var _cap_unregister;
2546
2663
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -2835,6 +2952,11 @@ const tooltipVariants = tv({
2835
2952
  return ()=>{
2836
2953
  isMountedRef.current = false;
2837
2954
  const { bridge: cap, name: capName } = unregisterRef.current;
2955
+ // BUG 22: only release bridge state on unmount if the form
2956
+ // is configured to forget unmounted fields. Default `false`
2957
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
2958
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
2959
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
2838
2960
  queueMicrotask(()=>{
2839
2961
  var _cap_unregister;
2840
2962
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -3311,6 +3433,11 @@ function Autocomplete(props) {
3311
3433
  return ()=>{
3312
3434
  isMountedRef.current = false;
3313
3435
  const { bridge: cap, name: capName } = unregisterRef.current;
3436
+ // BUG 22: only release bridge state on unmount if the form
3437
+ // is configured to forget unmounted fields. Default `false`
3438
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
3439
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
3440
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
3314
3441
  queueMicrotask(()=>{
3315
3442
  var _cap_unregister;
3316
3443
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -4618,6 +4745,11 @@ function CalendarIcon$2() {
4618
4745
  return ()=>{
4619
4746
  isMountedRef.current = false;
4620
4747
  const { bridge: cap, name: capName } = unregisterRef.current;
4748
+ // BUG 22: only release bridge state on unmount if the form
4749
+ // is configured to forget unmounted fields. Default `false`
4750
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
4751
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
4752
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
4621
4753
  queueMicrotask(()=>{
4622
4754
  var _cap_unregister;
4623
4755
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -4901,6 +5033,11 @@ function ClockIcon() {
4901
5033
  return ()=>{
4902
5034
  isMountedRef.current = false;
4903
5035
  const { bridge: cap, name: capName } = unregisterRef.current;
5036
+ // BUG 22: only release bridge state on unmount if the form
5037
+ // is configured to forget unmounted fields. Default `false`
5038
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
5039
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
5040
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
4904
5041
  queueMicrotask(()=>{
4905
5042
  var _cap_unregister;
4906
5043
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -5238,6 +5375,11 @@ const DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/;
5238
5375
  return ()=>{
5239
5376
  isMountedRef.current = false;
5240
5377
  const { bridge: cap, name: capName } = unregisterRef.current;
5378
+ // BUG 22: only release bridge state on unmount if the form
5379
+ // is configured to forget unmounted fields. Default `false`
5380
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
5381
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
5382
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
5241
5383
  queueMicrotask(()=>{
5242
5384
  var _cap_unregister;
5243
5385
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -5802,6 +5944,11 @@ function formatRange(range, locale) {
5802
5944
  return ()=>{
5803
5945
  isMountedRef.current = false;
5804
5946
  const { bridge: cap, name: capName } = unregisterRef.current;
5947
+ // BUG 22: only release bridge state on unmount if the form
5948
+ // is configured to forget unmounted fields. Default `false`
5949
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
5950
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
5951
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
5805
5952
  queueMicrotask(()=>{
5806
5953
  var _cap_unregister;
5807
5954
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -9946,6 +10093,11 @@ const DEFAULT_STEP = 1;
9946
10093
  return ()=>{
9947
10094
  isMountedRef.current = false;
9948
10095
  const { bridge: cap, name: capName } = unregisterRef.current;
10096
+ // BUG 22: only release bridge state on unmount if the form
10097
+ // is configured to forget unmounted fields. Default `false`
10098
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
10099
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
10100
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
9949
10101
  queueMicrotask(()=>{
9950
10102
  var _cap_unregister;
9951
10103
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -10493,6 +10645,11 @@ Slider.displayName = 'Slider';
10493
10645
  return ()=>{
10494
10646
  isMountedRef.current = false;
10495
10647
  const { bridge: cap, name: capName } = unregisterRef.current;
10648
+ // BUG 22: only release bridge state on unmount if the form
10649
+ // is configured to forget unmounted fields. Default `false`
10650
+ // keeps values in RHF so <Stepper> / tab-swap patterns can
10651
+ // read earlier answers back on later steps. See README-BUG.md § BUG 22.
10652
+ if (!(cap == null ? void 0 : cap.shouldUnregister)) return;
10496
10653
  queueMicrotask(()=>{
10497
10654
  var _cap_unregister;
10498
10655
  if (!isMountedRef.current) cap == null ? void 0 : (_cap_unregister = cap.unregister) == null ? void 0 : _cap_unregister.call(cap, capName);
@@ -1 +1 @@
1
- {"version":3,"file":"Autocomplete.d.ts","sourceRoot":"","sources":["../../../../src/components/Autocomplete/Autocomplete.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,yBAAyB,CAAC;AA8FjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,GAAG,IAAI,EACnB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,OAAO,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAGT;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAG,kBAAkB,EACvD,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,kDA6lClC"}
1
+ {"version":3,"file":"Autocomplete.d.ts","sourceRoot":"","sources":["../../../../src/components/Autocomplete/Autocomplete.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,yBAAyB,CAAC;AA8FjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,IAAI,GAAG,IAAI,EACnB,IAAI,EAAE,WAAW,GAAG,IAAI,EACxB,OAAO,EAAE,WAAW,GAAG,IAAI,GAC1B,OAAO,CAGT;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAG,kBAAkB,EACvD,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,kDAkmClC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA0DzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDA8M5C"}
1
+ {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AA0DzD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAuQ5C"}
@@ -42,6 +42,14 @@ export interface CheckboxSlotProps {
42
42
  errorText?: {
43
43
  className?: string;
44
44
  };
45
+ /**
46
+ * The `*` asterisk rendered next to the label when `required` is true.
47
+ * Themed by `checkboxVariants().requiredMark()`; override here to
48
+ * change colour / spacing. See README-BUG.md § BUG 21.
49
+ */
50
+ requiredMark?: {
51
+ className?: string;
52
+ };
45
53
  }
46
54
  /**
47
55
  * Props for the Dashforge TW `<Checkbox>` component.
@@ -85,6 +93,14 @@ export interface CheckboxProps {
85
93
  defaultChecked?: boolean;
86
94
  /** Disabled — combined with RBAC disabled via OR. */
87
95
  disabled?: boolean;
96
+ /**
97
+ * Renders a `*` asterisk next to the label and sets `aria-required="true"`
98
+ * on the underlying Radix control button. This is the visual + a11y marker
99
+ * for a mandatory consent box (privacy policy, terms of service).
100
+ * Presentational only: submit-time enforcement still requires
101
+ * `rules={{ required: … }}` or a resolver rule. See README-BUG.md § BUG 21.
102
+ */
103
+ required?: boolean;
88
104
  /**
89
105
  * Forces helper text below the control. When the bridge surfaces an
90
106
  * error and `helperText` is undefined, the bridge's error message
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/checkbox.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;AAElE,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,mBAAmB;QAC3B,QAAQ,CAAC,EAAE;YACT,QAAQ,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG;gBAAE,OAAO,CAAC,EAAE,gBAAgB,CAAA;aAAE,CAAC;YAC1E,SAAS,CAAC,EAAE,iBAAiB,CAAC;SAC/B,CAAC;KACH;CACF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,UAAU,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEhC,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IAEb,8EAA8E;IAC9E,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1C,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,wBAAwB;IACxB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,oDAAoD;IACpD,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAE9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C"}
1
+ {"version":3,"file":"checkbox.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/checkbox.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC;AAElE,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,mBAAmB;QAC3B,QAAQ,CAAC,EAAE;YACT,QAAQ,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG;gBAAE,OAAO,CAAC,EAAE,gBAAgB,CAAA;aAAE,CAAC;YAC1E,SAAS,CAAC,EAAE,iBAAiB,CAAC;SAC/B,CAAC;KACH;CACF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,UAAU,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAEhC,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IAEb,8EAA8E;IAC9E,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1C,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,8CAA8C;IAC9C,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;OAIG;IACH,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,wBAAwB;IACxB,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,oDAAoD;IACpD,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAE9B;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C"}
@@ -42,6 +42,7 @@ export declare const checkboxVariants: import("tailwind-variants").TVReturnType<
42
42
  control: string[];
43
43
  indicator: string;
44
44
  label: string;
45
+ requiredMark: string;
45
46
  helperText: string;
46
47
  errorText: string;
47
48
  }, undefined, {
@@ -72,6 +73,7 @@ export declare const checkboxVariants: import("tailwind-variants").TVReturnType<
72
73
  control: string[];
73
74
  indicator: string;
74
75
  label: string;
76
+ requiredMark: string;
75
77
  helperText: string;
76
78
  errorText: string;
77
79
  }, import("tailwind-variants").TVReturnType<{
@@ -102,6 +104,7 @@ export declare const checkboxVariants: import("tailwind-variants").TVReturnType<
102
104
  control: string[];
103
105
  indicator: string;
104
106
  label: string;
107
+ requiredMark: string;
105
108
  helperText: string;
106
109
  errorText: string;
107
110
  }, undefined, unknown, unknown, undefined>>;
@@ -1 +1 @@
1
- {"version":3,"file":"checkbox.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/checkbox.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAqD3B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
1
+ {"version":3,"file":"checkbox.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/Checkbox/checkbox.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAyD3B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAqD7D;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,kDAsPjD"}
1
+ {"version":3,"file":"DatePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DatePicker/DatePicker.tsx"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAqD7D;;;;;;;;;;GAUG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,kDA2PjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"DateRangePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/DateRangePicker.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAoQvE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,oBAAoB,kDA4N3D"}
1
+ {"version":3,"file":"DateRangePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DateRangePicker/DateRangePicker.tsx"],"names":[],"mappings":"AA6BA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAoQvE;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,oBAAoB,kDAiO3D"}
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DateTimePicker/DateTimePicker.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AA8ErE;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,mBAAmB,kDAyPzD"}
1
+ {"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/DateTimePicker/DateTimePicker.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AA8ErE;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,mBAAmB,kDA8PzD"}
@@ -1 +1 @@
1
- {"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../../src/components/NumberField/NumberField.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAuC/D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kDAgRlD"}
1
+ {"version":3,"file":"NumberField.d.ts","sourceRoot":"","sources":["../../../../src/components/NumberField/NumberField.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAuC/D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kDAqRlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"OTPField.d.ts","sourceRoot":"","sources":["../../../../src/components/OTPField/OTPField.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAgBvE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAmN5C"}
1
+ {"version":3,"file":"OTPField.d.ts","sourceRoot":"","sources":["../../../../src/components/OTPField/OTPField.tsx"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAgBvE;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAwN5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"RadioGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kDA4QhD"}
1
+ {"version":3,"file":"RadioGroup.d.ts","sourceRoot":"","sources":["../../../../src/components/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,eAAe,kDAiRhD"}
@@ -1 +1 @@
1
- {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../src/components/Select/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AAgBf,OAAO,KAAK,EAIV,WAAW,EACX,WAAW,EACZ,MAAM,mBAAmB,CAAC;AAsmB3B;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAA8B,CAAC,CAAC,SAAS,WAAW,GAAG,MAAM,EAC9E,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;CAAE,KAC3D,YAAY,GAAG,IAAI,CAAC"}
1
+ {"version":3,"file":"Select.d.ts","sourceRoot":"","sources":["../../../../src/components/Select/Select.tsx"],"names":[],"mappings":"AAAA,OAAO,EAUL,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AAgBf,OAAO,KAAK,EAIV,WAAW,EACX,WAAW,EACZ,MAAM,mBAAmB,CAAC;AA2mB3B;;;;;;;GAOG;AACH,eAAO,MAAM,MAAM,EAA8B,CAAC,CAAC,SAAS,WAAW,GAAG,MAAM,EAC9E,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG;IAAE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;CAAE,KAC3D,YAAY,GAAG,IAAI,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAEV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAgE3B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,yGAyXjB,CAAC;AAOH,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"Slider.d.ts","sourceRoot":"","sources":["../../../../src/components/Slider/Slider.tsx"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAEV,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EACjB,MAAM,mBAAmB,CAAC;AAgE3B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,MAAM,yGA8XjB,CAAC;AAOH,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/Switch.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,kDAsJxC"}
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/Switch.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD;;;;;;;;;;;GAWG;AACH,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,kDAyMxC"}
@@ -37,6 +37,14 @@ export interface SwitchSlotProps {
37
37
  errorText?: {
38
38
  className?: string;
39
39
  };
40
+ /**
41
+ * The `*` asterisk rendered next to the label when `required` is true.
42
+ * Themed by `switchVariants().requiredMark()`; override here to change
43
+ * colour / spacing. See README-BUG.md § BUG 21.
44
+ */
45
+ requiredMark?: {
46
+ className?: string;
47
+ };
40
48
  }
41
49
  /**
42
50
  * Props for the Dashforge TW `<Switch>` component.
@@ -80,6 +88,13 @@ export interface SwitchProps {
80
88
  * @default false
81
89
  */
82
90
  disabled?: boolean;
91
+ /**
92
+ * Renders a `*` asterisk next to the label and sets `aria-required="true"`
93
+ * on the underlying Radix control button. Presentational only: submit-time
94
+ * enforcement still requires `rules={{ required: … }}` or a resolver rule.
95
+ * See README-BUG.md § BUG 21.
96
+ */
97
+ required?: boolean;
83
98
  /** Helper line below the control. Auto-replaced by bridge error when invalid. */
84
99
  helperText?: ReactNode;
85
100
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"switch.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/switch.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE9D,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,mBAAmB;QAC3B,MAAM,CAAC,EAAE;YACP,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG;gBAAE,OAAO,CAAC,EAAE,gBAAgB,CAAA;aAAE,CAAC;YACxE,SAAS,CAAC,EAAE,eAAe,CAAC;SAC7B,CAAC;KACH;CACF;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,UAAU,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACpC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAE9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IAEb,sFAAsF;IACtF,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1C,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,iFAAiF;IACjF,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,uFAAuF;IACvF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,iFAAiF;IACjF,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,kDAAkD;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B,gFAAgF;IAChF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C"}
1
+ {"version":3,"file":"switch.types.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/switch.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAEnE;;;GAGG;AACH,MAAM,MAAM,kBAAkB,GAAG,IAAI,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;AAE9D,OAAO,QAAQ,sBAAsB,CAAC;IACpC,UAAU,mBAAmB;QAC3B,MAAM,CAAC,EAAE;YACP,QAAQ,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,GAAG;gBAAE,OAAO,CAAC,EAAE,gBAAgB,CAAA;aAAE,CAAC;YACxE,SAAS,CAAC,EAAE,eAAe,CAAC;SAC7B,CAAC;KACH;CACF;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACjC,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,KAAK,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/B,UAAU,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACvC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B;;;OAGG;IACH,IAAI,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAE9B,wEAAwE;IACxE,IAAI,EAAE,MAAM,CAAC;IAEb,sFAAsF;IACtF,KAAK,CAAC,EAAE,SAAS,CAAC;IAElB;;;;OAIG;IACH,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAE3B,gFAAgF;IAChF,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1C,gCAAgC;IAChC,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,CAAC;IAEzB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,iFAAiF;IACjF,UAAU,CAAC,EAAE,SAAS,CAAC;IAEvB;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB,uFAAuF;IACvF,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAE3B,iFAAiF;IACjF,EAAE,CAAC,EAAE,MAAM,CAAC;IAEZ,kDAAkD;IAClD,SAAS,CAAC,EAAE,eAAe,CAAC;IAE5B,gFAAgF;IAChF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C"}
@@ -38,6 +38,7 @@ export declare const switchVariants: import("tailwind-variants").TVReturnType<{
38
38
  control: string[];
39
39
  thumb: string[];
40
40
  label: string;
41
+ requiredMark: string;
41
42
  helperText: string;
42
43
  errorText: string;
43
44
  }, undefined, {
@@ -68,6 +69,7 @@ export declare const switchVariants: import("tailwind-variants").TVReturnType<{
68
69
  control: string[];
69
70
  thumb: string[];
70
71
  label: string;
72
+ requiredMark: string;
71
73
  helperText: string;
72
74
  errorText: string;
73
75
  }, import("tailwind-variants").TVReturnType<{
@@ -98,6 +100,7 @@ export declare const switchVariants: import("tailwind-variants").TVReturnType<{
98
100
  control: string[];
99
101
  thumb: string[];
100
102
  label: string;
103
+ requiredMark: string;
101
104
  helperText: string;
102
105
  errorText: string;
103
106
  }, undefined, unknown, unknown, undefined>>;
@@ -1 +1 @@
1
- {"version":3,"file":"switch.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/switch.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAsDzB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC"}
1
+ {"version":3,"file":"switch.variants.d.ts","sourceRoot":"","sources":["../../../../src/components/Switch/switch.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;GAUG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CAyDzB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,YAAY,CAAC,OAAO,cAAc,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../src/components/TextField/TextField.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,kDAqO9C"}
1
+ {"version":3,"file":"TextField.d.ts","sourceRoot":"","sources":["../../../../src/components/TextField/TextField.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAE3D;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,kDA0O9C"}
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../../src/components/Textarea/Textarea.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAoL5C"}
1
+ {"version":3,"file":"Textarea.d.ts","sourceRoot":"","sources":["../../../../src/components/Textarea/Textarea.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;;;;;;GAYG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,kDAyL5C"}
@@ -1 +1 @@
1
- {"version":3,"file":"TimePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/TimePicker/TimePicker.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkB7D;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,kDAgPjD"}
1
+ {"version":3,"file":"TimePicker.d.ts","sourceRoot":"","sources":["../../../../src/components/TimePicker/TimePicker.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAkB7D;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,eAAe,kDAqPjD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dashforge/tw",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.esm.js",
@@ -35,9 +35,9 @@
35
35
  "tailwind-merge": "^3.0.0",
36
36
  "tailwind-variants": "^3.1.1",
37
37
  "@dashforge/calendar-core": "1.0.0",
38
- "@dashforge/ui-core": "1.1.0",
39
- "@dashforge/forms": "1.1.0",
40
- "@dashforge/rbac": "1.0.0"
38
+ "@dashforge/rbac": "1.0.0",
39
+ "@dashforge/forms": "1.2.0",
40
+ "@dashforge/ui-core": "1.2.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": "^18.0.0 || ^19.0.0",