@tinybigui/react 0.8.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.d.cts CHANGED
@@ -2264,23 +2264,23 @@ interface CheckboxProps extends AriaCheckboxProps, Omit<React__default.HTMLAttri
2264
2264
  * Material Design 3 Checkbox Component (Layer 3: Styled)
2265
2265
  *
2266
2266
  * Built on React Aria for world-class accessibility.
2267
- * Uses CVA for type-safe variant management.
2268
- * Styled with Tailwind CSS using MD3 design tokens.
2267
+ * Implements the Variants-vs-States architecture: all interaction/selection
2268
+ * states are expressed as data-* attributes on the root and consumed by each
2269
+ * slot via group-data-[x]/checkbox Tailwind selectors — no state variants in CVA.
2269
2270
  *
2270
2271
  * Features:
2271
- * - 3 states: unchecked, checked, indeterminate
2272
- * - Error/invalid state support
2273
- * - Ripple effect (Material Design)
2274
- * - Full keyboard accessibility (via React Aria)
2275
- * - Screen reader support (via React Aria)
2276
- * - Focus management (via React Aria)
2277
- * - Form integration (name, value props)
2272
+ * - 3 states: unchecked, checked, indeterminate
2273
+ * - Error/invalid state support
2274
+ * - Ripple effect (Material Design)
2275
+ * - Full keyboard accessibility (via React Aria)
2276
+ * - Screen reader support (via React Aria)
2277
+ * - Focus management (via React Aria)
2278
+ * - Form integration (name, value props)
2278
2279
  *
2279
2280
  * MD3 Specifications:
2280
- * - Container: 18x18dp (within 40x40dp touch target)
2281
- * - Corner radius: 2dp (applied via SVG rx/ry attributes)
2282
- * - State layers: 8% hover, 12% focus/pressed
2283
- * - Disabled: 38% opacity
2281
+ * - Box: 18×18dp, 2dp corner radius, within 40×40dp touch target
2282
+ * - State-layer opacities: hover 8% | focus/pressed 10%
2283
+ * - Disabled: 38% opacity on root
2284
2284
  * - Label spacing: 16px (ml-4)
2285
2285
  *
2286
2286
  * @example
package/dist/index.d.ts CHANGED
@@ -2264,23 +2264,23 @@ interface CheckboxProps extends AriaCheckboxProps, Omit<React__default.HTMLAttri
2264
2264
  * Material Design 3 Checkbox Component (Layer 3: Styled)
2265
2265
  *
2266
2266
  * Built on React Aria for world-class accessibility.
2267
- * Uses CVA for type-safe variant management.
2268
- * Styled with Tailwind CSS using MD3 design tokens.
2267
+ * Implements the Variants-vs-States architecture: all interaction/selection
2268
+ * states are expressed as data-* attributes on the root and consumed by each
2269
+ * slot via group-data-[x]/checkbox Tailwind selectors — no state variants in CVA.
2269
2270
  *
2270
2271
  * Features:
2271
- * - 3 states: unchecked, checked, indeterminate
2272
- * - Error/invalid state support
2273
- * - Ripple effect (Material Design)
2274
- * - Full keyboard accessibility (via React Aria)
2275
- * - Screen reader support (via React Aria)
2276
- * - Focus management (via React Aria)
2277
- * - Form integration (name, value props)
2272
+ * - 3 states: unchecked, checked, indeterminate
2273
+ * - Error/invalid state support
2274
+ * - Ripple effect (Material Design)
2275
+ * - Full keyboard accessibility (via React Aria)
2276
+ * - Screen reader support (via React Aria)
2277
+ * - Focus management (via React Aria)
2278
+ * - Form integration (name, value props)
2278
2279
  *
2279
2280
  * MD3 Specifications:
