@dashforge/tw 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/index.esm.js +304 -219
  3. package/dist/src/components/Autocomplete/Autocomplete.d.ts.map +1 -1
  4. package/dist/src/components/Autocomplete/autocomplete.types.d.ts +10 -1
  5. package/dist/src/components/Autocomplete/autocomplete.types.d.ts.map +1 -1
  6. package/dist/src/components/Checkbox/Checkbox.d.ts.map +1 -1
  7. package/dist/src/components/Checkbox/checkbox.types.d.ts +10 -1
  8. package/dist/src/components/Checkbox/checkbox.types.d.ts.map +1 -1
  9. package/dist/src/components/DatePicker/DatePicker.d.ts.map +1 -1
  10. package/dist/src/components/DatePicker/datePicker.types.d.ts +10 -1
  11. package/dist/src/components/DatePicker/datePicker.types.d.ts.map +1 -1
  12. package/dist/src/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
  13. package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts +10 -1
  14. package/dist/src/components/DateRangePicker/dateRangePicker.types.d.ts.map +1 -1
  15. package/dist/src/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
  16. package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts +10 -1
  17. package/dist/src/components/DateTimePicker/dateTimePicker.types.d.ts.map +1 -1
  18. package/dist/src/components/NumberField/NumberField.d.ts.map +1 -1
  19. package/dist/src/components/NumberField/numberField.types.d.ts +10 -1
  20. package/dist/src/components/NumberField/numberField.types.d.ts.map +1 -1
  21. package/dist/src/components/OTPField/OTPField.d.ts.map +1 -1
  22. package/dist/src/components/OTPField/otpField.types.d.ts +10 -1
  23. package/dist/src/components/OTPField/otpField.types.d.ts.map +1 -1
  24. package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +1 -1
  25. package/dist/src/components/RadioGroup/radioGroup.types.d.ts +10 -1
  26. package/dist/src/components/RadioGroup/radioGroup.types.d.ts.map +1 -1
  27. package/dist/src/components/Select/Select.d.ts.map +1 -1
  28. package/dist/src/components/Select/select.types.d.ts +10 -1
  29. package/dist/src/components/Select/select.types.d.ts.map +1 -1
  30. package/dist/src/components/Switch/Switch.d.ts.map +1 -1
  31. package/dist/src/components/Switch/switch.types.d.ts +10 -1
  32. package/dist/src/components/Switch/switch.types.d.ts.map +1 -1
  33. package/dist/src/components/TextField/TextField.d.ts.map +1 -1
  34. package/dist/src/components/TextField/textField.types.d.ts +11 -1
  35. package/dist/src/components/TextField/textField.types.d.ts.map +1 -1
  36. package/dist/src/components/Textarea/Textarea.d.ts.map +1 -1
  37. package/dist/src/components/Textarea/textarea.types.d.ts +10 -1
  38. package/dist/src/components/Textarea/textarea.types.d.ts.map +1 -1
  39. package/dist/src/components/TimePicker/TimePicker.d.ts.map +1 -1
  40. package/dist/src/components/TimePicker/timePicker.types.d.ts +10 -1
  41. package/dist/src/components/TimePicker/timePicker.types.d.ts.map +1 -1
  42. package/dist/src/components/_shared/fieldTooltip.d.ts +49 -0
  43. package/dist/src/components/_shared/fieldTooltip.d.ts.map +1 -0
  44. package/dist/src/index.d.ts +1 -1
  45. package/package.json +3 -3
package/dist/index.esm.js CHANGED
@@ -1,5 +1,5 @@
1
- import { jsxs, jsx, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
- import { useMemo, forwardRef, useContext, useState, useEffect, useRef, useId, useCallback, Fragment, createContext, Children, isValidElement, memo, cloneElement, useLayoutEffect } from 'react';
1
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo, forwardRef, useContext, useState, useEffect, useRef, useId, useCallback, Fragment as Fragment$1, createContext, Children, isValidElement, memo, cloneElement, useLayoutEffect } from 'react';
3
3
  import { Slot } from '@radix-ui/react-slot';
4
4
  import { DashFormContext, useEngineVisibility } from '@dashforge/ui-core';
5
5
  import { useComponentDefaults } from '@dashforge/tw-theme';
@@ -9,6 +9,7 @@ import { useRbacOptional, resolveAccessState } from '@dashforge/rbac';
9
9
  import { tv } from 'tailwind-variants';
10
10
  export { tv } from 'tailwind-variants';
11
11
  import { useDashFieldMeta } from '@dashforge/forms';
12
+ import * as RadixTooltip from '@radix-ui/react-tooltip';
12
13
  import * as RadixCheckbox from '@radix-ui/react-checkbox';
13
14
  import * as RadixSwitch from '@radix-ui/react-switch';
14
15
  import * as RadixRadioGroup from '@radix-ui/react-radio-group';
@@ -17,7 +18,6 @@ import * as RadixPopover from '@radix-ui/react-popover';
17
18
  import * as RadixDialog from '@radix-ui/react-dialog';
18
19
  import * as RadixSlider from '@radix-ui/react-slider';
19
20
  import * as RadixMenu from '@radix-ui/react-dropdown-menu';
20
- import * as RadixTooltip from '@radix-ui/react-tooltip';
21
21
  import * as RadixAccordion from '@radix-ui/react-accordion';
22
22
 
23
23
  function _extends() {
@@ -630,6 +630,184 @@ Spinner.displayName = 'Spinner';
630
630
  }));
631
631
  });
632
632
 
