@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.
- package/dist/bodymap.js +78 -24
- package/dist/bodymap.js.map +1 -1
- package/dist/bodymap.mjs +78 -24
- package/dist/bodymap.mjs.map +1 -1
- package/dist/index.d.mts +215 -123
- package/dist/index.d.ts +215 -123
- package/dist/index.js +408 -259
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +258 -121
- package/dist/index.mjs.map +1 -1
- package/dist/pages.js +214 -157
- package/dist/pages.js.map +1 -1
- package/dist/pages.mjs +214 -157
- package/dist/pages.mjs.map +1 -1
- package/dist/theme/index.d.mts +895 -795
- package/dist/theme/index.d.ts +895 -795
- package/dist/theme/index.js +101 -20
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/index.mjs +99 -22
- package/dist/theme/index.mjs.map +1 -1
- package/dist/theme/tokens-css.js +88 -24
- package/dist/theme/tokens-css.js.map +1 -1
- package/dist/theme/tokens-css.mjs +88 -24
- package/dist/theme/tokens-css.mjs.map +1 -1
- package/package.json +1 -1
- package/src/components/custom/Workout/BaseBadge.tsx +5 -5
- package/src/components/custom/Workout/RowInventory.stories.tsx +5 -2
- package/src/components/custom/Workout/S3FullRail.stories.tsx +13 -1
- package/src/components/custom/Workout/SessionHeader.tsx +11 -13
- package/src/components/custom/Workout/SessionRail.stories.tsx +4 -1
- package/src/components/custom/Workout/SessionRail.tsx +16 -14
- package/src/components/custom/Workout/SupersetWrapper.stories.tsx +16 -25
- package/src/components/custom/Workout/SupersetWrapper.tsx +1 -1
- package/src/components/custom/Workout/TempoDisplay.tsx +3 -7
- package/src/components/custom/Workout/VolumeLandmarkBar.stories.tsx +4 -1
- package/src/components/custom/Workout/WorkoutPill.tsx +2 -2
- package/src/components/shell/DashboardShell.tsx +6 -3
- package/src/components/ui/surface/Surface.stories.tsx +244 -1
- package/src/components/ui/surface/Surface.test.tsx +244 -1
- package/src/components/ui/surface/Surface.tsx +98 -20
- package/src/components/ui/surface/SurfaceContext.ts +126 -0
- package/src/components/ui/surface/index.ts +13 -0
- package/src/components/ui/surface/surface.contract.test.ts +283 -0
- package/src/test/nativewind-stub.ts +13 -0
- package/src/theme/ColorSystem.stories.tsx +232 -47
- package/src/theme/ThemeProvider.test.tsx +24 -0
- package/src/theme/ThemeProvider.tsx +23 -6
- package/src/theme/config.ts +12 -0
- package/src/theme/elevation.ts +90 -67
- package/src/theme/global.css +35 -9
- package/src/theme/tokens/primitives.ts +40 -0
- package/src/theme/tokens/semantic.ts +63 -14
- 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
|
|
7
|
+
var React25 = require('react');
|
|
8
8
|
|
|
9
9
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
10
|
|
|
11
|
-
var
|
|
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
|
-
|
|
922
|
-
//
|
|
923
|
-
|
|
924
|
-
//
|
|
925
|
-
|
|
926
|
-
//
|
|
927
|
-
|
|
928
|
-
//
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
//
|
|
932
|
-
"
|
|
933
|
-
//
|
|
934
|
-
"
|
|
935
|
-
//
|
|
936
|
-
"
|
|
937
|
-
//
|
|
938
|
-
|
|
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 =
|
|
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 =
|
|
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] =
|
|
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 =
|
|
1392
|
-
const [isVisible, setIsVisible] =
|
|
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
|
|
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] =
|
|
2753
|
+
const [isHovered, setIsHovered] = React25.useState(false);
|
|
2637
2754
|
const theme = useTheme();
|
|
2638
|
-
const elevationLevel =
|
|
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 =
|
|
2646
|
-
const surfaceColor =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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:
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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 =
|
|
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] =
|
|
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 } =
|
|
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:
|
|
3550
|
-
if (
|
|
3551
|
-
return
|
|
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 } =
|
|
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 } =
|
|
3622
|
-
return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-1", className), children:
|
|
3623
|
-
if (
|
|
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] =
|
|
3807
|
-
const [portalPos, setPortalPos] =
|
|
3808
|
-
const openTimeoutRef =
|
|
3809
|
-
const closeTimeoutRef =
|
|
3810
|
-
const triggerRef =
|
|
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
|
-
|
|
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 =
|
|
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] =
|
|
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 } =
|
|
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 } =
|
|
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 =
|
|
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] =
|
|
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:
|
|
4024
|
-
if (
|
|
4025
|
-
return
|
|
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 } =
|
|
4148
|
+
const { openIndices, toggleIndex } = React25.useContext(AccordionContext);
|
|
4032
4149
|
const isOpen = openIndices.has(index);
|
|
4033
|
-
return /* @__PURE__ */ jsx(reactNative.View, { className, children:
|
|
4034
|
-
if (
|
|
4035
|
-
return
|
|
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 =
|
|
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 =
|
|
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] =
|
|
4283
|
+
const [internalIsOpen, setInternalIsOpen] = React25.useState(false);
|
|
4167
4284
|
const isOpen = controlledIsOpen ?? internalIsOpen;
|
|
4168
|
-
const closeTimerRef =
|
|
4169
|
-
const setIsOpen =
|
|
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 =
|
|
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 =
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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 =
|
|
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] =
|
|
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 } =
|
|
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 } =
|
|
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 } =
|
|
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 =
|
|
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] =
|
|
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 } =
|
|
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 =
|
|
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] =
|
|
4601
|
-
const [isHovered, setIsHovered] =
|
|
4602
|
-
const handlePress =
|
|
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 =
|
|
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:
|
|
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
|
|
4870
|
+
return React25.useContext(ToolbarButtonContext);
|
|
4754
4871
|
}
|
|
4755
|
-
var RadioGroupContext =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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] =
|
|
5249
|
-
const addToast =
|
|
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 =
|
|
5381
|
+
const removeToast = React25.useCallback((id) => {
|
|
5265
5382
|
setToasts((prev) => prev.filter((t17) => t17.id !== id));
|
|
5266
5383
|
}, []);
|
|
5267
|
-
const removeAllToasts =
|
|
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 =
|
|
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
|
-
|
|
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] =
|
|
5443
|
-
const [isOpen, setIsOpen] =
|
|
5444
|
-
const [highlightedIndex, setHighlightedIndex] =
|
|
5445
|
-
const selectedOption =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
5588
|
+
const handleClear = React25.useCallback(() => {
|
|
5472
5589
|
onChange?.(null);
|
|
5473
5590
|
setInputValue("");
|
|
5474
5591
|
setIsOpen(false);
|
|
5475
5592
|
}, [onChange]);
|
|
5476
|
-
const handleFocus =
|
|
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 =
|
|
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] =
|
|
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 =
|
|
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
|
-
|
|
5804
|
-
if (
|
|
5920
|
+
React25__default.default.Children.map(children, (child) => {
|
|
5921
|
+
if (React25__default.default.isValidElement(child)) {
|
|
5805
5922
|
const childProps = child.props;
|
|
5806
|
-
return
|
|
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
|
|
6138
|
+
theme,
|
|
6139
|
+
rounded,
|
|
6020
6140
|
className,
|
|
6021
6141
|
style,
|
|
6022
6142
|
children,
|
|
6023
6143
|
...props
|
|
6024
6144
|
}) {
|
|
6025
|
-
const
|
|
6026
|
-
const
|
|
6027
|
-
const
|
|
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
|
-
|
|
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 =
|
|
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 } =
|
|
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 } =
|
|
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 =
|
|
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 } =
|
|
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] =
|
|
6664
|
-
const [pageSize, setPageSize] =
|
|
6665
|
-
const [sortColumn, setSortColumn] =
|
|
6666
|
-
const [sortDirection, setSortDirection] =
|
|
6667
|
-
const sortedData =
|
|
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 =
|
|
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 =
|
|
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:
|
|
6768
|
-
if (
|
|
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
|
-
|
|
6771
|
-
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 } =
|
|
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 } =
|
|
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:
|
|
6814
|
-
if (
|
|
6815
|
-
return
|
|
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 } =
|
|
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] =
|
|
7019
|
-
|
|
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] =
|
|
7054
|
-
|
|
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 =
|
|
7214
|
-
return /* @__PURE__ */ jsx(reactNative.View, { className: cn("flex-row items-center", className), ...props, children: items.map((child, i) => /* @__PURE__ */ jsxs(
|
|
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: "
|
|
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] =
|
|
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] =
|
|
7406
|
-
const [opacity] =
|
|
7407
|
-
|
|
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
|
|
7606
|
+
var t2 = getSemanticColors("dark");
|
|
7472
7607
|
var solidVariantColors = {
|
|
7473
|
-
success:
|
|
7474
|
-
warning:
|
|
7475
|
-
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":
|
|
7516
|
-
deviation:
|
|
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
|
|
7972
|
+
var t3 = getSemanticColors("dark");
|
|
7838
7973
|
var INTER = "Inter, sans-serif";
|
|
7839
7974
|
var TEXT_TERTIARY = "#6B7280";
|
|
7840
|
-
var STATUS_ERROR =
|
|
7841
|
-
var STATUS_SUCCESS =
|
|
7842
|
-
var 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
|
|
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] =
|
|
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 =
|
|
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: "
|
|
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 ?
|
|
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: "
|
|
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
|
|
8262
|
+
var t4 = getSemanticColors("dark");
|
|
8128
8263
|
function getDotColor(deviation) {
|
|
8129
8264
|
const abs = Math.abs(deviation);
|
|
8130
|
-
if (deviation < -0.3) return
|
|
8265
|
+
if (deviation < -0.3) return t4["status-success"];
|
|
8131
8266
|
if (abs <= 0.3) return "#6B7280";
|
|
8132
|
-
if (abs <= 0.7) return
|
|
8133
|
-
return
|
|
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
|
|
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:
|
|
8342
|
+
building: t5["status-success"],
|
|
8208
8343
|
// below target ramp-up
|
|
8209
|
-
approaching:
|
|
8344
|
+
approaching: t5["status-warning"],
|
|
8210
8345
|
// nearing target
|
|
8211
|
-
target:
|
|
8346
|
+
target: t5["brand-primary"],
|
|
8212
8347
|
// exactly at target
|
|
8213
|
-
over1:
|
|
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] =
|
|
8254
|
-
|
|
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
|
|
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: "
|
|
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:
|
|
8401
|
-
current:
|
|
8402
|
-
next:
|
|
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] =
|
|
8409
|
-
|
|
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] =
|
|
8540
|
-
|
|
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] =
|
|
8966
|
-
|
|
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] =
|
|
8982
|
-
|
|
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] =
|
|
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] =
|
|
9205
|
-
const [labelOpacity] =
|
|
9206
|
-
const [infoOpacity] =
|
|
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
|
-
|
|
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
|
|
9684
|
+
var t7 = getSemanticColors("dark");
|
|
9550
9685
|
var dotColorMap = {
|
|
9551
9686
|
untrained: "#2C2C2C",
|
|
9552
|
-
behind:
|
|
9553
|
-
ontrack:
|
|
9554
|
-
target:
|
|
9555
|
-
over:
|
|
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
|
|
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 =
|
|
10271
|
-
const sep =
|
|
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] =
|
|
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
|
|
10519
|
+
var t9 = getSemanticColors("dark");
|
|
10385
10520
|
var INDICATOR_CONFIG = {
|
|
10386
|
-
imbalance: { Icon: ScaleIcon, color:
|
|
10387
|
-
overshoot: { Icon: AlertTriangleIcon, color:
|
|
10388
|
-
"velocity-loss": { Icon: TrendingDownIcon, color:
|
|
10389
|
-
"missed-reps": { Icon: CircleSlashIcon, color:
|
|
10390
|
-
pr: { Icon: AwardIcon, color:
|
|
10391
|
-
info: { Icon: InfoIcon, color:
|
|
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] =
|
|
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] =
|
|
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 ?
|
|
11023
|
+
const setsLabelColor = upcoming ? onSurface.secondary : paceToneColor(paceTone(totalSets > 0 ? setsDone / totalSets : 0, target));
|
|
10890
11024
|
return /* @__PURE__ */ jsxs(
|
|
10891
|
-
|
|
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:
|
|
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
|
-
|
|
11126
|
+
Surface,
|
|
10994
11127
|
{
|
|
11128
|
+
level: "elevated",
|
|
10995
11129
|
className,
|
|
10996
|
-
style: [{ width, flexDirection: "column"
|
|
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
|
-
|
|
11148
|
+
Surface,
|
|
11015
11149
|
{
|
|
11016
|
-
|
|
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: "
|
|
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] =
|
|
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] =
|
|
11484
|
-
|
|
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(
|
|
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 =
|
|
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 =
|
|
12639
|
+
const trend = React25.useMemo(
|
|
12505
12640
|
() => computeTrend(data, mesoBoundaries),
|
|
12506
12641
|
[data, mesoBoundaries]
|
|
12507
12642
|
);
|
|
12508
|
-
const [reveal] =
|
|
12509
|
-
const [selected, setSelected] =
|
|
12510
|
-
|
|
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] =
|
|
12965
|
-
const dotAnims =
|
|
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
|
-
|
|
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 =
|
|
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] =
|
|
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] =
|
|
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
|
-
|
|
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;
|