@titan-design/react-ui 0.9.2 → 0.10.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.
Files changed (53) hide show
  1. package/dist/bodymap.js +78 -24
  2. package/dist/bodymap.js.map +1 -1
  3. package/dist/bodymap.mjs +78 -24
  4. package/dist/bodymap.mjs.map +1 -1
  5. package/dist/index.d.mts +215 -123
  6. package/dist/index.d.ts +215 -123
  7. package/dist/index.js +408 -259
  8. package/dist/index.js.map +1 -1
  9. package/dist/index.mjs +258 -121
  10. package/dist/index.mjs.map +1 -1
  11. package/dist/pages.js +214 -157
  12. package/dist/pages.js.map +1 -1
  13. package/dist/pages.mjs +214 -157
  14. package/dist/pages.mjs.map +1 -1
  15. package/dist/theme/index.d.mts +895 -795
  16. package/dist/theme/index.d.ts +895 -795
  17. package/dist/theme/index.js +101 -20
  18. package/dist/theme/index.js.map +1 -1
  19. package/dist/theme/index.mjs +99 -22
  20. package/dist/theme/index.mjs.map +1 -1
  21. package/dist/theme/tokens-css.js +88 -24
  22. package/dist/theme/tokens-css.js.map +1 -1
  23. package/dist/theme/tokens-css.mjs +88 -24
  24. package/dist/theme/tokens-css.mjs.map +1 -1
  25. package/package.json +1 -1
  26. package/src/components/custom/Workout/BaseBadge.tsx +5 -5
  27. package/src/components/custom/Workout/RowInventory.stories.tsx +5 -2
  28. package/src/components/custom/Workout/S3FullRail.stories.tsx +13 -1
  29. package/src/components/custom/Workout/SessionHeader.tsx +11 -13
  30. package/src/components/custom/Workout/SessionRail.stories.tsx +4 -1
  31. package/src/components/custom/Workout/SessionRail.tsx +16 -14
  32. package/src/components/custom/Workout/SupersetWrapper.stories.tsx +16 -25
  33. package/src/components/custom/Workout/SupersetWrapper.tsx +1 -1
  34. package/src/components/custom/Workout/TempoDisplay.tsx +3 -7
  35. package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +4 -1
  36. package/src/components/custom/Workout/WorkoutPill.tsx +2 -2
  37. package/src/components/shell/DashboardShell.tsx +6 -3
  38. package/src/components/ui/surface/Surface.stories.tsx +244 -1
  39. package/src/components/ui/surface/Surface.test.tsx +244 -1
  40. package/src/components/ui/surface/Surface.tsx +98 -20
  41. package/src/components/ui/surface/SurfaceContext.ts +126 -0
  42. package/src/components/ui/surface/index.ts +13 -0
  43. package/src/components/ui/surface/surface.contract.test.ts +283 -0
  44. package/src/test/nativewind-stub.ts +13 -0
  45. package/src/theme/ColorSystem.stories.tsx +232 -47
  46. package/src/theme/ThemeProvider.test.tsx +24 -0
  47. package/src/theme/ThemeProvider.tsx +23 -6
  48. package/src/theme/config.ts +12 -0
  49. package/src/theme/elevation.ts +90 -67
  50. package/src/theme/global.css +35 -9
  51. package/src/theme/tokens/primitives.ts +40 -0
  52. package/src/theme/tokens/semantic.ts +63 -14
  53. package/tailwind.config.js +8 -0
package/dist/index.js CHANGED
@@ -4,11 +4,11 @@ var jsxRuntime = require('react/jsx-runtime');
4
4
  var reactNative = require('react-native');
5
5
  var clsx = require('clsx');
6
6
  var tailwindMerge = require('tailwind-merge');
7
- var React24 = require('react');
7
+ var React25 = require('react');
8
8
 
9
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
10
10
 
11
- var React24__default = /*#__PURE__*/_interopDefault(React24);
11
+ var React25__default = /*#__PURE__*/_interopDefault(React25);
12
12
 
13
13
  var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
14
14
  get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
@@ -339,6 +339,21 @@ var primitiveColors = {
339
339
  black: "#000000",
340
340
  transparent: "transparent"
341
341
  };
