@tinybigui/react 0.6.0 → 0.8.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
@@ -5065,106 +5065,48 @@ var Drawer = forwardRef(
5065
5065
  }
5066
5066
  );
5067
5067
  Drawer.displayName = "Drawer";
5068
- var BadgeHeadless = forwardRef(
5069
- ({ className, children, ...props }, ref) => {
5070
- return /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-flex", className), ...props, children });
5071
- }
5072
- );
5073
- BadgeHeadless.displayName = "BadgeHeadless";
5074
- var badgeVariants2 = cva(
5075
- ["absolute -top-1 -right-1 rounded-full flex items-center justify-center"],
5076
- {
5077
- variants: {
5078
- size: {
5079
- small: "size-1.5",
5080
- large: "min-w-4 h-4 px-1 text-label-small"
5081
- },
5082
- color: {
5083
- error: "bg-error text-on-error",
5084
- primary: "bg-primary text-on-primary"
5085
- },
5086
- invisible: {
5087
- true: "scale-0 opacity-0",
5088
- false: "scale-100 opacity-100"
5089
- },
5090
- reducedMotion: {
5091
- true: "",
5092
- false: "transition-[transform,opacity] duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
5093
- }
5094
- },
5095
- defaultVariants: {
5096
- size: "large",
5097
- color: "error",
5098
- invisible: false,
5099
- reducedMotion: false
5100
- }
5101
- }
5102
- );
5103
- var getDisplayValue = (count, max) => {
5068
+ var badgeAppearance = [
5069
+ // ── Shape ─────────────────────────────────────────────────────────────────────
5070
+ "flex items-center justify-center",
5071
+ "rounded-full",
5072
+ // ── Large (count) sizing — base defaults ──────────────────────────────────────
5073
+ // Height 16dp, min-width 16dp, horizontal padding 4dp
5074
+ "h-4 min-w-4 px-1",
5075
+ // ── Color error role (only MD3-spec role for badges) ────────────────────────
5076
+ "bg-error text-on-error",
5077
+ // ── Typography — label-small, tight leading, tabular numbers ──────────────────
5078
+ "text-label-small leading-none tabular-nums",
5079
+ // ── Visibility (runtime flag) ──────────────────────────────────────────────────
5080
+ // Base: fully visible
5081
+ "scale-100",
5082
+ // data-invisible: scale to zero (visually hidden; aria-label still readable by SR)
5083
+ "data-[invisible]:scale-0",
5084
+ // ── Dot content flag overrides (placed last — cascade wins over base sizing) ───
5085
+ // Clear out the count-pill sizing, set 6dp circle
5086
+ "data-[dot]:size-1.5",
5087
+ "data-[dot]:min-w-0",
5088
+ "data-[dot]:p-0",
5089
+ "data-[dot]:text-[0]"
5090
+ // suppress any stray text rendering on dot
5091
+ ];
5092
+ var badgeVariants2 = cva([
5093
+ // ── Anchored placement — badge center on host's top-right corner ──────────────
5094
+ // top-0 right-0 places the badge's own top-right at the host's top-right,
5095
+ // then the 1/2-element translate moves the badge center onto that corner.
5096
+ // Host-size-agnostic: works for any wrapped element (icon, avatar, nav chip).
5097
+ "absolute top-0 right-0 -translate-y-1/2 translate-x-1/2",
5098
+ ...badgeAppearance
5099
+ ]);
5100
+ var badgeStaticVariants = cva(["inline-flex", ...badgeAppearance]);
5101
+ function isBadgeConfig(badge) {
5102
+ return typeof badge === "object" && badge !== null && !isValidElement(badge) && "count" in badge;
5103
+ }
5104
+ function getBadgeDisplayValue(count, max) {
5104
5105
  if (count === void 0) return "";
5105
5106
  return count > max ? `${max}+` : count.toString();
5106
- };
5107
- var getAriaLabel = (count, override) => {
5108
- if (override) return override;
5107
+ }
5108
+ function getBadgeAriaLabel(count) {
5109
5109
  return count === void 0 ? "New" : `${count} notifications`;
5110
- };
5111
- var BadgeContent = forwardRef(
5112
- ({
5113
- count,
5114
- max = 999,
5115
- color = "error",
5116
- invisible = false,
5117
- "aria-label": ariaLabelOverride,
5118
- reducedMotion = false,
5119
- className
5120
- }, ref) => {
5121
- const size = count === void 0 ? "small" : "large";
5122
- const displayValue = getDisplayValue(count, max);
5123
- const ariaLabel = getAriaLabel(count, ariaLabelOverride);
5124
- return /* @__PURE__ */ jsx(
5125
- "span",
5126
- {
5127
- ref,
5128
- role: "status",
5129
- "aria-label": ariaLabel,
5130
- className: cn(badgeVariants2({ size, color, invisible, reducedMotion }), className),
5131
- children: displayValue
5132
- }
5133
- );
5134
- }
5135
- );
5136
- BadgeContent.displayName = "BadgeContent";
5137
- var Badge = forwardRef(
5138
- ({
5139
- count,
5140
- max = 999,
5141
- color = "error",
5142
- invisible = false,
5143
- "aria-label": ariaLabel,
5144
- className,
5145
- children
5146
- }, ref) => {
5147
- const isReduced = useReducedMotion();
5148
- const shouldShow = !invisible && (count === void 0 || count > 0);
5149
- return /* @__PURE__ */ jsxs(BadgeHeadless, { ref, className, children: [
5150
- children,
5151
- /* @__PURE__ */ jsx(
5152
- BadgeContent,
5153
- {
5154
- count,
5155
- max,
5156
- color,
5157
- invisible: !shouldShow,
5158
- "aria-label": ariaLabel,
5159
- reducedMotion: isReduced
5160
- }
5161
- )
5162
- ] });
5163
- }
5164
- );
5165
- Badge.displayName = "Badge";
5166
- function isBadgeConfig(badge) {
5167
- return typeof badge === "object" && badge !== null && !isValidElement(badge) && ("count" in badge || "color" in badge);
5168
5110
  }
5169
5111
  var DrawerItem = forwardRef(
5170
5112
  ({
@@ -5192,12 +5134,18 @@ var DrawerItem = forwardRef(
5192
5134
  const renderBadge = () => {
5193
5135
  if (!badge) return null;
5194
5136
  if (isBadgeConfig(badge)) {
5137
+ const max = 999;
5138
+ const isDot = badge.count === void 0;
5139
+ const displayValue = getBadgeDisplayValue(badge.count, max);
5140
+ const ariaLabel = getBadgeAriaLabel(badge.count);
5195
5141
  return /* @__PURE__ */ jsx("span", { className: "relative z-10 ml-auto flex shrink-0 items-center pr-2", children: /* @__PURE__ */ jsx(
5196
- Badge,
5142
+ "span",
5197
5143
  {
5198
- ...badge.count !== void 0 ? { count: badge.count } : {},
5199
- ...badge.color !== void 0 ? { color: badge.color } : {},
5200
- children: /* @__PURE__ */ jsx("span", {})
5144
+ role: "status",
5145
+ "aria-label": ariaLabel,
5146
+ "data-dot": isDot ? "" : void 0,
5147
+ className: cn(badgeStaticVariants()),
5148
+ children: displayValue
5201
5149
  }
5202
5150
  ) });
5203
5151
  }
@@ -8696,6 +8644,75 @@ var Search = forwardRef(
8696
8644
  }
8697
8645
  );
8698
8646
  Search.displayName = "Search";
8647
+ var BadgeHeadless = forwardRef(
8648
+ ({ className, children, ...props }, ref) => {
8649
+ return /* @__PURE__ */ jsx("div", { ref, className: cn("relative inline-flex", className), ...props, children });
8650
+ }
8651
+ );
8652
+ BadgeHeadless.displayName = "BadgeHeadless";
8653
+ var getDisplayValue = (count, max) => {
8654
+ if (count === void 0) return "";
8655
+ return count > max ? `${max}+` : count.toString();
8656
+ };
8657
+ var getAriaLabel = (count, override) => {
8658
+ if (override) return override;
8659
+ return count === void 0 ? "New" : `${count} notifications`;
8660
+ };
8661
+ var BadgeContent = forwardRef(
8662
+ ({
8663
+ count,
8664
+ max = 999,
8665
+ invisible = false,
8666
+ "aria-label": ariaLabelOverride,
8667
+ reducedMotion = false,
8668
+ className
8669
+ }, ref) => {
8670
+ const isDot = count === void 0;
8671
+ const displayValue = getDisplayValue(count, max);
8672
+ const ariaLabel = getAriaLabel(count, ariaLabelOverride);
8673
+ return /* @__PURE__ */ jsx(
8674
+ "span",
8675
+ {
8676
+ ref,
8677
+ role: "status",
8678
+ "aria-label": ariaLabel,
8679
+ "data-dot": isDot ? "" : void 0,
8680
+ "data-invisible": invisible ? "" : void 0,
8681
+ className: cn(
8682
+ badgeVariants2(),
8683
+ // MD3 Expressive spatial motion for show/hide scale animation.
8684
+ // Spatial pairing: scale transform → expressive-fast-spatial token.
8685
+ // Guarded at the component level; do NOT use CSS-only reduced-motion
8686
+ // because this is a JS-conditional class, not a persistent transition.
8687
+ !reducedMotion && "duration-expressive-fast-spatial ease-expressive-fast-spatial transition-transform",
8688
+ className
8689
+ ),
8690
+ children: displayValue
8691
+ }
8692
+ );
8693
+ }
8694
+ );
8695
+ BadgeContent.displayName = "BadgeContent";
8696
+ var Badge = forwardRef(
8697
+ ({ count, max = 999, invisible = false, "aria-label": ariaLabel, className, children }, ref) => {
8698
+ const isReduced = useReducedMotion();
8699
+ const shouldShow = !invisible && (count === void 0 || count > 0);
8700
+ return /* @__PURE__ */ jsxs(BadgeHeadless, { ref, className, children: [
8701
+ children,
8702
+ /* @__PURE__ */ jsx(
8703
+ BadgeContent,
8704
+ {
8705
+ count,
8706
+ max,
8707
+ invisible: !shouldShow,
8708
+ "aria-label": ariaLabel,
8709
+ reducedMotion: isReduced
8710
+ }
8711
+ )
8712
+ ] });
8713
+ }
8714
+ );
8715
+ Badge.displayName = "Badge";
8699
8716
  var splitButtonContainerVariants = cva(
8700
8717
  ["inline-flex items-center rounded-full overflow-hidden"],
8701
8718
  {
@@ -9330,13 +9347,30 @@ var FABMenuHeadless = forwardRef(
9330
9347
  }
9331
9348
  );
9332
9349
  FABMenuHeadless.displayName = "FABMenuHeadless";
9333
- var fabMenuVariants = cva(["relative", "inline-flex", "items-end"], {
9350
+ var fabMenuVariants = cva(["relative", "inline-flex"]);
9351
+ var fabMenuListVariants = cva(["absolute", "z-10", "flex", "gap-3"], {
9334
9352
  variants: {
9335
9353
  direction: {
9336
- up: ["flex-col-reverse", "gap-3"],
9337
- down: ["flex-col", "gap-3"],
9338
- left: ["flex-row-reverse", "gap-3", "items-center"],
9339
- right: ["flex-row", "gap-3", "items-center"]
9354
+ up: ["bottom-full", "mb-3", "end-0", "flex-col-reverse", "items-end", "origin-bottom"],
9355
+ down: ["top-full", "mt-3", "end-0", "flex-col", "items-end", "origin-top"],
9356
+ left: [
9357
+ "end-full",
9358
+ "me-3",
9359
+ "top-1/2",
9360
+ "-translate-y-1/2",
9361
+ "flex-row-reverse",
9362
+ "items-center",
9363
+ "origin-right"
9364
+ ],
9365
+ right: [
9366
+ "start-full",
9367
+ "ms-3",
9368
+ "top-1/2",
9369
+ "-translate-y-1/2",
9370
+ "flex-row",
9371
+ "items-center",
9372
+ "origin-left"
9373
+ ]
9340
9374
  }
9341
9375
  },
9342
9376
  defaultVariants: {
@@ -9344,19 +9378,129 @@ var fabMenuVariants = cva(["relative", "inline-flex", "items-end"], {
9344
9378
  }
9345
9379
  });
9346
9380
  var fabMenuItemVariants = cva(
9347
- ["relative", "flex", "items-center", "gap-3", "cursor-pointer"],
9381
+ [
9382
+ // Layout — full-rounded pill, NO overflow-hidden (focus ring extends outside)
9383
+ "relative inline-flex items-center cursor-pointer select-none",
9384
+ "rounded-full",
9385
+ "h-14 pl-4 pr-5 gap-3",
9386
+ // 56dp height, 16dp leading, 20dp trailing, 12dp gap
9387
+ // Effects transition for color/bg/shadow
9388
+ "transition-[color,background-color,box-shadow]",
9389
+ "duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
9390
+ // Disabled — self-targeting data-[x]: selectors
9391
+ "data-[disabled]:bg-on-surface/12 data-[disabled]:text-on-surface/38",
9392
+ "data-[disabled]:shadow-none data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none"
9393
+ ],
9348
9394
  {
9349
9395
  variants: {
9350
- isOpen: {
9351
- true: ["pointer-events-auto", "opacity-100"],
9352
- false: ["pointer-events-none", "opacity-0"]
9396
+ /**
9397
+ * Color role — controls container background, text color, and elevation.
9398
+ * State-layer color must equal the on-color (see fabMenuItemStateLayerVariants).
9399
+ *
9400
+ * Elevation per state:
9401
+ * base → elevation-3
9402
+ * hover → elevation-4 (group-data-[hovered]/fab-menu-item)
9403
+ * focus → elevation-3 (doubled selector wins over hover)
9404
+ * pressed→ elevation-3 (doubled selector wins over hover)
9405
+ * disabled → shadow-none (self-targeting data-[disabled])
9406
+ */
9407
+ color: {
9408
+ "primary-container": [
9409
+ "bg-primary-container text-on-primary-container",
9410
+ "shadow-elevation-3",
9411
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9412
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9413
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9414
+ ],
9415
+ "secondary-container": [
9416
+ "bg-secondary-container text-on-secondary-container",
9417
+ "shadow-elevation-3",
9418
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9419
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9420
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9421
+ ],
9422
+ "tertiary-container": [
9423
+ "bg-tertiary-container text-on-tertiary-container",
9424
+ "shadow-elevation-3",
9425
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9426
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9427
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9428
+ ],
9429
+ primary: [
9430
+ "bg-primary text-on-primary",
9431
+ "shadow-elevation-3",
9432
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9433
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9434
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9435
+ ],
9436
+ secondary: [
9437
+ "bg-secondary text-on-secondary",
9438
+ "shadow-elevation-3",
9439
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9440
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9441
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9442
+ ],
9443
+ tertiary: [
9444
+ "bg-tertiary text-on-tertiary",
9445
+ "shadow-elevation-3",
9446
+ "group-data-[hovered]/fab-menu-item:shadow-elevation-4",
9447
+ "group-data-[focus-visible]/fab-menu-item:shadow-elevation-3",
9448
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:shadow-elevation-3"
9449
+ ]
9353
9450
  }
9354
9451
  },
9355
9452
  defaultVariants: {
9356
- isOpen: false
9453
+ color: "primary-container"
9357
9454
  }
9358
9455
  }
9359
9456
  );
9457
+ var fabMenuItemStateLayerVariants = cva(
9458
+ [
9459
+ "absolute inset-0 rounded-[inherit] overflow-hidden pointer-events-none opacity-0",
9460
+ // Effects transition — opacity must not overshoot
9461
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
9462
+ // Hover: 8%
9463
+ "group-data-[hovered]/fab-menu-item:opacity-8",
9464
+ // Focus: 10%
9465
+ "group-data-[focus-visible]/fab-menu-item:opacity-10",
9466
+ // Pressed: 10% — doubled selector wins over hover's 8%
9467
+ "group-data-[pressed]/fab-menu-item:group-data-[pressed]/fab-menu-item:opacity-10",
9468
+ // No state layer when disabled
9469
+ "group-data-[disabled]/fab-menu-item:hidden"
9470
+ ],
9471
+ {
9472
+ variants: {
9473
+ color: {
9474
+ "primary-container": "bg-on-primary-container",
9475
+ "secondary-container": "bg-on-secondary-container",
9476
+ "tertiary-container": "bg-on-tertiary-container",
9477
+ primary: "bg-on-primary",
9478
+ secondary: "bg-on-secondary",
9479
+ tertiary: "bg-on-tertiary"
9480
+ }
9481
+ },
9482
+ defaultVariants: { color: "primary-container" }
9483
+ }
9484
+ );
9485
+ var fabMenuItemFocusRingVariants = cva([
9486
+ "pointer-events-none absolute inset-[-3px] rounded-full",
9487
+ "outline outline-2 outline-offset-0 outline-secondary",
9488
+ // Effects transition — opacity change must not overshoot
9489
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
9490
+ "opacity-0",
9491
+ "group-data-[focus-visible]/fab-menu-item:opacity-100"
9492
+ ]);
9493
+ var fabMenuItemIconVariants = cva([
9494
+ "relative z-10 inline-flex shrink-0 items-center justify-center",
9495
+ "size-6",
9496
+ // 24dp per MD3 spec
9497
+ // Color transition uses effects token (no spatial overshoot on color)
9498
+ "transition-colors duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
9499
+ ]);
9500
+ var fabMenuItemLabelVariants = cva([
9501
+ "relative z-10 inline-flex items-center",
9502
+ "text-title-medium"
9503
+ ]);
9360
9504
  var FABMenu = forwardRef(
9361
9505
  ({
9362
9506
  open: controlledOpen,
@@ -9395,7 +9539,7 @@ var FABMenu = forwardRef(
9395
9539
  setIsOpen(false);
9396
9540
  }, [setIsOpen]);
9397
9541
  const prevIsOpenRef = useRef(void 0);
9398
- useEffect(() => {
9542
+ useLayoutEffect(() => {
9399
9543
  if (prevIsOpenRef.current === void 0) {
9400
9544
  prevIsOpenRef.current = isOpen;
9401
9545
  return;
@@ -9458,119 +9602,143 @@ var FABMenu = forwardRef(
9458
9602
  }
9459
9603
  return child;
9460
9604
  });
9461
- return /* @__PURE__ */ jsx(FABMenuContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs(
9462
- "div",
9463
- {
9464
- ref: rootRef,
9465
- className: cn(fabMenuVariants({ direction }), className),
9466
- onKeyDown: handleKeyDown,
9467
- children: [
9468
- (isOpen || isExiting) && /* @__PURE__ */ jsx(
9469
- "div",
9605
+ return /* @__PURE__ */ jsx(FABMenuContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs("div", { ref: rootRef, className: cn(fabMenuVariants(), className), onKeyDown: handleKeyDown, children: [
9606
+ (isOpen || isExiting) && /* @__PURE__ */ jsx(
9607
+ "div",
9608
+ {
9609
+ className: cn(fabMenuListVariants({ direction })),
9610
+ role: "group",
9611
+ "aria-label": `${ariaLabel} actions`,
9612
+ children: indexedChildren
9613
+ }
9614
+ ),
9615
+ /* @__PURE__ */ jsx(
9616
+ FAB,
9617
+ {
9618
+ ref: triggerRef,
9619
+ onPress: toggle,
9620
+ "aria-label": ariaLabel,
9621
+ "aria-expanded": isOpen,
9622
+ icon: /* @__PURE__ */ jsx(
9623
+ "svg",
9470
9624
  {
9625
+ xmlns: "http://www.w3.org/2000/svg",
9626
+ viewBox: "0 0 24 24",
9627
+ fill: "currentColor",
9471
9628
  className: cn(
9472
- "inline-flex items-center gap-3",
9473
- direction === "up" && "flex-col-reverse",
9474
- direction === "down" && "flex-col",
9475
- direction === "left" && "flex-row-reverse",
9476
- direction === "right" && "flex-row"
9629
+ // Expressive fast-spatial: FAB icon is small, high-emphasis — matches FAB enter motion
9630
+ "h-6 w-6 transition-transform",
9631
+ reducedMotion ? "" : "duration-expressive-fast-spatial ease-expressive-fast-spatial",
9632
+ isOpen && "rotate-45"
9477
9633
  ),
9478
- role: "group",
9479
- "aria-label": `${ariaLabel} actions`,
9480
- children: indexedChildren
9634
+ "aria-hidden": "true",
9635
+ children: /* @__PURE__ */ jsx("path", { d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" })
9481
9636
  }
9482
9637
  ),
9483
- /* @__PURE__ */ jsx(
9484
- FAB,
9485
- {
9486
- ref: triggerRef,
9487
- onPress: toggle,
9488
- "aria-label": ariaLabel,
9489
- "aria-expanded": isOpen,
9490
- icon: /* @__PURE__ */ jsx(
9491
- "svg",
9492
- {
9493
- xmlns: "http://www.w3.org/2000/svg",
9494
- viewBox: "0 0 24 24",
9495
- fill: "currentColor",
9496
- className: cn(
9497
- "duration-short4 ease-standard h-6 w-6 transition-transform",
9498
- isOpen && "rotate-45"
9499
- ),
9500
- "aria-hidden": "true",
9501
- children: /* @__PURE__ */ jsx("path", { d: "M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" })
9502
- }
9503
- ),
9504
- className: cn(isOpen && "shadow-elevation-4")
9505
- }
9506
- )
9507
- ]
9508
- }
9509
- ) });
9638
+ className: cn(isOpen && "shadow-elevation-4")
9639
+ }
9640
+ )
9641
+ ] }) });
9510
9642
  }
9511
9643
  );
9512
9644
  FABMenu.displayName = "FABMenu";
9513
9645
  var FABMenuItem = forwardRef(
9514
- ({ icon, label, onPress, "aria-label": ariaLabel, isDisabled = false, className, index = 0 }, forwardedRef) => {
9646
+ ({
9647
+ icon,
9648
+ label,
9649
+ "aria-label": ariaLabel,
9650
+ onPress,
9651
+ color = "primary-container",
9652
+ isDisabled = false,
9653
+ className,
9654
+ index = 0
9655
+ }, forwardedRef) => {
9515
9656
  const internalRef = useRef(null);
9516
9657
  const buttonRef = forwardedRef ?? internalRef;
9517
- const { isOpen, isExiting, direction, reducedMotion, itemCount } = useFABMenuContext();
9658
+ const { isOpen, isExiting, reducedMotion, itemCount, direction } = useFABMenuContext();
9659
+ if (process.env.NODE_ENV === "development") {
9660
+ if (!label && !ariaLabel) {
9661
+ console.warn(
9662
+ "[FABMenuItem] Either `label` or `aria-label` must be provided for accessibility."
9663
+ );
9664
+ }
9665
+ }
9666
+ const [isPressed, setIsPressed] = useState(false);
9667
+ const handlePressStart = useCallback(() => setIsPressed(true), []);
9668
+ const handlePressEnd = useCallback(() => setIsPressed(false), []);
9669
+ const { isHovered, hoverProps } = useHover({ isDisabled });
9670
+ const { isFocusVisible, focusProps } = useFocusRing();
9518
9671
  const { buttonProps } = useButton(
9519
9672
  {
9520
- ...onPress && { onPress },
9521
- "aria-label": ariaLabel,
9522
- isDisabled
9673
+ ...onPress ? { onPress } : {},
9674
+ isDisabled,
9675
+ onPressStart: handlePressStart,
9676
+ onPressEnd: handlePressEnd,
9677
+ ...ariaLabel ? { "aria-label": ariaLabel } : {},
9678
+ elementType: "button"
9523
9679
  },
9524
9680
  buttonRef
9525
9681
  );
9526
- const { onMouseDown: handleRipple, ripples } = useRipple({
9527
- disabled: isDisabled
9528
- });
9529
- const mergedProps = mergeProps(buttonProps, {
9530
- type: "button",
9531
- onMouseDown: handleRipple
9532
- });
9682
+ const { onMouseDown: handleRipple, ripples } = useRipple({ disabled: isDisabled });
9533
9683
  const staggerDelay = reducedMotion ? 0 : isExiting ? Math.max(0, itemCount - 1 - index) * 30 : index * 30;
9684
+ const DIRECTION_ORIGIN = {
9685
+ up: "origin-bottom",
9686
+ down: "origin-top",
9687
+ left: "origin-right",
9688
+ right: "origin-left"
9689
+ };
9690
+ const originClass = reducedMotion ? void 0 : DIRECTION_ORIGIN[direction];
9534
9691
  const animationClass = reducedMotion ? void 0 : isOpen ? "animate-md-scale-in" : isExiting ? "animate-md-scale-out" : void 0;
9535
- const labelPosition = direction === "right" ? "after" : "before";
9536
- const labelChip = label ? /* @__PURE__ */ jsx("span", { className: "bg-surface-container text-label-large text-on-surface shadow-elevation-1 rounded-full px-3 py-1", children: label }) : null;
9537
- const isVisible = isOpen || isExiting;
9692
+ const mergedButtonProps = mergeProps$1(buttonProps, hoverProps, focusProps, {
9693
+ onMouseDown: handleRipple
9694
+ });
9695
+ const {
9696
+ isDisabled: _isDisabled,
9697
+ onPress: _onPress,
9698
+ onPressStart: _onPressStart,
9699
+ onPressEnd: _onPressEnd,
9700
+ onPressChange: _onPressChange,
9701
+ onPressUp: _onPressUp,
9702
+ ...htmlButtonProps
9703
+ } = mergedButtonProps;
9538
9704
  return /* @__PURE__ */ jsxs(
9539
- "div",
9705
+ "button",
9540
9706
  {
9707
+ ...htmlButtonProps,
9708
+ ref: buttonRef,
9709
+ type: "button",
9710
+ ...getInteractionDataAttributes({
9711
+ isHovered,
9712
+ isFocusVisible,
9713
+ isPressed,
9714
+ isDisabled
9715
+ }),
9716
+ "data-with-icon": icon ? "" : void 0,
9717
+ "data-with-label": label ? "" : void 0,
9541
9718
  className: cn(
9542
- "relative flex cursor-pointer items-center gap-3",
9543
- isVisible ? "opacity-100" : "opacity-0",
9544
- isOpen ? "pointer-events-auto" : "pointer-events-none",
9719
+ fabMenuItemVariants({ color }),
9720
+ // group/fab-menu-item: enables group-data-[x]/fab-menu-item child selectors in all slots
9721
+ "group/fab-menu-item",
9722
+ // Scale pivot toward the FAB so items appear to emanate from the trigger
9723
+ originClass,
9724
+ // Stagger animation class (animate-md-scale-in / animate-md-scale-out)
9725
+ animationClass,
9545
9726
  className
9546
9727
  ),
9728
+ style: staggerDelay > 0 ? { animationDelay: `${staggerDelay}ms` } : void 0,
9547
9729
  children: [
9548
- labelPosition === "before" && labelChip,
9549
- /* @__PURE__ */ jsxs(
9550
- "button",
9730
+ ripples,
9731
+ /* @__PURE__ */ jsx(
9732
+ "span",
9551
9733
  {
9552
- ...mergedProps,
9553
- ref: buttonRef,
9554
- className: cn(
9555
- "relative flex size-10 items-center justify-center overflow-hidden rounded-xl",
9556
- "bg-primary-container text-on-primary-container shadow-elevation-3",
9557
- animationClass
9558
- ),
9559
- style: staggerDelay > 0 ? { animationDelay: `${staggerDelay}ms` } : void 0,
9560
- children: [
9561
- /* @__PURE__ */ jsx(
9562
- "span",
9563
- {
9564
- "data-state-layer": true,
9565
- className: "bg-on-primary-container duration-spring-standard-fast-effects ease-spring-standard-fast-effects pointer-events-none absolute inset-0 rounded-xl opacity-0 transition-opacity hover:opacity-8"
9566
- }
9567
- ),
9568
- ripples,
9569
- /* @__PURE__ */ jsx("span", { className: "relative z-10 inline-flex shrink-0", children: icon })
9570
- ]
9734
+ className: cn(fabMenuItemStateLayerVariants({ color })),
9735
+ "data-state-layer": true,
9736
+ "aria-hidden": "true"
9571
9737
  }
9572
9738
  ),
9573
- labelPosition === "after" && labelChip
9739
+ /* @__PURE__ */ jsx("span", { className: cn(fabMenuItemFocusRingVariants()), "aria-hidden": "true" }),
9740
+ icon && /* @__PURE__ */ jsx("span", { className: cn(fabMenuItemIconVariants()), "aria-hidden": "true", children: icon }),
9741
+ label && /* @__PURE__ */ jsx("span", { className: cn(fabMenuItemLabelVariants()), children: label })
9574
9742
  ]
9575
9743
  }
9576
9744
  );
@@ -15126,6 +15294,6 @@ var DateField = forwardRef((props, forwardedRef) => {
15126
15294
  });
15127
15295
  DateField.displayName = "DateField";
15128
15296
 
15129
- 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, Switch, TYPOGRAPHY_ELEMENT_MAP, TYPOGRAPHY_USAGE, Tab, TabList, TabPanel, Tabs, TextField, TimePicker, TimePickerDial, TimePickerInput, Tooltip, TooltipOverlayHeadless, TooltipTrigger, TooltipTriggerHeadless, applyStateLayer, badgeVariants2 as badgeVariants, bottomSheetAnimationVariants, bottomSheetHandlePillVariants, bottomSheetHandleWrapperVariants, bottomSheetScrimVariants, bottomSheetVariants, buttonGroupFocusRingVariants, buttonGroupRootVariants, buttonGroupVariants, calendarCellVariants, cardVariants, chipVariants, clockDialContainerVariants, clockDialNumberVariants, clockHandCenterVariants, clockHandHandleVariants, clockHandTrackVariants, cn, datePickerActionButtonVariants, datePickerActionVariants, datePickerContainerVariants, datePickerDividerVariants, datePickerHeaderVariants, datePickerHeadlineVariants, datePickerNavVariants, datePickerRangeIndicatorVariants, datePickerScrimVariants, datePickerSupportingTextVariants, datePickerWeekdayVariants, dividerVariants, fabMenuItemVariants, fabMenuVariants, generateMD3Theme, getColorValue, getConnectedRadiusClasses, getFontFamily, getMD3Color, getResponsiveTypography, getTypographyClassName, getTypographyForElement, getTypographyStyle, getTypographyToken, hexToRgb, listItemVariants, listVariants, periodSelectorContainerVariants, periodSelectorItemVariants, pxToRem, remToPx, rgbToHex, richTooltipVariants, searchBarVariants, searchViewHeaderVariants, searchViewVariants, sliderActiveTrackVariants, sliderContainerVariants, sliderHandleStateLayerVariants, sliderHandleVariants, sliderInactiveTrackVariants, sliderTrackLayoutVariants, splitButtonContainerVariants, splitButtonDropdownVariants, splitButtonPrimaryVariants, splitButtonVariants, timeInputFieldVariants, timePickerActionButtonVariants, timePickerActionRowVariants, timePickerContainerVariants, timePickerHeadlineVariants, timePickerModeToggleVariants, timeSelectorContainerVariants, timeSeparatorVariants, tooltipVariants, truncateText, useBottomSheetContext, useBottomSheetDrag, useButtonGroup, useDialogContext, useFABMenuContext, useMenuContext, useOptionalButtonGroup, useSnackbar, withOpacity, yearItemVariants };
15297
+ 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, Switch, TYPOGRAPHY_ELEMENT_MAP, TYPOGRAPHY_USAGE, Tab, TabList, TabPanel, Tabs, TextField, TimePicker, TimePickerDial, TimePickerInput, Tooltip, TooltipOverlayHeadless, TooltipTrigger, TooltipTriggerHeadless, applyStateLayer, badgeVariants2 as badgeVariants, bottomSheetAnimationVariants, bottomSheetHandlePillVariants, bottomSheetHandleWrapperVariants, bottomSheetScrimVariants, bottomSheetVariants, buttonGroupFocusRingVariants, buttonGroupRootVariants, buttonGroupVariants, calendarCellVariants, cardVariants, chipVariants, clockDialContainerVariants, clockDialNumberVariants, clockHandCenterVariants, clockHandHandleVariants, clockHandTrackVariants, cn, datePickerActionButtonVariants, datePickerActionVariants, datePickerContainerVariants, datePickerDividerVariants, datePickerHeaderVariants, datePickerHeadlineVariants, datePickerNavVariants, datePickerRangeIndicatorVariants, datePickerScrimVariants, datePickerSupportingTextVariants, datePickerWeekdayVariants, dividerVariants, fabMenuItemFocusRingVariants, fabMenuItemIconVariants, fabMenuItemLabelVariants, fabMenuItemStateLayerVariants, fabMenuItemVariants, fabMenuListVariants, fabMenuVariants, generateMD3Theme, getColorValue, getConnectedRadiusClasses, getFontFamily, getMD3Color, getResponsiveTypography, getTypographyClassName, getTypographyForElement, getTypographyStyle, getTypographyToken, hexToRgb, listItemVariants, listVariants, periodSelectorContainerVariants, periodSelectorItemVariants, pxToRem, remToPx, rgbToHex, richTooltipVariants, searchBarVariants, searchViewHeaderVariants, searchViewVariants, sliderActiveTrackVariants, sliderContainerVariants, sliderHandleStateLayerVariants, sliderHandleVariants, sliderInactiveTrackVariants, sliderTrackLayoutVariants, splitButtonContainerVariants, splitButtonDropdownVariants, splitButtonPrimaryVariants, splitButtonVariants, timeInputFieldVariants, timePickerActionButtonVariants, timePickerActionRowVariants, timePickerContainerVariants, timePickerHeadlineVariants, timePickerModeToggleVariants, timeSelectorContainerVariants, timeSeparatorVariants, tooltipVariants, truncateText, useBottomSheetContext, useBottomSheetDrag, useButtonGroup, useDialogContext, useFABMenuContext, useMenuContext, useOptionalButtonGroup, useSnackbar, withOpacity, yearItemVariants };
15130
15298
  //# sourceMappingURL=index.js.map
15131
15299
  //# sourceMappingURL=index.js.map