@tinybigui/react 0.7.0 → 0.8.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.
package/dist/index.cjs CHANGED
@@ -2670,205 +2670,132 @@ var TextField = React.forwardRef(
2670
2670
  }
2671
2671
  );
2672
2672
  TextField.displayName = "TextField";
2673
- var checkboxVariants = classVarianceAuthority.cva(
2674
- [
2675
- // Base classes (always applied to label wrapper)
2676
- "relative inline-flex items-center cursor-pointer select-none",
2677
- "transition-opacity duration-200"
2678
- ],
2679
- {
2680
- variants: {
2681
- /**
2682
- * Disabled state
2683
- */
2684
- disabled: {
2685
- true: "opacity-38 cursor-not-allowed pointer-events-none",
2686
- false: ""
2687
- }
2688
- },
2689
- defaultVariants: {
2690
- disabled: false
2691
- }
2692
- }
2693
- );
2694
- var checkboxContainerVariants = classVarianceAuthority.cva(
2695
- [
2696
- // Base classes for checkbox visual container
2697
- "relative inline-flex items-center justify-center m-1",
2698
- "w-10 h-10",
2699
- // 40x40dp touch target (MD3 spec)
2700
- "flex-shrink-0",
2701
- "transition-all duration-200",
2702
- // State layer (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
2703
- "before:absolute before:inset-0 before:rounded-full before:transition-opacity before:duration-200",
2704
- "before:bg-current before:opacity-0",
2705
- "hover:before:opacity-8",
2706
- "active:before:opacity-12"
2707
- ],
2708
- {
2709
- variants: {
2710
- /**
2711
- * Checkbox state (determines visual appearance)
2712
- */
2713
- state: {
2714
- unchecked: "text-on-surface-variant",
2715
- checked: "text-primary",
2716
- indeterminate: "text-primary"
2717
- },
2718
- /**
2719
- * Error/invalid state
2720
- */
2721
- isInvalid: {
2722
- true: "text-error",
2723
- false: ""
2724
- },
2725
- /**
2726
- * Disabled state
2727
- */
2728
- disabled: {
2729
- true: "text-on-surface pointer-events-none",
2730
- false: ""
2731
- }
2732
- },
2733
- compoundVariants: [
2734
- // Error state overrides normal colors for all states
2735
- {
2736
- state: "unchecked",
2737
- isInvalid: true,
2738
- disabled: false,
2739
- className: "text-error"
2740
- },
2741
- {
2742
- state: "checked",
2743
- isInvalid: true,
2744
- disabled: false,
2745
- className: "text-error"
2746
- },
2747
- {
2748
- state: "indeterminate",
2749
- isInvalid: true,
2750
- disabled: false,
2751
- className: "text-error"
2752
- }
2753
- ],
2754
- defaultVariants: {
2755
- state: "unchecked",
2756
- isInvalid: false,
2757
- disabled: false
2758
- }
2759
- }
2760
- );
2761
- var checkboxIconBoxVariants = classVarianceAuthority.cva(
2762
- [
2763
- // Base classes for the checkbox box
2764
- // Note: Border radius is applied via SVG rx/ry attributes (2dp) in the component
2765
- "transition-all duration-200"
2766
- ],
2767
- {
2768
- variants: {
2769
- /**
2770
- * Checkbox state
2771
- */
2772
- state: {
2773
- unchecked: [
2774
- "fill-transparent",
2775
- "stroke-outline",
2776
- // MD3: outline color for unchecked
2777
- "stroke-4"
2778
- // MD3: 2dp outline width
2779
- ],
2780
- checked: [
2781
- "fill-current",
2782
- // Uses parent text color (primary or error)
2783
- "stroke-none"
2784
- ],
2785
- indeterminate: [
2786
- "fill-current",
2787
- // Uses parent text color (primary or error)
2788
- "stroke-none"
2789
- ]
2790
- },
2791
- /**
2792
- * Disabled state
2793
- */
2794
- disabled: {
2795
- true: ["fill-transparent", "stroke-current", "stroke-2"],
2796
- false: ""
2797
- }
2798
- },
2799
- compoundVariants: [
2800
- // Disabled state overrides fill for checked/indeterminate
2801
- {
2802
- state: "checked",
2803
- disabled: true,
2804
- className: "fill-current stroke-none"
2805
- },
2806
- {
2807
- state: "indeterminate",
2808
- disabled: true,
2809
- className: "fill-current stroke-none"
2810
- }
2811
- ],
2812
- defaultVariants: {
2813
- state: "unchecked",
2814
- disabled: false
2815
- }
2816
- }
2817
- );
2818
- var checkboxIconVariants = classVarianceAuthority.cva(
2819
- [
2820
- "fill-current",
2821
- // Inherits color from parent
2822
- "transition-all duration-200"
2823
- ],
2824
- {
2825
- variants: {
2826
- /**
2827
- * Icon type
2828
- */
2829
- type: {
2830
- check: "",
2831
- // Checkmark icon
2832
- dash: ""
2833
- // Dash/minus icon
2834
- }
2835
- },
2836
- defaultVariants: {
2837
- type: "check"
2673
+ var checkboxRootVariants = classVarianceAuthority.cva([
2674
+ "relative inline-flex items-center cursor-pointer select-none",
2675
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none",
2676
+ "data-[disabled]:opacity-38"
2677
+ ]);
2678
+ var checkboxControlVariants = classVarianceAuthority.cva([
2679
+ "relative flex items-center justify-center flex-shrink-0",
2680
+ "w-10 h-10 rounded-full",
2681
+ "overflow-hidden"
2682
+ ]);
2683
+ var checkboxStateLayerVariants = classVarianceAuthority.cva([
2684
+ "absolute inset-0 rounded-full pointer-events-none opacity-0",
2685
+ // Base state-layer color (unselected)
2686
+ "bg-on-surface",
2687
+ // Effects transition for opacity changes
2688
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2689
+ // Selected / indeterminate → primary color
2690
+ "group-data-[selected]/checkbox:bg-primary",
2691
+ "group-data-[indeterminate]/checkbox:bg-primary",
2692
+ // Invalid → error color (singly-chained)
2693
+ "group-data-[invalid]/checkbox:bg-error",
2694
+ // Invalid + selected → error wins (doubly-chained for specificity)
2695
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-error",
2696
+ // Interaction opacities (MD3: hover 8%, focus-visible 10%, pressed 10%)
2697
+ "group-data-[hovered]/checkbox:opacity-8",
2698
+ "group-data-[focus-visible]/checkbox:opacity-10",
2699
+ "group-data-[pressed]/checkbox:opacity-10",
2700
+ // No state layer when disabled
2701
+ "group-data-[disabled]/checkbox:hidden"
2702
+ ]);
2703
+ var checkboxFocusRingVariants = classVarianceAuthority.cva([
2704
+ "pointer-events-none absolute inset-0 rounded-full",
2705
+ "outline outline-2 outline-offset-0 outline-secondary",
2706
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2707
+ "opacity-0",
2708
+ "group-data-[focus-visible]/checkbox:opacity-100"
2709
+ ]);
2710
+ var checkboxBoxVariants = classVarianceAuthority.cva([
2711
+ // Base geometry
2712
+ "relative flex items-center justify-center flex-shrink-0",
2713
+ "w-[18px] h-[18px] rounded-[2px] border-2",
2714
+ // Effects transition for color changes
2715
+ "transition-[background-color,border-color] duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2716
+ // ── Unselected base ───────────────────────────────────────────────────────
2717
+ "bg-transparent border-outline",
2718
+ // ── Selected ──────────────────────────────────────────────────────────────
2719
+ "group-data-[selected]/checkbox:bg-primary group-data-[selected]/checkbox:border-primary",
2720
+ // ── Indeterminate ─────────────────────────────────────────────────────────
2721
+ "group-data-[indeterminate]/checkbox:bg-primary group-data-[indeterminate]/checkbox:border-primary",
2722
+ // ── Invalid (unselected) — singly chained ─────────────────────────────────
2723
+ "group-data-[invalid]/checkbox:border-error",
2724
+ // ── Invalid + selected — doubly chained (higher specificity) ──────────────
2725
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-error",
2726
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:border-error",
2727
+ // ── Invalid + indeterminate — doubly chained ───────────────────────────────
2728
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:bg-error",
2729
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:border-error",
2730
+ // ── Disabled (placed last — cascade wins over interaction colors) ──────────
2731
+ "group-data-[disabled]/checkbox:border-on-surface/38",
2732
+ "group-data-[disabled]/checkbox:bg-transparent",
2733
+ // ── Disabled + selected — doubly chained ──────────────────────────────────
2734
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:bg-on-surface/38",
2735
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:border-transparent",
2736
+ // ── Disabled + indeterminate — doubly chained ─────────────────────────────
2737
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:bg-on-surface/38",
2738
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:border-transparent"
2739
+ ]);
2740
+ var checkboxIconVariants = classVarianceAuthority.cva([
2741
+ "absolute inset-0 flex items-center justify-center",
2742
+ // Spatial transition for icon appearing (scale)
2743
+ "transition-transform duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial",
2744
+ // Base icon color
2745
+ "text-on-primary",
2746
+ // Invalid → on-error (doubly-chained for both selected and indeterminate)
2747
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-on-error",
2748
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:text-on-error",
2749
+ // Disabled → surface (doubly-chained)
2750
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:text-surface",
2751
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:text-surface"
2752
+ ]);
2753
+ var checkboxLabelVariants = classVarianceAuthority.cva(["text-body-large text-on-surface select-none ml-4"]);
2754
+ function CheckboxCheckIcon() {
2755
+ return /* @__PURE__ */ jsxRuntime.jsx(
2756
+ "svg",
2757
+ {
2758
+ xmlns: "http://www.w3.org/2000/svg",
2759
+ width: "18",
2760
+ height: "18",
2761
+ viewBox: "0 0 18 18",
2762
+ fill: "none",
2763
+ "aria-hidden": "true",
2764
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2765
+ "path",
2766
+ {
2767
+ d: "M4.5 9L7.2 11.7L13.5 5.4",
2768
+ stroke: "currentColor",
2769
+ strokeWidth: "2",
2770
+ strokeLinecap: "square",
2771
+ strokeLinejoin: "miter"
2772
+ }
2773
+ )
2838
2774
  }
2839
- }
2840
- );
2841
- var checkboxLabelVariants = classVarianceAuthority.cva(
2842
- [
2843
- "text-sm",
2844
- // MD3: Body Medium (14px)
2845
- "text-on-surface",
2846
- "select-none"
2847
- ],
2848
- {
2849
- variants: {
2850
- disabled: {
2851
- true: "",
2852
- false: ""
2853
- }
2854
- },
2855
- defaultVariants: {
2856
- disabled: false
2775
+ );
2776
+ }
2777
+ function CheckboxIndeterminateIcon() {
2778
+ return /* @__PURE__ */ jsxRuntime.jsx(
2779
+ "svg",
2780
+ {
2781
+ xmlns: "http://www.w3.org/2000/svg",
2782
+ width: "18",
2783
+ height: "18",
2784
+ viewBox: "0 0 18 18",
2785
+ fill: "none",
2786
+ "aria-hidden": "true",
2787
+ children: /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "4", y: "8", width: "10", height: "2", rx: "1", fill: "currentColor" })
2857
2788
  }
2858
- }
2859
- );
2789
+ );
2790
+ }
2860
2791
  var Checkbox = React.forwardRef(
2861
2792
  ({
2862
- // Content props
2863
2793
  children,
2864
- // State props
2865
2794
  isIndeterminate = false,
2866
2795
  isInvalid = false,
2867
2796
  disableRipple = false,
2868
2797
  isDisabled = false,
2869
- // Styling
2870
2798
  className,
2871
- // Other props
2872
2799
  ...props
2873
2800
  }, forwardedRef) => {
2874
2801
  const internalRef = React.useRef(null);
@@ -2881,17 +2808,17 @@ var Checkbox = React.forwardRef(
2881
2808
  "data-testid": _dataTestId,
2882
2809
  id: _htmlId,
2883
2810
  title: _htmlTitle,
2884
- ...restPropsWithoutHtmlAttrs
2811
+ ...ariaProps
2885
2812
  } = props;
2886
- const state = reactStately.useToggleState(restPropsWithoutHtmlAttrs);
2887
- const { inputProps, labelProps } = reactAria.useCheckbox(
2888
- restPropsWithoutHtmlAttrs,
2813
+ const state = reactStately.useToggleState(ariaProps);
2814
+ const { inputProps, labelProps, isPressed } = reactAria.useCheckbox(
2815
+ ariaProps,
2889
2816
  state,
2890
2817
  ref
2891
2818
  );
2892
2819
  const { isFocusVisible, focusProps } = reactAria.useFocusRing();
2820
+ const { isHovered, hoverProps } = reactAria.useHover({ isDisabled });
2893
2821
  const isSelected = state.isSelected;
2894
- const visualState = isIndeterminate ? "indeterminate" : isSelected ? "checked" : "unchecked";
2895
2822
  const { onMouseDown: handleRipple, ripples } = useRipple({
2896
2823
  disabled: isDisabled || disableRipple
2897
2824
  });
@@ -2901,8 +2828,8 @@ var Checkbox = React.forwardRef(
2901
2828
  }
2902
2829
  }, [isIndeterminate, ref]);
2903
2830
  if (process.env.NODE_ENV === "development") {
2904
- const ariaProps = restPropsWithoutHtmlAttrs;
2905
- if (!children && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
2831
+ const a = ariaProps;
2832
+ if (!children && !a["aria-label"] && !a["aria-labelledby"]) {
2906
2833
  console.warn(
2907
2834
  "[Checkbox] Checkbox should have a label (children) or aria-label for accessibility."
2908
2835
  );
@@ -2911,105 +2838,40 @@ var Checkbox = React.forwardRef(
2911
2838
  return /* @__PURE__ */ jsxRuntime.jsxs(
2912
2839
  "label",
2913
2840
  {
2914
- ...labelProps,
2915
- className: cn(
2916
- checkboxVariants({
2917
- disabled: isDisabled
2918
- }),
2919
- className
2920
- ),
2841
+ ...reactAria.mergeProps(labelProps, hoverProps),
2842
+ className: cn(checkboxRootVariants(), "group/checkbox", className),
2921
2843
  "data-testid": dataTestId,
2922
2844
  title: htmlTitle,
2845
+ ...getInteractionDataAttributes({
2846
+ isHovered,
2847
+ isFocusVisible,
2848
+ isPressed,
2849
+ isSelected,
2850
+ isDisabled,
2851
+ isInvalid,
2852
+ isIndeterminate,
2853
+ isReadOnly: ariaProps.isReadOnly ?? false
2854
+ }),
2923
2855
  children: [
2924
2856
  /* @__PURE__ */ jsxRuntime.jsx(reactAria.VisuallyHidden, { children: /* @__PURE__ */ jsxRuntime.jsx("input", { ...reactAria.mergeProps(inputProps, focusProps), ref, id: htmlId }) }),
2925
2857
  /* @__PURE__ */ jsxRuntime.jsxs(
2926
2858
  "div",
2927
2859
  {
2928
2860
  role: "presentation",
2929
- className: cn(
2930
- checkboxContainerVariants({
2931
- state: visualState,
2932
- isInvalid,
2933
- disabled: isDisabled
2934
- })
2935
- ),
2861
+ className: cn(checkboxControlVariants()),
2936
2862
  onMouseDown: handleRipple,
2937
2863
  children: [
2938
2864
  ripples,
2939
- /* @__PURE__ */ jsxRuntime.jsxs(
2940
- "svg",
2941
- {
2942
- width: "18",
2943
- height: "18",
2944
- viewBox: "0 0 18 18",
2945
- "aria-hidden": "true",
2946
- className: "relative z-10",
2947
- children: [
2948
- /* @__PURE__ */ jsxRuntime.jsx(
2949
- "rect",
2950
- {
2951
- x: "0",
2952
- y: "0",
2953
- width: "18",
2954
- height: "18",
2955
- rx: "2",
2956
- ry: "2",
2957
- className: cn(
2958
- checkboxIconBoxVariants({
2959
- state: visualState,
2960
- disabled: isDisabled
2961
- })
2962
- )
2963
- }
2964
- ),
2965
- isSelected && !isIndeterminate && /* @__PURE__ */ jsxRuntime.jsx(
2966
- "path",
2967
- {
2968
- d: "M14.1 4.5L6.3 12.3l-3.4-3.4L1.5 10.3l4.8 4.8 9.2-9.2z",
2969
- className: cn(checkboxIconVariants({ type: "check" }), "fill-on-primary")
2970
- }
2971
- ),
2972
- isIndeterminate && /* @__PURE__ */ jsxRuntime.jsx(
2973
- "rect",
2974
- {
2975
- x: "4",
2976
- y: "8",
2977
- width: "10",
2978
- height: "2",
2979
- className: cn(checkboxIconVariants({ type: "dash" }), "fill-on-primary")
2980
- }
2981
- ),
2982
- isFocusVisible && /* @__PURE__ */ jsxRuntime.jsx(
2983
- "rect",
2984
- {
2985
- x: "-3",
2986
- y: "-3",
2987
- width: "24",
2988
- height: "24",
2989
- rx: "12",
2990
- fill: "none",
2991
- stroke: "currentColor",
2992
- strokeWidth: "2",
2993
- className: "animate-pulse"
2994
- }
2995
- )
2996
- ]
2997
- }
2998
- )
2865
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(checkboxStateLayerVariants()), "aria-hidden": "true" }),
2866
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(checkboxFocusRingVariants()), "aria-hidden": "true" }),
2867
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(checkboxBoxVariants()), "aria-hidden": "true", children: [
2868
+ isSelected && !isIndeterminate && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(checkboxIconVariants()), children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxCheckIcon, {}) }),
2869
+ isIndeterminate && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(checkboxIconVariants()), children: /* @__PURE__ */ jsxRuntime.jsx(CheckboxIndeterminateIcon, {}) })
2870
+ ] })
2999
2871
  ]