342
+ var surfaceRampDark = {
343
+ inset: "#13100D",
344
+ // L*4.5 — sub-shell well / pressed
345
+ background: "#1C1916",
346
+ // L*9 — shell / frame
347
+ base: "#252321",
348
+ // L*13.5 — main content plane
349
+ elevated: "#2C2A28",
350
+ // L*17 — nav / rail
351
+ raised: "#31302F",
352
+ // L*20 — cards
353
+ overlay: "#373635"
354
+ // L*22.5 — hero / popover
355
+ };
356
+ var backgroundFrameDark = "#100D0A";
342
357
  var primitiveRamps = {
343
358
  red: {
344
359
  50: "#FFF4F4",
@@ -806,10 +821,19 @@ var semanticColorsLight = {
806
821
  "surface-overlay": primitiveColors.white,
807
822
  "surface-input": primitiveColors.neutral[50],
808
823
  // Input field background (filled variant)
824
+ // Deepest pressed pit (TD-surface-tokens, S-3) — light-mode counterpart of
825
+ // the dark ramp's `inset` plane; a placeholder pairing, not part of the
826
+ // dark-ramp investigation (surface.contract.test.ts is dark-mode only).
827
+ "surface-inset": primitiveColors.neutral[300],
809
828
  // Background colors (background-*)
810
829
  "background-base": "#EBEBEB",
811
830
  "background-default": primitiveColors.white,
812
831
  "background-subtle": primitiveColors.neutral[50],
832
+ // Frame/bezel chrome (TD-surface-tokens, S-3) — top bar + side nav shell,
833
+ // one step below `background-base` (darker still than `surface-inset`
834
+ // above, mirroring the dark-mode ordering). Placeholder pairing for light
835
+ // mode (see dark-mode note on `surface-inset` above).
836
+ "background-frame": primitiveColors.neutral[400],
813
837
  // Border colors (border-*)
814
838
  "border-default": "#E8E9EB",
815
839
  "border-subtle": primitiveColors.neutral[100],
@@ -825,6 +849,11 @@ var semanticColorsLight = {
825
849
  // Input field border on focus
826
850
  "border-input-error": primitiveColors.red[600],
827
851
  // Input field border on error
852
+ // Alpha hairline separators (surface-independent — composite toward black on
853
+ // light surfaces, mirroring the dark-mode white-alpha family). See §4/S-2.
854
+ "hairline-subtle": "rgba(0, 0, 0, 0.06)",
855
+ "hairline-default": "rgba(0, 0, 0, 0.09)",
856
+ "hairline-strong": "rgba(0, 0, 0, 0.14)",
828
857
  // Interactive states (interactive-*)
829
858
  "interactive-hover": "rgba(55, 65, 81, 0.04)",
830
859
  "interactive-focus": "rgba(55, 65, 81, 0.12)",
@@ -917,25 +946,46 @@ var semanticColorsDark = {
917
946
  "text-inverse": primitiveColors.neutral[900],
918
947
  "text-link": "#828DF8",
919
948
  "text-link-hover": primitiveColors.blue[400],
920
- // Surface colors - dark backgrounds
921
- "surface-base": primitiveColors.charcoal[700],
922
- // main surface
923
- "surface-elevated": primitiveColors.charcoal[600],
924
- // elevated surface
925
- "surface-raised": primitiveColors.charcoal[500],
926
- // raised surface
927
- "surface-overlay": primitiveColors.charcoal[600],
928
- // overlay surface
929
- "surface-input": primitiveColors.charcoal[600],
930
- // input surface
931
- // Background colors
932
- "background-base": primitiveColors.charcoal[900],
933
- // darkest charcoal
934
- "background-default": primitiveColors.charcoal[700],
935
- // main background
936
- "background-subtle": primitiveColors.charcoal[500],
937
- // subtle background
938
- // Border colors
949
+ // Surface colors - dark backgrounds — warm-tapered DERIVED ramp (TD-surface-tokens,
950
+ // S-1, re-spaced S-3). Shipped verbatim from `deriveSurfaceRamp()` — see
951
+ // `surfaceRampDark` in primitives.ts for the full derivation note. `surface-overlay`
952
+ // and `surface-elevated` are distinct (were both #191919 pre-S-1); `surface-input`
953
+ // tracks one plane above `surface-base`, same relative position as before the remap.
954
+ // `background-base` backs `Surface level="background"` (SurfaceContext.SURFACE_LEVEL_TOKEN),
955
+ // so it takes the ramp's `background` (shell/frame) role, NOT `inset`. The ramp's
956
+ // deepest `inset` plane is now promoted to `surface-inset` below (S-3) — still no
957
+ // `SurfaceLevel` member for it (follow-up, alongside the elevation.ts -1/-2 pressed
958
+ // levels — parallel workstream, not this branch).
959
+ "surface-base": surfaceRampDark.base,
960
+ // main surface (#252321, L*13.5)
961
+ "surface-elevated": surfaceRampDark.elevated,
962
+ // elevated surface (#2C2A28, L*17 — nav/rail)
963
+ "surface-raised": surfaceRampDark.raised,
964
+ // raised surface (#31302F, L*20 — cards)
965
+ "surface-overlay": surfaceRampDark.overlay,
966
+ // overlay surface (#373635, L*22.5 — hero/popover)
967
+ "surface-input": surfaceRampDark.elevated,
968
+ // input surface (#2C2A28 — one plane above base)
969
+ "surface-inset": surfaceRampDark.inset,
970
+ // deepest pressed pit (#13100D, L*4.5 — sub-shell well)
971
+ // Background colors — same ramp, the frame/shell end of it.
972
+ "background-base": surfaceRampDark.background,
973
+ // shell / frame (#1C1916, L*9 — Surface level="background")
974
+ "background-default": surfaceRampDark.base,
975
+ // main background (#252321, L*13.5 — matches surface-base)
976
+ "background-subtle": surfaceRampDark.elevated,
977
+ // subtle background (#2C2A28, L*17 — matches surface-elevated)
978
+ // Frame/bezel chrome (S-3) — the top bar + side nav shell; one step BELOW
979
+ // `background-base`, darker even than `surface-inset` — it exits the content
980
+ // ramp entirely rather than sitting in it. See `backgroundFrameDark` in
981
+ // primitives.ts.
982
+ "background-frame": backgroundFrameDark,
983
+ // frame / bezel (#100D0A, L*3.79)
984
+ // Border colors — `border-subtle` (#1C1C1C) previously collided with
985
+ // `surface-raised` (also #1C1C1C, an invisible border on raised cards). The
986
+ // re-spaced ramp above moved `surface-raised` to #2D2C2B, so this value is now
987
+ // distinct from every surface hex without needing to change it — see
988
+ // `surface.contract.test.ts` R2/R4.
939
989
  "border-default": primitiveColors.charcoal[400],
940
990
  // default border
941
991
  "border-subtle": primitiveColors.charcoal[500],
@@ -949,6 +999,14 @@ var semanticColorsDark = {
949
999
  "border-input-hover": primitiveColors.neutral[500],
950
1000
  "border-input-focus": "#828DF8",
951
1001
  "border-input-error": primitiveColors.red[500],
1002
+ // Alpha hairline separators — the primary separation cue (§4/S-2). Self-
1003
+ // normalizing: composites toward white by ~the same amount on ANY plane, so
1004
+ // one family works at every elevation instead of per-surface border tokens.
1005
+ // Shadows are demoted to floating-overlay use only (not shipped as a fill
1006
+ // separator here — see elevation.ts, follow-up S-4).
1007
+ "hairline-subtle": "rgba(255, 255, 255, 0.06)",
1008
+ "hairline-default": "rgba(255, 255, 255, 0.09)",
1009
+ "hairline-strong": "rgba(255, 255, 255, 0.14)",
952
1010
  // Interactive states
953
1011
  "interactive-hover": "rgba(255, 255, 255, 0.04)",
954
1012
  "interactive-focus": "rgba(255, 255, 255, 0.12)",
@@ -1194,7 +1252,7 @@ var textSizeStyles = {
1194
1252
  md: "text-sm",
1195
1253
  lg: "text-base"
1196
1254
  };
1197
- var Button = React24.forwardRef(function Button2({
1255
+ var Button = React25.forwardRef(function Button2({
1198
1256
  variant = "solid",
1199
1257
  size = "md",
1200
1258
  color = "primary",
@@ -1302,7 +1360,7 @@ var variantStyles2 = {
1302
1360
  error: "border-border-input-error"
1303
1361
  }
1304
1362
  };
1305
- var Input = React24.forwardRef(function Input2({
1363
+ var Input = React25.forwardRef(function Input2({
1306
1364
  size = "md",
1307
1365
  variant = "outline",
1308
1366
  isDisabled = false,
@@ -1322,7 +1380,7 @@ var Input = React24.forwardRef(function Input2({
1322
1380
  onBlur,
1323
1381
  ...props
1324
1382
  }, ref) {
1325
- const [isFocused, setIsFocused] = React24.useState(false);
1383
+ const [isFocused, setIsFocused] = React25.useState(false);
1326
1384
  const handleFocus = (e) => {
1327
1385
  setIsFocused(true);
1328
1386
  onFocus?.(e);
@@ -1388,8 +1446,8 @@ var Input = React24.forwardRef(function Input2({
1388
1446
  function InputGroup({ children, className }) {
1389
1447
  return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-col gap-4", className), children });
1390
1448
  }
1391
- var PasswordInput = React24.forwardRef(function PasswordInput2({ showIcon, hideIcon, ...props }, ref) {
1392
- const [isVisible, setIsVisible] = React24.useState(false);
1449
+ var PasswordInput = React25.forwardRef(function PasswordInput2({ showIcon, hideIcon, ...props }, ref) {
1450
+ const [isVisible, setIsVisible] = React25.useState(false);
1393
1451
  const toggleVisibility = () => setIsVisible(!isVisible);
1394
1452
  const defaultShowIcon = /* @__PURE__ */ jsxs(reactNative.View, { className: "w-5 h-5 items-center justify-center", children: [
1395
1453
  /* @__PURE__ */ jsx(reactNative.View, { className: "w-3 h-3 rounded-full border-2 border-text-secondary" }),
@@ -1478,9 +1536,11 @@ var lightThemeCSSVars = {
1478
1536
  "--color-surface-base": semanticColorsLight["surface-base"],
1479
1537
  "--color-surface-elevated": semanticColorsLight["surface-elevated"],
1480
1538
  "--color-surface-raised": semanticColorsLight["surface-raised"],
1539
+ "--color-surface-inset": semanticColorsLight["surface-inset"],
1481
1540
  "--color-background-base": semanticColorsLight["background-base"],
1482
1541
  "--color-background-default": semanticColorsLight["background-default"],
1483
1542
  "--color-background-subtle": semanticColorsLight["background-subtle"],
1543
+ "--color-background-frame": semanticColorsLight["background-frame"],
1484
1544
  "--color-border-default": semanticColorsLight["border-default"],
1485
1545
  "--color-border-subtle": semanticColorsLight["border-subtle"],
1486
1546
  "--color-border-strong": semanticColorsLight["border-strong"],
@@ -1537,6 +1597,9 @@ var lightThemeCSSVars = {
1537
1597
  "--color-border-input-hover": semanticColorsLight["border-input-hover"],
1538
1598
  "--color-border-input-focus": semanticColorsLight["border-input-focus"],
1539
1599
  "--color-border-input-error": semanticColorsLight["border-input-error"],
1600
+ "--color-hairline-subtle": semanticColorsLight["hairline-subtle"],
1601
+ "--color-hairline-default": semanticColorsLight["hairline-default"],
1602
+ "--color-hairline-strong": semanticColorsLight["hairline-strong"],
1540
1603
  "--color-interactive-disabled-text": semanticColorsLight["interactive-disabled-text"],
1541
1604
  "--color-avatar-background": semanticColorsLight["avatar-background"],
1542
1605
  "--color-avatar-text": semanticColorsLight["avatar-text"],
@@ -1576,9 +1639,11 @@ var darkThemeCSSVars = {
1576
1639
  "--color-surface-base": semanticColorsDark["surface-base"],
1577
1640
  "--color-surface-elevated": semanticColorsDark["surface-elevated"],
1578
1641
  "--color-surface-raised": semanticColorsDark["surface-raised"],
1642
+ "--color-surface-inset": semanticColorsDark["surface-inset"],
1579
1643
  "--color-background-base": semanticColorsDark["background-base"],
1580
1644
  "--color-background-default": semanticColorsDark["background-default"],
1581
1645
  "--color-background-subtle": semanticColorsDark["background-subtle"],
1646
+ "--color-background-frame": semanticColorsDark["background-frame"],
1582
1647
  "--color-border-default": semanticColorsDark["border-default"],
1583
1648
  "--color-border-subtle": semanticColorsDark["border-subtle"],
1584
1649
  "--color-border-strong": semanticColorsDark["border-strong"],
@@ -1635,6 +1700,9 @@ var darkThemeCSSVars = {
1635
1700
  "--color-border-input-hover": semanticColorsDark["border-input-hover"],
1636
1701
  "--color-border-input-focus": semanticColorsDark["border-input-focus"],
1637
1702
  "--color-border-input-error": semanticColorsDark["border-input-error"],
1703
+ "--color-hairline-subtle": semanticColorsDark["hairline-subtle"],
1704
+ "--color-hairline-default": semanticColorsDark["hairline-default"],
1705
+ "--color-hairline-strong": semanticColorsDark["hairline-strong"],
1638
1706
  "--color-interactive-disabled-text": semanticColorsDark["interactive-disabled-text"],
1639
1707
  "--color-avatar-background": semanticColorsDark["avatar-background"],
1640
1708
  "--color-avatar-text": semanticColorsDark["avatar-text"],
@@ -2269,6 +2337,10 @@ function getElevationShadow(baseColor, level, theme, isHovered = false) {
2269
2337
  elevationShadowCache.set(cacheKey, result);
2270
2338
  return result;
2271
2339
  }
2340
+ var PRESSED_ELEVATION_LEVEL = -1;
2341
+ function getPressedRecessShadow(fillColor, theme) {
2342
+ return getElevationShadow(fillColor, PRESSED_ELEVATION_LEVEL, theme);
2343
+ }
2272
2344
  function getBaseSurfaceColor(theme) {
2273
2345
  return theme === "light" ? semanticColorsLight["surface-raised"] : semanticColorsDark["surface-elevated"];
2274
2346
  }
@@ -2564,6 +2636,51 @@ var audiobookPreset = {
2564
2636
  },
2565
2637
  rootClasses: ["atmosphere-warm", "grain"]
2566
2638
  };
2639
+ var SURFACE_LEVEL_TOKEN = {
2640
+ background: "background-base",
2641
+ base: "surface-base",
2642
+ elevated: "surface-elevated",
2643
+ raised: "surface-raised",
2644
+ overlay: "surface-overlay"
2645
+ };
2646
+ var PRESSED_RAMP = ["inset", "background", "base", "elevated", "raised", "overlay"];
2647
+ var ON_SURFACE_TOKEN = {
2648
+ primary: "text-primary",
2649
+ secondary: "text-secondary",
2650
+ tertiary: "text-tertiary"
2651
+ };
2652
+ var DEFAULT_CONTEXT = { mode: "dark", level: "base" };
2653
+ var SurfaceContext = React25.createContext(DEFAULT_CONTEXT);
2654
+ function useSurface() {
2655
+ return React25.useContext(SurfaceContext);
2656
+ }
2657
+ function useSurfaceMode() {
2658
+ return React25.useContext(SurfaceContext).mode;
2659
+ }
2660
+ function onSurfaceColors(mode) {
2661
+ const c = getSemanticColors(mode);
2662
+ return {
2663
+ primary: c[ON_SURFACE_TOKEN.primary],
2664
+ secondary: c[ON_SURFACE_TOKEN.secondary],
2665
+ tertiary: c[ON_SURFACE_TOKEN.tertiary]
2666
+ };
2667
+ }
2668
+ function useOnSurfaceColor(role = "primary") {
2669
+ return getSemanticColors(useSurfaceMode())[ON_SURFACE_TOKEN[role]];
2670
+ }
2671
+ function insetFloor(mode) {
2672
+ const colors = getSemanticColors(mode);
2673
+ return colors["surface-inset"] ?? surfaceRampDark.inset;
2674
+ }
2675
+ function surfaceBackground(level, mode) {
2676
+ if (level === "inset") return insetFloor(mode);
2677
+ return getSemanticColors(mode)[SURFACE_LEVEL_TOKEN[level]];
2678
+ }
2679
+ function pressedLevel(parent) {
2680
+ const index = PRESSED_RAMP.indexOf(parent);
2681
+ const down = Math.max(0, index - 1);
2682
+ return PRESSED_RAMP[down];
2683
+ }
2567
2684
  function getTheme() {
2568
2685
  if (typeof document === "undefined") return "dark";
2569
2686
  return document.documentElement.classList.contains("light") ? "light" : "dark";
@@ -2600,7 +2717,7 @@ function getServerSnapshot() {
2600
2717
  return "dark";
2601
2718
  }
2602
2719
  function useTheme() {
2603
- return React24.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2720
+ return React25.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
2604
2721
  }
2605
2722
 
2606
2723
  // src/components/ui/card/Card.tsx
@@ -2633,17 +2750,17 @@ function Card({
2633
2750
  ...props
2634
2751
  }) {
2635
2752
  const isClickable = isInteractive || !!onPress;
2636
- const [isHovered, setIsHovered] = React24.useState(false);
2753
+ const [isHovered, setIsHovered] = React25.useState(false);
2637
2754
  const theme = useTheme();
2638
- const elevationLevel = React24.useMemo(() => {
2755
+ const elevationLevel = React25.useMemo(() => {
2639
2756
  const validated = getValidatedElevation("card", elevation);
2640
2757
  if (variant === "outline" || variant === "accent" || variant === "subtle") {
2641
2758
  return 1;
2642
2759
  }
2643
2760
  return validated;
2644
2761
  }, [variant, elevation]);
2645
- const baseColor = React24.useMemo(() => getBaseSurfaceColor(theme), [theme]);
2646
- const surfaceColor = React24.useMemo(() => {
2762
+ const baseColor = React25.useMemo(() => getBaseSurfaceColor(theme), [theme]);
2763
+ const surfaceColor = React25.useMemo(() => {
2647
2764
  if ((variant === "outline" || variant === "accent") && theme === "light") {
2648
2765
  return "#FAFAFA";
2649
2766
  }
@@ -2652,7 +2769,7 @@ function Card({
2652
2769
  }
2653
2770
  return getElevationSurface(baseColor, elevationLevel, theme);
2654
2771
  }, [baseColor, elevationLevel, theme, variant]);
2655
- const shadowStyle = React24.useMemo(() => {
2772
+ const shadowStyle = React25.useMemo(() => {
2656
2773
  const shouldHover = isHovered && isClickable;
2657
2774
  return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
2658
2775
  }, [baseColor, elevationLevel, theme, isHovered, isClickable]);
@@ -2683,11 +2800,11 @@ function Card({
2683
2800
  isLoading && "pointer-events-none animate-pulse",
2684
2801
  className
2685
2802
  );
2686
- const accentStyle = React24.useMemo(() => variant === "accent" ? {
2803
+ const accentStyle = React25.useMemo(() => variant === "accent" ? {
2687
2804
  borderLeftWidth: accentWidth ?? 3,
2688
2805
  borderLeftColor: accentColor ?? "var(--color-brand-primary)"
2689
2806
  } : {}, [variant, accentWidth, accentColor]);
2690
- const mergedStyle = React24.useMemo(() => {
2807
+ const mergedStyle = React25.useMemo(() => {
2691
2808
  const elevationStyle = {
2692
2809
  backgroundColor: bgColor || surfaceColor,
2693
2810
  borderRadius: 8,
@@ -3052,7 +3169,7 @@ function AvatarGroup({
3052
3169
  size = "md",
3053
3170
  className
3054
3171
  }) {
3055
- const childArray = React24__default.default.Children.toArray(children);
3172
+ const childArray = React25__default.default.Children.toArray(children);
3056
3173
  const visibleChildren = max ? childArray.slice(0, max) : childArray;
3057
3174
  const remainingCount = max ? Math.max(0, childArray.length - max) : 0;
3058
3175
  return /* @__PURE__ */ jsxs(reactNative.View, { className: cn("flex-row", className), children: [
@@ -3063,7 +3180,7 @@ function AvatarGroup({
3063
3180
  "border-2 border-surface-base rounded-full",
3064
3181
  index > 0 && "-ml-2"
3065
3182
  ),
3066
- children: React24__default.default.isValidElement(child) ? React24__default.default.cloneElement(child, { size }) : child
3183
+ children: React25__default.default.isValidElement(child) ? React25__default.default.cloneElement(child, { size }) : child
3067
3184
  },
3068
3185
  index
3069
3186
  )),
@@ -3106,7 +3223,7 @@ var sizeStyles6 = {
3106
3223
  md: { box: "w-5 h-5", icon: "w-3 h-3", label: "text-base" },
3107
3224
  lg: { box: "w-6 h-6", icon: "w-3.5 h-3.5", label: "text-lg" }
3108
3225
  };
3109
- var Checkbox = React24.forwardRef(function Checkbox2({
3226
+ var Checkbox = React25.forwardRef(function Checkbox2({
3110
3227
  isChecked = false,
3111
3228
  isIndeterminate = false,
3112
3229
  isDisabled = false,
@@ -3192,7 +3309,7 @@ var sizeStyles7 = {
3192
3309
  md: { track: "w-10 h-5", thumb: "w-4 h-4", translate: "translate-x-5" },
3193
3310
  lg: { track: "w-12 h-6", thumb: "w-5 h-5", translate: "translate-x-6" }
3194
3311
  };
3195
- var Switch = React24.forwardRef(function Switch2({
3312
+ var Switch = React25.forwardRef(function Switch2({
3196
3313
  isChecked = false,
3197
3314
  isDisabled = false,
3198
3315
  size = "md",
@@ -3251,7 +3368,7 @@ var Switch = React24.forwardRef(function Switch2({
3251
3368
  }
3252
3369
  );
3253
3370
  });
3254
- var ModalContext = React24.createContext({ size: "md", scrollBehavior: "outside" });
3371
+ var ModalContext = React25.createContext({ size: "md", scrollBehavior: "outside" });
3255
3372
  var sizeStyles8 = {
3256
3373
  xs: "max-w-xs",
3257
3374
  sm: "max-w-sm",
@@ -3309,7 +3426,7 @@ function Modal({
3309
3426
  ) });
3310
3427
  }
3311
3428
  function ModalContent({ children, className }) {
3312
- const { size } = React24.useContext(ModalContext);
3429
+ const { size } = React25.useContext(ModalContext);
3313
3430
  return /* @__PURE__ */ jsx(
3314
3431
  reactNative.Pressable,
3315
3432
  {
@@ -3342,7 +3459,7 @@ function ModalTitle({ children, className }) {
3342
3459
  );
3343
3460
  }
3344
3461
  function ModalCloseButton({ className }) {
3345
- const { onClose } = React24.useContext(ModalContext);
3462
+ const { onClose } = React25.useContext(ModalContext);
3346
3463
  return /* @__PURE__ */ jsx(
3347
3464
  reactNative.Pressable,
3348
3465
  {
@@ -3358,7 +3475,7 @@ function ModalCloseButton({ className }) {
3358
3475
  );
3359
3476
  }
3360
3477
  function ModalBody({ children, maxHeight, className }) {
3361
- const { scrollBehavior } = React24.useContext(ModalContext);
3478
+ const { scrollBehavior } = React25.useContext(ModalContext);
3362
3479
  if (scrollBehavior === "inside") {
3363
3480
  return /* @__PURE__ */ jsx(
3364
3481
  reactNative.ScrollView,
@@ -3494,7 +3611,7 @@ function SkeletonListItem({
3494
3611
  /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1", children: /* @__PURE__ */ jsx(SkeletonText, { lines, animation }) })
3495
3612
  ] });
3496
3613
  }
3497
- var TabsContext = React24.createContext({
3614
+ var TabsContext = React25.createContext({
3498
3615
  activeIndex: 0,
3499
3616
  setActiveIndex: () => {
3500
3617
  },
@@ -3511,7 +3628,7 @@ function Tabs({
3511
3628
  children,
3512
3629
  ...props
3513
3630
  }) {
3514
- const [internalIndex, setInternalIndex] = React24.useState(defaultIndex);
3631
+ const [internalIndex, setInternalIndex] = React25.useState(defaultIndex);
3515
3632
  const activeIndex = index ?? internalIndex;
3516
3633
  const setActiveIndex = (newIndex) => {
3517
3634
  if (index === void 0) {
@@ -3532,7 +3649,7 @@ function Tabs({
3532
3649
  ) });
3533
3650
  }
3534
3651
  function TabList({ children, className }) {
3535
- const { variant, orientation } = React24.useContext(TabsContext);
3652
+ const { variant, orientation } = React25.useContext(TabsContext);
3536
3653
  const variantStyles5 = {
3537
3654
  line: orientation === "horizontal" ? "border-b border-border" : "border-r border-border",
3538
3655
  enclosed: "bg-surface-raised rounded-lg p-1",
@@ -3546,9 +3663,9 @@ function TabList({ children, className }) {
3546
3663
  variantStyles5[variant],
3547
3664
  className
3548
3665
  ),
3549
- children: React24__default.default.Children.map(children, (child, index) => {
3550
- if (React24__default.default.isValidElement(child)) {
3551
- return React24__default.default.cloneElement(child, { index });
3666
+ children: React25__default.default.Children.map(children, (child, index) => {
3667
+ if (React25__default.default.isValidElement(child)) {
3668
+ return React25__default.default.cloneElement(child, { index });
3552
3669
  }
3553
3670
  return child;
3554
3671
  })
@@ -3573,7 +3690,7 @@ function Tab({
3573
3690
  className,
3574
3691
  children
3575
3692
  }) {
3576
- const { activeIndex, setActiveIndex, variant, orientation } = React24.useContext(TabsContext);
3693
+ const { activeIndex, setActiveIndex, variant, orientation } = React25.useContext(TabsContext);
3577
3694
  const isActive = activeIndex === index;
3578
3695
  const baseStyles = "font-medium text-sm transition-colors";
3579
3696
  const variantStyles5 = {
@@ -3618,9 +3735,9 @@ function Tab({
3618
3735
  );
3619
3736
  }
3620
3737
  function TabPanels({ children, className }) {
3621
- const { activeIndex } = React24.useContext(TabsContext);
3622
- return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-1", className), children: React24__default.default.Children.map(children, (child, index) => {
3623
- if (React24__default.default.isValidElement(child) && index === activeIndex) {
3738
+ const { activeIndex } = React25.useContext(TabsContext);
3739
+ return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-1", className), children: React25__default.default.Children.map(children, (child, index) => {
3740
+ if (React25__default.default.isValidElement(child) && index === activeIndex) {
3624
3741
  return child;
3625
3742
  }
3626
3743
  return null;
@@ -3803,13 +3920,13 @@ function Tooltip({
3803
3920
  usePortal: usePortalProp = false,
3804
3921
  ...props
3805
3922
  }) {
3806
- const [isVisible, setIsVisible] = React24.useState(false);
3807
- const [portalPos, setPortalPos] = React24.useState(null);
3808
- const openTimeoutRef = React24.useRef(null);
3809
- const closeTimeoutRef = React24.useRef(null);
3810
- const triggerRef = React24.useRef(null);
3923
+ const [isVisible, setIsVisible] = React25.useState(false);
3924
+ const [portalPos, setPortalPos] = React25.useState(null);
3925
+ const openTimeoutRef = React25.useRef(null);
3926
+ const closeTimeoutRef = React25.useRef(null);
3927
+ const triggerRef = React25.useRef(null);
3811
3928
  const isPortalMode = usePortalProp && reactNative.Platform.OS === "web" && !!createPortal;
3812
- React24.useEffect(() => {
3929
+ React25.useEffect(() => {
3813
3930
  if (!isVisible || !isPortalMode || !triggerRef.current) return;
3814
3931
  const node = triggerRef.current;
3815
3932
  const id = requestAnimationFrame(() => {
@@ -3943,7 +4060,7 @@ function Tooltip({
3943
4060
  )
3944
4061
  ] });
3945
4062
  }
3946
- var CollapseContext = React24.createContext({
4063
+ var CollapseContext = React25.createContext({
3947
4064
  isOpen: false,
3948
4065
  toggle: () => {
3949
4066
  }
@@ -3956,7 +4073,7 @@ function Collapse({
3956
4073
  children,
3957
4074
  ...props
3958
4075
  }) {
3959
- const [internalIsOpen, setInternalIsOpen] = React24.useState(defaultIsOpen);
4076
+ const [internalIsOpen, setInternalIsOpen] = React25.useState(defaultIsOpen);
3960
4077
  const isOpen = controlledIsOpen ?? internalIsOpen;
3961
4078
  const toggle = () => {
3962
4079
  const newState = !isOpen;
@@ -3968,7 +4085,7 @@ function Collapse({
3968
4085
  return /* @__PURE__ */ jsx(CollapseContext.Provider, { value: { isOpen, toggle }, children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("w-full", className), ...props, children }) });
3969
4086
  }
3970
4087
  function CollapseButton({ children, className }) {
3971
- const { isOpen, toggle } = React24.useContext(CollapseContext);
4088
+ const { isOpen, toggle } = React25.useContext(CollapseContext);
3972
4089
  return /* @__PURE__ */ jsxs(
3973
4090
  reactNative.Pressable,
3974
4091
  {
@@ -3988,11 +4105,11 @@ function CollapseButton({ children, className }) {
3988
4105
  );
3989
4106
  }
3990
4107
  function CollapseContent({ children, className }) {
3991
- const { isOpen } = React24.useContext(CollapseContext);
4108
+ const { isOpen } = React25.useContext(CollapseContext);
3992
4109
  if (!isOpen) return null;
3993
4110
  return /* @__PURE__ */ jsx(reactNative.View, { className: cn("overflow-hidden", className), children });
3994
4111
  }
3995
- var AccordionContext = React24.createContext({
4112
+ var AccordionContext = React25.createContext({
3996
4113
  openIndices: /* @__PURE__ */ new Set(),
3997
4114
  toggleIndex: () => {
3998
4115
  },
@@ -4005,7 +4122,7 @@ function Accordion({
4005
4122
  children,
4006
4123
  ...props
4007
4124
  }) {
4008
- const [openIndices, setOpenIndices] = React24.useState(new Set(defaultIndex));
4125
+ const [openIndices, setOpenIndices] = React25.useState(new Set(defaultIndex));
4009
4126
  const toggleIndex = (index) => {
4010
4127
  setOpenIndices((prev) => {
4011
4128
  const newSet = new Set(prev);
@@ -4020,19 +4137,19 @@ function Accordion({
4020
4137
  return newSet;
4021
4138
  });
4022
4139
  };
4023
- return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { openIndices, toggleIndex, allowMultiple }, children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("w-full divide-y divide-border", className), ...props, children: React24__default.default.Children.map(children, (child, index) => {
4024
- if (React24__default.default.isValidElement(child)) {
4025
- return React24__default.default.cloneElement(child, { index });
4140
+ return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { openIndices, toggleIndex, allowMultiple }, children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("w-full divide-y divide-border", className), ...props, children: React25__default.default.Children.map(children, (child, index) => {
4141
+ if (React25__default.default.isValidElement(child)) {
4142
+ return React25__default.default.cloneElement(child, { index });
4026
4143
  }
4027
4144
  return child;
4028
4145
  }) }) });
4029
4146
  }
4030
4147
  function AccordionItem({ index = 0, children, className }) {
4031
- const { openIndices, toggleIndex } = React24.useContext(AccordionContext);
4148
+ const { openIndices, toggleIndex } = React25.useContext(AccordionContext);
4032
4149
  const isOpen = openIndices.has(index);
4033
- return /* @__PURE__ */ jsx(reactNative.View, { className, children: React24__default.default.Children.map(children, (child) => {
4034
- if (React24__default.default.isValidElement(child)) {
4035
- return React24__default.default.cloneElement(child, {
4150
+ return /* @__PURE__ */ jsx(reactNative.View, { className, children: React25__default.default.Children.map(children, (child) => {
4151
+ if (React25__default.default.isValidElement(child)) {
4152
+ return React25__default.default.cloneElement(child, {
4036
4153
  isOpen,
4037
4154
  onToggle: () => toggleIndex(index)
4038
4155
  });
@@ -4075,7 +4192,7 @@ function Breadcrumbs({
4075
4192
  children,
4076
4193
  ...props
4077
4194
  }) {
4078
- const items = React24__default.default.Children.toArray(children);
4195
+ const items = React25__default.default.Children.toArray(children);
4079
4196
  let displayItems = items;
4080
4197
  if (maxItems && items.length > maxItems) {
4081
4198
  const firstItem = items[0];
@@ -4141,7 +4258,7 @@ function BreadcrumbItem({
4141
4258
  function BreadcrumbEllipsis() {
4142
4259
  return /* @__PURE__ */ jsx(reactNative.Text, { className: "text-sm text-text-tertiary", children: "..." });
4143
4260
  }
4144
- var PopoverContext = React24.createContext({
4261
+ var PopoverContext = React25.createContext({
4145
4262
  isOpen: false,
4146
4263
  setIsOpen: () => {
4147
4264
  },
@@ -4163,16 +4280,16 @@ function Popover({
4163
4280
  children,
4164
4281
  ...props
4165
4282
  }) {
4166
- const [internalIsOpen, setInternalIsOpen] = React24.useState(false);
4283
+ const [internalIsOpen, setInternalIsOpen] = React25.useState(false);
4167
4284
  const isOpen = controlledIsOpen ?? internalIsOpen;
4168
- const closeTimerRef = React24.useRef(null);
4169
- const setIsOpen = React24.useCallback((open) => {
4285
+ const closeTimerRef = React25.useRef(null);
4286
+ const setIsOpen = React25.useCallback((open) => {
4170
4287
  if (controlledIsOpen === void 0) {
4171
4288
  setInternalIsOpen(open);
4172
4289
  }
4173
4290
  onOpenChange?.(open);
4174
4291
  }, [controlledIsOpen, onOpenChange]);
4175
- const handleHoverIn = React24.useCallback(() => {
4292
+ const handleHoverIn = React25.useCallback(() => {
4176
4293
  if (triggerMode !== "hover") return;
4177
4294
  if (closeTimerRef.current) {
4178
4295
  clearTimeout(closeTimerRef.current);
@@ -4180,7 +4297,7 @@ function Popover({
4180
4297
  }
4181
4298
  setIsOpen(true);
4182
4299
  }, [triggerMode, setIsOpen]);
4183
- const handleHoverOut = React24.useCallback(() => {
4300
+ const handleHoverOut = React25.useCallback(() => {
4184
4301
  if (triggerMode !== "hover") return;
4185
4302
  closeTimerRef.current = setTimeout(() => {
4186
4303
  setIsOpen(false);
@@ -4196,7 +4313,7 @@ function Popover({
4196
4313
  );
4197
4314
  }
4198
4315
  function PopoverTrigger({ children, className }) {
4199
- const { isOpen, setIsOpen, triggerMode, handleHoverIn, handleHoverOut } = React24.useContext(PopoverContext);
4316
+ const { isOpen, setIsOpen, triggerMode, handleHoverIn, handleHoverOut } = React25.useContext(PopoverContext);
4200
4317
  const hoverProps = triggerMode === "hover" ? {
4201
4318
  onHoverIn: handleHoverIn,
4202
4319
  onHoverOut: handleHoverOut,
@@ -4222,7 +4339,7 @@ var SPACER_STYLES = {
4222
4339
  right: { top: 0, bottom: 0, left: 0, width: 8, transform: "translateX(-100%)" }
4223
4340
  };
4224
4341
  function PopoverContent({ children, className }) {
4225
- const { isOpen, setIsOpen, placement, triggerMode, handleHoverIn, handleHoverOut } = React24.useContext(PopoverContext);
4342
+ const { isOpen, setIsOpen, placement, triggerMode, handleHoverIn, handleHoverOut } = React25.useContext(PopoverContext);
4226
4343
  if (!isOpen) return null;
4227
4344
  const placementStyles3 = {
4228
4345
  top: "bottom-full left-0 mb-2",
@@ -4277,7 +4394,7 @@ function PopoverContent({ children, className }) {
4277
4394
  ] });
4278
4395
  }
4279
4396
  function PopoverCloseButton({ children, className }) {
4280
- const { setIsOpen } = React24.useContext(PopoverContext);
4397
+ const { setIsOpen } = React25.useContext(PopoverContext);
4281
4398
  return /* @__PURE__ */ jsx(
4282
4399
  reactNative.Pressable,
4283
4400
  {
@@ -4289,7 +4406,7 @@ function PopoverCloseButton({ children, className }) {
4289
4406
  }
4290
4407
  );
4291
4408
  }
4292
- var MenuContext = React24.createContext({
4409
+ var MenuContext = React25.createContext({
4293
4410
  isOpen: false,
4294
4411
  setIsOpen: () => {
4295
4412
  },
@@ -4303,7 +4420,7 @@ function Menu({
4303
4420
  children,
4304
4421
  ...props
4305
4422
  }) {
4306
- const [internalIsOpen, setInternalIsOpen] = React24.useState(false);
4423
+ const [internalIsOpen, setInternalIsOpen] = React25.useState(false);
4307
4424
  const isOpen = controlledIsOpen ?? internalIsOpen;
4308
4425
  const setIsOpen = (open) => {
4309
4426
  if (controlledIsOpen === void 0) {
@@ -4315,7 +4432,7 @@ function Menu({
4315
4432
  return /* @__PURE__ */ jsx(MenuContext.Provider, { value: { isOpen, setIsOpen, closeMenu }, children: /* @__PURE__ */ jsx(reactNative.View, { className: cn("relative", className), ...props, children }) });
4316
4433
  }
4317
4434
  function MenuTrigger({ children, className }) {
4318
- const { isOpen, setIsOpen } = React24.useContext(MenuContext);
4435
+ const { isOpen, setIsOpen } = React25.useContext(MenuContext);
4319
4436
  return /* @__PURE__ */ jsx(
4320
4437
  reactNative.Pressable,
4321
4438
  {
@@ -4328,7 +4445,7 @@ function MenuTrigger({ children, className }) {
4328
4445
  );
4329
4446
  }
4330
4447
  function MenuList({ children, className }) {
4331
- const { isOpen, setIsOpen } = React24.useContext(MenuContext);
4448
+ const { isOpen, setIsOpen } = React25.useContext(MenuContext);
4332
4449
  if (!isOpen) return null;
4333
4450
  return /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
4334
4451
  /* @__PURE__ */ jsx(
@@ -4362,7 +4479,7 @@ function MenuItem({
4362
4479
  className,
4363
4480
  children
4364
4481
  }) {
4365
- const { closeMenu } = React24.useContext(MenuContext);
4482
+ const { closeMenu } = React25.useContext(MenuContext);
4366
4483
  const handlePress = () => {
4367
4484
  if (isDisabled) return;
4368
4485
  onPress?.();
@@ -4406,7 +4523,7 @@ function MenuGroup({ label, children, className }) {
4406
4523
  children
4407
4524
  ] });
4408
4525
  }
4409
- var SelectContext = React24.createContext({
4526
+ var SelectContext = React25.createContext({
4410
4527
  value: null,
4411
4528
  isMulti: false,
4412
4529
  isOpen: false,
@@ -4430,7 +4547,7 @@ function Select({
4430
4547
  className,
4431
4548
  ...props
4432
4549
  }) {
4433
- const [isOpen, setIsOpen] = React24.useState(false);
4550
+ const [isOpen, setIsOpen] = React25.useState(false);
4434
4551
  const selectValue = (val) => {
4435
4552
  if (isMulti) {
4436
4553
  const newValues = values.includes(val) ? values.filter((v) => v !== val) : [...values, val];
@@ -4533,7 +4650,7 @@ function Select({
4533
4650
  ] }) });
4534
4651
  }
4535
4652
  function SelectOption({ option }) {
4536
- const { selectValue, isSelected, isMulti } = React24.useContext(SelectContext);
4653
+ const { selectValue, isSelected, isMulti } = React25.useContext(SelectContext);
4537
4654
  const selected = isSelected(option.value);
4538
4655
  return /* @__PURE__ */ jsxs(
4539
4656
  reactNative.Pressable,
@@ -4564,7 +4681,7 @@ function SelectOption({ option }) {
4564
4681
  }
4565
4682
  );
4566
4683
  }
4567
- var ToolbarButtonContext = React24.createContext({
4684
+ var ToolbarButtonContext = React25.createContext({
4568
4685
  isOpen: false,
4569
4686
  setIsOpen: () => {
4570
4687
  }
@@ -4597,16 +4714,16 @@ function ToolbarButton({
4597
4714
  children,
4598
4715
  ...props
4599
4716
  }) {
4600
- const [isOpen, setIsOpen] = React24.useState(false);
4601
- const [isHovered, setIsHovered] = React24.useState(false);
4602
- const handlePress = React24.useCallback(() => {
4717
+ const [isOpen, setIsOpen] = React25.useState(false);
4718
+ const [isHovered, setIsHovered] = React25.useState(false);
4719
+ const handlePress = React25.useCallback(() => {
4603
4720
  if (isDisabled) return;
4604
4721
  if (menuContent) {
4605
4722
  setIsOpen((prev) => !prev);
4606
4723
  }
4607
4724
  onPress?.();
4608
4725
  }, [isDisabled, menuContent, onPress]);
4609
- const handleClose = React24.useCallback(() => {
4726
+ const handleClose = React25.useCallback(() => {
4610
4727
  setIsOpen(false);
4611
4728
  }, []);
4612
4729
  const selected = isActive === void 0 ? isOpen : isActive;
@@ -4661,7 +4778,7 @@ function ToolbarButton({
4661
4778
  }
4662
4779
  ],
4663
4780
  children: [
4664
- icon && /* @__PURE__ */ jsx(reactNative.View, { className: "w-5 h-5 items-center justify-center", children: React24__default.default.isValidElement(icon) ? React24__default.default.cloneElement(icon, {
4781
+ icon && /* @__PURE__ */ jsx(reactNative.View, { className: "w-5 h-5 items-center justify-center", children: React25__default.default.isValidElement(icon) ? React25__default.default.cloneElement(icon, {
4665
4782
  size: 20,
4666
4783
  width: 20,
4667
4784
  height: 20,
@@ -4750,9 +4867,9 @@ function ToolbarButtonGroup({
4750
4867
  );
4751
4868
  }
4752
4869
  function useToolbarButton() {
4753
- return React24.useContext(ToolbarButtonContext);
4870
+ return React25.useContext(ToolbarButtonContext);
4754
4871
  }
4755
- var RadioGroupContext = React24.createContext(null);
4872
+ var RadioGroupContext = React25.createContext(null);
4756
4873
  var gapStyles2 = {
4757
4874
  sm: "gap-2",
4758
4875
  md: "gap-3",
@@ -4815,7 +4932,7 @@ function Radio({
4815
4932
  children,
4816
4933
  ...props
4817
4934
  }) {
4818
- const context = React24.useContext(RadioGroupContext);
4935
+ const context = React25.useContext(RadioGroupContext);
4819
4936
  if (!context) {
4820
4937
  throw new Error("Radio must be used within a RadioGroup");
4821
4938
  }
@@ -5194,7 +5311,7 @@ function ProgressSteps({
5194
5311
  }) {
5195
5312
  const { dot, connector } = stepSizeStyles[size];
5196
5313
  return /* @__PURE__ */ jsxs(reactNative.View, { className: cn("w-full", className), ...props, children: [
5197
- /* @__PURE__ */ jsx(reactNative.View, { className: "flex-row items-center", children: Array.from({ length: totalSteps }).map((_, index) => /* @__PURE__ */ jsxs(React24__default.default.Fragment, { children: [
5314
+ /* @__PURE__ */ jsx(reactNative.View, { className: "flex-row items-center", children: Array.from({ length: totalSteps }).map((_, index) => /* @__PURE__ */ jsxs(React25__default.default.Fragment, { children: [
5198
5315
  /* @__PURE__ */ jsx(
5199
5316
  reactNative.View,
5200
5317
  {
@@ -5229,7 +5346,7 @@ function ProgressSteps({
5229
5346
  )) })
5230
5347
  ] });
5231
5348
  }
5232
- var ToastContext = React24.createContext(null);
5349
+ var ToastContext = React25.createContext(null);
5233
5350
  var toastIdCounter = 0;
5234
5351
  var positionStyles = {
5235
5352
  "top": "top-4 left-1/2 -translate-x-1/2",
@@ -5245,8 +5362,8 @@ function ToastProvider({
5245
5362
  maxToasts = 5,
5246
5363
  children
5247
5364
  }) {
5248
- const [toasts, setToasts] = React24.useState([]);
5249
- const addToast = React24.useCallback((config) => {
5365
+ const [toasts, setToasts] = React25.useState([]);
5366
+ const addToast = React25.useCallback((config) => {
5250
5367
  const id = `toast-${++toastIdCounter}`;
5251
5368
  const newToast = {
5252
5369
  id,
@@ -5261,10 +5378,10 @@ function ToastProvider({
5261
5378
  });
5262
5379
  return id;
5263
5380
  }, [defaultDuration, maxToasts]);
5264
- const removeToast = React24.useCallback((id) => {
5381
+ const removeToast = React25.useCallback((id) => {
5265
5382
  setToasts((prev) => prev.filter((t17) => t17.id !== id));
5266
5383
  }, []);
5267
- const removeAllToasts = React24.useCallback(() => {
5384
+ const removeAllToasts = React25.useCallback(() => {
5268
5385
  setToasts([]);
5269
5386
  }, []);
5270
5387
  return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { toasts, addToast, removeToast, removeAllToasts }, children: [
@@ -5293,7 +5410,7 @@ function ToastProvider({
5293
5410
  ] });
5294
5411
  }
5295
5412
  function useToast() {
5296
- const context = React24.useContext(ToastContext);
5413
+ const context = React25.useContext(ToastContext);
5297
5414
  if (!context) {
5298
5415
  throw new Error("useToast must be used within a ToastProvider");
5299
5416
  }
@@ -5337,7 +5454,7 @@ function ToastItem({
5337
5454
  onClose
5338
5455
  }) {
5339
5456
  const { bg, border, icon } = statusStyles[status];
5340
- React24.useEffect(() => {
5457
+ React25.useEffect(() => {
5341
5458
  if (duration > 0) {
5342
5459
  const timer = setTimeout(onClose, duration);
5343
5460
  return () => clearTimeout(timer);
@@ -5439,18 +5556,18 @@ function Autocomplete({
5439
5556
  inputProps,
5440
5557
  ...props
5441
5558
  }) {
5442
- const [inputValue, setInputValue] = React24.useState("");
5443
- const [isOpen, setIsOpen] = React24.useState(false);
5444
- const [highlightedIndex, setHighlightedIndex] = React24.useState(-1);
5445
- const selectedOption = React24.useMemo(
5559
+ const [inputValue, setInputValue] = React25.useState("");
5560
+ const [isOpen, setIsOpen] = React25.useState(false);
5561
+ const [highlightedIndex, setHighlightedIndex] = React25.useState(-1);
5562
+ const selectedOption = React25.useMemo(
5446
5563
  () => options.find((o) => o.value === value),
5447
5564
  [options, value]
5448
5565
  );
5449
- const filteredOptions = React24.useMemo(() => {
5566
+ const filteredOptions = React25.useMemo(() => {
5450
5567
  if (inputValue.length < minChars) return [];
5451
5568
  return options.filter((option) => filterFn(option, inputValue));
5452
5569
  }, [options, inputValue, minChars, filterFn]);
5453
- const handleInputChange = React24.useCallback(
5570
+ const handleInputChange = React25.useCallback(
5454
5571
  (text) => {
5455
5572
  setInputValue(text);
5456
5573
  setIsOpen(true);
@@ -5459,7 +5576,7 @@ function Autocomplete({
5459
5576
  },
5460
5577
  [onInputChange]
5461
5578
  );
5462
- const handleSelectOption = React24.useCallback(
5579
+ const handleSelectOption = React25.useCallback(
5463
5580
  (option) => {
5464
5581
  if (option.isDisabled) return;
5465
5582
  onChange?.(option.value);
@@ -5468,18 +5585,18 @@ function Autocomplete({
5468
5585
  },
5469
5586
  [onChange]
5470
5587
  );
5471
- const handleClear = React24.useCallback(() => {
5588
+ const handleClear = React25.useCallback(() => {
5472
5589
  onChange?.(null);
5473
5590
  setInputValue("");
5474
5591
  setIsOpen(false);
5475
5592
  }, [onChange]);
5476
- const handleFocus = React24.useCallback(() => {
5593
+ const handleFocus = React25.useCallback(() => {
5477
5594
  setIsOpen(true);
5478
5595
  if (selectedOption && !inputValue) {
5479
5596
  setInputValue(selectedOption.label);
5480
5597
  }
5481
5598
  }, [selectedOption, inputValue]);
5482
- const handleBlur = React24.useCallback(() => {
5599
+ const handleBlur = React25.useCallback(() => {
5483
5600
  setTimeout(() => {
5484
5601
  setIsOpen(false);
5485
5602
  if (selectedOption) {
@@ -5653,7 +5770,7 @@ function HelpTip({
5653
5770
  className,
5654
5771
  ...props
5655
5772
  }) {
5656
- const [internalIsOpen, setInternalIsOpen] = React24.useState(false);
5773
+ const [internalIsOpen, setInternalIsOpen] = React25.useState(false);
5657
5774
  const isOpen = controlledIsOpen ?? internalIsOpen;
5658
5775
  const { icon: iconSize, text: textSize } = sizeStyles13[size];
5659
5776
  const handlePress = () => {
@@ -5759,7 +5876,7 @@ function FormField({
5759
5876
  }) {
5760
5877
  const isInvalid = !!errorMessage;
5761
5878
  const isHorizontal = orientation === "horizontal";
5762
- const fieldId = React24__default.default.useId();
5879
+ const fieldId = React25__default.default.useId();
5763
5880
  const helperId = `${fieldId}-helper`;
5764
5881
  const errorId = `${fieldId}-error`;
5765
5882
  return /* @__PURE__ */ jsxs(
@@ -5800,10 +5917,10 @@ function FormField({
5800
5917
  }
5801
5918
  ),
5802
5919
  /* @__PURE__ */ jsxs(reactNative.View, { className: cn(isHorizontal && "flex-1"), children: [
5803
- React24__default.default.Children.map(children, (child) => {
5804
- if (React24__default.default.isValidElement(child)) {
5920
+ React25__default.default.Children.map(children, (child) => {
5921
+ if (React25__default.default.isValidElement(child)) {
5805
5922
  const childProps = child.props;
5806
- return React24__default.default.cloneElement(child, {
5923
+ return React25__default.default.cloneElement(child, {
5807
5924
  accessibilityHint: errorMessage || helperText || childProps.accessibilityHint,
5808
5925
  accessibilityState: {
5809
5926
  ...childProps.accessibilityState,
@@ -6014,32 +6131,49 @@ function IconBox({
6014
6131
  }
6015
6132
  function Surface({
6016
6133
  elevation = 0,
6134
+ level,
6135
+ pressed = false,
6017
6136
  glowColor,
6018
6137
  glowIntensity,
6019
- theme = "dark",
6138
+ theme,
6139
+ rounded,
6020
6140
  className,
6021
6141
  style,
6022
6142
  children,
6023
6143
  ...props
6024
6144
  }) {
6025
- const baseColor = getBaseSurfaceColor(theme);
6026
- const surfaceColor = getElevationSurface(baseColor, elevation, theme);
6027
- const shadowStyle = getElevationShadow(baseColor, elevation, theme);
6145
+ const inherited = useSurface();
6146
+ const mode = theme ?? inherited.mode;
6147
+ const isPlane = level != null;
6148
+ const baseColor = getBaseSurfaceColor(mode);
6149
+ const resolvedLevel = pressed ? pressedLevel(inherited.level) : level ?? inherited.level;
6150
+ let backgroundColor;
6151
+ let shadowStyle;
6152
+ if (pressed) {
6153
+ backgroundColor = surfaceBackground(resolvedLevel, mode);
6154
+ shadowStyle = getPressedRecessShadow(backgroundColor, mode);
6155
+ } else if (isPlane) {
6156
+ backgroundColor = surfaceBackground(level, mode);
6157
+ shadowStyle = {};
6158
+ } else {
6159
+ backgroundColor = getElevationSurface(baseColor, elevation, mode);
6160
+ shadowStyle = getElevationShadow(baseColor, elevation, mode);
6161
+ }
6028
6162
  const glowStyle = glowColor ? getGlowShadow(glowColor, glowIntensity) : {};
6029
- return /* @__PURE__ */ jsx(
6163
+ const applyRounded = rounded ?? (pressed || !isPlane);
6164
+ const value = React25.useMemo(
6165
+ () => ({ mode, level: resolvedLevel }),
6166
+ [mode, resolvedLevel]
6167
+ );
6168
+ return /* @__PURE__ */ jsx(SurfaceContext.Provider, { value, children: /* @__PURE__ */ jsx(
6030
6169
  reactNative.View,
6031
6170
  {
6032
- className: cn("rounded-2xl", className),
6033
- style: [
6034
- { backgroundColor: surfaceColor },
6035
- shadowStyle,
6036
- glowStyle,
6037
- style
6038
- ],
6171
+ className: cn(applyRounded && "rounded-2xl", className),
6172
+ style: [{ backgroundColor }, shadowStyle, glowStyle, style],
6039
6173
  ...props,
6040
6174
  children
6041
6175
  }
6042
- );
6176
+ ) });
6043
6177
  }
6044
6178
  function ListItem({ className, children, onPress, ...props }) {
6045
6179
  const Container = onPress ? reactNative.Pressable : reactNative.View;
@@ -6277,7 +6411,7 @@ function Label(props) {
6277
6411
  function Overline(props) {
6278
6412
  return /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", ...props });
6279
6413
  }
6280
- var SidebarContext = React24.createContext({
6414
+ var SidebarContext = React25.createContext({
6281
6415
  isCollapsed: false
6282
6416
  });
6283
6417
  function Sidebar({
@@ -6321,7 +6455,7 @@ function SidebarFooter({ children, className }) {
6321
6455
  return /* @__PURE__ */ jsx(reactNative.View, { className: cn("px-2 py-4 border-t border-border-subtle", className), children });
6322
6456
  }
6323
6457
  function SidebarSection({ title, children, className }) {
6324
- const { isCollapsed } = React24.useContext(SidebarContext);
6458
+ const { isCollapsed } = React25.useContext(SidebarContext);
6325
6459
  return /* @__PURE__ */ jsxs(reactNative.View, { className: cn("px-2 py-2", className), children: [
6326
6460
  title && !isCollapsed && /* @__PURE__ */ jsx(reactNative.Text, { className: "px-3 py-2 text-xs font-semibold uppercase tracking-wider text-text-tertiary", children: title }),
6327
6461
  /* @__PURE__ */ jsx(reactNative.View, { className: "gap-0.5", children })
@@ -6338,7 +6472,7 @@ function SidebarItem({
6338
6472
  onPress,
6339
6473
  ...props
6340
6474
  }) {
6341
- const { isCollapsed, activeItem, onItemSelect } = React24.useContext(SidebarContext);
6475
+ const { isCollapsed, activeItem, onItemSelect } = React25.useContext(SidebarContext);
6342
6476
  const isActive = activeItem === id;
6343
6477
  const handlePress = (e) => {
6344
6478
  onItemSelect?.(id);
@@ -6390,7 +6524,7 @@ function SidebarItem({
6390
6524
  function SidebarDivider({ className }) {
6391
6525
  return /* @__PURE__ */ jsx(reactNative.View, { className: cn("h-px mx-4 my-2 bg-border-subtle", className) });
6392
6526
  }
6393
- var TableContext = React24.createContext({
6527
+ var TableContext = React25.createContext({
6394
6528
  sortDirection: null,
6395
6529
  selectedRows: /* @__PURE__ */ new Set(),
6396
6530
  selectable: false,
@@ -6472,7 +6606,7 @@ function TableHeaderCell({
6472
6606
  onPress,
6473
6607
  ...props
6474
6608
  }) {
6475
- const { sortColumn, sortDirection, onSort } = React24.useContext(TableContext);
6609
+ const { sortColumn, sortDirection, onSort } = React25.useContext(TableContext);
6476
6610
  const isSorted = sortKey && sortColumn === sortKey;
6477
6611
  const isSortable = !!sortKey && !!onSort;
6478
6612
  const ariaSort = isSorted ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : "none";
@@ -6660,11 +6794,11 @@ function useTable({
6660
6794
  defaultSortColumn,
6661
6795
  defaultSortDirection = null
6662
6796
  }) {
6663
- const [page, setPage] = React24.useState(0);
6664
- const [pageSize, setPageSize] = React24.useState(defaultPageSize);
6665
- const [sortColumn, setSortColumn] = React24.useState(defaultSortColumn);
6666
- const [sortDirection, setSortDirection] = React24.useState(defaultSortDirection);
6667
- const sortedData = React24.useMemo(() => {
6797
+ const [page, setPage] = React25.useState(0);
6798
+ const [pageSize, setPageSize] = React25.useState(defaultPageSize);
6799
+ const [sortColumn, setSortColumn] = React25.useState(defaultSortColumn);
6800
+ const [sortDirection, setSortDirection] = React25.useState(defaultSortDirection);
6801
+ const sortedData = React25.useMemo(() => {
6668
6802
  if (!sortColumn || !sortDirection) return data;
6669
6803
  return [...data].sort((a, b) => {
6670
6804
  const aVal = a[sortColumn];
@@ -6676,7 +6810,7 @@ function useTable({
6676
6810
  return sortDirection === "asc" ? comparison : -comparison;
6677
6811
  });
6678
6812
  }, [data, sortColumn, sortDirection]);
6679
- const paginatedData = React24.useMemo(() => {
6813
+ const paginatedData = React25.useMemo(() => {
6680
6814
  const start = page * pageSize;
6681
6815
  return sortedData.slice(start, start + pageSize);
6682
6816
  }, [sortedData, page, pageSize]);
@@ -6745,7 +6879,7 @@ function EmptyState({
6745
6879
  }
6746
6880
  );
6747
6881
  }
6748
- var StepperContext = React24.createContext({
6882
+ var StepperContext = React25.createContext({
6749
6883
  activeStep: 0,
6750
6884
  orientation: "horizontal"
6751
6885
  });
@@ -6764,11 +6898,11 @@ function Stepper({
6764
6898
  className
6765
6899
  ),
6766
6900
  ...props,
6767
- children: React24__default.default.Children.map(children, (child, index) => {
6768
- if (React24__default.default.isValidElement(child)) {
6901
+ children: React25__default.default.Children.map(children, (child, index) => {
6902
+ if (React25__default.default.isValidElement(child)) {
6769
6903
  return /* @__PURE__ */ jsxs(jsxRuntime.Fragment, { children: [
6770
- React24__default.default.cloneElement(child, { index }),
6771
- index < React24__default.default.Children.count(children) - 1 && /* @__PURE__ */ jsx(StepConnector, { index })
6904
+ React25__default.default.cloneElement(child, { index }),
6905
+ index < React25__default.default.Children.count(children) - 1 && /* @__PURE__ */ jsx(StepConnector, { index })
6772
6906
  ] });
6773
6907
  }
6774
6908
  return child;
@@ -6777,7 +6911,7 @@ function Stepper({
6777
6911
  ) });
6778
6912
  }
6779
6913
  function StepConnector({ index }) {
6780
- const { activeStep, orientation } = React24.useContext(StepperContext);
6914
+ const { activeStep, orientation } = React25.useContext(StepperContext);
6781
6915
  const isCompleted = index < activeStep;
6782
6916
  if (orientation === "horizontal") {
6783
6917
  return /* @__PURE__ */ jsx(
@@ -6801,7 +6935,7 @@ function StepConnector({ index }) {
6801
6935
  );
6802
6936
  }
6803
6937
  function Step({ index = 0, status, className, children }) {
6804
- const { activeStep, orientation } = React24.useContext(StepperContext);
6938
+ const { activeStep, orientation } = React25.useContext(StepperContext);
6805
6939
  const derivedStatus = status || (index < activeStep ? "completed" : index === activeStep ? "active" : "upcoming");
6806
6940
  return /* @__PURE__ */ jsx(
6807
6941
  reactNative.View,
@@ -6810,9 +6944,9 @@ function Step({ index = 0, status, className, children }) {
6810
6944
  orientation === "horizontal" ? "items-center" : "flex-row items-start",
6811
6945
  className
6812
6946
  ),
6813
- children: React24__default.default.Children.map(children, (child) => {
6814
- if (React24__default.default.isValidElement(child)) {
6815
- return React24__default.default.cloneElement(child, {
6947
+ children: React25__default.default.Children.map(children, (child) => {
6948
+ if (React25__default.default.isValidElement(child)) {
6949
+ return React25__default.default.cloneElement(child, {
6816
6950
  status: derivedStatus,
6817
6951
  index
6818
6952
  });
@@ -6856,7 +6990,7 @@ function StepIndicator({
6856
6990
  );
6857
6991
  }
6858
6992
  function StepLabel({ status = "upcoming", className, children }) {
6859
- const { orientation } = React24.useContext(StepperContext);
6993
+ const { orientation } = React25.useContext(StepperContext);
6860
6994
  return /* @__PURE__ */ jsx(
6861
6995
  reactNative.Text,
6862
6996
  {
@@ -7015,8 +7149,8 @@ function DateTime({
7015
7149
  className,
7016
7150
  ...props
7017
7151
  }) {
7018
- const [now, setNow] = React24.useState(() => Date.now());
7019
- React24.useEffect(() => {
7152
+ const [now, setNow] = React25.useState(() => Date.now());
7153
+ React25.useEffect(() => {
7020
7154
  if (!live) return;
7021
7155
  const id = setInterval(() => setNow(Date.now()), refreshMs);
7022
7156
  return () => clearInterval(id);
@@ -7050,8 +7184,8 @@ function useTimer(options = {}) {
7050
7184
  tickMs = 1e3
7051
7185
  } = options;
7052
7186
  const isControlled = controlledElapsedMs != null;
7053
- const [internalElapsedMs, setInternalElapsedMs] = React24.useState(0);
7054
- React24.useEffect(() => {
7187
+ const [internalElapsedMs, setInternalElapsedMs] = React25.useState(0);
7188
+ React25.useEffect(() => {
7055
7189
  if (isControlled || !autoTick || !running) return;
7056
7190
  const id = setInterval(() => {
7057
7191
  setInternalElapsedMs((prev) => prev + tickMs);
@@ -7210,8 +7344,8 @@ function MetricGroup({
7210
7344
  children,
7211
7345
  ...props
7212
7346
  }) {
7213
- const items = React24__default.default.Children.toArray(children);
7214
- return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-row items-center", className), ...props, children: items.map((child, i) => /* @__PURE__ */ jsxs(React24__default.default.Fragment, { children: [
7347
+ const items = React25__default.default.Children.toArray(children);
7348
+ return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-row items-center", className), ...props, children: items.map((child, i) => /* @__PURE__ */ jsxs(React25__default.default.Fragment, { children: [
7215
7349
  /* @__PURE__ */ jsx(reactNative.View, { className: "flex-1 items-center", children: child }),
7216
7350
  i < items.length - 1 && /* @__PURE__ */ jsx(
7217
7351
  reactNative.View,
@@ -7222,13 +7356,14 @@ function MetricGroup({
7222
7356
  )
7223
7357
  ] }, i)) });
7224
7358
  }
7359
+ var t = getSemanticColors("dark");
7225
7360
  var baseBadgeSizeConfig = {
7226
7361
  sm: { fontSize: 9, paddingH: 6, paddingV: 2, iconSize: 10 },
7227
7362
  md: { fontSize: 10, paddingH: 8, paddingV: 2, iconSize: 12 },
7228
7363
  lg: { fontSize: 12, paddingH: 10, paddingV: 4, iconSize: 14 }
7229
7364
  };
7230
7365
  var variantColors = {
7231
- plain: { backgroundColor: "#1C1C1C", borderColor: "#1F1F1F" },
7366
+ plain: { backgroundColor: t["surface-raised"], borderColor: "#1F1F1F" },
7232
7367
  pr: {
7233
7368
  backgroundColor: "rgba(255, 121, 0, 0.12)",
7234
7369
  borderColor: "rgba(255, 121, 0, 0.3)"
@@ -7243,7 +7378,7 @@ function BaseBadge({
7243
7378
  children,
7244
7379
  ...props
7245
7380
  }) {
7246
- const [scaleAnim] = React24.useState(() => new reactNative.Animated.Value(1));
7381
+ const [scaleAnim] = React25.useState(() => new reactNative.Animated.Value(1));
7247
7382
  const config = baseBadgeSizeConfig[size];
7248
7383
  const colors = variantColors[variant];
7249
7384
  const handlePressIn = () => {
@@ -7402,9 +7537,9 @@ function PrBadge({
7402
7537
  ...props
7403
7538
  }) {
7404
7539
  const resolvedLabel = labelProp ?? typeLabels[type];
7405
- const [scale] = React24.useState(() => new reactNative.Animated.Value(animate ? 0.8 : 1));
7406
- const [opacity] = React24.useState(() => new reactNative.Animated.Value(animate ? 0 : 1));
7407
- React24.useEffect(() => {
7540
+ const [scale] = React25.useState(() => new reactNative.Animated.Value(animate ? 0.8 : 1));
7541
+ const [opacity] = React25.useState(() => new reactNative.Animated.Value(animate ? 0 : 1));
7542
+ React25.useEffect(() => {
7408
7543
  if (!animate) return;
7409
7544
  reactNative.Animated.parallel([
7410
7545
  reactNative.Animated.timing(scale, {
@@ -7468,11 +7603,11 @@ function PrBadge({
7468
7603
  }
7469
7604
  return badge;
7470
7605
  }
7471
- var t = getSemanticColors("dark");
7606
+ var t2 = getSemanticColors("dark");
7472
7607
  var solidVariantColors = {
7473
- success: t["status-success"],
7474
- warning: t["status-warning"],
7475
- error: t["status-error"],
7608
+ success: t2["status-success"],
7609
+ warning: t2["status-warning"],
7610
+ error: t2["status-error"],
7476
7611
  neutral: "#6B7280"
7477
7612
  };
7478
7613
  var ringVariantStyles = {
@@ -7512,8 +7647,8 @@ var iconColors2 = {
7512
7647
  warning: "#6B4000",
7513
7648
  error: "#5C1A1A",
7514
7649
  neutral: "#D1D5DB",
7515
- "on-track": t["status-success"],
7516
- deviation: t["status-warning"],
7650
+ "on-track": t2["status-success"],
7651
+ deviation: t2["status-warning"],
7517
7652
  future: "#6B7280"
7518
7653
  };
7519
7654
  var sizeDimensions = {
@@ -7834,19 +7969,19 @@ function MetricCell({ children, color, fontSize = 11 }) {
7834
7969
  }
7835
7970
 
7836
7971
  // src/components/custom/Workout/TempoDisplay.tsx
7837
- var t2 = getSemanticColors("dark");
7972
+ var t3 = getSemanticColors("dark");
7838
7973
  var INTER = "Inter, sans-serif";
7839
7974
  var TEXT_TERTIARY = "#6B7280";
7840
- var STATUS_ERROR = t2["status-error"];
7841
- var STATUS_SUCCESS = t2["status-success"];
7842
- var STATUS_WARNING = t2["status-warning"];
7975
+ var STATUS_ERROR = t3["status-error"];
7976
+ var STATUS_SUCCESS = t3["status-success"];
7977
+ var STATUS_WARNING = t3["status-warning"];
7843
7978
  var ON_TARGET_MS = 100;
7844
7979
  function getTempoFillPct(elapsedMs, targetMs) {
7845
7980
  if (!targetMs) return 100;
7846
7981
  return Math.min(100, elapsedMs / targetMs * 100);
7847
7982
  }
7848
7983
  function activeNumberTone(elapsedMs, targetMs) {
7849
- if (targetMs == null) return t2["text-primary"];
7984
+ if (targetMs == null) return t3["text-primary"];
7850
7985
  const remainingMs = targetMs - elapsedMs;
7851
7986
  if (remainingMs > ON_TARGET_MS) return STATUS_WARNING;
7852
7987
  if (remainingMs >= -ON_TARGET_MS) return STATUS_SUCCESS;
@@ -7975,7 +8110,7 @@ function TempoDisplay({
7975
8110
  className,
7976
8111
  ...props
7977
8112
  }) {
7978
- const [showTooltip, setShowTooltip] = React24.useState(false);
8113
+ const [showTooltip, setShowTooltip] = React25.useState(false);
7979
8114
  const [eccentric, pauseBottom, concentric, pauseTop] = roundTempo(tempo);
7980
8115
  const isSm = size === "sm";
7981
8116
  const fontSize = fontSizeProp ?? (isSm ? 9 : 11);
@@ -7983,7 +8118,7 @@ function TempoDisplay({
7983
8118
  const chromePadY = Math.round(fontSize * 0.3);
7984
8119
  const chromeRadius = Math.round(fontSize * 0.4);
7985
8120
  const labelFont = Math.max(9, Math.round(fontSize * 0.5));
7986
- const handlePress = React24.useCallback(() => {
8121
+ const handlePress = React25.useCallback(() => {
7987
8122
  if (onPress) {
7988
8123
  onPress();
7989
8124
  }
@@ -7998,7 +8133,7 @@ function TempoDisplay({
7998
8133
  style: {
7999
8134
  flexDirection: "row",
8000
8135
  alignItems: "center",
8001
- backgroundColor: "#1C1C1C",
8136
+ backgroundColor: t3["surface-raised"],
8002
8137
  paddingHorizontal: chromePadX,
8003
8138
  paddingVertical: chromePadY,
8004
8139
  borderRadius: chromeRadius
@@ -8013,7 +8148,7 @@ function TempoDisplay({
8013
8148
  fontSize: labelFont,
8014
8149
  fontWeight: "500",
8015
8150
  // Live-muted green while a rep is running, tertiary at rest.
8016
- color: live ? t2["status-live-muted"] : TEXT_TERTIARY,
8151
+ color: live ? t3["status-live-muted"] : TEXT_TERTIARY,
8017
8152
  letterSpacing: 0.5,
8018
8153
  textTransform: "uppercase",
8019
8154
  marginRight: Math.round(fontSize * 0.5)
@@ -8071,7 +8206,7 @@ function TempoDisplay({
8071
8206
  reactNative.View,
8072
8207
  {
8073
8208
  style: {
8074
- backgroundColor: "#191919",
8209
+ backgroundColor: t3["surface-overlay"],
8075
8210
  borderRadius: 6,
8076
8211
  paddingVertical: 8,
8077
8212
  paddingHorizontal: 12,
@@ -8124,13 +8259,13 @@ function TempoDisplay({
8124
8259
  }
8125
8260
  );
8126
8261
  }
8127
- var t3 = getSemanticColors("dark");
8262
+ var t4 = getSemanticColors("dark");
8128
8263
  function getDotColor(deviation) {
8129
8264
  const abs = Math.abs(deviation);
8130
- if (deviation < -0.3) return t3["status-success"];
8265
+ if (deviation < -0.3) return t4["status-success"];
8131
8266
  if (abs <= 0.3) return "#6B7280";
8132
- if (abs <= 0.7) return t3["status-warning"];
8133
- return t3["status-error"];
8267
+ if (abs <= 0.7) return t4["status-warning"];
8268
+ return t4["status-error"];
8134
8269
  }
8135
8270
  function getDeviationDescription(deviation) {
8136
8271
  if (deviation < -0.3) return "lighter than planned";
@@ -8198,19 +8333,19 @@ function DeviationBar({
8198
8333
  }
8199
8334
  );
8200
8335
  }
8201
- var t4 = getSemanticColors("dark");
8336
+ var t5 = getSemanticColors("dark");
8202
8337
  var TRACK_BG = "#333333";
8203
8338
  var LABEL_COLOR = "#6B7280";
8204
8339
  var TARGET_LINE_COLOR = "rgba(33, 150, 243, 0.5)";
8205
8340
  var AT_TARGET_GLOW = "0 0 5px 1px rgba(33, 150, 243, 0.35), 0 0 10px 3px rgba(33, 150, 243, 0.15)";
8206
8341
  var ZONE = {
8207
- building: t4["status-success"],
8342
+ building: t5["status-success"],
8208
8343
  // below target ramp-up
8209
- approaching: t4["status-warning"],
8344
+ approaching: t5["status-warning"],
8210
8345
  // nearing target
8211
- target: t4["brand-primary"],
8346
+ target: t5["brand-primary"],
8212
8347
  // exactly at target
8213
- over1: t4["status-error"],
8348
+ over1: t5["status-error"],
8214
8349
  // mild over-target
8215
8350
  over2: WORKOUT_TOKENS.intensity.over2,
8216
8351
  // moderate over-target
@@ -8250,8 +8385,8 @@ function IntensityBar({
8250
8385
  const pct2 = Math.round(Math.max(0, level) * 100);
8251
8386
  const zone = zoneForPct(pct2);
8252
8387
  const atTarget = isAtTarget(pct2, threshold);
8253
- const [fillAnim] = React24.useState(() => new reactNative.Animated.Value(fillLevel));
8254
- React24.useEffect(() => {
8388
+ const [fillAnim] = React25.useState(() => new reactNative.Animated.Value(fillLevel));
8389
+ React25.useEffect(() => {
8255
8390
  const animation = reactNative.Animated.timing(fillAnim, {
8256
8391
  toValue: fillLevel,
8257
8392
  duration: 250,
@@ -8379,12 +8514,12 @@ var MESO_ACCENT_GRADIENT_LIGHT = primitiveRamps.orange[300];
8379
8514
  var WORKOUT_PILL_DELOAD = primitiveRamps.magenta[600];
8380
8515
 
8381
8516
  // src/components/custom/Workout/WorkoutPill.tsx
8382
- var t5 = getSemanticColors("dark");
8517
+ var t6 = getSemanticColors("dark");
8383
8518
  var statusBgColors = {
8384
8519
  completed: "rgba(46,213,115,0.15)",
8385
8520
  current: "rgba(255,121,0,0.15)",
8386
8521
  next: "transparent",
8387
- upcoming: "#1C1C1C",
8522
+ upcoming: t6["surface-raised"],
8388
8523
  missed: "rgba(209,67,67,0.1)",
8389
8524
  deload: "rgba(186,41,150,0.15)"
8390
8525
  };
@@ -8397,16 +8532,16 @@ var statusBorderStyles = {
8397
8532
  deload: { borderWidth: 1, borderColor: "rgba(186,41,150,0.3)" }
8398
8533
  };
8399
8534
  var textColors = {
8400
- completed: t5["status-success"],
8401
- current: t5["brand-primary"],
8402
- next: t5["brand-primary"],
8535
+ completed: t6["status-success"],
8536
+ current: t6["brand-primary"],
8537
+ next: t6["brand-primary"],
8403
8538
  upcoming: "#6B7280",
8404
8539
  missed: "rgba(209,67,67,0.7)",
8405
8540
  deload: WORKOUT_PILL_DELOAD
8406
8541
  };
8407
8542
  function usePulse(enabled) {
8408
- const [opacity] = React24.useState(() => new reactNative.Animated.Value(1));
8409
- React24.useEffect(() => {
8543
+ const [opacity] = React25.useState(() => new reactNative.Animated.Value(1));
8544
+ React25.useEffect(() => {
8410
8545
  if (!enabled) {
8411
8546
  opacity.setValue(1);
8412
8547
  return;
@@ -8536,8 +8671,8 @@ var PULSE_HALF_MS = 950;
8536
8671
  var PULSE_MIN_OPACITY = 0.45;
8537
8672
  var SEGMENTED_BAR_GAP = 5;
8538
8673
  function usePulse2(active) {
8539
- const [value] = React24.useState(() => new reactNative.Animated.Value(0));
8540
- React24.useEffect(() => {
8674
+ const [value] = React25.useState(() => new reactNative.Animated.Value(0));
8675
+ React25.useEffect(() => {
8541
8676
  if (!active) return;
8542
8677
  const loop = reactNative.Animated.loop(
8543
8678
  reactNative.Animated.sequence([
@@ -8962,8 +9097,8 @@ function getReducedMotionPreference() {
8962
9097
  return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
8963
9098
  }
8964
9099
  function usePrefersReducedMotion() {
8965
- const [reduced, setReduced] = React24.useState(getReducedMotionPreference);
8966
- React24.useEffect(() => {
9100
+ const [reduced, setReduced] = React25.useState(getReducedMotionPreference);
9101
+ React25.useEffect(() => {
8967
9102
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
8968
9103
  const mq = window.matchMedia("(prefers-reduced-motion: reduce)");
8969
9104
  const handler = () => setReduced(mq.matches);
@@ -8978,8 +9113,8 @@ var ANIMATION_EASING = reactNative.Easing.bezier(0.22, 1, 0.36, 1);
8978
9113
  var POP_EASING = reactNative.Easing.bezier(0.34, 1.56, 0.64, 1);
8979
9114
  function useLiveRepPop(active, liveRepIndex, liveVelocity, isNewPeak) {
8980
9115
  const prefersReducedMotion = usePrefersReducedMotion();
8981
- const [liveScale] = React24.useState(() => new reactNative.Animated.Value(1));
8982
- React24.useEffect(() => {
9116
+ const [liveScale] = React25.useState(() => new reactNative.Animated.Value(1));
9117
+ React25.useEffect(() => {
8983
9118
  if (!active || liveRepIndex == null || liveVelocity == null) return;
8984
9119
  if (prefersReducedMotion) {
8985
9120
  liveScale.setValue(1);
@@ -9027,7 +9162,7 @@ function HeroVelocityChart({
9027
9162
  }) {
9028
9163
  const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
9029
9164
  const liveScale = useLiveRepPop(true, liveRepIndex, liveVelocity, isNewPeak);
9030
- const [plotW, setPlotW] = React24.useState(0);
9165
+ const [plotW, setPlotW] = React25.useState(0);
9031
9166
  const onPlotLayout = (e) => setPlotW(e.nativeEvent.layout.width);
9032
9167
  const plotHeight = Math.max(0, height - HERO_LABEL_HEADROOM);
9033
9168
  const barHeight = (velocity) => scaleDenom > 0 ? Math.max(HERO_MIN_BAR_HEIGHT, Math.min(1, velocity / scaleDenom) * plotHeight) : HERO_MIN_BAR_HEIGHT;
@@ -9201,9 +9336,9 @@ function VelocityStrip({
9201
9336
  return SET_STRIP_VARIABLE_COLOR;
9202
9337
  };
9203
9338
  const meanZone = hasZones ? classifyBand(meanVelocity, zones)?.label ?? "" : getVelocityZoneName(meanVelocity);
9204
- const [heightAnim] = React24.useState(() => new reactNative.Animated.Value(expanded ? height : 3));
9205
- const [labelOpacity] = React24.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
9206
- const [infoOpacity] = React24.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
9339
+ const [heightAnim] = React25.useState(() => new reactNative.Animated.Value(expanded ? height : 3));
9340
+ const [labelOpacity] = React25.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
9341
+ const [infoOpacity] = React25.useState(() => new reactNative.Animated.Value(expanded ? 1 : 0));
9207
9342
  const liveVelocity = liveRepIndex != null ? doneVelocities[liveRepIndex] : void 0;
9208
9343
  const isNewPeak = liveVelocity != null && maxVelocity > 0 && liveVelocity === maxVelocity;
9209
9344
  const liveScale = useLiveRepPop(
@@ -9212,7 +9347,7 @@ function VelocityStrip({
9212
9347
  liveVelocity,
9213
9348
  isNewPeak
9214
9349
  );
9215
- React24.useEffect(() => {
9350
+ React25.useEffect(() => {
9216
9351
  if (variant !== "expanded" || !framed) return;
9217
9352
  reactNative.Animated.parallel([
9218
9353
  reactNative.Animated.timing(heightAnim, {
@@ -9546,13 +9681,13 @@ function VelocityStrip({
9546
9681
  }
9547
9682
  return stripContent;
9548
9683
  }
9549
- var t6 = getSemanticColors("dark");
9684
+ var t7 = getSemanticColors("dark");
9550
9685
  var dotColorMap = {
9551
9686
  untrained: "#2C2C2C",
9552
- behind: t6["brand-secondary"],
9553
- ontrack: t6["status-success"],
9554
- target: t6["brand-primary"],
9555
- over: t6["status-error"]
9687
+ behind: t7["brand-secondary"],
9688
+ ontrack: t7["status-success"],
9689
+ target: t7["brand-primary"],
9690
+ over: t7["status-error"]
9556
9691
  };
9557
9692
  function MuscleGroupChip({
9558
9693
  name,
@@ -10255,7 +10390,7 @@ function RestTimer({
10255
10390
  }
10256
10391
  );
10257
10392
  }
10258
- var t7 = getSemanticColors("dark");
10393
+ var t8 = getSemanticColors("dark");
10259
10394
  var TIMES = "\xD7";
10260
10395
  var AT = "@";
10261
10396
  function SetsRepsLoad({
@@ -10267,8 +10402,8 @@ function SetsRepsLoad({
10267
10402
  className,
10268
10403
  ...props
10269
10404
  }) {
10270
- const value = t7["text-primary"];
10271
- const sep = t7["text-tertiary"];
10405
+ const value = t8["text-primary"];
10406
+ const sep = t8["text-tertiary"];
10272
10407
  return /* @__PURE__ */ jsxs(
10273
10408
  reactNative.View,
10274
10409
  {
@@ -10359,7 +10494,7 @@ function compactUntil(ms) {
10359
10494
  return `${Math.round(d / 7)}w`;
10360
10495
  }
10361
10496
  function ScheduleTiles({ when, now, gap = 1, ...props }) {
10362
- const [mountNow] = React24.useState(() => Date.now());
10497
+ const [mountNow] = React25.useState(() => Date.now());
10363
10498
  const reference = now ?? mountNow;
10364
10499
  const whenMs = when instanceof Date ? when.getTime() : when;
10365
10500
  const soon = whenMs - reference < DAY_MS;
@@ -10381,14 +10516,14 @@ function ScheduleTiles({ when, now, gap = 1, ...props }) {
10381
10516
  )
10382
10517
  ] });
10383
10518
  }
10384
- var t8 = getSemanticColors("dark");
10519
+ var t9 = getSemanticColors("dark");
10385
10520
  var INDICATOR_CONFIG = {
10386
- imbalance: { Icon: ScaleIcon, color: t8["status-error"], label: "Left/right imbalance" },
10387
- overshoot: { Icon: AlertTriangleIcon, color: t8["status-error"], label: "Load overshoot" },
10388
- "velocity-loss": { Icon: TrendingDownIcon, color: t8["status-warning"], label: "Velocity loss" },
10389
- "missed-reps": { Icon: CircleSlashIcon, color: t8["status-warning"], label: "Missed reps" },
10390
- pr: { Icon: AwardIcon, color: t8["status-success"], label: "Personal record" },
10391
- info: { Icon: InfoIcon, color: t8["status-info"], label: "More info" }
10521
+ imbalance: { Icon: ScaleIcon, color: t9["status-error"], label: "Left/right imbalance" },
10522
+ overshoot: { Icon: AlertTriangleIcon, color: t9["status-error"], label: "Load overshoot" },
10523
+ "velocity-loss": { Icon: TrendingDownIcon, color: t9["status-warning"], label: "Velocity loss" },
10524
+ "missed-reps": { Icon: CircleSlashIcon, color: t9["status-warning"], label: "Missed reps" },
10525
+ pr: { Icon: AwardIcon, color: t9["status-success"], label: "Personal record" },
10526
+ info: { Icon: InfoIcon, color: t9["status-info"], label: "More info" }
10392
10527
  };
10393
10528
  var INDICATOR_PRECEDENCE = [
10394
10529
  "imbalance",
@@ -10621,7 +10756,7 @@ function CollapsedCard({
10621
10756
  totalPlannedSets,
10622
10757
  supersetPosition
10623
10758
  }) {
10624
- const [pressed, setPressed] = React24.useState(false);
10759
+ const [pressed, setPressed] = React25.useState(false);
10625
10760
  const completedSets = setVelocities?.length ?? 0;
10626
10761
  const remaining = Math.max(0, (totalPlannedSets ?? 0) - completedSets);
10627
10762
  const borderRadius = getSupersetBorderRadius(supersetPosition);
@@ -10853,7 +10988,7 @@ function ExerciseCard({
10853
10988
  onExpandedChange,
10854
10989
  ...rest
10855
10990
  }) {
10856
- const [internalExpanded, setInternalExpanded] = React24.useState(defaultExpanded ?? false);
10991
+ const [internalExpanded, setInternalExpanded] = React25.useState(defaultExpanded ?? false);
10857
10992
  const isControlled = expanded !== void 0;
10858
10993
  const isExpanded = isControlled ? expanded : internalExpanded;
10859
10994
  const onToggle = () => {
@@ -10864,8 +10999,6 @@ function ExerciseCard({
10864
10999
  if (upcoming) return /* @__PURE__ */ jsx(UpcomingCard, { ...rest, onToggle });
10865
11000
  return isExpanded ? /* @__PURE__ */ jsx(ExpandedCard, { ...rest, onToggle }) : /* @__PURE__ */ jsx(CollapsedCard, { ...rest, onToggle });
10866
11001
  }
10867
- var t9 = getSemanticColors("dark");
10868
- var HEADER_BG = t9["background-base"];
10869
11002
  var BAR_HEIGHT = 9;
10870
11003
  var BAR_GAP = 3;
10871
11004
  function SessionHeader({
@@ -10883,17 +11016,18 @@ function SessionHeader({
10883
11016
  }) {
10884
11017
  const upcoming = next != null;
10885
11018
  const totalSets = plan.reduce((sum, e) => sum + e.sets, 0);
11019
+ const onSurface = onSurfaceColors(useSurfaceMode());
10886
11020
  const hasPace = !upcoming && budgetMs != null && elapsedMs != null;
10887
11021
  const target = hasPace ? elapsedMs / budgetMs : void 0;
10888
11022
  const setsLabel = upcoming ? `${totalSets} sets` : `${Math.floor(setsDone)}/${totalSets} sets`;
10889
- const setsLabelColor = upcoming ? t9["text-secondary"] : paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target));
11023
+ const setsLabelColor = upcoming ? onSurface.secondary : paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target));
10890
11024
  return /* @__PURE__ */ jsxs(
10891
- reactNative.View,
11025
+ Surface,
10892
11026
  {
11027
+ level: "background",
10893
11028
  className,
10894
11029
  style: [
10895
11030
  {
10896
- backgroundColor: HEADER_BG,
10897
11031
  paddingTop: 11,
10898
11032
  paddingRight: 12,
10899
11033
  paddingBottom: 12,
@@ -10914,7 +11048,7 @@ function SessionHeader({
10914
11048
  lineHeight: 18,
10915
11049
  fontWeight: "700",
10916
11050
  fontFamily: '"Space Grotesk", sans-serif',
10917
- color: t9["text-primary"],
11051
+ color: onSurface.primary,
10918
11052
  marginBottom: 10
10919
11053
  },
10920
11054
  testID: "session-rail-title",
@@ -10970,7 +11104,6 @@ function SessionHeader({
10970
11104
  }
10971
11105
  );
10972
11106
  }
10973
- var INSET = primitiveColors.charcoal[600];
10974
11107
  var DIVIDER = primitiveColors.charcoal[300];
10975
11108
  var DEFAULT_WIDTH = 246;
10976
11109
  function SessionRail({
@@ -10990,10 +11123,11 @@ function SessionRail({
10990
11123
  ...props
10991
11124
  }) {
10992
11125
  return /* @__PURE__ */ jsxs(
10993
- reactNative.View,
11126
+ Surface,
10994
11127
  {
11128
+ level: "elevated",
10995
11129
  className,
10996
- style: [{ width, flexDirection: "column", backgroundColor: INSET }, style],
11130
+ style: [{ width, flexDirection: "column" }, style],
10997
11131
  testID: "session-rail",
10998
11132
  ...props,
10999
11133
  children: [
@@ -11011,9 +11145,10 @@ function SessionRail({
11011
11145
  }
11012
11146
  ),
11013
11147
  /* @__PURE__ */ jsx(
11014
- reactNative.View,
11148
+ Surface,
11015
11149
  {
11016
- style: [{ flex: 1, backgroundColor: INSET }, neumorphicShadows.charcoal.pressed.subtle],
11150
+ level: "elevated",
11151
+ style: [{ flex: 1 }, neumorphicShadows.charcoal.pressed.subtle],
11017
11152
  testID: "session-rail-list",
11018
11153
  children: exercises.map((ex, i) => /* @__PURE__ */ jsx(
11019
11154
  reactNative.View,
@@ -11050,7 +11185,7 @@ function SessionRail({
11050
11185
  var DEFAULTS = {
11051
11186
  label: "SS",
11052
11187
  color: getSemanticColors("dark")["brand-primary"],
11053
- bgBase: "#101010"
11188
+ bgBase: getSemanticColors("dark")["background-base"]
11054
11189
  };
11055
11190
  function SupersetWrapper({
11056
11191
  label = DEFAULTS.label,
@@ -11112,7 +11247,7 @@ function clampProgress(currentWeek, weekCount) {
11112
11247
  return Math.max(0, Math.min(1, ratio));
11113
11248
  }
11114
11249
  function MesoSegment({ meso, isActive, onPress }) {
11115
- const [pressScale] = React24.useState(() => new reactNative.Animated.Value(1));
11250
+ const [pressScale] = React25.useState(() => new reactNative.Animated.Value(1));
11116
11251
  const handlePressIn = () => {
11117
11252
  reactNative.Animated.timing(pressScale, {
11118
11253
  toValue: 0.98,
@@ -11480,8 +11615,8 @@ function MesoCard({
11480
11615
  ...props
11481
11616
  }) {
11482
11617
  const isExpandable = onToggle != null;
11483
- const [highlight] = React24.useState(() => new reactNative.Animated.Value(highlighted ? 1 : 0));
11484
- React24.useEffect(() => {
11618
+ const [highlight] = React25.useState(() => new reactNative.Animated.Value(highlighted ? 1 : 0));
11619
+ React25.useEffect(() => {
11485
11620
  const animation = reactNative.Animated.timing(highlight, {
11486
11621
  toValue: highlighted ? 1 : 0,
11487
11622
  duration: 250,
@@ -12031,7 +12166,7 @@ function renderCoachingText(text, highlights) {
12031
12166
  children: part
12032
12167
  },
12033
12168
  `${part}-${index}`
12034
- ) : /* @__PURE__ */ jsx(React24.Fragment, { children: part }, `t-${index}`)
12169
+ ) : /* @__PURE__ */ jsx(React25.Fragment, { children: part }, `t-${index}`)
12035
12170
  );
12036
12171
  }
12037
12172
  function StatusPill({ badge }) {
@@ -12497,17 +12632,17 @@ function StrengthTrendChart({
12497
12632
  className,
12498
12633
  ...props
12499
12634
  }) {
12500
- const geometry = React24.useMemo(
12635
+ const geometry = React25.useMemo(
12501
12636
  () => buildGeometry(data, projection, mesoBoundaries, width, height),
12502
12637
  [data, projection, mesoBoundaries, width, height]
12503
12638
  );
12504
- const trend = React24.useMemo(
12639
+ const trend = React25.useMemo(
12505
12640
  () => computeTrend(data, mesoBoundaries),
12506
12641
  [data, mesoBoundaries]
12507
12642
  );
12508
- const [reveal] = React24.useState(() => new reactNative.Animated.Value(animateOnMount ? 0 : 1));
12509
- const [selected, setSelected] = React24.useState(null);
12510
- React24.useEffect(() => {
12643
+ const [reveal] = React25.useState(() => new reactNative.Animated.Value(animateOnMount ? 0 : 1));
12644
+ const [selected, setSelected] = React25.useState(null);
12645
+ React25.useEffect(() => {
12511
12646
  if (!animateOnMount) return;
12512
12647
  const animation = reactNative.Animated.timing(reveal, {
12513
12648
  toValue: 1,
@@ -12961,12 +13096,12 @@ function CapacityBandChart({
12961
13096
  className,
12962
13097
  ...props
12963
13098
  }) {
12964
- const [reveal] = React24.useState(() => new reactNative.Animated.Value(0));
12965
- const dotAnims = React24.useMemo(
13099
+ const [reveal] = React25.useState(() => new reactNative.Animated.Value(0));
13100
+ const dotAnims = React25.useMemo(
12966
13101
  () => Array.from({ length: workouts.length }, () => new reactNative.Animated.Value(0)),
12967
13102
  [workouts.length]
12968
13103
  );
12969
- React24.useEffect(() => {
13104
+ React25.useEffect(() => {
12970
13105
  reveal.setValue(0);
12971
13106
  dotAnims.forEach((a) => a.setValue(0));
12972
13107
  const draw = reactNative.Animated.timing(reveal, {
@@ -12989,7 +13124,7 @@ function CapacityBandChart({
12989
13124
  }, [reveal, dotAnims, band.length, workouts.length]);
12990
13125
  const plotWidth = width - PADDING_LEFT - PADDING_RIGHT;
12991
13126
  const plotHeight = height - PADDING_TOP - PADDING_BOTTOM;
12992
- const scale = React24.useMemo(() => {
13127
+ const scale = React25.useMemo(() => {
12993
13128
  const times = band.map((p) => parseTime(p.date));
12994
13129
  projection?.withTraining.forEach((p) => times.push(parseTime(p.date)));
12995
13130
  projection?.withRest.forEach((p) => times.push(parseTime(p.date)));
@@ -13298,7 +13433,7 @@ function ZoneTrack({
13298
13433
  const s = ZONE_SIZES[size];
13299
13434
  const trackHeight = trackHeightProp ?? s.trackHeight;
13300
13435
  const needleOverhang = needleOverhangProp ?? s.needleOverhang;
13301
- const [trackW, setTrackW] = React24.useState(0);
13436
+ const [trackW, setTrackW] = React25.useState(0);
13302
13437
  const onTrackLayout = (e) => setTrackW(e.nativeEvent.layout.width);
13303
13438
  const tickCount = ticks?.length ?? 0;
13304
13439
  const tickSpacing = trackW > 0 && tickCount > 0 ? trackW / tickCount : Infinity;
@@ -14305,7 +14440,7 @@ function TopBar({
14305
14440
  onSelectDevice,
14306
14441
  className
14307
14442
  }) {
14308
- const [width, setWidth] = React24.useState(SUBTITLE_MIN);
14443
+ const [width, setWidth] = React25.useState(SUBTITLE_MIN);
14309
14444
  const onLayout = (e) => setWidth(e.nativeEvent.layout.width);
14310
14445
  const subtitleVisible = showSubtitle ?? width >= SUBTITLE_MIN;
14311
14446
  const clockVisible = showClock ?? width >= CLOCK_MIN;
@@ -14453,8 +14588,10 @@ function DashboardShell({
14453
14588
  return (
14454
14589
  // Column: the TopBar spans the FULL width across the top, and the SideNav sits BELOW it
14455
14590
  // in the content row (not a full-height left rail). This keeps the brand/status band
14456
- // unbroken edge-to-edge and lets the nav align under it.
14457
- /* @__PURE__ */ jsxs(reactNative.View, { className: cn("flex-1 bg-surface-base", className), children: [
14591
+ // unbroken edge-to-edge and lets the nav align under it. The shell is the outermost
14592
+ // Surface it owns the base plane and seeds the on-surface colour context (mode) for
14593
+ // the whole dashboard tree.
14594
+ /* @__PURE__ */ jsxs(Surface, { level: "base", className: cn("flex-1", className), children: [
14458
14595
  /* @__PURE__ */ jsx(TopBar, { state, devices, subtitle, onSelectDevice }),
14459
14596
  /* @__PURE__ */ jsxs(reactNative.View, { className: "flex-1 flex-row", children: [
14460
14597
  /* @__PURE__ */ jsx(SideNav, { activeKey, items: navItems, liveKey, onNavigate }),
@@ -14666,6 +14803,7 @@ exports.ModalTitle = ModalTitle;
14666
14803
  exports.MuscleGroupChip = MuscleGroupChip;
14667
14804
  exports.NavItem = NavItem;
14668
14805
  exports.Overline = Overline;
14806
+ exports.PRESSED_ELEVATION_LEVEL = PRESSED_ELEVATION_LEVEL;
14669
14807
  exports.Paragraph = Paragraph;
14670
14808
  exports.PasswordInput = PasswordInput;
14671
14809
  exports.PersonStandingIcon = PersonStandingIcon;
@@ -14685,6 +14823,7 @@ exports.ReadinessCheck = ReadinessCheck;
14685
14823
  exports.RestTimer = RestTimer;
14686
14824
  exports.SET_STRIP_VARIABLE_COLOR = SET_STRIP_VARIABLE_COLOR;
14687
14825
  exports.SET_STRIP_ZONES = SET_STRIP_ZONES;
14826
+ exports.SURFACE_LEVEL_TOKEN = SURFACE_LEVEL_TOKEN;
14688
14827
  exports.ScaleIcon = ScaleIcon;
14689
14828
  exports.Scatter = Scatter;
14690
14829
  exports.ScheduleTiles = ScheduleTiles;
@@ -14729,6 +14868,7 @@ exports.StepperStep = Step;
14729
14868
  exports.StrengthTrendChart = StrengthTrendChart;
14730
14869
  exports.SupersetWrapper = SupersetWrapper;
14731
14870
  exports.Surface = Surface;
14871
+ exports.SurfaceContext = SurfaceContext;
14732
14872
  exports.SvgIcon = SvgIcon;
14733
14873
  exports.Switch = Switch;
14734
14874
  exports.Tab = Tab;
@@ -14767,6 +14907,7 @@ exports.ZoneTrack = ZoneTrack;
14767
14907
  exports.alpha = alpha;
14768
14908
  exports.applyThemePreset = applyThemePreset;
14769
14909
  exports.audiobookPreset = audiobookPreset;
14910
+ exports.backgroundFrameDark = backgroundFrameDark;
14770
14911
  exports.bestTextColor = bestTextColor;
14771
14912
  exports.buttonSizes = buttonSizes;
14772
14913
  exports.calculateMeanVelocity = calculateMeanVelocity;
@@ -14805,6 +14946,7 @@ exports.getFieldValidationProps = getFieldValidationProps;
14805
14946
  exports.getGlowShadow = getGlowShadow;
14806
14947
  exports.getHoverColors = getHoverColors;
14807
14948
  exports.getLuminance = getLuminance;
14949
+ exports.getPressedRecessShadow = getPressedRecessShadow;
14808
14950
  exports.getResultColor = getResultColor;
14809
14951
  exports.getSemanticColors = getSemanticColors;
14810
14952
  exports.getStatusColor = getStatusColor;
@@ -14826,8 +14968,10 @@ exports.lighten = lighten;
14826
14968
  exports.linearGradient = linearGradient;
14827
14969
  exports.liveAuraColor = liveAuraColor;
14828
14970
  exports.neumorphicShadows = neumorphicShadows;
14971
+ exports.onSurfaceColors = onSurfaceColors;
14829
14972
  exports.paceTone = paceTone;
14830
14973
  exports.paceToneColor = paceToneColor;
14974
+ exports.pressedLevel = pressedLevel;
14831
14975
  exports.primitiveBorderRadius = primitiveBorderRadius;
14832
14976
  exports.primitiveBreakpoints = primitiveBreakpoints;
14833
14977
  exports.primitiveColors = primitiveColors;
@@ -14850,7 +14994,12 @@ exports.semanticTypography = semanticTypography;
14850
14994
  exports.sequentialEffort = sequentialEffort;
14851
14995
  exports.shadowColors = shadowColors;
14852
14996
  exports.statusPillColor = statusPillColor;
14997
+ exports.surfaceBackground = surfaceBackground;
14853
14998
  exports.surfaceGradient = surfaceGradient;
14999
+ exports.surfaceRampDark = surfaceRampDark;
15000
+ exports.useOnSurfaceColor = useOnSurfaceColor;
15001
+ exports.useSurface = useSurface;
15002
+ exports.useSurfaceMode = useSurfaceMode;
14854
15003
  exports.useTable = useTable;
14855
15004
  exports.useTimer = useTimer;
14856
15005
  exports.useToast = useToast;