2280
- * - Container: 18x18dp (within 40x40dp touch target)
2281
- * - Corner radius: 2dp (applied via SVG rx/ry attributes)
2282
- * - State layers: 8% hover, 12% focus/pressed
2283
- * - Disabled: 38% opacity
2281
+ * - Box: 18×18dp, 2dp corner radius, within 40×40dp touch target
2282
+ * - State-layer opacities: hover 8% | focus/pressed 10%
2283
+ * - Disabled: 38% opacity on root
2284
2284
  * - Label spacing: 16px (ml-4)
2285
2285
  *
2286
2286
  * @example
package/dist/index.js CHANGED
@@ -2665,205 +2665,132 @@ var TextField = forwardRef(
2665
2665
  }
2666
2666
  );
2667
2667
  TextField.displayName = "TextField";
2668
- var checkboxVariants = cva(
2669
- [
2670
- // Base classes (always applied to label wrapper)
2671
- "relative inline-flex items-center cursor-pointer select-none",
2672
- "transition-opacity duration-200"
2673
- ],
2674
- {
2675
- variants: {
2676
- /**
2677
- * Disabled state
2678
- */
2679
- disabled: {
2680
- true: "opacity-38 cursor-not-allowed pointer-events-none",
2681
- false: ""
2682
- }
2683
- },
2684
- defaultVariants: {
2685
- disabled: false
2686
- }
2687
- }
2688
- );
2689
- var checkboxContainerVariants = cva(
2690
- [
2691
- // Base classes for checkbox visual container
2692
- "relative inline-flex items-center justify-center m-1",
2693
- "w-10 h-10",
2694
- // 40x40dp touch target (MD3 spec)
2695
- "flex-shrink-0",
2696
- "transition-all duration-200",
2697
- // State layer (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
2698
- "before:absolute before:inset-0 before:rounded-full before:transition-opacity before:duration-200",
2699
- "before:bg-current before:opacity-0",
2700
- "hover:before:opacity-8",
2701
- "active:before:opacity-12"
2702
- ],
2703
- {
2704
- variants: {
2705
- /**
2706
- * Checkbox state (determines visual appearance)
2707
- */
2708
- state: {
2709
- unchecked: "text-on-surface-variant",
2710
- checked: "text-primary",
2711
- indeterminate: "text-primary"
2712
- },
2713
- /**
2714
- * Error/invalid state
2715
- */
2716
- isInvalid: {
2717
- true: "text-error",
2718
- false: ""
2719
- },
2720
- /**
2721
- * Disabled state
2722
- */
2723
- disabled: {
2724
- true: "text-on-surface pointer-events-none",
2725
- false: ""
2726
- }
2727
- },
2728
- compoundVariants: [
2729
- // Error state overrides normal colors for all states
2730
- {
2731
- state: "unchecked",
2732
- isInvalid: true,
2733
- disabled: false,
2734
- className: "text-error"
2735
- },
2736
- {
2737
- state: "checked",
2738
- isInvalid: true,
2739
- disabled: false,
2740
- className: "text-error"
2741
- },
2742
- {
2743
- state: "indeterminate",
2744
- isInvalid: true,
2745
- disabled: false,
2746
- className: "text-error"
2747
- }
2748
- ],
2749
- defaultVariants: {
2750
- state: "unchecked",
2751
- isInvalid: false,
2752
- disabled: false
2753
- }
2754
- }
2755
- );
2756
- var checkboxIconBoxVariants = cva(
2757
- [
2758
- // Base classes for the checkbox box
2759
- // Note: Border radius is applied via SVG rx/ry attributes (2dp) in the component
2760
- "transition-all duration-200"
2761
- ],
2762
- {
2763
- variants: {
2764
- /**
2765
- * Checkbox state
2766
- */
2767
- state: {
2768
- unchecked: [
2769
- "fill-transparent",
2770
- "stroke-outline",
2771
- // MD3: outline color for unchecked
2772
- "stroke-4"
2773
- // MD3: 2dp outline width
2774
- ],
2775
- checked: [
2776
- "fill-current",
2777
- // Uses parent text color (primary or error)
2778
- "stroke-none"
2779
- ],
2780
- indeterminate: [
2781
- "fill-current",
2782
- // Uses parent text color (primary or error)
2783
- "stroke-none"
2784
- ]
2785
- },
2786
- /**
2787
- * Disabled state
2788
- */
2789
- disabled: {
2790
- true: ["fill-transparent", "stroke-current", "stroke-2"],
2791
- false: ""
2792
- }
2793
- },
2794
- compoundVariants: [
2795
- // Disabled state overrides fill for checked/indeterminate
2796
- {
2797
- state: "checked",
2798
- disabled: true,
2799
- className: "fill-current stroke-none"
2800
- },
2801
- {
2802
- state: "indeterminate",
2803
- disabled: true,
2804
- className: "fill-current stroke-none"
2805
- }
2806
- ],
2807
- defaultVariants: {
2808
- state: "unchecked",
2809
- disabled: false
2810
- }
2811
- }
2812
- );
2813
- var checkboxIconVariants = cva(
2814
- [
2815
- "fill-current",
2816
- // Inherits color from parent
2817
- "transition-all duration-200"
2818
- ],
2819
- {
2820
- variants: {
2821
- /**
2822
- * Icon type
2823
- */
2824
- type: {
2825
- check: "",
2826
- // Checkmark icon
2827
- dash: ""
2828
- // Dash/minus icon
2829
- }
2830
- },
2831
- defaultVariants: {
2832
- type: "check"
2668
+ var checkboxRootVariants = cva([
2669
+ "relative inline-flex items-center cursor-pointer select-none",
2670
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none",
2671
+ "data-[disabled]:opacity-38"
2672
+ ]);
2673
+ var checkboxControlVariants = cva([
2674
+ "relative flex items-center justify-center flex-shrink-0",
2675
+ "w-10 h-10 rounded-full",
2676
+ "overflow-hidden"
2677
+ ]);
2678
+ var checkboxStateLayerVariants = cva([
2679
+ "absolute inset-0 rounded-full pointer-events-none opacity-0",
2680
+ // Base state-layer color (unselected)
2681
+ "bg-on-surface",
2682
+ // Effects transition for opacity changes
2683
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2684
+ // Selected / indeterminate → primary color
2685
+ "group-data-[selected]/checkbox:bg-primary",
2686
+ "group-data-[indeterminate]/checkbox:bg-primary",
2687
+ // Invalid → error color (singly-chained)
2688
+ "group-data-[invalid]/checkbox:bg-error",
2689
+ // Invalid + selected → error wins (doubly-chained for specificity)
2690
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-error",
2691
+ // Interaction opacities (MD3: hover 8%, focus-visible 10%, pressed 10%)
2692
+ "group-data-[hovered]/checkbox:opacity-8",
2693
+ "group-data-[focus-visible]/checkbox:opacity-10",
2694
+ "group-data-[pressed]/checkbox:opacity-10",
2695
+ // No state layer when disabled
2696
+ "group-data-[disabled]/checkbox:hidden"
2697
+ ]);
2698
+ var checkboxFocusRingVariants = cva([
2699
+ "pointer-events-none absolute inset-0 rounded-full",
2700
+ "outline outline-2 outline-offset-0 outline-secondary",
2701
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2702
+ "opacity-0",
2703
+ "group-data-[focus-visible]/checkbox:opacity-100"
2704
+ ]);
2705
+ var checkboxBoxVariants = cva([
2706
+ // Base geometry
2707
+ "relative flex items-center justify-center flex-shrink-0",
2708
+ "w-[18px] h-[18px] rounded-[2px] border-2",
2709
+ // Effects transition for color changes
2710
+ "transition-[background-color,border-color] duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
2711
+ // ── Unselected base ───────────────────────────────────────────────────────
2712
+ "bg-transparent border-outline",
2713
+ // ── Selected ──────────────────────────────────────────────────────────────
2714
+ "group-data-[selected]/checkbox:bg-primary group-data-[selected]/checkbox:border-primary",
2715
+ // ── Indeterminate ─────────────────────────────────────────────────────────
2716
+ "group-data-[indeterminate]/checkbox:bg-primary group-data-[indeterminate]/checkbox:border-primary",
2717
+ // ── Invalid (unselected) — singly chained ─────────────────────────────────
2718
+ "group-data-[invalid]/checkbox:border-error",
2719
+ // ── Invalid + selected — doubly chained (higher specificity) ──────────────
2720
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:bg-error",
2721
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:border-error",
2722
+ // ── Invalid + indeterminate — doubly chained ───────────────────────────────
2723
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:bg-error",
2724
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:border-error",
2725
+ // ── Disabled (placed last — cascade wins over interaction colors) ──────────
2726
+ "group-data-[disabled]/checkbox:border-on-surface/38",
2727
+ "group-data-[disabled]/checkbox:bg-transparent",
2728
+ // ── Disabled + selected — doubly chained ──────────────────────────────────
2729
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:bg-on-surface/38",
2730
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:border-transparent",
2731
+ // ── Disabled + indeterminate — doubly chained ─────────────────────────────
2732
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:bg-on-surface/38",
2733
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:border-transparent"
2734
+ ]);
2735
+ var checkboxIconVariants = cva([
2736
+ "absolute inset-0 flex items-center justify-center",
2737
+ // Spatial transition for icon appearing (scale)
2738
+ "transition-transform duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial",
2739
+ // Base icon color
2740
+ "text-on-primary",
2741
+ // Invalid → on-error (doubly-chained for both selected and indeterminate)
2742
+ "group-data-[invalid]/checkbox:group-data-[selected]/checkbox:text-on-error",
2743
+ "group-data-[invalid]/checkbox:group-data-[indeterminate]/checkbox:text-on-error",
2744
+ // Disabled → surface (doubly-chained)
2745
+ "group-data-[selected]/checkbox:group-data-[disabled]/checkbox:text-surface",
2746
+ "group-data-[indeterminate]/checkbox:group-data-[disabled]/checkbox:text-surface"
2747
+ ]);
2748
+ var checkboxLabelVariants = cva(["text-body-large text-on-surface select-none ml-4"]);
2749
+ function CheckboxCheckIcon() {
2750
+ return /* @__PURE__ */ jsx(
2751
+ "svg",
2752
+ {
2753
+ xmlns: "http://www.w3.org/2000/svg",
2754
+ width: "18",
2755
+ height: "18",
2756
+ viewBox: "0 0 18 18",
2757
+ fill: "none",
2758
+ "aria-hidden": "true",
2759
+ children: /* @__PURE__ */ jsx(
2760
+ "path",
2761
+ {
2762
+ d: "M4.5 9L7.2 11.7L13.5 5.4",
2763
+ stroke: "currentColor",
2764
+ strokeWidth: "2",
2765
+ strokeLinecap: "square",
2766
+ strokeLinejoin: "miter"
2767
+ }
2768
+ )
2833
2769
  }
2834
- }
2835
- );
2836
- var checkboxLabelVariants = cva(
2837
- [
2838
- "text-sm",
2839
- // MD3: Body Medium (14px)
2840
- "text-on-surface",
2841
- "select-none"
2842
- ],
2843
- {
2844
- variants: {
2845
- disabled: {
2846
- true: "",
2847
- false: ""
2848
- }
2849
- },
2850
- defaultVariants: {
2851
- disabled: false
2770
+ );
2771
+ }
2772
+ function CheckboxIndeterminateIcon() {
2773
+ return /* @__PURE__ */ jsx(
2774
+ "svg",
2775
+ {
2776
+ xmlns: "http://www.w3.org/2000/svg",
2777
+ width: "18",
2778
+ height: "18",
2779
+ viewBox: "0 0 18 18",
2780
+ fill: "none",
2781
+ "aria-hidden": "true",
2782
+ children: /* @__PURE__ */ jsx("rect", { x: "4", y: "8", width: "10", height: "2", rx: "1", fill: "currentColor" })
2852
2783
  }
2853
- }
2854
- );
2784
+ );
2785
+ }
2855
2786
  var Checkbox = forwardRef(
2856
2787
  ({
2857
- // Content props
2858
2788
  children,
2859
- // State props
2860
2789
  isIndeterminate = false,
2861
2790
  isInvalid = false,
2862
2791
  disableRipple = false,
2863
2792
  isDisabled = false,
2864
- // Styling
2865
2793
  className,
2866
- // Other props
2867
2794
  ...props
2868
2795
  }, forwardedRef) => {
2869
2796
  const internalRef = useRef(null);
@@ -2876,17 +2803,17 @@ var Checkbox = forwardRef(
2876
2803
  "data-testid": _dataTestId,
2877
2804
  id: _htmlId,
2878
2805
  title: _htmlTitle,
2879
- ...restPropsWithoutHtmlAttrs
2806
+ ...ariaProps
2880
2807
  } = props;
2881
- const state = useToggleState(restPropsWithoutHtmlAttrs);
2882
- const { inputProps, labelProps } = useCheckbox(
2883
- restPropsWithoutHtmlAttrs,
2808
+ const state = useToggleState(ariaProps);
2809
+ const { inputProps, labelProps, isPressed } = useCheckbox(
2810
+ ariaProps,
2884
2811
  state,
2885
2812
  ref
2886
2813
  );
2887
2814
  const { isFocusVisible, focusProps } = useFocusRing();
2815
+ const { isHovered, hoverProps } = useHover({ isDisabled });
2888
2816
  const isSelected = state.isSelected;
2889
- const visualState = isIndeterminate ? "indeterminate" : isSelected ? "checked" : "unchecked";
2890
2817
  const { onMouseDown: handleRipple, ripples } = useRipple({
2891
2818
  disabled: isDisabled || disableRipple
2892
2819
  });
@@ -2896,8 +2823,8 @@ var Checkbox = forwardRef(
2896
2823
  }
2897
2824
  }, [isIndeterminate, ref]);
2898
2825
  if (process.env.NODE_ENV === "development") {
2899
- const ariaProps = restPropsWithoutHtmlAttrs;
2900
- if (!children && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
2826
+ const a = ariaProps;
2827
+ if (!children && !a["aria-label"] && !a["aria-labelledby"]) {
2901
2828
  console.warn(
2902
2829
  "[Checkbox] Checkbox should have a label (children) or aria-label for accessibility."
2903
2830
  );
@@ -2906,105 +2833,40 @@ var Checkbox = forwardRef(
2906
2833
  return /* @__PURE__ */ jsxs(
2907
2834
  "label",
2908
2835
  {
2909
- ...labelProps,
2910
- className: cn(
2911
- checkboxVariants({
2912
- disabled: isDisabled
2913
- }),
2914
- className
2915
- ),
2836
+ ...mergeProps$1(labelProps, hoverProps),
2837
+ className: cn(checkboxRootVariants(), "group/checkbox", className),
2916
2838
  "data-testid": dataTestId,
2917
2839
  title: htmlTitle,
2840
+ ...getInteractionDataAttributes({
2841
+ isHovered,
2842
+ isFocusVisible,
2843
+ isPressed,
2844
+ isSelected,
2845
+ isDisabled,
2846
+ isInvalid,
2847
+ isIndeterminate,
2848
+ isReadOnly: ariaProps.isReadOnly ?? false
2849
+ }),
2918
2850
  children: [
2919
2851
  /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("input", { ...mergeProps$1(inputProps, focusProps), ref, id: htmlId }) }),
2920
2852
  /* @__PURE__ */ jsxs(
2921
2853
  "div",
2922
2854
  {
2923
2855
  role: "presentation",
2924
- className: cn(
2925
- checkboxContainerVariants({
2926
- state: visualState,
2927
- isInvalid,
2928
- disabled: isDisabled
2929
- })
2930
- ),
2856
+ className: cn(checkboxControlVariants()),
2931
2857
  onMouseDown: handleRipple,
2932
2858
  children: [
2933
2859
  ripples,
2934
- /* @__PURE__ */ jsxs(
2935
- "svg",
2936
- {
2937
- width: "18",
2938
- height: "18",
2939
- viewBox: "0 0 18 18",
2940
- "aria-hidden": "true",
2941
- className: "relative z-10",
2942
- children: [
2943
- /* @__PURE__ */ jsx(
2944
- "rect",
2945
- {
2946
- x: "0",
2947
- y: "0",
2948
- width: "18",
2949
- height: "18",
2950
- rx: "2",
2951
- ry: "2",
2952
- className: cn(
2953
- checkboxIconBoxVariants({
2954
- state: visualState,
2955
- disabled: isDisabled
2956
- })
2957
- )
2958
- }
2959
- ),
2960
- isSelected && !isIndeterminate && /* @__PURE__ */ jsx(
2961
- "path",
2962
- {
2963
- d: "M14.1 4.5L6.3 12.3l-3.4-3.4L1.5 10.3l4.8 4.8 9.2-9.2z",
2964
- className: cn(checkboxIconVariants({ type: "check" }), "fill-on-primary")
2965
- }
2966
- ),
2967
- isIndeterminate && /* @__PURE__ */ jsx(
2968
- "rect",
2969
- {
2970
- x: "4",
2971
- y: "8",
2972
- width: "10",
2973
- height: "2",
2974
- className: cn(checkboxIconVariants({ type: "dash" }), "fill-on-primary")
2975
- }
2976
- ),
2977
- isFocusVisible && /* @__PURE__ */ jsx(
2978
- "rect",
2979
- {
2980
- x: "-3",
2981
- y: "-3",
2982
- width: "24",
2983
- height: "24",
2984
- rx: "12",
2985
- fill: "none",
2986
- stroke: "currentColor",
2987
- strokeWidth: "2",
2988
- className: "animate-pulse"
2989
- }
2990
- )
2991
- ]
2992
- }
2993
- )
2860
+ /* @__PURE__ */ jsx("span", { className: cn(checkboxStateLayerVariants()), "aria-hidden": "true" }),
2861
+ /* @__PURE__ */ jsx("span", { className: cn(checkboxFocusRingVariants()), "aria-hidden": "true" }),
2862
+ /* @__PURE__ */ jsxs("div", { className: cn(checkboxBoxVariants()), "aria-hidden": "true", children: [
2863
+ isSelected && !isIndeterminate && /* @__PURE__ */ jsx("span", { className: cn(checkboxIconVariants()), children: /* @__PURE__ */ jsx(CheckboxCheckIcon, {}) }),
2864
+ isIndeterminate && /* @__PURE__ */ jsx("span", { className: cn(checkboxIconVariants()), children: /* @__PURE__ */ jsx(CheckboxIndeterminateIcon, {}) })
2865
+ ] })
2994
2866
  ]
2995
2867
  }
2996
2868
  ),
2997
- children && /* @__PURE__ */ jsx(
2998
- "span",
2999
- {
3000
- className: cn(
3001
- checkboxLabelVariants({
3002
- disabled: isDisabled
3003
- })
3004
- ),
3005
- children
3006
- }
3007
- )
2869
+ children && /* @__PURE__ */ jsx("span", { className: cn(checkboxLabelVariants()), children })
3008
2870
  ]
3009
2871
  }
3010
2872
  );