@tinybigui/react 0.10.0 → 0.11.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.js CHANGED
@@ -5398,28 +5398,42 @@ var ProgressHeadless = forwardRef(
5398
5398
  }
5399
5399
  );
5400
5400
  ProgressHeadless.displayName = "ProgressHeadless";
5401
- var CardHeadless = forwardRef(function CardHeadless2({ className, children, ...ariaButtonProps }, forwardedRef) {
5401
+ var CardHeadless = forwardRef(function CardHeadless2({ className, children, onMouseDown, onMouseUp, onMouseLeave, ...rest }, forwardedRef) {
5402
5402
  const internalRef = useRef(null);
5403
5403
  const ref = forwardedRef ?? internalRef;
5404
- const isInteractive = !!(ariaButtonProps.onPress ?? ariaButtonProps.href);
5405
- const { buttonProps } = useButton({ elementType: "div", ...ariaButtonProps }, ref);
5406
- const { focusProps, isFocusVisible } = useFocusRing();
5404
+ const isInteractive = !!(rest.onPress ?? rest.href);
5405
+ const { buttonProps } = useButton({ elementType: "div", ...rest }, ref);
5406
+ const {
5407
+ isDisabled: _isDisabled,
5408
+ onPress: _onPress,
5409
+ onPressStart: _onPressStart,
5410
+ onPressEnd: _onPressEnd,
5411
+ onPressChange: _onPressChange,
5412
+ onPressUp: _onPressUp,
5413
+ href: _href,
5414
+ target: _target,
5415
+ rel: _rel,
5416
+ ...htmlAttrs
5417
+ } = rest;
5418
+ const mouseHandlers = { onMouseDown, onMouseUp, onMouseLeave };
5407
5419
  if (isInteractive) {
5408
- const interactiveProps = mergeProps(buttonProps, focusProps, {
5409
- className,
5410
- "data-focus-visible": isFocusVisible ? "true" : void 0
5411
- });
5420
+ const interactiveProps = mergeProps(buttonProps, mouseHandlers, htmlAttrs, { className });
5412
5421
  return /* @__PURE__ */ jsx("div", { ...interactiveProps, ref, children });
5413
5422
  }
5414
- return /* @__PURE__ */ jsx("div", { role: "article", className, ref, children });
5423
+ return /* @__PURE__ */ jsx("div", { role: "article", className, ref, ...mouseHandlers, ...htmlAttrs, children });
5415
5424
  });
5416
5425
  CardHeadless.displayName = "CardHeadless";
5417
5426
  var cardVariants = cva(
5418
5427
  [
5419
5428
  // Shape: MD3 medium corner = 12dp
5420
- "relative overflow-hidden rounded-md",
5421
- // Shadow transition (effects propertyuse spring standard fast effects)
5422
- "transition-shadow duration-spring-standard-fast-effects ease-spring-standard-fast-effects"
5429
+ "relative overflow-hidden rounded-md text-on-surface",
5430
+ // Transition: effects propertiesstandard default tier (cards are standard-size, not <48dp)
5431
+ // Covers shadow (elevation), opacity (disabled fade), border-color (outlined state)
5432
+ "transition-[box-shadow,opacity,border-color] duration-spring-standard-default-effects ease-spring-standard-default-effects",
5433
+ // Interactive affordance (content flag set by the component)
5434
+ "data-[interactive]:cursor-pointer",
5435
+ // Disabled — self-targeting selectors (38% container, no interaction)
5436
+ "data-[disabled]:cursor-not-allowed data-[disabled]:pointer-events-none data-[disabled]:opacity-38"
5423
5437
  ],
5424
5438
  {
5425
5439
  variants: {
@@ -5427,92 +5441,74 @@ var cardVariants = cva(
5427
5441
  * Card visual variant per MD3 specification.
5428
5442
  */
5429
5443
  variant: {
5430
- elevated: ["shadow-elevation-1", "hover:shadow-elevation-2"],
5431
- filled: ["shadow-elevation-0"],
5432
- outlined: ["border", "border-outline-variant", "shadow-elevation-0"]
5433
- },
5434
- /**
5435
- * Whether the card is interactive (has onPress or href).
5436
- * Interactive cards gain a cursor, keyboard focus ring, and state layer.
5437
- */
5438
- isInteractive: {
5439
- true: [
5440
- "cursor-pointer",
5441
- "focus-visible:outline-2",
5442
- "focus-visible:outline-primary",
5443
- "focus-visible:outline-offset-2"
5444
+ /**
5445
+ * Elevated — separation via shadow.
5446
+ * MD3: container=surface-container-low.
5447
+ * Elevation: 1 base → 2 hover → 1 focus → 1 pressed → 4 dragged.
5448
+ */
5449
+ elevated: [
5450
+ "bg-surface-container-low",
5451
+ "shadow-elevation-1",
5452
+ "data-[hovered]:shadow-elevation-2",
5453
+ "data-[focus-visible]:shadow-elevation-1",
5454
+ "data-[pressed]:data-[pressed]:shadow-elevation-1",
5455
+ "data-[dragged]:data-[dragged]:data-[dragged]:shadow-elevation-4",
5456
+ "data-[disabled]:shadow-none"
5444
5457
  ],
5445
- false: "cursor-default"
5446
- },
5447
- /**
5448
- * Whether the card is currently being dragged.
5449
- * Applies elevated shadow level 4 with a slower, more intentional transition
5450
- * to communicate physical lift per MD3 motion spec.
5451
- */
5452
- isDragged: {
5453
- true: [
5454
- "shadow-elevation-4",
5455
- // Override base transition to use a slower, decelerate curve for drag onset
5456
- "duration-medium2",
5457
- "ease-emphasized-decelerate"
5458
+ /**
5459
+ * Filled — subtle container fill, no resting shadow.
5460
+ * MD3: container=surface-container-highest.
5461
+ * Elevation: 0 base 1 hover → 0 focus → 0 pressed → 3 dragged.
5462
+ */
5463
+ filled: [
5464
+ "bg-surface-container-highest",
5465
+ "shadow-none",
5466
+ "data-[hovered]:shadow-elevation-1",
5467
+ "data-[focus-visible]:shadow-none",
5468
+ "data-[pressed]:data-[pressed]:shadow-none",
5469
+ "data-[dragged]:data-[dragged]:data-[dragged]:shadow-elevation-3",
5470
+ "data-[disabled]:shadow-none"
5458
5471
  ],
5459
- false: ""
5460
- },
5461
- /**
5462
- * Whether the card is disabled.
5463
- * MD3 spec: 38% opacity, no pointer events.
5464
- */
5465
- isDisabled: {
5466
- true: ["opacity-38", "pointer-events-none"],
5467
- false: ""
5472
+ /**
5473
+ * Outlined — visual boundary via border, no resting shadow.
5474
+ * MD3: container=surface, outline=outline-variant.
5475
+ * Elevation: 0 base 1 hover → 0 focus → 0 pressed → 3 dragged.
5476
+ */
5477
+ outlined: [
5478
+ "bg-surface border border-outline-variant",
5479
+ "shadow-none",
5480
+ "data-[hovered]:shadow-elevation-1",
5481
+ "data-[focus-visible]:shadow-none",
5482
+ "data-[pressed]:data-[pressed]:shadow-none",
5483
+ "data-[dragged]:data-[dragged]:data-[dragged]:shadow-elevation-3",
5484
+ "data-[disabled]:shadow-none"
5485
+ ]
5468
5486
  }
5469
5487
  },
5470
- compoundVariants: [
5471
- // Filled + enabled
5472
- {
5473
- variant: "filled",
5474
- isDisabled: false,
5475
- class: "bg-surface-container-highest"
5476
- },
5477
- // Filled + disabled
5478
- {
5479
- variant: "filled",
5480
- isDisabled: true,
5481
- class: "bg-surface-container-variant"
5482
- },
5483
- // Elevated + enabled
5484
- {
5485
- variant: "elevated",
5486
- isDisabled: true,
5487
- class: "bg-surface"
5488
- },
5489
- // Elevated + disabled
5490
- {
5491
- variant: "elevated",
5492
- isDisabled: false,
5493
- class: "bg-surface-container-low"
5494
- },
5495
- // Outlined + enabled
5496
- {
5497
- variant: "outlined",
5498
- isDisabled: true,
5499
- class: "bg-surface"
5500
- },
5501
- // Outlined + disabled
5502
- {
5503
- variant: "outlined",
5504
- isDisabled: false,
5505
- class: "bg-surface"
5506
- }
5507
- ],
5508
5488
  defaultVariants: {
5509
- variant: "elevated",
5510
- isInteractive: false,
5511
- isDragged: false,
5512
- isDisabled: false
5489
+ variant: "elevated"
5513
5490
  }
5514
5491
  }
5515
5492
  );
5493
+ var cardStateLayerVariants = cva([
5494
+ "pointer-events-none absolute inset-0 rounded-[inherit] opacity-0",
5495
+ "bg-on-surface",
5496
+ // Effects transition for opacity — standard default tier (200ms, no overshoot)
5497
+ "transition-opacity duration-spring-standard-default-effects ease-spring-standard-default-effects",
5498
+ "group-data-[hovered]/card:opacity-8",
5499
+ "group-data-[focus-visible]/card:opacity-10",
5500
+ "group-data-[pressed]/card:group-data-[pressed]/card:opacity-10",
5501
+ "group-data-[dragged]/card:group-data-[dragged]/card:group-data-[dragged]/card:opacity-16",
5502
+ "group-data-[disabled]/card:hidden"
5503
+ ]);
5504
+ var cardFocusRingVariants = cva([
5505
+ "pointer-events-none absolute inset-0 z-20 rounded-[inherit]",
5506
+ "outline outline-2 -outline-offset-2 outline-secondary",
5507
+ // Effects transition — standard default tier, opacity must not overshoot
5508
+ "transition-opacity duration-spring-standard-default-effects ease-spring-standard-default-effects",
5509
+ "opacity-0",
5510
+ "group-data-[focus-visible]/card:opacity-100"
5511
+ ]);
5516
5512
  var Card = forwardRef(function Card2({
5517
5513
  variant = "elevated",
5518
5514
  onPress,
@@ -5523,9 +5519,15 @@ var Card = forwardRef(function Card2({
5523
5519
  children,
5524
5520
  "aria-label": ariaLabel
5525
5521
  }, ref) {
5522
+ const internalRef = useRef(null);
5523
+ const resolvedRef = ref ?? internalRef;
5526
5524
  const isInteractive = !!(onPress ?? href);
5527
5525
  const [isDragged, setIsDragged] = useState(false);
5528
5526
  const [isPressed, setIsPressed] = useState(false);
5527
+ const { isHovered, hoverProps } = useHover({ isDisabled: !isInteractive || isDisabled });
5528
+ const { isFocusVisible, focusProps } = useFocusRing();
5529
+ const handlePressStart = useCallback(() => setIsPressed(true), []);
5530
+ const handlePressEnd = useCallback(() => setIsPressed(false), []);
5529
5531
  const { onMouseDown: handleRipple, ripples } = useRipple({
5530
5532
  disabled: !isInteractive || isDisabled
5531
5533
  });
@@ -5539,42 +5541,41 @@ var Card = forwardRef(function Card2({
5539
5541
  const handleMouseLeave = () => {
5540
5542
  if (isDraggable) setIsDragged(false);
5541
5543
  };
5542
- const handlePressStart = () => setIsPressed(true);
5543
- const handlePressEnd = () => setIsPressed(false);
5544
+ const interactionAttrs = isInteractive ? getInteractionDataAttributes({ isHovered, isFocusVisible, isPressed, isDisabled }) : {};
5545
+ const interactiveHandlers = isInteractive ? mergeProps$1(hoverProps, focusProps, {
5546
+ onPressStart: handlePressStart,
5547
+ onPressEnd: handlePressEnd
5548
+ }) : {};
5544
5549
  return /* @__PURE__ */ jsxs(
5545
5550
  CardHeadless,
5546
5551
  {
5547
- ref,
5552
+ ref: resolvedRef,
5548
5553
  ...onPress !== void 0 && { onPress },
5549
5554
  ...href !== void 0 && { href },
5550
5555
  isDisabled,
5551
5556
  ...ariaLabel !== void 0 && { "aria-label": ariaLabel },
5552
- onPressStart: handlePressStart,
5553
- onPressEnd: handlePressEnd,
5554
- onMouseDown: handleMouseDown,
5555
- onMouseUp: handleMouseUp,
5556
- onMouseLeave: handleMouseLeave,
5557
- className: cn(
5558
- cardVariants({ variant, isInteractive, isDragged, isDisabled }),
5559
- "group",
5560
- className
5561
- ),
5557
+ ...interactiveHandlers,
5558
+ ...isInteractive && { onMouseDown: handleMouseDown },
5559
+ ...isInteractive && isDraggable && {
5560
+ onMouseUp: handleMouseUp,
5561
+ onMouseLeave: handleMouseLeave
5562
+ },
5563
+ ...interactionAttrs,
5564
+ "data-interactive": isInteractive ? "" : void 0,
5565
+ "data-dragged": isInteractive && isDragged ? "" : void 0,
5566
+ className: cn(cardVariants({ variant }), "group/card", className),
5562
5567
  children: [
5563
5568
  isInteractive && /* @__PURE__ */ jsx(
5564
- "div",
5569
+ "span",
5565
5570
  {
5566
5571
  "data-testid": "card-state-layer",
5567
- "data-pressed": isPressed ? "" : void 0,
5568
5572
  "aria-hidden": "true",
5569
- className: cn(
5570
- "bg-on-surface pointer-events-none absolute inset-0 rounded-md",
5571
- "opacity-0 group-hover:opacity-8 data-[pressed]:opacity-12",
5572
- "duration-spring-standard-fast-effects ease-spring-standard-fast-effects transition-opacity"
5573
- )
5573
+ className: cn(cardStateLayerVariants())
5574
5574
  }
5575
5575
  ),
5576
5576
  isInteractive && ripples,
5577
- children
5577
+ isInteractive && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: cn(cardFocusRingVariants()) }),
5578
+ /* @__PURE__ */ jsx("div", { className: "relative z-10", children })
5578
5579
  ]
5579
5580
  }
5580
5581
  );
@@ -5584,7 +5585,7 @@ var cardMediaVariants = cva("w-full object-cover", {
5584
5585
  variants: {
5585
5586
  aspectRatio: {
5586
5587
  "16/9": "aspect-video",
5587
- "4/3": "aspect-video",
5588
+ "4/3": "aspect-[4/3]",
5588
5589
  "1/1": "aspect-square",
5589
5590
  auto: ""
5590
5591
  }
@@ -5608,7 +5609,7 @@ var CardMedia = forwardRef(function CardMedia2({ src, alt, aspectRatio = "auto",
5608
5609
  CardMedia.displayName = "CardMedia";
5609
5610
  var CardHeader = forwardRef(function CardHeader2({ headline, subheader, className }, ref) {
5610
5611
  return /* @__PURE__ */ jsxs("div", { ref, className: cn("p-4", className), children: [
5611
- /* @__PURE__ */ jsx("h3", { className: "text-on-surface text-title-large", children: headline }),
5612
+ /* @__PURE__ */ jsx("h3", { className: "text-on-surface text-title-medium", children: headline }),
5612
5613
  subheader !== void 0 && /* @__PURE__ */ jsx("p", { className: "text-on-surface-variant text-body-medium mt-1", children: subheader })
5613
5614
  ] });
5614
5615
  });
@@ -11155,7 +11156,7 @@ var BottomSheetModalPanel = ({
11155
11156
  "aria-modal": "true",
11156
11157
  className: cn(className, getAnimationClassName?.(animationState)),
11157
11158
  "data-animation-state": animationState,
11158
- "data-dragging": isDragging || void 0,
11159
+ "data-dragging": isDragging ? "" : void 0,
11159
11160
  style: panelStyle,
11160
11161
  onTransitionEnd,
11161
11162
  children
@@ -11292,7 +11293,7 @@ var BottomSheetHeadless = forwardRef(
11292
11293
  ref,
11293
11294
  className: cn(className, getAnimationClassName?.(animationState)),
11294
11295
  "data-animation-state": animationState,
11295
- "data-dragging": isDragging || void 0,
11296
+ "data-dragging": isDragging ? "" : void 0,
11296
11297
  style: panelStyle,
11297
11298
  onTransitionEnd: handleTransitionEnd,
11298
11299
  children
@@ -11307,7 +11308,6 @@ var bottomSheetAnimationVariants = cva("", {
11307
11308
  variants: {
11308
11309
  animationState: {
11309
11310
  // entering: initial mount frame — sheet starts below viewport (translateY(100%))
11310
- // The CSS is handled inside animate-md-slide-in-bottom keyframes
11311
11311
  entering: ["opacity-0"],
11312
11312
  // visible: entry animation active — animate-md-slide-in-bottom runs once
11313
11313
  visible: ["animate-md-slide-in-bottom"],
@@ -11324,52 +11324,38 @@ var bottomSheetAnimationVariants = cva("", {
11324
11324
  var bottomSheetVariants = cva(
11325
11325
  [
11326
11326
  // Position: fixed to bottom edge, full width
11327
- "fixed",
11328
- "bottom-0",
11329
- "left-0",
11330
- "right-0",
11327
+ "fixed bottom-0 left-0 right-0",
11331
11328
  // Surface token
11332
11329
  "bg-surface-container-low",
11333
11330
  // Elevation level 1 per MD3 spec
11334
11331
  "shadow-elevation-1",
11335
- // Shape: extra-large top corners (28dp), bottom corners are 0 (attached to screen edge)
11332
+ // Shape: extra-large top corners (28dp), square bottom (screen-attached)
11333
+ // NOTE: measurement-derived value from MD3 spec; permitted exception per component-variants rule
11336
11334
  "rounded-t-xl",
11337
11335
  // Layout
11338
- "flex",
11339
- "flex-col",
11340
- // Max width constraint (full width up to 640dp)
11336
+ "flex flex-col",
11337
+ // Width constraint (full width up to 640dp)
11341
11338
  "mx-auto",
11342
11339
  // NOTE: measurement-derived value from MD3 spec; permitted exception
11343
11340
  "w-[640px] max-w-full",
11344
- // Clip content during height transitions (sheet shrinks/grows from bottom edge)
11341
+ // Clip content during height transitions
11345
11342
  "overflow-hidden",
11346
- // Transition: height for snap spring (MD3 spec sheet "resizes" between heights)
11347
- // Standard personality, default speed tier, spatial: no overshoot.
11348
- // During drag, data-[dragging=true]:transition-none suppresses this so the
11349
- // sheet height follows the pointer 1:1 without transition lag.
11350
- // After drag release, the spring transition animates height to the new snap position.
11343
+ // Snap spring: spatial property (height), standard personality, default tier
11351
11344
  "transition-[height]",
11352
11345
  "duration-spring-standard-default-spatial",
11353
11346
  "ease-spring-standard-default-spatial",
11354
- "data-[dragging=true]:transition-none",
11347
+ // Suppress spring while dragging so the sheet follows the pointer 1:1
11348
+ "data-[dragging]:transition-none",
11355
11349
  "will-change-[height]",
11356
- // Responsive layout: when viewport > 640dp, apply wider top margin per MD3 spec.
11357
- // The sheet remains bottom-anchored at all sizes. Side centering is handled by
11358
- // mx-auto + max-w-[640px] — at 752dp viewport this naturally produces 56dp side
11359
- // margins on each side (exactly matching MD3 measurements).
11360
- // Top margin is expressed as max-height so the sheet cannot overlap the top edge:
11361
- // - Default: 72dp top margin (max-h-[calc(100vh-72px)])
11362
- // - Wide viewport (> 640dp): 56dp top margin (sm:max-h-[calc(100vh-56px)])
11350
+ // Responsive layout: top margin expressed as max-height
11363
11351
  // NOTE: measurement-derived values from MD3 spec; permitted exception
11364
11352
  "max-h-[calc(100vh-72px)]",
11365
- "sm:max-h-[calc(100vh-56px)]",
11366
- // Top corners rounded at wide layout (sheet floats away from screen edge)
11367
- "rounded-t-xl"
11353
+ "sm:max-h-[calc(100vh-56px)]"
11368
11354
  ],
11369
11355
  {
11370
11356
  variants: {
11371
11357
  variant: {
11372
- // Modal: above scrim (z-50)
11358
+ // Modal: rendered above the scrim (z-50)
11373
11359
  modal: "z-50",
11374
11360
  // Standard: sits above normal content but below overlays
11375
11361
  standard: "z-10"
@@ -11381,62 +11367,96 @@ var bottomSheetVariants = cva(
11381
11367
  }
11382
11368
  );
11383
11369
  var bottomSheetScrimVariants = cva([
11384
- "fixed",
11385
- "inset-0",
11386
- "z-40",
11387
- "bg-scrim",
11388
- "opacity-32",
11389
- "transition-opacity",
11390
- "duration-short4",
11391
- "ease-standard"
11370
+ "fixed inset-0 z-40",
11371
+ "bg-scrim opacity-32",
11372
+ // Screen-level effects transition (scrim enters/exits the screen, not an on-screen state change)
11373
+ "transition-opacity duration-short4 ease-standard"
11392
11374
  ]);
11393
11375
  var bottomSheetHandleWrapperVariants = cva([
11394
- // Center the handle pill horizontally
11395
- "flex",
11396
- "items-center",
11397
- "justify-center",
11398
- // Top/bottom padding creates the 48dp touch target area
11399
- // 22dp top + 4dp handle + 22dp bottom ≈ 48dp interaction zone (per MD3 measurements)
11376
+ // Center the pill horizontally; provide positioning context for overlays
11377
+ "relative flex items-center justify-center w-full",
11378
+ // 48dp touch target (22dp top + 4dp pill + 22dp bottom)
11400
11379
  // NOTE: measurement-derived value from MD3 spec; permitted exception
11401
11380
  "py-[22px]",
11402
- // Full width so the touch target spans the sheet
11403
- "w-full",
11404
- // Focus ring styling for keyboard/switch navigation
11405
- // MD3 spec: focus indicator color = secondary, thickness = 3dp, offset = 2dp
11381
+ // Suppress browser default focus outline — the focus-ring overlay slot handles it
11406
11382
  "focus-visible:outline-none",
11407
- "focus-visible:ring-3",
11408
- "focus-visible:ring-secondary",
11409
- "focus-visible:ring-offset-2",
11410
- "focus-visible:rounded-sm",
11411
- // Cursor affordance
11383
+ // Cursor affordance for drag interaction
11412
11384
  "cursor-ns-resize"
11413
11385
  ]);
11386
+ var bottomSheetHandleStateLayerVariants = cva([
11387
+ // Overlay positioned centrally — sits behind the pill
11388
+ "absolute pointer-events-none",
11389
+ // Pill-shaped to complement the handle's form
11390
+ "rounded-full",
11391
+ // Sized wider than the pill to provide a visible state layer halo
11392
+ // 48dp wide × 16dp tall — centred by the flex wrapper
11393
+ "w-12 h-4",
11394
+ // State-layer color (same role as the pill)
11395
+ "bg-on-surface-variant",
11396
+ // Effects transition — opacity must NOT overshoot
11397
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
11398
+ // Opacity at rest
11399
+ "opacity-0",
11400
+ // Hover: 8%
11401
+ "group-data-[hovered]/handle:opacity-8",
11402
+ // Focus-visible: 10%
11403
+ "group-data-[focus-visible]/handle:opacity-10",
11404
+ // Pressed: 10% (doubled selector wins over hover at same cascade position)
11405
+ "group-data-[pressed]/handle:group-data-[pressed]/handle:opacity-10",
11406
+ // Dragging: 16% (MD3 dragged state — highest on-screen opacity)
11407
+ // Doubled selector wins over hover + pressed
11408
+ "group-data-[dragging]/handle:group-data-[dragging]/handle:opacity-16"
11409
+ ]);
11410
+ var bottomSheetHandleFocusRingVariants = cva([
11411
+ "absolute pointer-events-none",
11412
+ "rounded-full",
11413
+ // Sized to sit around the state layer halo
11414
+ "w-14 h-5",
11415
+ // MD3 focus indicator: secondary color, 2dp weight
11416
+ "outline outline-2 outline-offset-0 outline-secondary",
11417
+ // Effects transition — opacity change must NOT overshoot
11418
+ "transition-opacity duration-spring-standard-fast-effects ease-spring-standard-fast-effects",
11419
+ // Hidden at rest; shown on keyboard/programmatic focus
11420
+ "opacity-0",
11421
+ "group-data-[focus-visible]/handle:opacity-100"
11422
+ ]);
11414
11423
  var bottomSheetHandlePillVariants = cva([
11424
+ "relative z-10 pointer-events-none",
11415
11425
  "bg-on-surface-variant",
11416
- "opacity-40",
11417
11426
  "rounded-full",
11418
11427
  // Dimensions: 32dp × 4dp per MD3 spec (measurement-derived; permitted exception)
11419
11428
  "w-8",
11420
- // 32dp = 2rem = w-8
11421
- "h-1",
11422
- // 4dp = 0.25rem = h-1
11423
- // Pill itself is decorative; the wrapper handles interaction
11424
- "pointer-events-none"
11429
+ // 32dp = 2rem
11430
+ "h-1"
11431
+ // 4dp = 0.25rem
11425
11432
  ]);
11426
11433
  function BottomSheetHandle({
11427
11434
  className,
11428
11435
  "aria-label": ariaLabelOverride
11429
11436
  }) {
11430
11437
  const { handleProps, isDragging } = useBottomSheetContext();
11431
- return /* @__PURE__ */ jsx(
11438
+ const { isHovered, hoverProps } = useHover({});
11439
+ const { isFocusVisible, focusProps } = useFocusRing();
11440
+ const mergedHandleProps = mergeProps$1(handleProps, hoverProps, focusProps);
11441
+ return /* @__PURE__ */ jsxs(
11432
11442
  "div",
11433
11443
  {
11434
- ...handleProps,
11444
+ ...mergedHandleProps,
11435
11445
  ...ariaLabelOverride !== void 0 ? { "aria-label": ariaLabelOverride } : {},
11436
- className: cn(bottomSheetHandleWrapperVariants(), className),
11446
+ className: cn(bottomSheetHandleWrapperVariants(), "group/handle", className),
11437
11447
  "data-testid": "bottom-sheet-handle",
11438
- "data-dragging": isDragging || void 0,
11439
- children: /* @__PURE__ */ jsx("span", { className: bottomSheetHandlePillVariants(), "aria-hidden": "true" })
11448
+ ...getInteractionDataAttributes({
11449
+ isHovered,
11450
+ isFocusVisible,
11451
+ // Treat active drag as pressed — drives the state layer to 10% opacity
11452
+ isPressed: isDragging
11453
+ }),
11454
+ "data-dragging": isDragging ? "" : void 0,
11455
+ children: [
11456
+ /* @__PURE__ */ jsx("span", { className: cn(bottomSheetHandleStateLayerVariants()), "aria-hidden": "true" }),
11457
+ /* @__PURE__ */ jsx("span", { className: cn(bottomSheetHandleFocusRingVariants()), "aria-hidden": "true" }),
11458
+ /* @__PURE__ */ jsx("span", { className: cn(bottomSheetHandlePillVariants()), "aria-hidden": "true" })
11459
+ ]
11440
11460
  }
11441
11461
  );
11442
11462
  }