3000
2872
  }
3001
2873
  ),
3002
- children && /* @__PURE__ */ jsxRuntime.jsx(
3003
- "span",
3004
- {
3005
- className: cn(
3006
- checkboxLabelVariants({
3007
- disabled: isDisabled
3008
- })
3009
- ),
3010
- children
3011
- }
3012
- )
2874
+ children && /* @__PURE__ */ jsxRuntime.jsx("span", { className: cn(checkboxLabelVariants()), children })
3013
2875
  ]
3014
2876
  }
3015
2877
  );
@@ -5070,106 +4932,48 @@ var Drawer = React.forwardRef(
5070
4932
  }
5071
4933
  );
5072
4934
  Drawer.displayName = "Drawer";
5073
- var BadgeHeadless = React.forwardRef(
5074
- ({ className, children, ...props }, ref) => {
5075
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-flex", className), ...props, children });
5076
- }
5077
- );
5078
- BadgeHeadless.displayName = "BadgeHeadless";
5079
- var badgeVariants2 = classVarianceAuthority.cva(
5080
- ["absolute -top-1 -right-1 rounded-full flex items-center justify-center"],
5081
- {
5082
- variants: {
5083
- size: {
5084
- small: "size-1.5",
5085
- large: "min-w-4 h-4 px-1 text-label-small"
5086
- },
5087
- color: {
5088
- error: "bg-error text-on-error",
5089
- primary: "bg-primary text-on-primary"
5090
- },
5091
- invisible: {
5092
- true: "scale-0 opacity-0",
5093
- false: "scale-100 opacity-100"
5094
- },
5095
- reducedMotion: {
5096
- true: "",
5097
- false: "transition-[transform,opacity] duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
5098
- }
5099
- },
5100
- defaultVariants: {
5101
- size: "large",
5102
- color: "error",
5103
- invisible: false,
5104
- reducedMotion: false
5105
- }
5106
- }
5107
- );
5108
- var getDisplayValue = (count, max) => {
4935
+ var badgeAppearance = [
4936
+ // ── Shape ─────────────────────────────────────────────────────────────────────
4937
+ "flex items-center justify-center",
4938
+ "rounded-full",
4939
+ // ── Large (count) sizing — base defaults ──────────────────────────────────────
4940
+ // Height 16dp, min-width 16dp, horizontal padding 4dp
4941
+ "h-4 min-w-4 px-1",
4942
+ // ── Color error role (only MD3-spec role for badges) ────────────────────────
4943
+ "bg-error text-on-error",
4944
+ // ── Typography — label-small, tight leading, tabular numbers ──────────────────
4945
+ "text-label-small leading-none tabular-nums",
4946
+ // ── Visibility (runtime flag) ──────────────────────────────────────────────────
4947
+ // Base: fully visible
4948
+ "scale-100",
4949
+ // data-invisible: scale to zero (visually hidden; aria-label still readable by SR)
4950
+ "data-[invisible]:scale-0",
4951
+ // ── Dot content flag overrides (placed last — cascade wins over base sizing) ───
4952
+ // Clear out the count-pill sizing, set 6dp circle
4953
+ "data-[dot]:size-1.5",
4954
+ "data-[dot]:min-w-0",
4955
+ "data-[dot]:p-0",
4956
+ "data-[dot]:text-[0]"
4957
+ // suppress any stray text rendering on dot
4958
+ ];
4959
+ var badgeVariants2 = classVarianceAuthority.cva([
4960
+ // ── Anchored placement — badge center on host's top-right corner ──────────────
4961
+ // top-0 right-0 places the badge's own top-right at the host's top-right,
4962
+ // then the 1/2-element translate moves the badge center onto that corner.
4963
+ // Host-size-agnostic: works for any wrapped element (icon, avatar, nav chip).
4964
+ "absolute top-0 right-0 -translate-y-1/2 translate-x-1/2",
4965
+ ...badgeAppearance
4966
+ ]);
4967
+ var badgeStaticVariants = classVarianceAuthority.cva(["inline-flex", ...badgeAppearance]);
4968
+ function isBadgeConfig(badge) {
4969
+ return typeof badge === "object" && badge !== null && !React.isValidElement(badge) && "count" in badge;
4970
+ }
4971
+ function getBadgeDisplayValue(count, max) {
5109
4972
  if (count === void 0) return "";
5110
4973
  return count > max ? `${max}+` : count.toString();
5111
- };
5112
- var getAriaLabel = (count, override) => {
5113
- if (override) return override;
4974
+ }
4975
+ function getBadgeAriaLabel(count) {
5114
4976
  return count === void 0 ? "New" : `${count} notifications`;
5115
- };
5116
- var BadgeContent = React.forwardRef(
5117
- ({
5118
- count,
5119
- max = 999,
5120
- color = "error",
5121
- invisible = false,
5122
- "aria-label": ariaLabelOverride,
5123
- reducedMotion = false,
5124
- className
5125
- }, ref) => {
5126
- const size = count === void 0 ? "small" : "large";
5127
- const displayValue = getDisplayValue(count, max);
5128
- const ariaLabel = getAriaLabel(count, ariaLabelOverride);
5129
- return /* @__PURE__ */ jsxRuntime.jsx(
5130
- "span",
5131
- {
5132
- ref,
5133
- role: "status",
5134
- "aria-label": ariaLabel,
5135
- className: cn(badgeVariants2({ size, color, invisible, reducedMotion }), className),
5136
- children: displayValue
5137
- }
5138
- );
5139
- }
5140
- );
5141
- BadgeContent.displayName = "BadgeContent";
5142
- var Badge = React.forwardRef(
5143
- ({
5144
- count,
5145
- max = 999,
5146
- color = "error",
5147
- invisible = false,
5148
- "aria-label": ariaLabel,
5149
- className,
5150
- children
5151
- }, ref) => {
5152
- const isReduced = useReducedMotion();
5153
- const shouldShow = !invisible && (count === void 0 || count > 0);
5154
- return /* @__PURE__ */ jsxRuntime.jsxs(BadgeHeadless, { ref, className, children: [
5155
- children,
5156
- /* @__PURE__ */ jsxRuntime.jsx(
5157
- BadgeContent,
5158
- {
5159
- count,
5160
- max,
5161
- color,
5162
- invisible: !shouldShow,
5163
- "aria-label": ariaLabel,
5164
- reducedMotion: isReduced
5165
- }
5166
- )
5167
- ] });
5168
- }
5169
- );
5170
- Badge.displayName = "Badge";
5171
- function isBadgeConfig(badge) {
5172
- return typeof badge === "object" && badge !== null && !React.isValidElement(badge) && ("count" in badge || "color" in badge);
5173
4977
  }
5174
4978
  var DrawerItem = React.forwardRef(
5175
4979
  ({
@@ -5197,12 +5001,18 @@ var DrawerItem = React.forwardRef(
5197
5001
  const renderBadge = () => {
5198
5002
  if (!badge) return null;
5199
5003
  if (isBadgeConfig(badge)) {
5004
+ const max = 999;
5005
+ const isDot = badge.count === void 0;
5006
+ const displayValue = getBadgeDisplayValue(badge.count, max);
5007
+ const ariaLabel = getBadgeAriaLabel(badge.count);
5200
5008
  return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "relative z-10 ml-auto flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsxRuntime.jsx(
5201
- Badge,
5009
+ "span",
5202
5010
  {
5203
- ...badge.count !== void 0 ? { count: badge.count } : {},
5204
- ...badge.color !== void 0 ? { color: badge.color } : {},
5205
- children: /* @__PURE__ */ jsxRuntime.jsx("span", {})
5011
+ role: "status",
5012
+ "aria-label": ariaLabel,
5013
+ "data-dot": isDot ? "" : void 0,
5014
+ className: cn(badgeStaticVariants()),
5015
+ children: displayValue
5206
5016
  }
5207
5017
  ) });
5208
5018
  }
@@ -8701,6 +8511,75 @@ var Search = React.forwardRef(
8701
8511
  }
8702
8512
  );
8703
8513
  Search.displayName = "Search";
8514
+ var BadgeHeadless = React.forwardRef(
8515
+ ({ className, children, ...props }, ref) => {
8516
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: cn("relative inline-flex", className), ...props, children });
8517
+ }
8518
+ );
8519
+ BadgeHeadless.displayName = "BadgeHeadless";
8520
+ var getDisplayValue = (count, max) => {
8521
+ if (count === void 0) return "";
8522
+ return count > max ? `${max}+` : count.toString();
8523
+ };
8524
+ var getAriaLabel = (count, override) => {
8525
+ if (override) return override;
8526
+ return count === void 0 ? "New" : `${count} notifications`;
8527
+ };
8528
+ var BadgeContent = React.forwardRef(
8529
+ ({
8530
+ count,
8531
+ max = 999,
8532
+ invisible = false,
8533
+ "aria-label": ariaLabelOverride,
8534
+ reducedMotion = false,
8535
+ className
8536
+ }, ref) => {
8537
+ const isDot = count === void 0;
8538
+ const displayValue = getDisplayValue(count, max);
8539
+ const ariaLabel = getAriaLabel(count, ariaLabelOverride);
8540
+ return /* @__PURE__ */ jsxRuntime.jsx(
8541
+ "span",
8542
+ {
8543
+ ref,
8544
+ role: "status",
8545
+ "aria-label": ariaLabel,
8546
+ "data-dot": isDot ? "" : void 0,
8547
+ "data-invisible": invisible ? "" : void 0,
8548
+ className: cn(
8549
+ badgeVariants2(),
8550
+ // MD3 Expressive spatial motion for show/hide scale animation.
8551
+ // Spatial pairing: scale transform → expressive-fast-spatial token.
8552
+ // Guarded at the component level; do NOT use CSS-only reduced-motion
8553
+ // because this is a JS-conditional class, not a persistent transition.
8554
+ !reducedMotion && "duration-expressive-fast-spatial ease-expressive-fast-spatial transition-transform",
8555
+ className
8556
+ ),
8557
+ children: displayValue
8558
+ }
8559
+ );
8560
+ }
8561
+ );
8562
+ BadgeContent.displayName = "BadgeContent";
8563
+ var Badge = React.forwardRef(
8564
+ ({ count, max = 999, invisible = false, "aria-label": ariaLabel, className, children }, ref) => {
8565
+ const isReduced = useReducedMotion();
8566
+ const shouldShow = !invisible && (count === void 0 || count > 0);
8567
+ return /* @__PURE__ */ jsxRuntime.jsxs(BadgeHeadless, { ref, className, children: [
8568
+ children,
8569
+ /* @__PURE__ */ jsxRuntime.jsx(
8570
+ BadgeContent,
8571
+ {
8572
+ count,
8573
+ max,
8574
+ invisible: !shouldShow,
8575
+ "aria-label": ariaLabel,
8576
+ reducedMotion: isReduced
8577
+ }
8578
+ )
8579
+ ] });
8580
+ }
8581
+ );
8582
+ Badge.displayName = "Badge";
8704
8583
  var splitButtonContainerVariants = classVarianceAuthority.cva(
8705
8584
  ["inline-flex items-center rounded-full overflow-hidden"],
8706
8585
  {