@tinybigui/react 0.19.0 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -6555,7 +6555,6 @@ var snackbarBaseVariants = cva(
6555
6555
  "min-w-72",
6556
6556
  "max-w-snackbar-max",
6557
6557
  "w-max",
6558
- "min-h-12",
6559
6558
  // Restore pointer events so hover/focus timer pause works
6560
6559
  "pointer-events-auto",
6561
6560
  // Surface
@@ -6566,25 +6565,27 @@ var snackbarBaseVariants = cva(
6566
6565
  "shadow-elevation-3",
6567
6566
  // Layout
6568
6567
  "flex",
6569
- "items-center",
6570
6568
  "gap-x-1",
6571
- "pl-4 pr-2",
6572
- // Typography
6569
+ "pl-4",
6570
+ // Typography base (inherited by message/supporting-text slots)
6573
6571
  "text-body-medium",
6574
6572
  "text-inverse-on-surface",
6575
- // Transition (properties used by both entry and exit)
6573
+ // Slide + fade transition spring-standard effects tokens (no overshoot).
6574
+ // The translate offset is small (12px), so using the effects token pair for
6575
+ // BOTH opacity AND transform is safe: no visible overshoot at this scale.
6576
6576
  "transition-[opacity,transform]",
6577
6577
  "will-change-[opacity,transform]"
6578
6578
  ],
6579
6579
  {
6580
6580
  variants: {
6581
6581
  /**
6582
- * Whether the Snackbar has supporting text (two-line layout).
6583
- * Adjusts vertical padding to MD3 spec for two-line configuration.
6582
+ * Two-line density mode.
6583
+ * false 48dp, items centered (single-line message)
6584
+ * true — 68dp, items top-aligned (message + supporting text)
6584
6585
  */
6585
6586
  twoLine: {
6586
- true: "py-1",
6587
- false: "py-1"
6587
+ false: ["min-h-12", "items-center", "pr-1"],
6588
+ true: ["min-h-[4.25rem]", "items-start", "pr-1"]
6588
6589
  }
6589
6590
  },
6590
6591
  defaultVariants: {
@@ -6610,53 +6611,211 @@ cva("", {
6610
6611
  var snackbarAnimationVariants = cva("", {
6611
6612
  variants: {
6612
6613
  animationState: {
6613
- entering: ["opacity-0", "scale-75"],
6614
- visible: ["scale-100", "opacity-100", "duration-medium1", "ease-emphasized-decelerate"],
6615
- exiting: ["scale-75", "opacity-0", "duration-short4", "ease-standard-accelerate"],
6616
- exited: ["scale-75", "opacity-0", "duration-short4", "ease-standard-accelerate"]
6614
+ entering: [],
6615
+ visible: [],
6616
+ exiting: [],
6617
+ exited: []
6617
6618
  },
6618
6619
  enterDirection: {
6619
- up: ["origin-bottom"],
6620
- down: ["origin-top"]
6620
+ up: [],
6621
+ down: []
6621
6622
  }
6622
6623
  },
6623
- defaultVariants: {
6624
- animationState: "entering",
6625
- enterDirection: "up"
6626
- }
6627
- });
6628
- cva([...snackbarBaseVariants()], {
6629
- variants: {
6630
- animationState: {
6631
- entering: ["opacity-0", "scale-75"],
6632
- visible: ["scale-100", "opacity-100", "duration-medium1", "ease-emphasized-decelerate"],
6633
- exiting: ["scale-75", "opacity-0", "duration-short4", "ease-standard-accelerate"],
6634
- exited: ["scale-75", "opacity-0", "duration-short4", "ease-standard-accelerate"]
6624
+ compoundVariants: [
6625
+ // ── entering ──────────────────────────────────────────────────────────────
6626
+ // No transition duration — instant jump to offset state before first paint.
6627
+ {
6628
+ animationState: "entering",
6629
+ enterDirection: "up",
6630
+ className: ["opacity-0", "translate-y-3"]
6635
6631
  },
6636
- enterDirection: {
6637
- up: ["origin-bottom"],
6638
- down: ["origin-top"]
6632
+ {
6633
+ animationState: "entering",
6634
+ enterDirection: "down",
6635
+ className: ["opacity-0", "-translate-y-3"]
6639
6636
  },
6640
- position: {
6641
- "bottom-center": ["bottom-4", "left-1/2", "-translate-x-1/2"],
6642
- "bottom-left": ["bottom-4", "left-4"],
6643
- "bottom-right": ["bottom-4", "right-4"],
6644
- "top-center": ["top-4", "left-1/2", "-translate-x-1/2"],
6645
- "top-left": ["top-4", "left-4"],
6646
- "top-right": ["top-4", "right-4"]
6637
+ // ── visible ───────────────────────────────────────────────────────────────
6638
+ // spring-standard default effects = 200ms, no overshoot.
6639
+ {
6640
+ animationState: "visible",
6641
+ enterDirection: "up",
6642
+ className: [
6643
+ "opacity-100",
6644
+ "translate-y-0",
6645
+ "duration-spring-standard-default-effects",
6646
+ "ease-spring-standard-default-effects"
6647
+ ]
6648
+ },
6649
+ {
6650
+ animationState: "visible",
6651
+ enterDirection: "down",
6652
+ className: [
6653
+ "opacity-100",
6654
+ "translate-y-0",
6655
+ "duration-spring-standard-default-effects",
6656
+ "ease-spring-standard-default-effects"
6657
+ ]
6658
+ },
6659
+ // ── exiting ───────────────────────────────────────────────────────────────
6660
+ // spring-standard fast effects = 150ms (quicker exit).
6661
+ {
6662
+ animationState: "exiting",
6663
+ enterDirection: "up",
6664
+ className: [
6665
+ "opacity-0",
6666
+ "translate-y-3",
6667
+ "duration-spring-standard-fast-effects",
6668
+ "ease-spring-standard-fast-effects"
6669
+ ]
6670
+ },
6671
+ {
6672
+ animationState: "exiting",
6673
+ enterDirection: "down",
6674
+ className: [
6675
+ "opacity-0",
6676
+ "-translate-y-3",
6677
+ "duration-spring-standard-fast-effects",
6678
+ "ease-spring-standard-fast-effects"
6679
+ ]
6680
+ },
6681
+ // ── exited ────────────────────────────────────────────────────────────────
6682
+ // Hold final position — element is removed from DOM shortly after.
6683
+ {
6684
+ animationState: "exited",
6685
+ enterDirection: "up",
6686
+ className: ["opacity-0", "translate-y-3"]
6647
6687
  },
6648
- twoLine: {
6649
- true: "py-1",
6650
- false: "py-1"
6688
+ {
6689
+ animationState: "exited",
6690
+ enterDirection: "down",
6691
+ className: ["opacity-0", "-translate-y-3"]
6651
6692
  }
6652
- },
6693
+ ],
6653
6694
  defaultVariants: {
6654
6695
  animationState: "entering",
6655
- enterDirection: "up",
6656
- position: "bottom-center",
6657
- twoLine: false
6696
+ enterDirection: "up"
6658
6697
  }
6659
6698
  });
6699
+ cva(
6700
+ [
6701
+ "min-w-72",
6702
+ "max-w-snackbar-max",
6703
+ "w-max",
6704
+ "pointer-events-auto",
6705
+ "bg-inverse-surface",
6706
+ "rounded-xs",
6707
+ "shadow-elevation-3",
6708
+ "flex",
6709
+ "gap-x-1",
6710
+ "pl-4",
6711
+ "text-body-medium",
6712
+ "text-inverse-on-surface",
6713
+ "transition-[opacity,transform]",
6714
+ "will-change-[opacity,transform]"
6715
+ ],
6716
+ {
6717
+ variants: {
6718
+ twoLine: {
6719
+ false: ["min-h-12", "items-center", "pr-1"],
6720
+ true: ["min-h-[4.25rem]", "items-start", "pr-1"]
6721
+ },
6722
+ animationState: {
6723
+ entering: [],
6724
+ visible: [],
6725
+ exiting: [],
6726
+ exited: []
6727
+ },
6728
+ enterDirection: {
6729
+ up: [],
6730
+ down: []
6731
+ },
6732
+ position: {
6733
+ "bottom-center": ["bottom-4", "left-1/2", "-translate-x-1/2"],
6734
+ "bottom-left": ["bottom-4", "left-4"],
6735
+ "bottom-right": ["bottom-4", "right-4"],
6736
+ "top-center": ["top-4", "left-1/2", "-translate-x-1/2"],
6737
+ "top-left": ["top-4", "left-4"],
6738
+ "top-right": ["top-4", "right-4"]
6739
+ }
6740
+ },
6741
+ compoundVariants: [
6742
+ {
6743
+ animationState: "entering",
6744
+ enterDirection: "up",
6745
+ className: ["opacity-0", "translate-y-3"]
6746
+ },
6747
+ {
6748
+ animationState: "entering",
6749
+ enterDirection: "down",
6750
+ className: ["opacity-0", "-translate-y-3"]
6751
+ },
6752
+ {
6753
+ animationState: "visible",
6754
+ enterDirection: "up",
6755
+ className: [
6756
+ "opacity-100",
6757
+ "translate-y-0",
6758
+ "duration-spring-standard-default-effects",
6759
+ "ease-spring-standard-default-effects"
6760
+ ]
6761
+ },
6762
+ {
6763
+ animationState: "visible",
6764
+ enterDirection: "down",
6765
+ className: [
6766
+ "opacity-100",
6767
+ "translate-y-0",
6768
+ "duration-spring-standard-default-effects",
6769
+ "ease-spring-standard-default-effects"
6770
+ ]
6771
+ },
6772
+ {
6773
+ animationState: "exiting",
6774
+ enterDirection: "up",
6775
+ className: [
6776
+ "opacity-0",
6777
+ "translate-y-3",
6778
+ "duration-spring-standard-fast-effects",
6779
+ "ease-spring-standard-fast-effects"
6780
+ ]
6781
+ },
6782
+ {
6783
+ animationState: "exiting",
6784
+ enterDirection: "down",
6785
+ className: [
6786
+ "opacity-0",
6787
+ "-translate-y-3",
6788
+ "duration-spring-standard-fast-effects",
6789
+ "ease-spring-standard-fast-effects"
6790
+ ]
6791
+ },
6792
+ {
6793
+ animationState: "exited",
6794
+ enterDirection: "up",
6795
+ className: ["opacity-0", "translate-y-3"]
6796
+ },
6797
+ {
6798
+ animationState: "exited",
6799
+ enterDirection: "down",
6800
+ className: ["opacity-0", "-translate-y-3"]
6801
+ }
6802
+ ],
6803
+ defaultVariants: {
6804
+ animationState: "entering",
6805
+ enterDirection: "up",
6806
+ position: "bottom-center",
6807
+ twoLine: false
6808
+ }
6809
+ }
6810
+ );
6811
+ var snackbarContentVariants = cva([
6812
+ "flex",
6813
+ "flex-col",
6814
+ "flex-1",
6815
+ "min-w-0",
6816
+ "py-3",
6817
+ "pr-2"
6818
+ ]);
6660
6819
  var snackbarMessageVariants = cva([
6661
6820
  "flex-1",
6662
6821
  "text-body-medium",
@@ -6665,15 +6824,83 @@ var snackbarMessageVariants = cva([
6665
6824
  var snackbarSupportingTextVariants = cva([
6666
6825
  "text-body-medium",
6667
6826
  "text-inverse-on-surface",
6668
- "opacity-80"
6827
+ "mt-1"
6669
6828
  ]);
6670
- var snackbarActionVariants = cva(["shrink-0", "text-inverse-primary"]);
6671
- var snackbarCloseVariants = cva(["shrink-0", "text-inverse-on-surface"]);
6672
- var snackbarContentVariants = cva(["flex", "flex-col", "flex-1", "min-w-0 py-2 pr-2"]);
6673
- cva(["scale-75", "opacity-0"]);
6829
+ cva(["opacity-0"]);
6674
6830
  function getEnterDirection(position) {
6675
6831
  return position.startsWith("top") ? "down" : "up";
6676
6832
  }
6833
+ var snackbarActionVariants = cva([
6834
+ // Layout
6835
+ "relative inline-flex items-center justify-center shrink-0",
6836
+ "h-9 px-3",
6837
+ "rounded-full cursor-pointer select-none",
6838
+ // Typography (MD3 text button: label-large)
6839
+ "text-label-large",
6840
+ "text-inverse-primary",
6841
+ // Effects transition (color)
6842
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6843
+ // Disabled
6844
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none",
6845
+ "data-[disabled]:text-on-surface/38"
6846
+ ]);
6847
+ var snackbarActionStateLayerVariants = cva([
6848
+ "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
6849
+ "bg-inverse-primary",
6850
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6851
+ // Hover: 8%
6852
+ "group-data-[hovered]/snackbar-action:opacity-8",
6853
+ // Focus: 10%
6854
+ "group-data-[focus-visible]/snackbar-action:opacity-10",
6855
+ // Pressed: 10%, doubled selector wins over hover
6856
+ "group-data-[pressed]/snackbar-action:group-data-[pressed]/snackbar-action:opacity-10",
6857
+ // No state layer when disabled
6858
+ "group-data-[disabled]/snackbar-action:hidden"
6859
+ ]);
6860
+ var snackbarActionFocusRingVariants = cva([
6861
+ "pointer-events-none absolute inset-[-3px] rounded-full",
6862
+ "outline outline-2 outline-offset-0 outline-inverse-primary",
6863
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6864
+ "opacity-0",
6865
+ "group-data-[focus-visible]/snackbar-action:opacity-100"
6866
+ ]);
6867
+ var snackbarCloseVariants = cva([
6868
+ // Layout
6869
+ "relative inline-flex items-center justify-center shrink-0",
6870
+ "size-8",
6871
+ "rounded-full cursor-pointer select-none",
6872
+ // Color
6873
+ "text-inverse-on-surface",
6874
+ // Effects transition (color)
6875
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6876
+ // Disabled
6877
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none",
6878
+ "data-[disabled]:text-on-surface/38"
6879
+ ]);
6880
+ var snackbarCloseStateLayerVariants = cva([
6881
+ "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
6882
+ "bg-inverse-on-surface",
6883
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6884
+ // Hover: 8%
6885
+ "group-data-[hovered]/snackbar-close:opacity-8",
6886
+ // Focus: 10%
6887
+ "group-data-[focus-visible]/snackbar-close:opacity-10",
6888
+ // Pressed: 10%, doubled selector wins over hover
6889
+ "group-data-[pressed]/snackbar-close:group-data-[pressed]/snackbar-close:opacity-10",
6890
+ // No state layer when disabled
6891
+ "group-data-[disabled]/snackbar-close:hidden"
6892
+ ]);
6893
+ var snackbarCloseFocusRingVariants = cva([
6894
+ "pointer-events-none absolute inset-[-3px] rounded-full",
6895
+ "outline outline-2 outline-offset-0 outline-inverse-on-surface",
6896
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
6897
+ "opacity-0",
6898
+ "group-data-[focus-visible]/snackbar-close:opacity-100"
6899
+ ]);
6900
+ var snackbarCloseIconVariants = cva([
6901
+ "relative z-10 inline-flex shrink-0 items-center justify-center",
6902
+ "size-6"
6903
+ ]);
6677
6904
  function CloseIcon() {
6678
6905
  return /* @__PURE__ */ jsx(
6679
6906
  "svg",
@@ -6688,6 +6915,52 @@ function CloseIcon() {
6688
6915
  }
6689
6916
  );
6690
6917
  }
6918
+ function SnackbarActionButton({ label, onAction }) {
6919
+ const ref = useRef(null);
6920
+ const { buttonProps, isPressed } = useButton({ onPress: onAction }, ref);
6921
+ const { isHovered, hoverProps } = useHover({});
6922
+ const { isFocusVisible, focusProps } = useFocusRing();
6923
+ const { onMouseDown, ripples } = useRipple();
6924
+ return /* @__PURE__ */ jsxs(
6925
+ "button",
6926
+ {
6927
+ type: "button",
6928
+ ...mergeProps$1(buttonProps, hoverProps, focusProps, { onMouseDown }),
6929
+ ref,
6930
+ className: cn(snackbarActionVariants(), "group/snackbar-action"),
6931
+ ...getInteractionDataAttributes({ isHovered, isFocusVisible, isPressed }),
6932
+ children: [
6933
+ ripples,
6934
+ /* @__PURE__ */ jsx("span", { className: snackbarActionStateLayerVariants(), "aria-hidden": "true" }),
6935
+ /* @__PURE__ */ jsx("span", { className: snackbarActionFocusRingVariants(), "aria-hidden": "true" }),
6936
+ /* @__PURE__ */ jsx("span", { className: "relative z-10", children: label })
6937
+ ]
6938
+ }
6939
+ );
6940
+ }
6941
+ function SnackbarCloseButton({ onPress }) {
6942
+ const ref = useRef(null);
6943
+ const { buttonProps, isPressed } = useButton({ onPress, "aria-label": "Close" }, ref);
6944
+ const { isHovered, hoverProps } = useHover({});
6945
+ const { isFocusVisible, focusProps } = useFocusRing();
6946
+ const { onMouseDown, ripples } = useRipple();
6947
+ return /* @__PURE__ */ jsxs(
6948
+ "button",
6949
+ {
6950
+ type: "button",
6951
+ ...mergeProps$1(buttonProps, hoverProps, focusProps, { onMouseDown }),
6952
+ ref,
6953
+ className: cn(snackbarCloseVariants(), "group/snackbar-close"),
6954
+ ...getInteractionDataAttributes({ isHovered, isFocusVisible, isPressed }),
6955
+ children: [
6956
+ ripples,
6957
+ /* @__PURE__ */ jsx("span", { className: snackbarCloseStateLayerVariants(), "aria-hidden": "true" }),
6958
+ /* @__PURE__ */ jsx("span", { className: snackbarCloseFocusRingVariants(), "aria-hidden": "true" }),
6959
+ /* @__PURE__ */ jsx("span", { className: snackbarCloseIconVariants(), "aria-hidden": "true", children: /* @__PURE__ */ jsx(CloseIcon, {}) })
6960
+ ]
6961
+ }
6962
+ );
6963
+ }
6691
6964
  var Snackbar = forwardRef(function Snackbar2({
6692
6965
  message,
6693
6966
  supportingText,
@@ -6700,6 +6973,7 @@ var Snackbar = forwardRef(function Snackbar2({
6700
6973
  className
6701
6974
  }, ref) {
6702
6975
  const isTwoLine = Boolean(supportingText);
6976
+ const reducedMotion = useReducedMotion();
6703
6977
  const baseClassName = cn(snackbarBaseVariants({ twoLine: isTwoLine }), className);
6704
6978
  return /* @__PURE__ */ jsx(
6705
6979
  SnackbarHeadless,
@@ -6714,31 +6988,22 @@ var Snackbar = forwardRef(function Snackbar2({
6714
6988
  position,
6715
6989
  ...onClose !== void 0 && { onClose },
6716
6990
  className: baseClassName,
6717
- getAnimationClassName: (state, pos) => snackbarAnimationVariants({ animationState: state, enterDirection: getEnterDirection(pos) }),
6991
+ getAnimationClassName: (state, pos) => {
6992
+ if (reducedMotion) {
6993
+ return state === "visible" ? "opacity-100 duration-spring-standard-default-effects ease-spring-standard-default-effects" : "opacity-0";
6994
+ }
6995
+ return snackbarAnimationVariants({
6996
+ animationState: state,
6997
+ enterDirection: getEnterDirection(pos)
6998
+ });
6999
+ },
6718
7000
  children: ({ onClose: triggerClose }) => /* @__PURE__ */ jsxs(Fragment, { children: [
6719
7001
  /* @__PURE__ */ jsxs("div", { className: snackbarContentVariants(), children: [
6720
7002
  /* @__PURE__ */ jsx("span", { className: snackbarMessageVariants(), children: message }),
6721
7003
  supportingText && /* @__PURE__ */ jsx("span", { className: snackbarSupportingTextVariants(), children: supportingText })
6722
7004
  ] }),
6723
- action && /* @__PURE__ */ jsx("span", { className: snackbarActionVariants(), children: /* @__PURE__ */ jsx(
6724
- Button,
6725
- {
6726
- variant: "text",
6727
- onPress: action.onAction,
6728
- className: "text-inverse-primary hover:text-inverse-primary px-3",
6729
- children: action.label
6730
- }
6731
- ) }),
6732
- showClose && /* @__PURE__ */ jsx("span", { className: snackbarCloseVariants(), children: /* @__PURE__ */ jsx(
6733
- IconButton,
6734
- {
6735
- variant: "standard",
6736
- "aria-label": "Close",
6737
- onPress: triggerClose,
6738
- className: "text-inverse-on-surface hover:text-inverse-on-surface",
6739
- children: /* @__PURE__ */ jsx(CloseIcon, {})
6740
- }
6741
- ) })
7005
+ action && /* @__PURE__ */ jsx(SnackbarActionButton, { label: action.label, onAction: action.onAction }),
7006
+ showClose && /* @__PURE__ */ jsx(SnackbarCloseButton, { onPress: triggerClose })
6742
7007
  ] })
6743
7008
  }
6744
7009
  );
@@ -9362,105 +9627,354 @@ var Badge = forwardRef(
9362
9627
  }
9363
9628
  );
9364
9629
  Badge.displayName = "Badge";
9365
- var splitButtonContainerVariants = cva(
9366
- ["inline-flex items-center rounded-full overflow-hidden"],
9630
+ var splitButtonContainerVariants = cva([
9631
+ "relative inline-flex items-stretch",
9632
+ "gap-0.5"
9633
+ // MD3 2dp gap between segments
9634
+ ]);
9635
+ var splitButtonLeadingVariants = cva(
9636
+ [
9637
+ // Layout
9638
+ "group/sb-leading relative inline-flex items-center justify-center",
9639
+ "cursor-pointer select-none",
9640
+ // Shape — asymmetric corners via CSS variable
9641
+ "rounded-tl-full rounded-bl-full",
9642
+ "rounded-tr-[var(--sb-inner-radius,var(--radius-xs))]",
9643
+ "rounded-br-[var(--sb-inner-radius,var(--radius-xs))]",
9644
+ // Inner-corner morph — xs/sm/md defaults; lg/xl override in size variants below.
9645
+ // Specificity ladder: rest (0,0,0) < hover (0,1,0) < focus (0,2,0) < pressed (0,3,0)
9646
+ "[--sb-inner-radius:var(--radius-xs)]",
9647
+ "data-[hovered]:[--sb-inner-radius:var(--radius-sm)]",
9648
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-sm)]",
9649
+ // Pressed morphs stronger than hover/focus — tripled selector → (0,3,0)
9650
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-lg)]",
9651
+ // Spatial transition for border-radius morphing
9652
+ "transition-[border-radius]",
9653
+ "duration-expressive-fast-spatial ease-expressive-fast-spatial",
9654
+ // Disabled — self-targeting
9655
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none"
9656
+ ],
9367
9657
  {
9368
9658
  variants: {
9659
+ /**
9660
+ * Visual variant — controls container color, text color, and elevation.
9661
+ * State layer color is handled in splitButtonStateLayerVariants.
9662
+ */
9369
9663
  variant: {
9370
- filled: "bg-primary shadow-elevation-0 hover:shadow-elevation-1",
9371
- tonal: "bg-secondary-container",
9372
- outlined: "border border-outline bg-transparent"
9664
+ /**
9665
+ * Filled — highest emphasis.
9666
+ * container=primary, label=on-primary
9667
+ * Elevation: 0 base → 1 hover → 0 focus/pressed
9668
+ */
9669
+ filled: [
9670
+ "bg-primary text-on-primary shadow-none",
9671
+ "group-data-[hovered]/sb-leading:shadow-elevation-1",
9672
+ "group-data-[focus-visible]/sb-leading:shadow-none",
9673
+ "group-data-[pressed]/sb-leading:group-data-[pressed]/sb-leading:shadow-none",
9674
+ // Disabled
9675
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9676
+ ],
9677
+ /**
9678
+ * Tonal — secondary emphasis.
9679
+ * container=secondary-container, label=on-secondary-container
9680
+ * Elevation: 0 base → 1 hover → 0 focus/pressed
9681
+ */
9682
+ tonal: [
9683
+ "bg-secondary-container text-on-secondary-container shadow-none",
9684
+ "group-data-[hovered]/sb-leading:shadow-elevation-1",
9685
+ "group-data-[focus-visible]/sb-leading:shadow-none",
9686
+ "group-data-[pressed]/sb-leading:group-data-[pressed]/sb-leading:shadow-none",
9687
+ // Disabled
9688
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9689
+ ],
9690
+ /**
9691
+ * Outlined — medium emphasis. Transparent with border.
9692
+ * container=transparent, border=outline, label=primary
9693
+ * Elevation: always 0
9694
+ */
9695
+ outlined: [
9696
+ "bg-transparent border border-outline text-primary",
9697
+ // Disabled
9698
+ "data-[disabled]:border-on-surface/12 data-[disabled]:text-on-surface/38"
9699
+ ],
9700
+ /**
9701
+ * Elevated — uses surface-container-low with a level-1 shadow base.
9702
+ * container=surface-container-low, label=primary
9703
+ * Elevation: 1 base → 2 hover → 1 focus/pressed
9704
+ */
9705
+ elevated: [
9706
+ "bg-surface-container-low text-primary shadow-elevation-1",
9707
+ "group-data-[hovered]/sb-leading:shadow-elevation-2",
9708
+ "group-data-[focus-visible]/sb-leading:shadow-elevation-1",
9709
+ "group-data-[pressed]/sb-leading:group-data-[pressed]/sb-leading:shadow-elevation-1",
9710
+ // Disabled
9711
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9712
+ ]
9373
9713
  },
9714
+ /**
9715
+ * Size — governs height, horizontal padding, typography, and inner-corner rest/morph values.
9716
+ * lg/xl need larger rest radii so their morph steps differ from xs/sm/md.
9717
+ */
9374
9718
  size: {
9375
- small: "h-8",
9376
- medium: "h-10",
9377
- large: "h-12"
9378
- },
9379
- isDisabled: {
9380
- true: "opacity-38 pointer-events-none",
9381
- false: ""
9719
+ xs: "h-8 pl-4 pr-3 text-label-large",
9720
+ sm: "h-10 pl-6 pr-4 text-label-large",
9721
+ md: "h-14 pl-8 pr-6 text-title-medium",
9722
+ lg: [
9723
+ "h-24 pl-10 pr-8 text-headline-small",
9724
+ // lg rest=sm, hover/focus→lg, pressed→xl
9725
+ "[--sb-inner-radius:var(--radius-sm)]",
9726
+ "data-[hovered]:[--sb-inner-radius:var(--radius-lg)]",
9727
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-lg)]",
9728
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-xl)]"
9729
+ ],
9730
+ xl: [
9731
+ "h-[8.5rem] pl-12 pr-10 text-headline-large",
9732
+ // xl rest=md, hover/focus→lg, pressed→xl
9733
+ "[--sb-inner-radius:var(--radius-md)]",
9734
+ "data-[hovered]:[--sb-inner-radius:var(--radius-lg)]",
9735
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-lg)]",
9736
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-xl)]"
9737
+ ]
9382
9738
  }
9383
9739
  },
9384
9740
  defaultVariants: {
9385
9741
  variant: "filled",
9386
- size: "medium",
9387
- isDisabled: false
9742
+ size: "sm"
9388
9743
  }
9389
9744
  }
9390
9745
  );
9391
- var splitButtonPrimaryVariants = cva(
9746
+ var splitButtonTrailingVariants = cva(
9392
9747
  [
9393
- "group/primary relative inline-flex items-center justify-center cursor-pointer",
9394
- "h-full font-medium tracking-[0.1px]",
9395
- "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2"
9748
+ // Layout square so that selected (rounded-full on all corners) = perfect circle
9749
+ "group/sb-trailing relative inline-flex items-center justify-center shrink-0",
9750
+ "cursor-pointer select-none",
9751
+ // Shape — asymmetric corners, inner on the left side
9752
+ "rounded-tr-full rounded-br-full",
9753
+ "rounded-tl-[var(--sb-inner-radius,var(--radius-xs))]",
9754
+ "rounded-bl-[var(--sb-inner-radius,var(--radius-xs))]",
9755
+ // Inner-corner morph — xs/sm/md defaults; lg/xl override in size variants below.
9756
+ // Specificity ladder: rest (0,0,0) < hover (0,1,0) < focus (0,2,0) < pressed (0,3,0) < selected (0,4,0)
9757
+ "[--sb-inner-radius:var(--radius-xs)]",
9758
+ "data-[hovered]:[--sb-inner-radius:var(--radius-sm)]",
9759
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-sm)]",
9760
+ // Pressed morphs stronger than hover/focus — tripled → (0,3,0)
9761
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-lg)]",
9762
+ // Selected (menu open) → full circle; quadrupled → (0,4,0) always wins
9763
+ "data-[selected]:data-[selected]:data-[selected]:data-[selected]:[--sb-inner-radius:var(--radius-full)]",
9764
+ // Spatial transition for border-radius morphing
9765
+ "transition-[border-radius]",
9766
+ "duration-expressive-fast-spatial ease-expressive-fast-spatial",
9767
+ // Disabled — self-targeting
9768
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none"
9396
9769
  ],
9397
9770
  {
9398
9771
  variants: {
9399
9772
  variant: {
9400
- filled: "text-on-primary",
9401
- tonal: "text-on-secondary-container",
9402
- outlined: "text-primary"
9773
+ filled: [
9774
+ "bg-primary text-on-primary shadow-none",
9775
+ "group-data-[hovered]/sb-trailing:shadow-elevation-1",
9776
+ "group-data-[focus-visible]/sb-trailing:shadow-none",
9777
+ "group-data-[pressed]/sb-trailing:group-data-[pressed]/sb-trailing:shadow-none",
9778
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9779
+ ],
9780
+ tonal: [
9781
+ "bg-secondary-container text-on-secondary-container shadow-none",
9782
+ "group-data-[hovered]/sb-trailing:shadow-elevation-1",
9783
+ "group-data-[focus-visible]/sb-trailing:shadow-none",
9784
+ "group-data-[pressed]/sb-trailing:group-data-[pressed]/sb-trailing:shadow-none",
9785
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9786
+ ],
9787
+ outlined: [
9788
+ "bg-transparent border border-outline text-primary",
9789
+ "data-[disabled]:border-on-surface/12 data-[disabled]:text-on-surface/38"
9790
+ ],
9791
+ elevated: [
9792
+ "bg-surface-container-low text-primary shadow-elevation-1",
9793
+ "group-data-[hovered]/sb-trailing:shadow-elevation-2",
9794
+ "group-data-[focus-visible]/sb-trailing:shadow-elevation-1",
9795
+ "group-data-[pressed]/sb-trailing:group-data-[pressed]/sb-trailing:shadow-elevation-1",
9796
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38 data-[disabled]:shadow-none"
9797
+ ]
9403
9798
  },
9404
9799
  size: {
9405
- small: "pl-4 pr-3 text-xs",
9406
- medium: "pl-6 pr-4 text-sm",
9407
- large: "pl-8 pr-5 text-base"
9800
+ // Square dimensions (width = height) so selected state = perfect circle.
9801
+ // Per-size inner-radius rest/morph values mirror the leading segment.
9802
+ xs: "h-8 w-8",
9803
+ sm: "h-10 w-10",
9804
+ md: "h-14 w-14",
9805
+ lg: [
9806
+ "h-24 w-24",
9807
+ // lg rest=sm, hover/focus→lg, pressed→xl; selected→full handled in base classes
9808
+ "[--sb-inner-radius:var(--radius-sm)]",
9809
+ "data-[hovered]:[--sb-inner-radius:var(--radius-lg)]",
9810
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-lg)]",
9811
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-xl)]"
9812
+ ],
9813
+ xl: [
9814
+ "h-[8.5rem] w-[8.5rem]",
9815
+ // xl rest=md, hover/focus→lg, pressed→xl; selected→full handled in base classes
9816
+ "[--sb-inner-radius:var(--radius-md)]",
9817
+ "data-[hovered]:[--sb-inner-radius:var(--radius-lg)]",
9818
+ "data-[focus-visible]:data-[focus-visible]:[--sb-inner-radius:var(--radius-lg)]",
9819
+ "data-[pressed]:data-[pressed]:data-[pressed]:[--sb-inner-radius:var(--radius-xl)]"
9820
+ ]
9408
9821
  }
9409
9822
  },
9410
9823
  defaultVariants: {
9411
9824
  variant: "filled",
9412
- size: "medium"
9825
+ size: "sm"
9413
9826
  }
9414
9827
  }
9415
9828
  );
9416
- var splitButtonDropdownVariants = cva(
9829
+ var splitButtonStateLayerVariants = cva(
9417
9830
  [
9418
- "group/dropdown relative inline-flex items-center justify-center cursor-pointer",
9419
- "h-full",
9420
- "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2"
9831
+ "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
9832
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
9421
9833
  ],
9422
9834
  {
9423
9835
  variants: {
9424
9836
  variant: {
9425
- filled: "text-on-primary border-l border-on-primary/38",
9426
- tonal: "text-on-secondary-container border-l border-on-secondary-container/38",
9427
- outlined: "text-primary border-l border-outline"
9837
+ filled: "bg-on-primary",
9838
+ tonal: "bg-on-secondary-container",
9839
+ outlined: "bg-primary",
9840
+ elevated: "bg-primary"
9428
9841
  },
9429
- size: {
9430
- small: "px-1.5",
9431
- medium: "px-2",
9432
- large: "px-3"
9842
+ /**
9843
+ * groupScope identifies which segment this state layer belongs to so it
9844
+ * reads from the correct group-data-[x]/<scope> selectors.
9845
+ */
9846
+ groupScope: {
9847
+ leading: [
9848
+ "group-data-[hovered]/sb-leading:opacity-8",
9849
+ "group-data-[focus-visible]/sb-leading:opacity-10",
9850
+ "group-data-[pressed]/sb-leading:group-data-[pressed]/sb-leading:opacity-10",
9851
+ "group-data-[disabled]/sb-leading:hidden"
9852
+ ],
9853
+ trailing: [
9854
+ "group-data-[hovered]/sb-trailing:opacity-8",
9855
+ "group-data-[focus-visible]/sb-trailing:opacity-10",
9856
+ "group-data-[pressed]/sb-trailing:group-data-[pressed]/sb-trailing:opacity-10",
9857
+ "group-data-[disabled]/sb-trailing:hidden"
9858
+ ]
9433
9859
  }
9434
9860
  },
9435
9861
  defaultVariants: {
9436
9862
  variant: "filled",
9437
- size: "medium"
9863
+ groupScope: "leading"
9438
9864
  }
9439
9865
  }
9440
9866
  );
9867
+ var splitButtonFocusRingVariants = cva(
9868
+ [
9869
+ "pointer-events-none absolute inset-[-3px]",
9870
+ "outline outline-2 outline-offset-0 outline-secondary",
9871
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
9872
+ "opacity-0"
9873
+ ],
9874
+ {
9875
+ variants: {
9876
+ /**
9877
+ * Corner shape must match the segment it wraps.
9878
+ * Leading: full-left, inner-right follows --sb-inner-radius.
9879
+ * Trailing: full-right, inner-left follows --sb-inner-radius.
9880
+ */
9881
+ groupScope: {
9882
+ leading: [
9883
+ "rounded-tl-full rounded-bl-full",
9884
+ "rounded-tr-[calc(var(--sb-inner-radius,var(--radius-xs))+3px)]",
9885
+ "rounded-br-[calc(var(--sb-inner-radius,var(--radius-xs))+3px)]",
9886
+ "group-data-[focus-visible]/sb-leading:opacity-100"
9887
+ ],
9888
+ trailing: [
9889
+ "rounded-tr-full rounded-br-full",
9890
+ "rounded-tl-[calc(var(--sb-inner-radius,var(--radius-xs))+3px)]",
9891
+ "rounded-bl-[calc(var(--sb-inner-radius,var(--radius-xs))+3px)]",
9892
+ "group-data-[focus-visible]/sb-trailing:opacity-100"
9893
+ ]
9894
+ }
9895
+ },
9896
+ defaultVariants: { groupScope: "leading" }
9897
+ }
9898
+ );
9899
+ var splitButtonLabelVariants = cva(["relative z-10 inline-flex items-center"]);
9900
+ var splitButtonIconVariants = cva(
9901
+ [
9902
+ "relative z-10 inline-flex shrink-0 items-center justify-center",
9903
+ // Spatial spring motion for the optical-offset translate
9904
+ "transition-transform duration-spring-standard-fast-spatial ease-spring-standard-fast-spatial",
9905
+ // Reset offset when the trailing segment is in selected state (menu open)
9906
+ "group-data-[selected]/sb-trailing:translate-x-0"
9907
+ ],
9908
+ {
9909
+ variants: {
9910
+ size: {
9911
+ // Include per-size icon dimension + unselected optical offset
9912
+ xs: ["size-5", "-translate-x-px"],
9913
+ sm: ["size-5", "-translate-x-px"],
9914
+ md: ["size-6", "-translate-x-0.5"],
9915
+ lg: ["size-8", "-translate-x-[3px]"],
9916
+ xl: ["size-10", "-translate-x-[6px]"]
9917
+ }
9918
+ },
9919
+ defaultVariants: { size: "sm" }
9920
+ }
9921
+ );
9922
+ var splitButtonMenuVariants = cva([
9923
+ "absolute top-full right-0 z-50 mt-1 min-w-40",
9924
+ "bg-surface-container rounded-md py-2",
9925
+ "shadow-elevation-2",
9926
+ "animate-md-scale-in"
9927
+ ]);
9928
+ var splitButtonMenuItemVariants = cva(
9929
+ [
9930
+ "text-body-large text-on-surface cursor-pointer px-4 py-2",
9931
+ "hover:bg-on-surface/8",
9932
+ "focus:bg-on-surface/10 focus:outline-none"
9933
+ ],
9934
+ {
9935
+ variants: {
9936
+ isDisabled: {
9937
+ true: "text-on-surface/38 pointer-events-none cursor-not-allowed",
9938
+ false: ""
9939
+ }
9940
+ },
9941
+ defaultVariants: { isDisabled: false }
9942
+ }
9943
+ );
9441
9944
  var splitButtonVariants = {
9442
9945
  container: splitButtonContainerVariants,
9443
- primary: splitButtonPrimaryVariants,
9444
- dropdown: splitButtonDropdownVariants
9946
+ leading: splitButtonLeadingVariants,
9947
+ trailing: splitButtonTrailingVariants,
9948
+ stateLayer: splitButtonStateLayerVariants,
9949
+ focusRing: splitButtonFocusRingVariants,
9950
+ label: splitButtonLabelVariants,
9951
+ icon: splitButtonIconVariants,
9952
+ menu: splitButtonMenuVariants,
9953
+ menuItem: splitButtonMenuItemVariants
9445
9954
  };
9446
- var ChevronIcon = ({ isOpen }) => /* @__PURE__ */ jsx(
9955
+ var ChevronIcon = ({
9956
+ isOpen,
9957
+ reducedMotion
9958
+ }) => /* @__PURE__ */ jsx(
9447
9959
  "svg",
9448
9960
  {
9449
9961
  "aria-hidden": "true",
9450
9962
  "data-testid": "split-button-chevron",
9451
- width: "18",
9452
- height: "18",
9453
9963
  viewBox: "0 0 24 24",
9454
9964
  fill: "none",
9455
9965
  xmlns: "http://www.w3.org/2000/svg",
9456
- className: cn("duration-short4 ease-standard transition-transform", isOpen && "rotate-180"),
9966
+ className: cn(
9967
+ "size-full",
9968
+ !reducedMotion && "duration-expressive-fast-spatial ease-expressive-fast-spatial transition-transform",
9969
+ isOpen && "rotate-180"
9970
+ ),
9457
9971
  children: /* @__PURE__ */ jsx("path", { d: "M7 10l5 5 5-5H7z", fill: "currentColor" })
9458
9972
  }
9459
9973
  );
9460
9974
  var SplitButton = forwardRef(
9461
9975
  ({
9462
9976
  variant = "filled",
9463
- size = "medium",
9977
+ size = "sm",
9464
9978
  primaryLabel,
9465
9979
  onPrimaryAction,
9466
9980
  items,
@@ -9468,32 +9982,73 @@ var SplitButton = forwardRef(
9468
9982
  "aria-label": ariaLabel,
9469
9983
  className
9470
9984
  }, forwardedRef) => {
9471
- const primaryRef = useRef(null);
9472
- const dropdownRef = useRef(null);
9985
+ const leadingRef = useRef(null);
9986
+ const trailingRef = useRef(null);
9473
9987
  const menuRef = useRef(null);
9988
+ const reducedMotion = useReducedMotion();
9474
9989
  const menuState = useMenuTriggerState({});
9475
- const { buttonProps: primaryButtonProps } = useButton(
9990
+ const [isLeadingPressed, setIsLeadingPressed] = useState(false);
9991
+ const handleLeadingPressStart = useCallback(() => setIsLeadingPressed(true), []);
9992
+ const handleLeadingPressEnd = useCallback(() => setIsLeadingPressed(false), []);
9993
+ const { isHovered: isLeadingHovered, hoverProps: leadingHoverProps } = useHover({
9994
+ isDisabled
9995
+ });
9996
+ const { isFocusVisible: isLeadingFocusVisible, focusProps: leadingFocusProps } = useFocusRing();
9997
+ const { buttonProps: leadingButtonProps } = useButton(
9476
9998
  {
9477
9999
  isDisabled,
9478
10000
  onPress: onPrimaryAction,
10001
+ onPressStart: handleLeadingPressStart,
10002
+ onPressEnd: handleLeadingPressEnd,
9479
10003
  elementType: "button"
9480
10004
  },
9481
- primaryRef
10005
+ leadingRef
9482
10006
  );
9483
- const handleDropdownPress = useCallback(() => {
10007
+ const [isTrailingPressed, setIsTrailingPressed] = useState(false);
10008
+ const handleTrailingPressStart = useCallback(() => setIsTrailingPressed(true), []);
10009
+ const handleTrailingPressEnd = useCallback(() => setIsTrailingPressed(false), []);
10010
+ const { isHovered: isTrailingHovered, hoverProps: trailingHoverProps } = useHover({
10011
+ isDisabled
10012
+ });
10013
+ const { isFocusVisible: isTrailingFocusVisible, focusProps: trailingFocusProps } = useFocusRing();
10014
+ const handleTrailingPress = useCallback(() => {
9484
10015
  if (menuState.isOpen) {
9485
10016
  menuState.close();
9486
10017
  } else {
9487
10018
  menuState.open();
9488
10019
  }
9489
10020
  }, [menuState]);
9490
- const { buttonProps: dropdownButtonProps } = useButton(
10021
+ const { buttonProps: trailingButtonProps } = useButton(
9491
10022
  {
9492
10023
  isDisabled,
9493
- onPress: handleDropdownPress,
10024
+ onPress: handleTrailingPress,
10025
+ onPressStart: handleTrailingPressStart,
10026
+ onPressEnd: handleTrailingPressEnd,
9494
10027
  elementType: "button"
9495
10028
  },
9496
- dropdownRef
10029
+ trailingRef
10030
+ );
10031
+ const { onMouseDown: handleLeadingRipple, ripples: leadingRipples } = useRipple({
10032
+ disabled: isDisabled
10033
+ });
10034
+ const { onMouseDown: handleTrailingRipple, ripples: trailingRipples } = useRipple({
10035
+ disabled: isDisabled
10036
+ });
10037
+ const onLeadingMouseDown = useCallback(
10038
+ (e) => {
10039
+ const ariaHandler = leadingButtonProps.onMouseDown;
10040
+ ariaHandler?.(e);
10041
+ handleLeadingRipple(e);
10042
+ },
10043
+ [leadingButtonProps, handleLeadingRipple]
10044
+ );
10045
+ const onTrailingMouseDown = useCallback(
10046
+ (e) => {
10047
+ const ariaHandler = trailingButtonProps.onMouseDown;
10048
+ ariaHandler?.(e);
10049
+ handleTrailingRipple(e);
10050
+ },
10051
+ [trailingButtonProps, handleTrailingRipple]
9497
10052
  );
9498
10053
  const handleMenuItemSelect = useCallback(
9499
10054
  (item) => {
@@ -9509,13 +10064,11 @@ var SplitButton = forwardRef(
9509
10064
  const handleGlobalKeyDown = (e) => {
9510
10065
  if (e.key === "Escape") {
9511
10066
  menuState.close();
9512
- dropdownRef.current?.focus();
10067
+ trailingRef.current?.focus();
9513
10068
  }
9514
10069
  };
9515
10070
  document.addEventListener("keydown", handleGlobalKeyDown);
9516
- return () => {
9517
- document.removeEventListener("keydown", handleGlobalKeyDown);
9518
- };
10071
+ return () => document.removeEventListener("keydown", handleGlobalKeyDown);
9519
10072
  }, [menuState, menuState.isOpen]);
9520
10073
  const handleMenuKeyDown = useCallback(
9521
10074
  (e) => {
@@ -9548,7 +10101,7 @@ var SplitButton = forwardRef(
9548
10101
  }
9549
10102
  case "Escape": {
9550
10103
  menuState.close();
9551
- dropdownRef.current?.focus();
10104
+ trailingRef.current?.focus();
9552
10105
  break;
9553
10106
  }
9554
10107
  }
@@ -9573,28 +10126,6 @@ var SplitButton = forwardRef(
9573
10126
  },
9574
10127
  [menuState]
9575
10128
  );
9576
- const { onMouseDown: handlePrimaryRipple, ripples: primaryRipples } = useRipple({
9577
- disabled: isDisabled
9578
- });
9579
- const { onMouseDown: handleDropdownRipple, ripples: dropdownRipples } = useRipple({
9580
- disabled: isDisabled
9581
- });
9582
- const onPrimaryMouseDown = useCallback(
9583
- (e) => {
9584
- const ariaHandler = primaryButtonProps.onMouseDown;
9585
- ariaHandler?.(e);
9586
- handlePrimaryRipple(e);
9587
- },
9588
- [primaryButtonProps, handlePrimaryRipple]
9589
- );
9590
- const onDropdownMouseDown = useCallback(
9591
- (e) => {
9592
- const ariaHandler = dropdownButtonProps.onMouseDown;
9593
- ariaHandler?.(e);
9594
- handleDropdownRipple(e);
9595
- },
9596
- [dropdownButtonProps, handleDropdownRipple]
9597
- );
9598
10129
  return /* @__PURE__ */ jsxs("div", { className: "relative inline-flex", children: [
9599
10130
  /* @__PURE__ */ jsxs(
9600
10131
  "div",
@@ -9602,63 +10133,81 @@ var SplitButton = forwardRef(
9602
10133
  ref: forwardedRef,
9603
10134
  role: "group",
9604
10135
  "aria-label": ariaLabel ?? `${primaryLabel} split button`,
9605
- className: cn(splitButtonContainerVariants({ variant, size, isDisabled }), className),
10136
+ className: cn(splitButtonContainerVariants(), className),
9606
10137
  children: [
9607
10138
  /* @__PURE__ */ jsxs(
9608
10139
  "button",
9609
10140
  {
9610
- ...primaryButtonProps,
9611
- ref: primaryRef,
10141
+ ...mergeProps$1(leadingButtonProps, leadingHoverProps, leadingFocusProps),
10142
+ ref: leadingRef,
9612
10143
  type: "button",
9613
10144
  tabIndex: isDisabled ? -1 : 0,
9614
- onMouseDown: onPrimaryMouseDown,
9615
- className: splitButtonPrimaryVariants({ variant, size }),
10145
+ onMouseDown: onLeadingMouseDown,
10146
+ ...getInteractionDataAttributes({
10147
+ isHovered: isLeadingHovered,
10148
+ isFocusVisible: isLeadingFocusVisible,
10149
+ isPressed: isLeadingPressed,
10150
+ isDisabled
10151
+ }),
10152
+ className: splitButtonLeadingVariants({ variant, size }),
9616
10153
  children: [
9617
10154
  /* @__PURE__ */ jsx(
9618
10155
  "span",
9619
10156
  {
9620
10157
  "data-testid": "primary-state-layer",
9621
10158
  "aria-hidden": "true",
9622
- className: cn(
9623
- "pointer-events-none absolute inset-0 bg-current opacity-0",
9624
- "duration-spring-standard-fast-effects ease-spring-standard-fast-effects transition-opacity",
9625
- "group-hover/primary:opacity-8"
9626
- )
10159
+ className: splitButtonStateLayerVariants({ variant, groupScope: "leading" })
9627
10160
  }
9628
10161
  ),
9629
- primaryRipples,
9630
- /* @__PURE__ */ jsx("span", { className: "relative z-10", children: primaryLabel })
10162
+ leadingRipples,
10163
+ /* @__PURE__ */ jsx(
10164
+ "span",
10165
+ {
10166
+ "aria-hidden": "true",
10167
+ className: splitButtonFocusRingVariants({ groupScope: "leading" })
10168
+ }
10169
+ ),
10170
+ /* @__PURE__ */ jsx("span", { className: splitButtonLabelVariants(), children: primaryLabel })
9631
10171
  ]
9632
10172
  }
9633
10173
  ),
9634
- /* @__PURE__ */ jsx("span", { "data-testid": "split-button-divider", "aria-hidden": "true" }),
9635
10174
  /* @__PURE__ */ jsxs(
9636
10175
  "button",
9637
10176
  {
9638
- ...dropdownButtonProps,
9639
- ref: dropdownRef,
10177
+ ...mergeProps$1(trailingButtonProps, trailingHoverProps, trailingFocusProps),
10178
+ ref: trailingRef,
9640
10179
  type: "button",
9641
10180
  tabIndex: isDisabled ? -1 : 0,
9642
10181
  "aria-haspopup": "menu",
9643
10182
  "aria-expanded": menuState.isOpen,
9644
10183
  "aria-label": `${primaryLabel} options, expand`,
9645
- onMouseDown: onDropdownMouseDown,
9646
- className: splitButtonDropdownVariants({ variant, size }),
10184
+ onMouseDown: onTrailingMouseDown,
10185
+ ...getInteractionDataAttributes({
10186
+ isHovered: isTrailingHovered,
10187
+ isFocusVisible: isTrailingFocusVisible,
10188
+ isPressed: isTrailingPressed,
10189
+ isSelected: menuState.isOpen,
10190
+ isDisabled
10191
+ }),
10192
+ className: splitButtonTrailingVariants({ variant, size }),
9647
10193
  children: [
9648
10194
  /* @__PURE__ */ jsx(
9649
10195
  "span",
9650
10196
  {
9651
10197
  "data-testid": "dropdown-state-layer",
9652
10198
  "aria-hidden": "true",
9653
- className: cn(
9654
- "pointer-events-none absolute inset-0 bg-current opacity-0",
9655
- "duration-spring-standard-fast-effects ease-spring-standard-fast-effects transition-opacity",
9656
- "group-hover/dropdown:opacity-8"
9657
- )
10199
+ className: splitButtonStateLayerVariants({ variant, groupScope: "trailing" })
9658
10200
  }
9659
10201
  ),
9660
- dropdownRipples,
9661
- /* @__PURE__ */ jsx("span", { className: "relative z-10", children: /* @__PURE__ */ jsx(ChevronIcon, { isOpen: menuState.isOpen }) })
10202
+ trailingRipples,
10203
+ /* @__PURE__ */ jsx(
10204
+ "span",
10205
+ {
10206
+ "aria-hidden": "true",
10207
+ className: splitButtonFocusRingVariants({ groupScope: "trailing" })
10208
+ }
10209
+ ),
10210
+ /* @__PURE__ */ jsx("span", { className: splitButtonIconVariants({ size }), children: /* @__PURE__ */ jsx(ChevronIcon, { isOpen: menuState.isOpen, reducedMotion }) })
9662
10211
  ]
9663
10212
  }
9664
10213
  )
@@ -9672,10 +10221,7 @@ var SplitButton = forwardRef(
9672
10221
  role: "menu",
9673
10222
  "aria-label": `${primaryLabel} options`,
9674
10223
  onKeyDown: handleMenuKeyDown,
9675
- className: cn(
9676
- "bg-surface-container absolute top-full right-0 z-50 mt-1 min-w-40 rounded-md py-2",
9677
- "shadow-elevation-2"
9678
- ),
10224
+ className: splitButtonMenuVariants(),
9679
10225
  children: items.map((item) => /* @__PURE__ */ jsx(
9680
10226
  "li",
9681
10227
  {
@@ -9684,11 +10230,7 @@ var SplitButton = forwardRef(
9684
10230
  "aria-disabled": item.isDisabled ?? void 0,
9685
10231
  onClick: () => handleMenuItemSelect(item),
9686
10232
  onKeyDown: (e) => handleMenuItemKeyDown(e, item),
9687
- className: cn(
9688
- "text-body-large text-on-surface cursor-pointer px-4 py-2",
9689
- "hover:bg-on-surface/8",
9690
- item.isDisabled && "text-on-surface/38 pointer-events-none"
9691
- ),
10233
+ className: splitButtonMenuItemVariants({ isDisabled: item.isDisabled ?? false }),
9692
10234
  children: item.label
9693
10235
  },
9694
10236
  item.label
@@ -9708,32 +10250,32 @@ var SplitButtonHeadless = forwardRef(
9708
10250
  "aria-label": ariaLabel,
9709
10251
  className
9710
10252
  }, forwardedRef) => {
9711
- const primaryRef = useRef(null);
9712
- const dropdownRef = useRef(null);
10253
+ const leadingRef = useRef(null);
10254
+ const trailingRef = useRef(null);
9713
10255
  const menuRef = useRef(null);
9714
10256
  const menuState = useMenuTriggerState({});
9715
- const { buttonProps: primaryButtonProps } = useButton(
10257
+ const { buttonProps: leadingButtonProps } = useButton(
9716
10258
  {
9717
10259
  isDisabled,
9718
10260
  onPress: onPrimaryAction,
9719
10261
  elementType: "button"
9720
10262
  },
9721
- primaryRef
10263
+ leadingRef
9722
10264
  );
9723
- const handleDropdownPress = useCallback(() => {
10265
+ const handleTrailingPress = useCallback(() => {
9724
10266
  if (menuState.isOpen) {
9725
10267
  menuState.close();
9726
10268
  } else {
9727
10269
  menuState.open();
9728
10270
  }
9729
10271
  }, [menuState]);
9730
- const { buttonProps: dropdownButtonProps } = useButton(
10272
+ const { buttonProps: trailingButtonProps } = useButton(
9731
10273
  {
9732
10274
  isDisabled,
9733
- onPress: handleDropdownPress,
10275
+ onPress: handleTrailingPress,
9734
10276
  elementType: "button"
9735
10277
  },
9736
- dropdownRef
10278
+ trailingRef
9737
10279
  );
9738
10280
  const handleMenuItemSelect = useCallback(
9739
10281
  (item) => {
@@ -9749,13 +10291,11 @@ var SplitButtonHeadless = forwardRef(
9749
10291
  const handleGlobalKeyDown = (e) => {
9750
10292
  if (e.key === "Escape") {
9751
10293
  menuState.close();
9752
- dropdownRef.current?.focus();
10294
+ trailingRef.current?.focus();
9753
10295
  }
9754
10296
  };
9755
10297
  document.addEventListener("keydown", handleGlobalKeyDown);
9756
- return () => {
9757
- document.removeEventListener("keydown", handleGlobalKeyDown);
9758
- };
10298
+ return () => document.removeEventListener("keydown", handleGlobalKeyDown);
9759
10299
  }, [menuState, menuState.isOpen]);
9760
10300
  const handleMenuKeyDown = useCallback(
9761
10301
  (e) => {
@@ -9788,7 +10328,7 @@ var SplitButtonHeadless = forwardRef(
9788
10328
  }
9789
10329
  case "Escape": {
9790
10330
  menuState.close();
9791
- dropdownRef.current?.focus();
10331
+ trailingRef.current?.focus();
9792
10332
  break;
9793
10333
  }
9794
10334
  }
@@ -9824,19 +10364,18 @@ var SplitButtonHeadless = forwardRef(
9824
10364
  /* @__PURE__ */ jsx(
9825
10365
  "button",
9826
10366
  {
9827
- ...primaryButtonProps,
9828
- ref: primaryRef,
10367
+ ...leadingButtonProps,
10368
+ ref: leadingRef,
9829
10369
  type: "button",
9830
10370
  tabIndex: isDisabled ? -1 : 0,
9831
10371
  children: primaryLabel
9832
10372
  }
9833
10373
  ),
9834
- /* @__PURE__ */ jsx("span", { "aria-hidden": "true" }),
9835
10374
  /* @__PURE__ */ jsx(
9836
10375
  "button",
9837
10376
  {
9838
- ...dropdownButtonProps,
9839
- ref: dropdownRef,
10377
+ ...trailingButtonProps,
10378
+ ref: trailingRef,
9840
10379
  type: "button",
9841
10380
  tabIndex: isDisabled ? -1 : 0,
9842
10381
  "aria-haspopup": "menu",
@@ -15877,6 +16416,6 @@ var DateField = forwardRef((props, forwardedRef) => {
15877
16416
  });
15878
16417
  DateField.displayName = "DateField";
15879
16418
 
15880
- export { AppBar, AppBarHeadless, Badge, BadgeContent, BadgeHeadless, BottomSheet, BottomSheetContext, BottomSheetHandle, BottomSheetHeadless, Button, ButtonGroup, ButtonGroupContext, ButtonGroupHeadless, CalendarCore, Card, CardActions, CardContent, CardHeader, CardHeadless, CardMedia, Checkbox, Chip, ChipHeadless, ChipSet, DateField, DatePicker, DatePickerDocked, DatePickerModal, DatePickerModalInput, Dialog, DialogActions, DialogContent, DialogContext, DialogHeadless, DialogHeadline, Divider, DividerHeadless, Drawer, DrawerIconOnlyContext, DrawerItem, DrawerSection, FAB, FABHeadless, FABMenu, FABMenuContext, FABMenuHeadless, FABMenuItem, HeadlessDrawer, HeadlessDrawerItem, HeadlessMenu, HeadlessMenuDivider, HeadlessMenuItem, HeadlessMenuSection, HeadlessMenuTrigger, HeadlessNavigationBar, HeadlessNavigationBarItem, HeadlessTab, HeadlessTabList, HeadlessTabPanel, IconButton, IconButtonHeadless, List, ListHeadless, ListItem, ListItemHeadless, ListItemLeading, ListItemText, ListItemTrailing, Menu, MenuContext, MenuDivider, MenuItem, MenuSection, MenuTrigger, NavigationBar, NavigationBarItem, Progress, ProgressHeadless, Radio, RadioGroup, RadioGroupHeadless, RadioHeadless, RichTooltip, STATE_LAYER_OPACITY, Search, SearchBar, SearchBarHeadless, SearchView, SearchViewHeadless, Slider, SliderHeadless, Snackbar, SnackbarContext, SnackbarHeadless, SnackbarProvider, SplitButton, SplitButtonHeadless, StyledActionButton, StyledCalendarCell, StyledCalendarTitle, StyledNavButton, StyledWeekday, StyledYearItem, Switch, TYPOGRAPHY_ELEMENT_MAP, TYPOGRAPHY_USAGE, Tab, TabList, TabPanel, Tabs, TextField, TimePicker, TimePickerDial, TimePickerInput, Tooltip, TooltipOverlayHeadless, TooltipTrigger, TooltipTriggerHeadless, actionButtonFocusRingVariants, actionButtonStateLayerVariants, actionButtonVariants, actionRowVariants, applyStateLayer, badgeVariants2 as badgeVariants, bottomSheetAnimationVariants, bottomSheetHandlePillVariants, bottomSheetHandleWrapperVariants, bottomSheetScrimVariants, bottomSheetVariants, buttonGroupFocusRingVariants, buttonGroupRootVariants, buttonGroupVariants, calendarCellFocusRingVariants, calendarCellStateLayerVariants, calendarCellVariants, calendarDividerVariants, calendarHeaderVariants, calendarTitleIconVariants, calendarTitleStateLayerVariants, calendarTitleTextVariants, calendarTitleVariants, cardVariants, chipVariants, clockDialContainerVariants, clockDialNumberVariants, clockHandCenterVariants, clockHandHandleVariants, clockHandTrackVariants, cn, dateFieldVariants, dateInputErrorVariants, dateInputFieldGroupVariants, dateInputFieldVariants, dateInputLabelVariants, datePickerContainerVariants, dateSegmentPlaceholderVariants, dividerVariants, dockedFieldGroupVariants, dockedLabelVariants, dockedTriggerStateLayerVariants, dockedTriggerVariants, fabMenuItemFocusRingVariants, fabMenuItemIconVariants, fabMenuItemLabelVariants, fabMenuItemStateLayerVariants, fabMenuItemVariants, fabMenuListVariants, fabMenuVariants, generateMD3Theme, getColorValue, getConnectedRadiusClasses, getFontFamily, getMD3Color, getResponsiveTypography, getTypographyClassName, getTypographyForElement, getTypographyStyle, getTypographyToken, headlineVariants, hexToRgb, listItemVariants, listVariants, modalDialogVariants, modalHeaderVariants, modeToggleStateLayerVariants, modeToggleVariants, navButtonFocusRingVariants, navButtonStateLayerVariants, navButtonVariants, periodSelectorContainerVariants, periodSelectorItemVariants, popoverVariants, pxToRem, remToPx, rgbToHex, richTooltipVariants, scrimVariants2 as scrimVariants, searchBarAvatarVariants, searchBarFocusRingVariants, searchBarInputVariants, searchBarLeadingIconVariants, searchBarRootVariants, searchBarStateLayerVariants, searchBarTrailingActionVariants, searchBarTrailingActionsVariants, searchViewBackButtonVariants, searchViewClearButtonVariants, searchViewContentVariants, searchViewDividerVariants, searchViewHeaderVariants, searchViewInputVariants, searchViewTrailingActionVariants, searchViewTrailingActionsVariants, searchViewVariants, sliderActiveTrackVariants, sliderContainerVariants, sliderHandleStateLayerVariants, sliderHandleVariants, sliderInactiveTrackVariants, sliderTrackLayoutVariants, splitButtonContainerVariants, splitButtonDropdownVariants, splitButtonPrimaryVariants, splitButtonVariants, supportingTextVariants, timeInputFieldVariants, timePickerActionButtonVariants, timePickerActionRowVariants, timePickerContainerVariants, timePickerHeadlineVariants, timePickerModeToggleVariants, timeSelectorContainerVariants, timeSeparatorVariants, tooltipVariants, truncateText, useBottomSheetContext, useBottomSheetDrag, useButtonGroup, useDialogContext, useFABMenuContext, useMenuContext, useOptionalButtonGroup, useSnackbar, weekdayVariants, withOpacity, yearGridVariants, yearItemFocusRingVariants, yearItemStateLayerVariants, yearItemVariants };
16419
+ export { AppBar, AppBarHeadless, Badge, BadgeContent, BadgeHeadless, BottomSheet, BottomSheetContext, BottomSheetHandle, BottomSheetHeadless, Button, ButtonGroup, ButtonGroupContext, ButtonGroupHeadless, CalendarCore, Card, CardActions, CardContent, CardHeader, CardHeadless, CardMedia, Checkbox, Chip, ChipHeadless, ChipSet, DateField, DatePicker, DatePickerDocked, DatePickerModal, DatePickerModalInput, Dialog, DialogActions, DialogContent, DialogContext, DialogHeadless, DialogHeadline, Divider, DividerHeadless, Drawer, DrawerIconOnlyContext, DrawerItem, DrawerSection, FAB, FABHeadless, FABMenu, FABMenuContext, FABMenuHeadless, FABMenuItem, HeadlessDrawer, HeadlessDrawerItem, HeadlessMenu, HeadlessMenuDivider, HeadlessMenuItem, HeadlessMenuSection, HeadlessMenuTrigger, HeadlessNavigationBar, HeadlessNavigationBarItem, HeadlessTab, HeadlessTabList, HeadlessTabPanel, IconButton, IconButtonHeadless, List, ListHeadless, ListItem, ListItemHeadless, ListItemLeading, ListItemText, ListItemTrailing, Menu, MenuContext, MenuDivider, MenuItem, MenuSection, MenuTrigger, NavigationBar, NavigationBarItem, Progress, ProgressHeadless, Radio, RadioGroup, RadioGroupHeadless, RadioHeadless, RichTooltip, STATE_LAYER_OPACITY, Search, SearchBar, SearchBarHeadless, SearchView, SearchViewHeadless, Slider, SliderHeadless, Snackbar, SnackbarContext, SnackbarHeadless, SnackbarProvider, SplitButton, SplitButtonHeadless, StyledActionButton, StyledCalendarCell, StyledCalendarTitle, StyledNavButton, StyledWeekday, StyledYearItem, Switch, TYPOGRAPHY_ELEMENT_MAP, TYPOGRAPHY_USAGE, Tab, TabList, TabPanel, Tabs, TextField, TimePicker, TimePickerDial, TimePickerInput, Tooltip, TooltipOverlayHeadless, TooltipTrigger, TooltipTriggerHeadless, actionButtonFocusRingVariants, actionButtonStateLayerVariants, actionButtonVariants, actionRowVariants, applyStateLayer, badgeVariants2 as badgeVariants, bottomSheetAnimationVariants, bottomSheetHandlePillVariants, bottomSheetHandleWrapperVariants, bottomSheetScrimVariants, bottomSheetVariants, buttonGroupFocusRingVariants, buttonGroupRootVariants, buttonGroupVariants, calendarCellFocusRingVariants, calendarCellStateLayerVariants, calendarCellVariants, calendarDividerVariants, calendarHeaderVariants, calendarTitleIconVariants, calendarTitleStateLayerVariants, calendarTitleTextVariants, calendarTitleVariants, cardVariants, chipVariants, clockDialContainerVariants, clockDialNumberVariants, clockHandCenterVariants, clockHandHandleVariants, clockHandTrackVariants, cn, dateFieldVariants, dateInputErrorVariants, dateInputFieldGroupVariants, dateInputFieldVariants, dateInputLabelVariants, datePickerContainerVariants, dateSegmentPlaceholderVariants, dividerVariants, dockedFieldGroupVariants, dockedLabelVariants, dockedTriggerStateLayerVariants, dockedTriggerVariants, fabMenuItemFocusRingVariants, fabMenuItemIconVariants, fabMenuItemLabelVariants, fabMenuItemStateLayerVariants, fabMenuItemVariants, fabMenuListVariants, fabMenuVariants, generateMD3Theme, getColorValue, getConnectedRadiusClasses, getFontFamily, getMD3Color, getResponsiveTypography, getTypographyClassName, getTypographyForElement, getTypographyStyle, getTypographyToken, headlineVariants, hexToRgb, listItemVariants, listVariants, modalDialogVariants, modalHeaderVariants, modeToggleStateLayerVariants, modeToggleVariants, navButtonFocusRingVariants, navButtonStateLayerVariants, navButtonVariants, periodSelectorContainerVariants, periodSelectorItemVariants, popoverVariants, pxToRem, remToPx, rgbToHex, richTooltipVariants, scrimVariants2 as scrimVariants, searchBarAvatarVariants, searchBarFocusRingVariants, searchBarInputVariants, searchBarLeadingIconVariants, searchBarRootVariants, searchBarStateLayerVariants, searchBarTrailingActionVariants, searchBarTrailingActionsVariants, searchViewBackButtonVariants, searchViewClearButtonVariants, searchViewContentVariants, searchViewDividerVariants, searchViewHeaderVariants, searchViewInputVariants, searchViewTrailingActionVariants, searchViewTrailingActionsVariants, searchViewVariants, sliderActiveTrackVariants, sliderContainerVariants, sliderHandleStateLayerVariants, sliderHandleVariants, sliderInactiveTrackVariants, sliderTrackLayoutVariants, splitButtonContainerVariants, splitButtonFocusRingVariants, splitButtonIconVariants, splitButtonLabelVariants, splitButtonLeadingVariants, splitButtonMenuItemVariants, splitButtonMenuVariants, splitButtonStateLayerVariants, splitButtonTrailingVariants, splitButtonVariants, supportingTextVariants, timeInputFieldVariants, timePickerActionButtonVariants, timePickerActionRowVariants, timePickerContainerVariants, timePickerHeadlineVariants, timePickerModeToggleVariants, timeSelectorContainerVariants, timeSeparatorVariants, tooltipVariants, truncateText, useBottomSheetContext, useBottomSheetDrag, useButtonGroup, useDialogContext, useFABMenuContext, useMenuContext, useOptionalButtonGroup, useSnackbar, weekdayVariants, withOpacity, yearGridVariants, yearItemFocusRingVariants, yearItemStateLayerVariants, yearItemVariants };
15881
16420
  //# sourceMappingURL=index.js.map
15882
16421
  //# sourceMappingURL=index.js.map