633
+ const tooltipVariants = tv({
634
+ slots: {
635
+ content: [
636
+ 'z-50 max-w-xs rounded-md px-3 py-1.5 text-xs font-medium',
637
+ // Auto-invert via the dashforgePreset() CSS-var swap:
638
+ // - Light mode: `bg-neutral-900` = #171717 (dark surface) +
639
+ // `text-neutral-50` = #fafafa (light text) — DARK tooltip
640
+ // on the light page (high contrast).
641
+ // - Dark mode: `bg-neutral-900` flips to #f5f5f5 (light) +
642
+ // `text-neutral-50` flips to #0a0a0a (dark text) — LIGHT
643
+ // tooltip on the dark page (high contrast against page).
644
+ // Adding `dark:bg-neutral-50 dark:text-neutral-900` (the old
645
+ // pattern) would force the dark-mode tooltip back to a dark
646
+ // surface — invisible against the dark page.
647
+ 'bg-neutral-900 text-neutral-50',
648
+ 'shadow-md',
649
+ 'data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95',
650
+ 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
651
+ 'motion-reduce:transition-none motion-reduce:duration-0'
652
+ ],
653
+ // Arrow tracks the content bg — auto-inverts the same way.
654
+ arrow: 'fill-neutral-900'
655
+ }
656
+ });
657
+
658
+ /**
659
+ * Dashforge TW `<Tooltip>` — hoverable / focusable tooltip.
660
+ *
661
+ * Built on `@radix-ui/react-tooltip`:
662
+ * - APG tooltip pattern: `role="tooltip"`, `aria-describedby` wired
663
+ * to the trigger automatically (Radix manages the id linkage).
664
+ * - Shows on hover OR keyboard focus.
665
+ * - Dismissed on Escape or pointer leave.
666
+ *
667
+ * Wrap any single React node — it becomes the trigger via Radix's
668
+ * `asChild` slot. The trigger inherits `aria-describedby` so screen
669
+ * readers announce the tooltip content along with the trigger.
670
+ *
671
+ * @example
672
+ * ```tsx
673
+ * <Tooltip content="Delete this item">
674
+ * <Button variant="ghost">
675
+ * <TrashIcon />
676
+ * </Button>
677
+ * </Tooltip>
678
+ * ```
679
+ *
680
+ * Each consumer can also wrap the entire app once in
681
+ * `<RadixTooltip.Provider>` to share delay/skip configuration; we
682
+ * include a per-component provider here for ease-of-use.
683
+ */ function Tooltip(props) {
684
+ var _themeSlotProps_content, _slotProps_content, _themeSlotProps_arrow, _slotProps_arrow;
685
+ const themeDefaults = useComponentDefaults('Tooltip');
686
+ const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
687
+ const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
688
+ const { children, content, side = 'top', align = 'center', hideArrow = false, delayDuration = 200, open, onOpenChange, sideOffset = 4, sx, slotProps } = merged;
689
+ const v = tooltipVariants();
690
+ return jsx(RadixTooltip.Provider, {
691
+ delayDuration: delayDuration,
692
+ children: jsxs(RadixTooltip.Root, {
693
+ open: open,
694
+ onOpenChange: onOpenChange,
695
+ children: [
696
+ jsx(RadixTooltip.Trigger, {
697
+ asChild: true,
698
+ children: children
699
+ }),
700
+ jsx(RadixTooltip.Portal, {
701
+ children: jsxs(RadixTooltip.Content, {
702
+ side: side,
703
+ align: align,
704
+ sideOffset: sideOffset,
705
+ className: cn(v.content(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_content = themeSlotProps.content) == null ? void 0 : _themeSlotProps_content.className, slotProps == null ? void 0 : (_slotProps_content = slotProps.content) == null ? void 0 : _slotProps_content.className),
706
+ children: [
707
+ content,
708
+ !hideArrow && jsx(RadixTooltip.Arrow, {
709
+ className: cn(v.arrow(), themeSlotProps == null ? void 0 : (_themeSlotProps_arrow = themeSlotProps.arrow) == null ? void 0 : _themeSlotProps_arrow.className, slotProps == null ? void 0 : (_slotProps_arrow = slotProps.arrow) == null ? void 0 : _slotProps_arrow.className)
710
+ })
711
+ ]
712
+ })
713
+ })
714
+ ]
715
+ })
716
+ });
717
+ }
718
+
719
+ /** Normalise `string | config` to a config (or null when absent). */ function normalizeFieldTooltip(tooltip) {
720
+ if (tooltip == null) return null;
721
+ return typeof tooltip === 'string' ? {
722
+ content: tooltip
723
+ } : tooltip;
724
+ }
725
+ /**
726
+ * Resolve the effective tooltip config (Option C): deep-merge the
727
+ * per-instance `tooltip` over the theme default. The instance wins per
728
+ * key, so the theme can set `icon` / `position` / `side` while the
729
+ * instance supplies just `content` (via the string shorthand).
730
+ */ function resolveFieldTooltip(instance, themeDefault) {
731
+ const inst = normalizeFieldTooltip(instance);
732
+ const base = normalizeFieldTooltip(themeDefault);
733
+ if (!inst && !base) return null;
734
+ if (!inst) return base;
735
+ if (!base) return inst;
736
+ return _extends({}, base, inst);
737
+ }
738
+ /** Built-in default trigger icon — inline SVG, no external dependency. */ function InfoCircleIcon() {
739
+ return jsxs("svg", {
740
+ width: "16",
741
+ height: "16",
742
+ viewBox: "0 0 24 24",
743
+ fill: "none",
744
+ stroke: "currentColor",
745
+ strokeWidth: "1.7",
746
+ strokeLinecap: "round",
747
+ strokeLinejoin: "round",
748
+ "aria-hidden": "true",
749
+ children: [
750
+ jsx("circle", {
751
+ cx: "12",
752
+ cy: "12",
753
+ r: "9"
754
+ }),
755
+ jsx("path", {
756
+ d: "M12 16v-4"
757
+ }),
758
+ jsx("path", {
759
+ d: "M12 8h.01"
760
+ })
761
+ ]
762
+ });
763
+ }
764
+ /** The focusable ⓘ trigger + the Radix-based `<Tooltip>` popup. */ function LabelTooltipTrigger({ config }) {
765
+ const { content, icon, position = 'after', side = 'top' } = config;
766
+ return jsx(Tooltip, {
767
+ content: content,
768
+ side: side,
769
+ children: jsx("button", {
770
+ type: "button",
771
+ "aria-label": "More information",
772
+ className: cn('inline-flex items-center justify-center align-middle leading-none text-neutral-500 hover:text-neutral-700 cursor-help', position === 'before' ? 'mr-1' : 'ml-1'),
773
+ children: icon != null ? icon : jsx(InfoCircleIcon, {})
774
+ })
775
+ });
776
+ }
777
+ /**
778
+ * Compose the primary label block — `label` plus its optional `required`
779
+ * mark — with the help-tooltip trigger. The required asterisk stays part
780
+ * of the primary block; the `ⓘ` is secondary and sits before/after that
781
+ * whole block. Returns the plain primary block when there is no tooltip.
782
+ *
783
+ * @param label - the label node.
784
+ * @param config - resolved tooltip config (from {@link resolveFieldTooltip}) or `null`.
785
+ * @param requiredMark - the required-asterisk node (or falsy), rendered as
786
+ * part of the primary block, immediately after the label.
787
+ */ function renderLabelWithTooltip(label, config, requiredMark) {
788
+ const primary = requiredMark ? jsxs(Fragment, {
789
+ children: [
790
+ label,
791
+ requiredMark
792
+ ]
793
+ }) : label;
794
+ if (!config) return primary;
795
+ const trigger = jsx(LabelTooltipTrigger, {
796
+ config: config
797
+ });
798
+ return config.position === 'before' ? jsxs(Fragment, {
799
+ children: [
800
+ trigger,
801
+ primary
802
+ ]
803
+ }) : jsxs(Fragment, {
804
+ children: [
805
+ primary,
806
+ trigger
807
+ ]
808
+ });
809
+ }
810
+
633
811
  /**
634
812
  * `useStandaloneFieldWarning` — dev-only guard for `@dashforge/tw` form
635
813
  * widgets rendered outside a `DashFormProvider` and without a controlled
@@ -849,10 +1027,12 @@ Spinner.displayName = 'Spinner';
849
1027
  * - `aria-describedby` links the input to the helper/error text node.
850
1028
  * - Required fields get the native `required` attribute + a visual `*`.
851
1029
  */ function TextField(props) {
852
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _slotProps_prefix, _themeSlotProps_input, _slotProps_input, _slotProps_suffix, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1030
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _slotProps_prefix, _themeSlotProps_input, _slotProps_input, _slotProps_suffix, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
853
1031
  const themeDefaults = useComponentDefaults('TextField');
854
1032
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
855
1033
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1034
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1035
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
856
1036
  const { name, rules, visibleWhen, layout = 'stacked', size, label, helperText, required, error, disabled, fullWidth, access, sx, slotProps, placeholder, type, onChange: userOnChange, onBlur: userOnBlur, value: userValue, defaultValue } = merged, rest = _object_without_properties_loose(merged, [
857
1037
  "name",
858
1038
  "rules",
@@ -971,17 +1151,14 @@ Spinner.displayName = 'Spinner';
971
1151
  return jsxs("div", {
972
1152
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
973
1153
  children: [
974
- label && jsxs("label", {
1154
+ label && jsx("label", {
975
1155
  htmlFor: inputId,
976
1156
  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),
977
- children: [
978
- label,
979
- required && jsx("span", {
980
- "aria-hidden": "true",
981
- 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),
982
- children: "*"
983
- })
984
- ]
1157
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
1158
+ "aria-hidden": "true",
1159
+ 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),
1160
+ children: "*"
1161
+ }))
985
1162
  }),
986
1163
  jsxs("div", {
987
1164
  className: cn(v.inputWrapper(), themeSlotProps == null ? void 0 : (_themeSlotProps_inputWrapper = themeSlotProps.inputWrapper) == null ? void 0 : _themeSlotProps_inputWrapper.className, slotProps == null ? void 0 : (_slotProps_inputWrapper = slotProps.inputWrapper) == null ? void 0 : _slotProps_inputWrapper.className),
@@ -1169,10 +1346,12 @@ Spinner.displayName = 'Spinner';
1169
1346
  * rather than MUI slot components.
1170
1347
  */ function Checkbox(props) {
1171
1348
  var _ref;
1172
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_indicator, _slotProps_indicator, _themeSlotProps_label, _slotProps_label, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1349
+ 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;
1173
1350
  const themeDefaults = useComponentDefaults('Checkbox');
1174
1351
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1175
1352
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1353
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1354
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1176
1355
  const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1177
1356
  // ───── Hooks (always called, unconditional) ─────
1178
1357
  const bridge = useContext(DashFormContext);
@@ -1310,7 +1489,7 @@ Spinner.displayName = 'Spinner';
1310
1489
  label && jsx("label", {
1311
1490
  htmlFor: controlId,
1312
1491
  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),
1313
- children: label
1492
+ children: renderLabelWithTooltip(label, tooltipConfig)
1314
1493
  }),
1315
1494
  resolvedHelperText && jsx("p", {
1316
1495
  className: cn(resolvedError ? v.errorText() : v.helperText(), resolvedError ? [
@@ -1407,10 +1586,12 @@ Spinner.displayName = 'Spinner';
1407
1586
  * translate-x distance so the knob lands flush at each end.
1408
1587
  */ function Switch(props) {
1409
1588
  var _ref;
1410
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_control, _slotProps_control, _themeSlotProps_thumb, _slotProps_thumb, _themeSlotProps_label, _slotProps_label, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1589
+ 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;
1411
1590
  const themeDefaults = useComponentDefaults('Switch');
1412
1591
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1413
1592
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1593
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1594
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1414
1595
  const { name, rules, visibleWhen, label, helperText, error, access, size, disabled, checked, defaultChecked, onCheckedChange, sx, slotProps } = merged;
1415
1596
  const bridge = useContext(DashFormContext);
1416
1597
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
@@ -1522,7 +1703,7 @@ Spinner.displayName = 'Spinner';
1522
1703
  label && jsx("label", {
1523
1704
  htmlFor: controlId,
1524
1705
  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),
1525
- children: label
1706
+ children: renderLabelWithTooltip(label, tooltipConfig)
1526
1707
  }),
1527
1708
  resolvedHelperText && jsx("p", {
1528
1709
  className: cn(resolvedError ? v.errorText() : v.helperText(), resolvedError ? [
@@ -1660,10 +1841,12 @@ Spinner.displayName = 'Spinner';
1660
1841
  * keyboard-accessible by default (arrow keys move selection).
1661
1842
  */ function RadioGroup(props) {
1662
1843
  var _ref;
1663
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_optionList, _slotProps_optionList, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1844
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_optionList, _slotProps_optionList, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1664
1845
  const themeDefaults = useComponentDefaults('RadioGroup');
1665
1846
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1666
1847
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
1848
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
1849
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1667
1850
  const { name, options, label, rules, helperText, required, error, disabled, size, layout, access, visibleWhen, sx, slotProps, value: explicitValue, defaultValue, onValueChange } = merged;
1668
1851
  // ───── Hooks (unconditional) ─────
1669
1852
  const bridge = useContext(DashFormContext);
@@ -1779,17 +1962,14 @@ Spinner.displayName = 'Spinner';
1779
1962
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
1780
1963
  "aria-describedby": resolvedHelperText ? helperId : undefined,
1781
1964
  children: [
1782
- label && jsxs("div", {
1965
+ label && jsx("div", {
1783
1966
  id: labelId,
1784
1967
  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),
1785
- children: [
1786
- label,
1787
- required && jsx("span", {
1788
- "aria-hidden": "true",
1789
- 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),
1790
- children: "*"
1791
- })
1792
- ]
1968
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
1969
+ "aria-hidden": "true",
1970
+ 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),
1971
+ children: "*"
1972
+ }))
1793
1973
  }),
1794
1974
  jsx(RadixRadioGroup.Root, _extends({
1795
1975
  name: name
@@ -1950,10 +2130,12 @@ Spinner.displayName = 'Spinner';
1950
2130
  * `aria-describedby` links to the helper/error text node, required
1951
2131
  * fields get the native `required` attribute + a visual `*`.
1952
2132
  */ function Textarea(props) {
1953
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_input, _slotProps_input, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
2133
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_input, _slotProps_input, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
1954
2134
  const themeDefaults = useComponentDefaults('Textarea');
1955
2135
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
1956
2136
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
2137
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
2138
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
1957
2139
  const { name, rules, visibleWhen, layout = 'stacked', size, resize, label, helperText, required, error, disabled, fullWidth, access, sx, slotProps, placeholder, rows = 3, onChange: userOnChange, onBlur: userOnBlur, value: userValue, defaultValue } = merged, rest = _object_without_properties_loose(merged, [
1958
2140
  "name",
1959
2141
  "rules",
@@ -2061,17 +2243,14 @@ Spinner.displayName = 'Spinner';
2061
2243
  return jsxs("div", {
2062
2244
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
2063
2245
  children: [
2064
- label && jsxs("label", {
2246
+ label && jsx("label", {
2065
2247
  htmlFor: inputId,
2066
2248
  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),
2067
- children: [
2068
- label,
2069
- required && jsx("span", {
2070
- "aria-hidden": "true",
2071
- 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),
2072
- children: "*"
2073
- })
2074
- ]
2249
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
2250
+ "aria-hidden": "true",
2251
+ 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),
2252
+ children: "*"
2253
+ }))
2075
2254
  }),
2076
2255
  jsx("div", {
2077
2256
  className: cn(v.inputWrapper(), themeSlotProps == null ? void 0 : (_themeSlotProps_inputWrapper = themeSlotProps.inputWrapper) == null ? void 0 : _themeSlotProps_inputWrapper.className, slotProps == null ? void 0 : (_slotProps_inputWrapper = slotProps.inputWrapper) == null ? void 0 : _slotProps_inputWrapper.className),
@@ -2251,10 +2430,12 @@ Spinner.displayName = 'Spinner';
2251
2430
  * `aria-valuemin` / `aria-valuemax` automatically)
2252
2431
  */ function NumberField(props) {
2253
2432
  var _parseFromInput, _parseFromInput1;
2254
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_input, _slotProps_input, _themeSlotProps_stepper, _slotProps_stepper, _themeSlotProps_stepperButton, _slotProps_stepperButton, _themeSlotProps_stepperButton1, _slotProps_stepperButton1, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
2433
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_input, _slotProps_input, _themeSlotProps_stepper, _slotProps_stepper, _themeSlotProps_stepperButton, _slotProps_stepperButton, _themeSlotProps_stepperButton1, _slotProps_stepperButton1, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
2255
2434
  const themeDefaults = useComponentDefaults('NumberField');
2256
2435
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
2257
2436
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
2437
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
2438
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
2258
2439
  const { name, rules, visibleWhen, layout = 'stacked', size, label, helperText, required, error, disabled, fullWidth, access, sx, slotProps, placeholder, min, max, step = 1, showStepper = false, onChange: userOnChange, onBlur: userOnBlur, value: userValue, defaultValue } = merged, rest = _object_without_properties_loose(merged, [
2259
2440
  "name",
2260
2441
  "rules",
@@ -2405,17 +2586,14 @@ Spinner.displayName = 'Spinner';
2405
2586
  return jsxs("div", {
2406
2587
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
2407
2588
  children: [
2408
- label && jsxs("label", {
2589
+ label && jsx("label", {
2409
2590
  htmlFor: inputId,
2410
2591
  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),
2411
- children: [
2412
- label,
2413
- required && jsx("span", {
2414
- "aria-hidden": "true",
2415
- 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),
2416
- children: "*"
2417
- })
2418
- ]
2592
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
2593
+ "aria-hidden": "true",
2594
+ 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),
2595
+ children: "*"
2596
+ }))
2419
2597
  }),
2420
2598
  jsxs("div", {
2421
2599
  className: cn(v.inputWrapper(), themeSlotProps == null ? void 0 : (_themeSlotProps_inputWrapper = themeSlotProps.inputWrapper) == null ? void 0 : _themeSlotProps_inputWrapper.className, slotProps == null ? void 0 : (_slotProps_inputWrapper = slotProps.inputWrapper) == null ? void 0 : _slotProps_inputWrapper.className),
@@ -2582,10 +2760,12 @@ Spinner.displayName = 'Spinner';
2582
2760
  * `inputMode="numeric" | "text"` per mode + `autoComplete="one-time-code"`
2583
2761
  * so iOS Safari + Android Chrome trigger SMS autofill correctly.
2584
2762
  */ function OTPField(props) {
2585
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_slotsRow, _slotProps_slotsRow, _themeSlotProps_hiddenInput, _slotProps_hiddenInput, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
2763
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_slotsRow, _slotProps_slotsRow, _themeSlotProps_hiddenInput, _slotProps_hiddenInput, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
2586
2764
  const themeDefaults = useComponentDefaults('OTPField');
2587
2765
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
2588
2766
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
2767
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
2768
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
2589
2769
  const { name, rules, visibleWhen, size, label, helperText, required, error, disabled, access, sx, slotProps, length = 6, mode = 'numeric', value: userValue, defaultValue, onChange: userOnChange, onComplete } = merged;
2590
2770
  // ───── Hooks (unconditional) ─────
2591
2771
  const bridge = useContext(DashFormContext);
@@ -2688,18 +2868,15 @@ Spinner.displayName = 'Spinner';
2688
2868
  return jsxs("div", {
2689
2869
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
2690
2870
  children: [
2691
- label && jsxs("label", {
2871
+ label && jsx("label", {
2692
2872
  id: labelId,
2693
2873
  htmlFor: inputId,
2694
2874
  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),
2695
- children: [
2696
- label,
2697
- required && jsx("span", {
2698
- "aria-hidden": "true",
2699
- 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),
2700
- children: "*"
2701
- })
2702
- ]
2875
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
2876
+ "aria-hidden": "true",
2877
+ 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),
2878
+ children: "*"
2879
+ }))
2703
2880
  }),
2704
2881
  jsxs("div", {
2705
2882
  className: cn(v.slotsRow(), themeSlotProps == null ? void 0 : (_themeSlotProps_slotsRow = themeSlotProps.slotsRow) == null ? void 0 : _themeSlotProps_slotsRow.className, slotProps == null ? void 0 : (_slotProps_slotsRow = slotProps.slotsRow) == null ? void 0 : _slotProps_slotsRow.className),
@@ -3009,10 +3186,12 @@ const defaultGetOptionDisabled = (option)=>Boolean(option.disabled);
3009
3186
  * shapes, and async runtime options (`optionsFromFieldData`) are
3010
3187
  * deferred to F5-A-bis.
3011
3188
  */ function Autocomplete(props) {
3012
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_chipsList, _slotProps_chipsList, _themeSlotProps_input, _slotProps_input, _themeSlotProps_clearButton, _slotProps_clearButton, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_popover, _slotProps_popover, _themeSlotProps_listBox, _slotProps_listBox, _themeSlotProps_emptyState, _slotProps_emptyState, _themeSlotProps_emptyState1, _slotProps_emptyState1, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
3189
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_inputWrapper, _slotProps_inputWrapper, _themeSlotProps_chipsList, _slotProps_chipsList, _themeSlotProps_input, _slotProps_input, _themeSlotProps_clearButton, _slotProps_clearButton, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_popover, _slotProps_popover, _themeSlotProps_listBox, _slotProps_listBox, _themeSlotProps_emptyState, _slotProps_emptyState, _themeSlotProps_emptyState1, _slotProps_emptyState1, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
3013
3190
  const themeDefaults = useComponentDefaults('Autocomplete');
3014
3191
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
3015
3192
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
3193
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
3194
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
3016
3195
  const { name, rules, options, visibleWhen, layout = 'stacked', size, label, helperText, required, error, disabled, fullWidth, access, sx, slotProps, placeholder, value: explicitValue, defaultValue, onValueChange, emptyMessage = 'No matching options', getOptionValue = defaultGetOptionValue, getOptionLabel = defaultGetOptionLabel, getOptionDisabled = defaultGetOptionDisabled, getOptionKey, multiple, freeSolo, loadOptions, loadDebounceMs = 250, loadingMessage = 'Loading…' } = merged;
3017
3196
  const isMulti = Boolean(multiple);
3018
3197
  // Default the React-key accessor to `getOptionValue` (typical case:
@@ -3600,18 +3779,15 @@ const defaultGetOptionDisabled = (option)=>Boolean(option.disabled);
3600
3779
  ref: rootRef,
3601
3780
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
3602
3781
  children: [
3603
- label && jsxs("label", {
3782
+ label && jsx("label", {
3604
3783
  id: labelId,
3605
3784
  htmlFor: `${baseId}-input`,
3606
3785
  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),
3607
- children: [
3608
- label,
3609
- required && jsx("span", {
3610
- "aria-hidden": "true",
3611
- 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),
3612
- children: "*"
3613
- })
3614
- ]
3786
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
3787
+ "aria-hidden": "true",
3788
+ 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),
3789
+ children: "*"
3790
+ }))
3615
3791
  }),
3616
3792
  jsxs("div", {
3617
3793
  className: cn(v.inputWrapper(), // Multi mode: let chips wrap and replace the fixed `h-*`
@@ -4202,10 +4378,12 @@ function CalendarIcon$2() {
4202
4378
  * Storage contract: an ISO `YYYY-MM-DD` string, or `null` — shared with the
4203
4379
  * MUI `@dashforge/ui` `DatePicker`.
4204
4380
  */ function DatePicker(_props) {
4205
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4381
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4206
4382
  const themeDefaults = useComponentDefaults('DatePicker');
4207
4383
  const props = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, _props);
4208
4384
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
4385
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
4386
+ const tooltipConfig = resolveFieldTooltip(_props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
4209
4387
  const { name, rules, label, helperText, error, required, disabled, placeholder, layout = 'stacked', visibleWhen, access, value: explicitValue, defaultValue, onChange, minDate, maxDate, disabledDates, isDateDisabled, weekStartDay, locale, fullWidth, sx, slotProps, testId } = props;
4210
4388
  // ───── Hooks (unconditional, before any early return) ─────
4211
4389
  const bridge = useContext(DashFormContext);
@@ -4331,17 +4509,14 @@ function CalendarIcon$2() {
4331
4509
  "data-testid": testId,
4332
4510
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
4333
4511
  children: [
4334
- label && jsxs("label", {
4512
+ label && jsx("label", {
4335
4513
  htmlFor: fieldId,
4336
4514
  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),
4337
- children: [
4338
- label,
4339
- required && jsx("span", {
4340
- "aria-hidden": "true",
4341
- 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),
4342
- children: "*"
4343
- })
4344
- ]
4515
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
4516
+ "aria-hidden": "true",
4517
+ 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),
4518
+ children: "*"
4519
+ }))
4345
4520
  }),
4346
4521
  jsx(Popover, {
4347
4522
  open: isOpen,
@@ -4479,10 +4654,12 @@ function ClockIcon() {
4479
4654
  * shared with the MUI `@dashforge/ui` `TimePicker`. `hour12` is display-only.
4480
4655
  */ function TimePicker(_props) {
4481
4656
  var _timeStringToMinutes, _timeStringToMinutes1;
4482
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4657
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4483
4658
  const themeDefaults = useComponentDefaults('TimePicker');
4484
4659
  const props = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, _props);
4485
4660
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
4661
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
4662
+ const tooltipConfig = resolveFieldTooltip(_props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
4486
4663
  const { name, rules, label, helperText, error, required, disabled, placeholder, layout = 'stacked', visibleWhen, access, value: explicitValue, defaultValue, onChange, minTime, maxTime, stepMinutes, hour12 = false, fullWidth, sx, slotProps, testId } = props;
4487
4664
  const bridge = useContext(DashFormContext);
4488
4665
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
@@ -4616,17 +4793,14 @@ function ClockIcon() {
4616
4793
  "data-testid": testId,
4617
4794
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
4618
4795
  children: [
4619
- label && jsxs("label", {
4796
+ label && jsx("label", {
4620
4797
  htmlFor: fieldId,
4621
4798
  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),
4622
- children: [
4623
- label,
4624
- required && jsx("span", {
4625
- "aria-hidden": "true",
4626
- 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),
4627
- children: "*"
4628
- })
4629
- ]
4799
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
4800
+ "aria-hidden": "true",
4801
+ 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),
4802
+ children: "*"
4803
+ }))
4630
4804
  }),
4631
4805
  jsx(Popover, {
4632
4806
  open: isOpen,
@@ -4817,10 +4991,12 @@ const DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/;
4817
4991
  * Storage contract: a naive ISO datetime `"YYYY-MM-DDTHH:mm"` — no seconds,
4818
4992
  * no timezone. Shared with the MUI `@dashforge/ui` `DateTimePicker`.
4819
4993
  */ function DateTimePicker(_props) {
4820
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4994
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
4821
4995
  const themeDefaults = useComponentDefaults('DateTimePicker');
4822
4996
  const props = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, _props);
4823
4997
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
4998
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
4999
+ const tooltipConfig = resolveFieldTooltip(_props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
4824
5000
  const { name, rules, label, helperText, error, required, disabled, placeholder, layout = 'stacked', visibleWhen, access, value: explicitValue, defaultValue, onChange, minDate, maxDate, disabledDates, isDateDisabled, weekStartDay, locale, stepMinutes, hour12 = false, fullWidth, sx, slotProps, testId } = props;
4825
5001
  const bridge = useContext(DashFormContext);
4826
5002
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
@@ -4946,17 +5122,14 @@ const DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}):(\d{2})/;
4946
5122
  "data-testid": testId,
4947
5123
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
4948
5124
  children: [
4949
- label && jsxs("label", {
5125
+ label && jsx("label", {
4950
5126
  htmlFor: fieldId,
4951
5127
  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),
4952
- children: [
4953
- label,
4954
- required && jsx("span", {
4955
- "aria-hidden": "true",
4956
- 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),
4957
- children: "*"
4958
- })
4959
- ]
5128
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
5129
+ "aria-hidden": "true",
5130
+ 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),
5131
+ children: "*"
5132
+ }))
4960
5133
  }),
4961
5134
  jsx(Popover, {
4962
5135
  open: isOpen,
@@ -5382,10 +5555,12 @@ function formatRange(range, locale) {
5382
5555
  * Storage contract: a `{ start, end }` pair of ISO `YYYY-MM-DD` dates —
5383
5556
  * shared with the MUI `@dashforge/ui` `DateRangePicker`.
5384
5557
  */ function DateRangePicker(_props) {
5385
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
5558
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_helperText, _slotProps_helperText;
5386
5559
  const themeDefaults = useComponentDefaults('DateRangePicker');
5387
5560
  const props = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, _props);
5388
5561
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
5562
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
5563
+ const tooltipConfig = resolveFieldTooltip(_props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
5389
5564
  const { name, rules, label, helperText, error, required, disabled, placeholder, layout = 'stacked', visibleWhen, access, value: explicitValue, defaultValue, onChange, minDate, maxDate, disabledDates, isDateDisabled, weekStartDay, locale, fullWidth, sx, slotProps, testId } = props;
5390
5565
  const bridge = useContext(DashFormContext);
5391
5566
  const isVisible = useEngineVisibility(bridge == null ? void 0 : bridge.engine, visibleWhen);
@@ -5504,17 +5679,14 @@ function formatRange(range, locale) {
5504
5679
  "data-testid": testId,
5505
5680
  className: cn(v.root(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_root = themeSlotProps.root) == null ? void 0 : _themeSlotProps_root.className, slotProps == null ? void 0 : (_slotProps_root = slotProps.root) == null ? void 0 : _slotProps_root.className),
5506
5681
  children: [
5507
- label && jsxs("label", {
5682
+ label && jsx("label", {
5508
5683
  htmlFor: fieldId,
5509
5684
  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),
5510
- children: [
5511
- label,
5512
- required && jsx("span", {
5513
- "aria-hidden": "true",
5514
- 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),
5515
- children: "*"
5516
- })
5517
- ]
5685
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
5686
+ "aria-hidden": "true",
5687
+ 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),
5688
+ children: "*"
5689
+ }))
5518
5690
  }),
5519
5691
  jsx(Popover, {
5520
5692
  open: isOpen,
@@ -5731,7 +5903,7 @@ function formatRange(range, locale) {
5731
5903
  href: item.href,
5732
5904
  onClick: item.onClick,
5733
5905
  className: cn(v.link(), themeSlotProps == null ? void 0 : (_themeSlotProps_link = themeSlotProps.link) == null ? void 0 : _themeSlotProps_link.className, slotProps == null ? void 0 : (_slotProps_link = slotProps.link) == null ? void 0 : _slotProps_link.className),
5734
- children: item.icon ? jsxs(Fragment, {
5906
+ children: item.icon ? jsxs(Fragment$1, {
5735
5907
  children: [
5736
5908
  jsx("span", {
5737
5909
  "aria-hidden": "true",
@@ -5750,7 +5922,7 @@ function formatRange(range, locale) {
5750
5922
  themeSlotProps == null ? void 0 : (_themeSlotProps_link1 = themeSlotProps.link) == null ? void 0 : _themeSlotProps_link1.className,
5751
5923
  slotProps == null ? void 0 : (_slotProps_link1 = slotProps.link) == null ? void 0 : _slotProps_link1.className
5752
5924
  ]),
5753
- children: item.icon ? jsxs(Fragment, {
5925
+ children: item.icon ? jsxs(Fragment$1, {
5754
5926
  children: [
5755
5927
  jsx("span", {
5756
5928
  "aria-hidden": "true",
@@ -5899,7 +6071,7 @@ function formatRange(range, locale) {
5899
6071
  const Link = linkComponent;
5900
6072
  const linkClasses = cn(v.itemLink(), isActive && v.itemActive(), themeSlotProps == null ? void 0 : (_themeSlotProps_itemLink = themeSlotProps.itemLink) == null ? void 0 : _themeSlotProps_itemLink.className, slotProps == null ? void 0 : (_slotProps_itemLink = slotProps.itemLink) == null ? void 0 : _slotProps_itemLink.className, isActive && (themeSlotProps == null ? void 0 : (_themeSlotProps_itemActive = themeSlotProps.itemActive) == null ? void 0 : _themeSlotProps_itemActive.className), slotProps == null ? void 0 : (_slotProps_itemActive = slotProps.itemActive) == null ? void 0 : _slotProps_itemActive.className);
5901
6073
  // Visual content — same in `<a>` / `<button>` branches below.
5902
- const content = jsxs(Fragment$1, {
6074
+ const content = jsxs(Fragment, {
5903
6075
  children: [
5904
6076
  item.icon && jsx("span", {
5905
6077
  "aria-hidden": "true",
@@ -6446,7 +6618,7 @@ function formatRange(range, locale) {
6446
6618
  jsxs("div", {
6447
6619
  className: v.body(),
6448
6620
  children: [
6449
- nav && jsxs(Fragment$1, {
6621
+ nav && jsxs(Fragment, {
6450
6622
  children: [
6451
6623
  jsx("aside", {
6452
6624
  className: cn(v.nav(), themeSlotProps == null ? void 0 : (_themeSlotProps_nav = themeSlotProps.nav) == null ? void 0 : _themeSlotProps_nav.className, slotProps == null ? void 0 : (_slotProps_nav = slotProps.nav) == null ? void 0 : _slotProps_nav.className),
@@ -6712,7 +6884,7 @@ const ConfirmContext = /*#__PURE__*/ createContext(null);
6712
6884
  "aria-labelledby": (opts == null ? void 0 : opts.title) != null ? titleId : undefined,
6713
6885
  onClick: handleDialogClick,
6714
6886
  className: cn(v.backdrop(), v.dialog(), (_mergedSlotProps_backdrop = mergedSlotProps.backdrop) == null ? void 0 : _mergedSlotProps_backdrop.className, (_mergedSlotProps_dialog = mergedSlotProps.dialog) == null ? void 0 : _mergedSlotProps_dialog.className),
6715
- children: opts != null && jsxs(Fragment$1, {
6887
+ children: opts != null && jsxs(Fragment, {
6716
6888
  children: [
6717
6889
  opts.title != null && jsx("h2", {
6718
6890
  id: titleId,
@@ -8746,7 +8918,7 @@ if (process.env.NODE_ENV !== 'production') {
8746
8918
  */ function flattenChildren(children) {
8747
8919
  const flat = [];
8748
8920
  Children.forEach(children, (child)=>{
8749
- if (/*#__PURE__*/ isValidElement(child) && child.type === Fragment) {
8921
+ if (/*#__PURE__*/ isValidElement(child) && child.type === Fragment$1) {
8750
8922
  const nested = child.props.children;
8751
8923
  flat.push(...flattenChildren(nested));
8752
8924
  return;
@@ -8799,7 +8971,7 @@ if (process.env.NODE_ENV !== 'production') {
8799
8971
  sawStrayDom = true;
8800
8972
  return;
8801
8973
  }
8802
- pass.push(jsx(Fragment, {
8974
+ pass.push(jsx(Fragment$1, {
8803
8975
  children: child
8804
8976
  }, `stepper-passthrough-${i}`));
8805
8977
  });
@@ -9089,7 +9261,7 @@ if (process.env.NODE_ENV !== 'production') {
9089
9261
  const labelClass = 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);
9090
9262
  const helperClass = cn(v.helperText(), themeSlotProps == null ? void 0 : (_themeSlotProps_helperText = themeSlotProps.helperText) == null ? void 0 : _themeSlotProps_helperText.className, slotProps == null ? void 0 : (_slotProps_helperText = slotProps.helperText) == null ? void 0 : _slotProps_helperText.className);
9091
9263
  const optionalClass = cn(v.optionalTag(), themeSlotProps == null ? void 0 : (_themeSlotProps_optionalTag = themeSlotProps.optionalTag) == null ? void 0 : _themeSlotProps_optionalTag.className, slotProps == null ? void 0 : (_slotProps_optionalTag = slotProps.optionalTag) == null ? void 0 : _slotProps_optionalTag.className);
9092
- return jsxs(Fragment, {
9264
+ return jsxs(Fragment$1, {
9093
9265
  children: [
9094
9266
  jsxs("div", {
9095
9267
  role: "listitem",
@@ -9205,10 +9377,10 @@ Stepper.displayName = 'Stepper';
9205
9377
  ]
9206
9378
  });
9207
9379
  }
9208
- if (icon) return jsx(Fragment$1, {
9380
+ if (icon) return jsx(Fragment, {
9209
9381
  children: icon
9210
9382
  });
9211
- return jsx(Fragment$1, {
9383
+ return jsx(Fragment, {
9212
9384
  children: index + 1
9213
9385
  });
9214
9386
  }
@@ -10060,10 +10232,12 @@ Slider.displayName = 'Slider';
10060
10232
  * array so `onChange` gets the precise literal type.
10061
10233
  */ function SelectInner(props, ref) {
10062
10234
  var _ref;
10063
- var _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_triggerText, _slotProps_triggerText, _themeSlotProps_triggerPlaceholder, _slotProps_triggerPlaceholder, _themeSlotProps_chevron, _slotProps_chevron, _themeSlotProps_popover, _slotProps_popover, _themeSlotProps_listBox, _slotProps_listBox, _themeSlotProps_emptyState, _slotProps_emptyState, _themeSlotProps_helperText, _slotProps_helperText, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_chipsList, _slotProps_chipsList, _themeSlotProps_chip, _slotProps_chip, _themeSlotProps_chipRemove, _slotProps_chipRemove, _triggerRef_current;
10235
+ var _themeDefaults_defaults, _themeSlotProps_root, _slotProps_root, _themeSlotProps_label, _slotProps_label, _themeSlotProps_requiredMark, _slotProps_requiredMark, _themeSlotProps_trigger, _slotProps_trigger, _themeSlotProps_triggerText, _slotProps_triggerText, _themeSlotProps_triggerPlaceholder, _slotProps_triggerPlaceholder, _themeSlotProps_chevron, _slotProps_chevron, _themeSlotProps_popover, _slotProps_popover, _themeSlotProps_listBox, _slotProps_listBox, _themeSlotProps_emptyState, _slotProps_emptyState, _themeSlotProps_helperText, _slotProps_helperText, _themeSlotProps_errorText, _slotProps_errorText, _themeSlotProps_chipsList, _slotProps_chipsList, _themeSlotProps_chip, _slotProps_chip, _themeSlotProps_chipRemove, _slotProps_chipRemove, _triggerRef_current;
10064
10236
  const themeDefaults = useComponentDefaults('Select');
10065
10237
  const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
10066
10238
  const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
10239
+ // Option C deep-merge: instance `tooltip` over `theme…defaults.tooltip`.
10240
+ const tooltipConfig = resolveFieldTooltip(props.tooltip, themeDefaults == null ? void 0 : (_themeDefaults_defaults = themeDefaults.defaults) == null ? void 0 : _themeDefaults_defaults.tooltip);
10067
10241
  const { name, rules, label, helperText, error, required, disabled, fullWidth, layout, size, visibleWhen, access, options, placeholder = 'Select…', emptyState = 'No options', value: userValue, defaultValue, onChange, onBlur, multiple = false, sx, slotProps, testId } = merged;
10068
10242
  // ───── Hooks (unconditional, above the early returns) ─────
10069
10243
  const bridge = useContext(DashFormContext);
@@ -10420,16 +10594,13 @@ Slider.displayName = 'Slider';
10420
10594
  className: rootClasses,
10421
10595
  "data-testid": testId,
10422
10596
  children: [
10423
- label != null && jsxs("label", {
10597
+ label != null && jsx("label", {
10424
10598
  htmlFor: controlId,
10425
10599
  className: labelClasses,
10426
- children: [
10427
- label,
10428
- required && jsx("span", {
10429
- className: requiredMarkClasses,
10430
- children: "*"
10431
- })
10432
- ]
10600
+ children: renderLabelWithTooltip(label, tooltipConfig, required && jsx("span", {
10601
+ className: requiredMarkClasses,
10602
+ children: "*"
10603
+ }))
10433
10604
  }),
10434
10605
  jsxs(RadixPopover.Root, {
10435
10606
  open: isOpen,
@@ -13626,7 +13797,7 @@ CardActionArea.displayName = 'CardActionArea';
13626
13797
  // `inline-flex items-center` provides vertical alignment with
13627
13798
  // any leading / trailing slots.
13628
13799
  const leading = avatar != null ? avatar : icon;
13629
- const innerContent = jsxs(Fragment$1, {
13800
+ const innerContent = jsxs(Fragment, {
13630
13801
  children: [
13631
13802
  leading != null && jsx("span", {
13632
13803
  className: "-ml-0.5 inline-flex items-center shrink-0",
@@ -14039,7 +14210,7 @@ Typography.displayName = 'Typography';
14039
14210
  key
14040
14211
  }));
14041
14212
  } else {
14042
- result.push(jsx(Fragment, {
14213
+ result.push(jsx(Fragment$1, {
14043
14214
  children: divider
14044
14215
  }, key));
14045
14216
  }
@@ -15335,92 +15506,6 @@ function useTabs(options) {
15335
15506
  });
15336
15507
  }
15337
15508
 
15338
- const tooltipVariants = tv({
15339
- slots: {
15340
- content: [
15341
- 'z-50 max-w-xs rounded-md px-3 py-1.5 text-xs font-medium',
15342
- // Auto-invert via the dashforgePreset() CSS-var swap:
15343
- // - Light mode: `bg-neutral-900` = #171717 (dark surface) +
15344
- // `text-neutral-50` = #fafafa (light text) — DARK tooltip
15345
- // on the light page (high contrast).
15346
- // - Dark mode: `bg-neutral-900` flips to #f5f5f5 (light) +
15347
- // `text-neutral-50` flips to #0a0a0a (dark text) — LIGHT
15348
- // tooltip on the dark page (high contrast against page).
15349
- // Adding `dark:bg-neutral-50 dark:text-neutral-900` (the old
15350
- // pattern) would force the dark-mode tooltip back to a dark
15351
- // surface — invisible against the dark page.
15352
- 'bg-neutral-900 text-neutral-50',
15353
- 'shadow-md',
15354
- 'data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95',
15355
- 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
15356
- 'motion-reduce:transition-none motion-reduce:duration-0'
15357
- ],
15358
- // Arrow tracks the content bg — auto-inverts the same way.
15359
- arrow: 'fill-neutral-900'
15360
- }
15361
- });
15362
-
15363
- /**
15364
- * Dashforge TW `<Tooltip>` — hoverable / focusable tooltip.
15365
- *
15366
- * Built on `@radix-ui/react-tooltip`:
15367
- * - APG tooltip pattern: `role="tooltip"`, `aria-describedby` wired
15368
- * to the trigger automatically (Radix manages the id linkage).
15369
- * - Shows on hover OR keyboard focus.
15370
- * - Dismissed on Escape or pointer leave.
15371
- *
15372
- * Wrap any single React node — it becomes the trigger via Radix's
15373
- * `asChild` slot. The trigger inherits `aria-describedby` so screen
15374
- * readers announce the tooltip content along with the trigger.
15375
- *
15376
- * @example
15377
- * ```tsx
15378
- * <Tooltip content="Delete this item">
15379
- * <Button variant="ghost">
15380
- * <TrashIcon />
15381
- * </Button>
15382
- * </Tooltip>
15383
- * ```
15384
- *
15385
- * Each consumer can also wrap the entire app once in
15386
- * `<RadixTooltip.Provider>` to share delay/skip configuration; we
15387
- * include a per-component provider here for ease-of-use.
15388
- */ function Tooltip(props) {
15389
- var _themeSlotProps_content, _slotProps_content, _themeSlotProps_arrow, _slotProps_arrow;
15390
- const themeDefaults = useComponentDefaults('Tooltip');
15391
- const merged = _extends({}, themeDefaults == null ? void 0 : themeDefaults.defaults, props);
15392
- const themeSlotProps = themeDefaults == null ? void 0 : themeDefaults.slotProps;
15393
- const { children, content, side = 'top', align = 'center', hideArrow = false, delayDuration = 200, open, onOpenChange, sideOffset = 4, sx, slotProps } = merged;
15394
- const v = tooltipVariants();
15395
- return jsx(RadixTooltip.Provider, {
15396
- delayDuration: delayDuration,
15397
- children: jsxs(RadixTooltip.Root, {
15398
- open: open,
15399
- onOpenChange: onOpenChange,
15400
- children: [
15401
- jsx(RadixTooltip.Trigger, {
15402
- asChild: true,
15403
- children: children
15404
- }),
15405
- jsx(RadixTooltip.Portal, {
15406
- children: jsxs(RadixTooltip.Content, {
15407
- side: side,
15408
- align: align,
15409
- sideOffset: sideOffset,
15410
- className: cn(v.content(), sx, themeSlotProps == null ? void 0 : (_themeSlotProps_content = themeSlotProps.content) == null ? void 0 : _themeSlotProps_content.className, slotProps == null ? void 0 : (_slotProps_content = slotProps.content) == null ? void 0 : _slotProps_content.className),
15411
- children: [
15412
- content,
15413
- !hideArrow && jsx(RadixTooltip.Arrow, {
15414
- className: cn(v.arrow(), themeSlotProps == null ? void 0 : (_themeSlotProps_arrow = themeSlotProps.arrow) == null ? void 0 : _themeSlotProps_arrow.className, slotProps == null ? void 0 : (_slotProps_arrow = slotProps.arrow) == null ? void 0 : _slotProps_arrow.className)
15415
- })
15416
- ]
15417
- })
15418
- })
15419
- ]
15420
- })
15421
- });
15422
- }
15423
-
15424
15509
  const accordionVariants = tv({
15425
15510
  slots: {
15426
15511
  root: 'w-full',
@@ -17074,7 +17159,7 @@ function HeaderCell$1(props) {
17074
17159
  // ───── Data row ─────
17075
17160
  function Row(props) {
17076
17161
  const { row, rowId, rowIndex, isSelected, isExpanded, visibleCols, columnTypes, rowSelection, showSelectionColumn, showExpandColumn, showRowActionsColumn, expandable, rowActions, labels, toggleRow, toggleExpand, isInteractive, rowClass, cellClass, selectionCellClass, expandToggleCellClass, rowActionsCellClass, expandedRowClass, totalColumnCount } = props;
17077
- return jsxs(Fragment$1, {
17162
+ return jsxs(Fragment, {
17078
17163
  children: [
17079
17164
  jsxs("tr", {
17080
17165
  "data-selected": isSelected ? 'true' : 'false',
@@ -17249,7 +17334,7 @@ function SortIcon$1(props) {
17249
17334
  d: "M8 4l4 6H4z"
17250
17335
  }) : props.direction === 'desc' ? jsx("path", {
17251
17336
  d: "M8 12L4 6h8z"
17252
- }) : jsxs(Fragment$1, {
17337
+ }) : jsxs(Fragment, {
17253
17338
  children: [
17254
17339
  jsx("path", {
17255
17340
  d: "M8 3l3 4H5z",
@@ -19096,7 +19181,7 @@ function HeaderCell(props) {
19096
19181
  // ───── Virtualized body ─────
19097
19182
  function renderVirtualizedBody(args) {
19098
19183
  const { vWindow, renderedRows, visibleCols, columnTypes, columnWidths, selection, rowSelection, showSelectionColumn, showRowActionsColumn, rowActions, getRowId, isInteractive, labels, classes } = args;
19099
- return jsxs(Fragment$1, {
19184
+ return jsxs(Fragment, {
19100
19185
  children: [
19101
19186
  vWindow.paddingTop > 0 && jsx("tr", {
19102
19187
  "aria-hidden": "true",
@@ -19255,7 +19340,7 @@ function SortIcon(props) {
19255
19340
  d: "M8 4l4 6H4z"
19256
19341
  }) : props.direction === 'desc' ? jsx("path", {
19257
19342
  d: "M8 12L4 6h8z"
19258
- }) : jsxs(Fragment$1, {
19343
+ }) : jsxs(Fragment, {
19259
19344
  children: [
19260
19345
  jsx("path", {
19261
19346
  d: "M8 3l3 4H5z",
@@ -19321,6 +19406,6 @@ function SearchIcon(props) {
19321
19406
  */ // ───── Components ─────
19322
19407
  /**
19323
19408
  * Package version (synced with `package.json` at publish time).
19324
- */ const VERSION = '1.4.0';
19409
+ */ const VERSION = '1.5.1';
19325
19410
 
19326
19411
  export { AVATAR_SOFT_FALLBACK, AVATAR_TONE_FALLBACK, Accordion, Alert, AlertTitle, AppShell, AspectRatio, Autocomplete, Avatar, AvatarGroup, Badge, Box, Breadcrumbs, Button, Calendar, Card, CardActionArea, CardContent, Checkbox, Chip, ConfirmDialogProvider, Container, DRAWER_SIZE_PRESETS, DataGrid, DatePicker, DateRangePicker, DateTimePicker, Dialog, Divider, Drawer, Grid, ICON_BUTTON_BASE, ICON_BUTTON_SIZE_OVERRIDES, IconButton, Image, LeftNav, Link, Menu, MenuContent, MenuItem, MenuLabel, MenuSeparator, MenuSkeleton, MenuTrigger, NumberField, OTPField, Pagination, Popover, Progress, RadioGroup, RenderButton, RenderChip, RenderText, RenderTwoLine, RowActionsMenu, SPINNER_COLORS, SPINNER_STROKE_WIDTH, SPINNER_TRACK_OPACITY, Select, Skeleton, Slider, SnackbarProvider, Spinner, Stack, Step, Stepper, Switch, Table, Tabs, TextField, Textarea, TimePicker, Tooltip, TopBar, Typography, VERSION, Video, VisuallyHidden, accordionVariants, alertVariants, appShellVariants, autocompleteVariants, avatarVariants, badgeVariants, boxVariants, breadcrumbsVariants, buttonVariants, calendarDayVariants, calendarVariants, checkboxVariants, chipVariants, cn, confirmDialogVariants, containerVariants, dataGridVariants, datePickerVariants, dateRangeDayVariants, dateRangePickerVariants, dateTimePickerVariants, dialogVariants, dividerLineVariants, dividerVariants, drawerVariants, getNestedValue, gridVariants, imageVariants, leftNavVariants, linkVariants, menuVariants, numberFieldVariants, otpFieldVariants, paginationVariants, popoverVariants, progressVariants, radioGroupVariants, selectVariants, skeletonVariants, sliderVariants, snackbarVariants, spinnerVariants, stackVariants, stepperVariants, switchVariants, tableVariants, tabsVariants, textFieldVariants, textareaVariants, timePickerVariants, tooltipVariants, topBarVariants, typographyVariants, useAccessState, useConfirm, useSnackbar, useStep, videoVariants };