@titan-design/react-ui 0.2.7 → 0.3.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 (82) hide show
  1. package/dist/bodymap-BhG55xHM.d.mts +318 -0
  2. package/dist/bodymap-BhG55xHM.d.ts +318 -0
  3. package/dist/bodymap.d.mts +3 -0
  4. package/dist/bodymap.d.ts +3 -0
  5. package/dist/bodymap.js +2670 -0
  6. package/dist/bodymap.js.map +1 -0
  7. package/dist/bodymap.mjs +1101 -0
  8. package/dist/bodymap.mjs.map +1 -0
  9. package/dist/{chunk-5SSKGS6E.mjs → chunk-7XPB4NAO.mjs} +124 -4
  10. package/dist/chunk-7XPB4NAO.mjs.map +1 -0
  11. package/dist/{chunk-3VLOBS6O.mjs → chunk-P7TSQUN6.mjs} +3 -3
  12. package/dist/{chunk-3VLOBS6O.mjs.map → chunk-P7TSQUN6.mjs.map} +1 -1
  13. package/dist/chunk-TOD2WQBG.mjs +1048 -0
  14. package/dist/chunk-TOD2WQBG.mjs.map +1 -0
  15. package/dist/index.d.mts +375 -249
  16. package/dist/index.d.ts +375 -249
  17. package/dist/index.js +1259 -918
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +1314 -2107
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/theme/index.d.mts +260 -0
  22. package/dist/theme/index.d.ts +260 -0
  23. package/dist/theme/index.js +122 -2
  24. package/dist/theme/index.js.map +1 -1
  25. package/dist/theme/index.mjs +2 -2
  26. package/dist/theme/tokens-css.d.mts +5 -3
  27. package/dist/theme/tokens-css.d.ts +5 -3
  28. package/dist/theme/tokens-css.js +318 -9
  29. package/dist/theme/tokens-css.js.map +1 -1
  30. package/dist/theme/tokens-css.mjs +1 -1
  31. package/dist/theme/tokens-css.mjs.map +1 -1
  32. package/package.json +10 -1
  33. package/src/bodymap.ts +37 -0
  34. package/src/components/custom/Table/Table.test.tsx +27 -0
  35. package/src/components/custom/Table/Table.tsx +33 -17
  36. package/src/components/custom/Workout/ActiveWorkoutPage.stories.tsx +118 -0
  37. package/src/components/custom/Workout/ActiveWorkoutPage.test.tsx +171 -0
  38. package/src/components/custom/Workout/ActiveWorkoutPage.tsx +447 -0
  39. package/src/components/custom/Workout/BodyMap.tsx +5 -6
  40. package/src/components/custom/Workout/BodyMapDetailPanel.tsx +7 -8
  41. package/src/components/custom/Workout/CapacityBandChart.tsx +1 -1
  42. package/src/components/custom/Workout/ExerciseCard.test.tsx +24 -0
  43. package/src/components/custom/Workout/ExerciseCard.tsx +28 -15
  44. package/src/components/custom/Workout/ExerciseDetailPage.stories.tsx +225 -0
  45. package/src/components/custom/Workout/ExerciseDetailPage.test.tsx +128 -0
  46. package/src/components/custom/Workout/ExerciseDetailPage.tsx +630 -0
  47. package/src/components/custom/Workout/InputBar.tsx +6 -7
  48. package/src/components/custom/Workout/MesoCard.tsx +4 -2
  49. package/src/components/custom/Workout/MesoProgressBar.test.tsx +12 -0
  50. package/src/components/custom/Workout/MesoProgressBar.tsx +5 -1
  51. package/src/components/custom/Workout/MesoStatusCard.tsx +5 -5
  52. package/src/components/custom/Workout/PlaceholderStrip.tsx +2 -3
  53. package/src/components/custom/Workout/PrHistoryModal.tsx +5 -5
  54. package/src/components/custom/Workout/ProgramPlanningPage.stories.tsx +257 -0
  55. package/src/components/custom/Workout/ProgramPlanningPage.test.tsx +142 -0
  56. package/src/components/custom/Workout/ProgramPlanningPage.tsx +422 -0
  57. package/src/components/custom/Workout/ReadinessCheck.tsx +7 -8
  58. package/src/components/custom/Workout/RestTimer.test.tsx +10 -0
  59. package/src/components/custom/Workout/RestTimer.tsx +11 -9
  60. package/src/components/custom/Workout/SetRow.tsx +13 -19
  61. package/src/components/custom/Workout/StatusDot.tsx +1 -0
  62. package/src/components/custom/Workout/StrengthTrendChart.tsx +5 -5
  63. package/src/components/custom/Workout/TempoDisplay.tsx +3 -1
  64. package/src/components/custom/Workout/TrainingStatusPage.stories.tsx +212 -0
  65. package/src/components/custom/Workout/TrainingStatusPage.test.tsx +131 -0
  66. package/src/components/custom/Workout/TrainingStatusPage.tsx +321 -0
  67. package/src/components/custom/Workout/VelocityStrip.test.tsx +10 -0
  68. package/src/components/custom/Workout/VelocityStrip.tsx +16 -15
  69. package/src/components/custom/Workout/WeekRow.tsx +1 -1
  70. package/src/components/custom/Workout/WorkoutCard.tsx +5 -3
  71. package/src/components/custom/Workout/index.ts +71 -32
  72. package/src/theme/config.completeness.test.ts +77 -0
  73. package/src/theme/config.ts +151 -0
  74. package/src/theme/manifest/design-freeze.test.ts +155 -0
  75. package/src/theme/manifest/extract-css-properties.fixture.html +29 -0
  76. package/src/theme/manifest/extract-css-properties.test.ts +112 -0
  77. package/src/theme/tokens-css.ts +5 -3
  78. package/src/theme/workout-tokens.ts +12 -14
  79. package/src/utils/index.ts +10 -0
  80. package/src/utils/workout-format.test.ts +81 -0
  81. package/src/utils/workout-format.ts +83 -0
  82. package/dist/chunk-5SSKGS6E.mjs.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,37 +1,13 @@
1
- import { getHoverColors, getValidatedElevation, getBaseSurfaceColor, getElevationSurface, getElevationShadow, getGlowShadow, neumorphicShadows } from './chunk-3VLOBS6O.mjs';
2
- export { applyThemePreset, audiobookPreset, componentElevationRanges, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darken, defaultPreset, elevationSystem, getBaseSurfaceColor, getElevationConfig, getElevationShadow, getElevationSurface, getGlowShadow, getHoverColors, getValidatedElevation, hexToRgb, hsvToRgb, isCssPropertyManifest, isDark, lighten, neumorphicShadows, rgbToHex, rgbToHsv, shadowColors, validateCssPropertyManifest } from './chunk-3VLOBS6O.mjs';
3
- import { semanticColorsDark, __require } from './chunk-5SSKGS6E.mjs';
4
- export { buttonSizes, darkThemeCSSVars, discreteRainbow, getDiscreteRainbowColor, getSemanticColors, getThemeCSSVars, gluestackConfig, lightThemeCSSVars, primitiveBorderRadius, primitiveBreakpoints, primitiveColors, primitiveShadows, primitiveSpacing, primitiveTypography, primitiveZIndex, semanticColorsDark, semanticColorsLight, semanticTypography } from './chunk-5SSKGS6E.mjs';
1
+ import { jsxs, jsx, cn, WORKOUT_TOKENS, Fragment, Card, Badge, MesoStatusCard } from './chunk-TOD2WQBG.mjs';
2
+ export { Badge, BadgeText, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Indicator, MesoStatusCard, Sparkline, StatusDot, cn } from './chunk-TOD2WQBG.mjs';
3
+ import { getHoverColors, getBaseSurfaceColor, getElevationSurface, getElevationShadow, getGlowShadow, neumorphicShadows } from './chunk-P7TSQUN6.mjs';
4
+ export { applyThemePreset, audiobookPreset, componentElevationRanges, createFlatShadow, createPressedHoverShadow, createPressedShadow, createRaisedHoverShadow, createRaisedShadow, darken, defaultPreset, elevationSystem, getBaseSurfaceColor, getElevationConfig, getElevationShadow, getElevationSurface, getGlowShadow, getHoverColors, getValidatedElevation, hexToRgb, hsvToRgb, isCssPropertyManifest, isDark, lighten, neumorphicShadows, rgbToHex, rgbToHsv, shadowColors, validateCssPropertyManifest } from './chunk-P7TSQUN6.mjs';
5
+ import { semanticColorsDark, __require } from './chunk-7XPB4NAO.mjs';
6
+ export { buttonSizes, darkThemeCSSVars, discreteRainbow, getDiscreteRainbowColor, getSemanticColors, getThemeCSSVars, gluestackConfig, lightThemeCSSVars, primitiveBorderRadius, primitiveBreakpoints, primitiveColors, primitiveShadows, primitiveSpacing, primitiveTypography, primitiveZIndex, semanticColorsDark, semanticColorsLight, semanticTypography } from './chunk-7XPB4NAO.mjs';
5
7
  import { Pressable, ActivityIndicator, Text, View, TextInput, Platform, StyleSheet, Easing, Image, Modal as Modal$1, ScrollView, Animated } from 'react-native';
6
- import { clsx } from 'clsx';
7
- import { twMerge } from 'tailwind-merge';
8
- import { jsx as jsx$1, jsxs as jsxs$1, Fragment } from 'react/jsx-runtime';
9
- import React24, { forwardRef, useState, createContext, useMemo, useContext, useRef, useEffect, useCallback, useSyncExternalStore, Fragment as Fragment$1 } from 'react';
8
+ import React23, { forwardRef, useState, createContext, useContext, useRef, useEffect, useCallback, useMemo } from 'react';
10
9
  import { Dumbbell, Star } from 'lucide-react';
11
- import BodyHighlighter from 'react-native-body-highlighter';
12
10
 
13
- function cn(...inputs) {
14
- return twMerge(clsx(inputs));
15
- }
16
- function wrapJsx(fn) {
17
- return function(type, props, ...rest) {
18
- if (props && typeof props.className === "string" && props.className) {
19
- const cn2 = props.className;
20
- const cssStyle = { $$css: true, [cn2]: cn2 };
21
- const existing = props.style;
22
- props = {
23
- ...props,
24
- style: existing ? [cssStyle, existing] : cssStyle
25
- };
26
- delete props.className;
27
- }
28
- return fn(type, props, ...rest);
29
- };
30
- }
31
- var jsx = wrapJsx(jsx$1);
32
- var jsxs = wrapJsx(jsxs$1);
33
-
34
- // src/components/ui/alert/Alert.tsx
35
11
  var statusColors = {
36
12
  success: {
37
13
  subtle: "bg-status-success-subtle",
@@ -472,328 +448,6 @@ var PasswordInput = forwardRef(function PasswordInput2({ showIcon, hideIcon, ...
472
448
  }
473
449
  );
474
450
  });
475
- function getTheme() {
476
- if (typeof document === "undefined") return "dark";
477
- return document.documentElement.classList.contains("light") ? "light" : "dark";
478
- }
479
- var listeners = [];
480
- function subscribe(listener) {
481
- listeners = [...listeners, listener];
482
- if (typeof document !== "undefined" && listeners.length === 1) {
483
- const observer = new MutationObserver((mutations) => {
484
- for (const mutation of mutations) {
485
- if (mutation.type === "attributes" && mutation.attributeName === "class") {
486
- listeners.forEach((l) => l());
487
- }
488
- }
489
- });
490
- observer.observe(document.documentElement, {
491
- attributes: true,
492
- attributeFilter: ["class"]
493
- });
494
- subscribe._observer = observer;
495
- }
496
- return () => {
497
- listeners = listeners.filter((l) => l !== listener);
498
- if (listeners.length === 0 && subscribe._observer) {
499
- subscribe._observer.disconnect();
500
- subscribe._observer = null;
501
- }
502
- };
503
- }
504
- function getSnapshot() {
505
- return getTheme();
506
- }
507
- function getServerSnapshot() {
508
- return "dark";
509
- }
510
- function useTheme() {
511
- return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
512
- }
513
-
514
- // src/components/ui/card/Card.tsx
515
- var variantStyles3 = {
516
- elevated: "",
517
- // Will be set dynamically via elevation system
518
- outline: "border-2 border-border-strong",
519
- // Thicker border with stronger contrast
520
- filled: "",
521
- // Will be set dynamically via elevation system
522
- accent: "border border-border",
523
- subtle: "border border-border-subtle"
524
- };
525
- function Card({
526
- variant = "elevated",
527
- elevation = 2,
528
- isInteractive = false,
529
- isLoading = false,
530
- onPress,
531
- borderColor,
532
- bgColor,
533
- accentColor,
534
- accentWidth,
535
- className,
536
- children,
537
- style,
538
- skeletonHasHeader = true,
539
- skeletonHasFooter = false,
540
- skeletonContentLines = 3,
541
- ...props
542
- }) {
543
- const isClickable = isInteractive || !!onPress;
544
- const [isHovered, setIsHovered] = useState(false);
545
- const theme = useTheme();
546
- const elevationLevel = useMemo(() => {
547
- const validated = getValidatedElevation("card", elevation);
548
- if (variant === "outline" || variant === "accent" || variant === "subtle") {
549
- return 1;
550
- }
551
- return validated;
552
- }, [variant, elevation]);
553
- const baseColor = useMemo(() => getBaseSurfaceColor(theme), [theme]);
554
- const surfaceColor = useMemo(() => {
555
- if ((variant === "outline" || variant === "accent") && theme === "light") {
556
- return "#FAFAFA";
557
- }
558
- if (variant === "subtle") {
559
- return getElevationSurface(baseColor, 0, theme);
560
- }
561
- return getElevationSurface(baseColor, elevationLevel, theme);
562
- }, [baseColor, elevationLevel, theme, variant]);
563
- const shadowStyle = useMemo(() => {
564
- const shouldHover = isHovered && isClickable;
565
- return getElevationShadow(baseColor, elevationLevel, theme, shouldHover);
566
- }, [baseColor, elevationLevel, theme, isHovered, isClickable]);
567
- const cardContent = isLoading ? /* @__PURE__ */ jsxs(Fragment, { children: [
568
- skeletonHasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
569
- /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
570
- /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
571
- ] }),
572
- /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: skeletonContentLines }).map((_, i) => /* @__PURE__ */ jsx(
573
- View,
574
- {
575
- className: cn(
576
- "h-4 bg-interactive-disabled rounded",
577
- i < skeletonContentLines - 1 ? "mb-2 w-full" : "w-4/5"
578
- )
579
- },
580
- i
581
- )) }),
582
- skeletonHasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
583
- ] }) : children;
584
- const baseClassName = cn(
585
- "rounded-lg overflow-hidden relative",
586
- // Apply variant styles, but only use default border color if no custom borderColor
587
- variant === "outline" ? borderColor ? "border-2" : variantStyles3[variant] : variantStyles3[variant],
588
- // Remove Tailwind shadow classes - we're using elevation shadows via style prop
589
- isClickable && "web:cursor-pointer web:transition-all web:duration-150",
590
- isClickable && "web:hover:-translate-y-0.5 active:scale-[0.99]",
591
- isLoading && "pointer-events-none animate-pulse",
592
- className
593
- );
594
- const accentStyle = useMemo(() => variant === "accent" ? {
595
- borderLeftWidth: accentWidth ?? 3,
596
- borderLeftColor: accentColor ?? "var(--color-brand-primary)"
597
- } : {}, [variant, accentWidth, accentColor]);
598
- const mergedStyle = useMemo(() => {
599
- const elevationStyle = {
600
- backgroundColor: bgColor || surfaceColor,
601
- borderRadius: 8,
602
- overflow: "hidden",
603
- ...shadowStyle,
604
- ...accentStyle
605
- };
606
- if (borderColor) {
607
- elevationStyle.borderColor = borderColor;
608
- }
609
- if (!style) return elevationStyle;
610
- return [elevationStyle, style];
611
- }, [style, surfaceColor, shadowStyle, borderColor, bgColor, accentStyle]);
612
- if (isClickable) {
613
- return /* @__PURE__ */ jsx(
614
- Pressable,
615
- {
616
- onPress,
617
- onHoverIn: () => setIsHovered(true),
618
- onHoverOut: () => setIsHovered(false),
619
- accessibilityRole: "button",
620
- className: baseClassName,
621
- style: mergedStyle,
622
- ...props,
623
- children: cardContent
624
- }
625
- );
626
- }
627
- return /* @__PURE__ */ jsx(View, { className: baseClassName, style: mergedStyle, ...props, children: cardContent });
628
- }
629
- function CardHeader({ children, className }) {
630
- return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-6", className), children });
631
- }
632
- function CardTitle({ children, className }) {
633
- return /* @__PURE__ */ jsx(
634
- Text,
635
- {
636
- accessibilityRole: "header",
637
- className: cn("text-lg font-semibold text-text-primary font-heading", className),
638
- children
639
- }
640
- );
641
- }
642
- function CardDescription({ children, className }) {
643
- return /* @__PURE__ */ jsx(Text, { className: cn("mt-1.5 text-sm text-text-secondary", className), children });
644
- }
645
- function CardContent({ children, className }) {
646
- return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4", className), children });
647
- }
648
- function CardFooter({ children, className }) {
649
- return /* @__PURE__ */ jsx(View, { className: cn("px-6 py-4 flex-row items-center gap-2", className), children });
650
- }
651
- function CardSkeleton({
652
- hasHeader = true,
653
- hasFooter = false,
654
- contentLines = 3,
655
- className
656
- }) {
657
- return /* @__PURE__ */ jsxs(Card, { variant: "elevated", elevation: 2, className: cn("animate-pulse", className), children: [
658
- hasHeader && /* @__PURE__ */ jsxs(CardHeader, { children: [
659
- /* @__PURE__ */ jsx(View, { className: "h-5 w-1/3 bg-interactive-disabled rounded" }),
660
- /* @__PURE__ */ jsx(View, { className: "mt-2 h-4 w-2/3 bg-interactive-disabled rounded" })
661
- ] }),
662
- /* @__PURE__ */ jsx(CardContent, { children: Array.from({ length: contentLines }).map((_, i) => /* @__PURE__ */ jsx(
663
- View,
664
- {
665
- className: cn(
666
- "h-4 bg-interactive-disabled rounded",
667
- i < contentLines - 1 ? "mb-2 w-full" : "w-4/5"
668
- )
669
- },
670
- i
671
- )) }),
672
- hasFooter && /* @__PURE__ */ jsx(CardFooter, { children: /* @__PURE__ */ jsx(View, { className: "h-9 w-24 bg-interactive-disabled rounded" }) })
673
- ] });
674
- }
675
- var sizeStyles3 = {
676
- xs: "w-1 h-1",
677
- sm: "w-1.5 h-1.5",
678
- md: "w-2 h-2",
679
- lg: "w-2.5 h-2.5"
680
- };
681
- var colorStyles = {
682
- default: "bg-text-tertiary",
683
- primary: "bg-brand-primary",
684
- success: "bg-status-success",
685
- error: "bg-status-error",
686
- warning: "bg-status-warning",
687
- info: "bg-status-info"
688
- };
689
- function Indicator({
690
- size = "sm",
691
- color = "default",
692
- customColor,
693
- glow = false,
694
- ring = false,
695
- className,
696
- style,
697
- ...props
698
- }) {
699
- const dynamicStyle = {
700
- ...typeof style === "object" ? style : {},
701
- ...customColor ? { backgroundColor: customColor } : {},
702
- ...glow && !customColor ? {} : {},
703
- ...glow && customColor ? { boxShadow: `0 0 6px ${customColor}` } : {}
704
- };
705
- return /* @__PURE__ */ jsx(
706
- View,
707
- {
708
- className: cn(
709
- "rounded-full shrink-0",
710
- sizeStyles3[size],
711
- !customColor && colorStyles[color],
712
- ring && "border-2 border-background-base",
713
- glow && !customColor && color === "success" && "shadow-[0_0_6px_rgba(20,184,166,0.6)]",
714
- glow && !customColor && color === "error" && "shadow-[0_0_6px_rgba(239,68,68,0.6)]",
715
- glow && !customColor && color === "warning" && "shadow-[0_0_6px_rgba(245,158,11,0.6)]",
716
- glow && !customColor && color === "primary" && "shadow-[0_0_6px_rgba(255,121,0,0.6)]",
717
- className
718
- ),
719
- style: Object.keys(dynamicStyle).length > 0 ? dynamicStyle : style,
720
- ...props
721
- }
722
- );
723
- }
724
-
725
- // src/components/ui/badge/Badge.tsx
726
- var variantColorStyles = {
727
- solid: {
728
- default: "bg-border-strong text-text-inverse",
729
- primary: "bg-brand-primary text-text-inverse",
730
- secondary: "bg-brand-secondary text-text-inverse",
731
- success: "bg-status-success text-text-inverse",
732
- error: "bg-status-error text-text-inverse",
733
- warning: "bg-status-warning text-text-inverse",
734
- info: "bg-status-info text-text-inverse"
735
- },
736
- subtle: {
737
- default: "bg-surface-raised text-text-secondary",
738
- primary: "bg-brand-primary-subtle text-brand-primary",
739
- secondary: "bg-brand-secondary-subtle text-brand-secondary",
740
- success: "bg-status-success-subtle text-status-success",
741
- error: "bg-status-error-subtle text-status-error",
742
- warning: "bg-status-warning-subtle text-status-warning",
743
- info: "bg-status-info-subtle text-status-info"
744
- },
745
- outline: {
746
- default: "border border-border-strong text-text-secondary",
747
- primary: "border border-brand-primary text-brand-primary",
748
- secondary: "border border-brand-secondary text-brand-secondary",
749
- success: "border border-status-success text-status-success",
750
- error: "border border-status-error text-status-error",
751
- warning: "border border-status-warning text-status-warning",
752
- info: "border border-status-info text-status-info"
753
- }
754
- };
755
- var sizeStyles4 = {
756
- sm: "px-1.5 py-0.5 text-xs",
757
- md: "px-2 py-0.5 text-xs",
758
- lg: "px-2.5 py-1 text-sm"
759
- };
760
- function Badge({
761
- variant = "subtle",
762
- color = "default",
763
- size = "md",
764
- dot,
765
- dotColor,
766
- className,
767
- children,
768
- ...props
769
- }) {
770
- return /* @__PURE__ */ jsxs(
771
- View,
772
- {
773
- className: cn(
774
- "inline-flex items-center justify-center rounded-full font-medium",
775
- variantColorStyles[variant][color],
776
- sizeStyles4[size],
777
- className
778
- ),
779
- ...props,
780
- children: [
781
- dot && /* @__PURE__ */ jsx(
782
- Indicator,
783
- {
784
- size: "xs",
785
- color: dotColor ?? (color === "default" || color === "secondary" ? "default" : color),
786
- className: "mr-0.5"
787
- }
788
- ),
789
- typeof children === "string" ? /* @__PURE__ */ jsx(Text, { className: "text-inherit font-medium", children }) : children
790
- ]
791
- }
792
- );
793
- }
794
- function BadgeText({ children, className }) {
795
- return /* @__PURE__ */ jsx(Text, { className: cn("text-inherit font-medium", className), children });
796
- }
797
451
  var sizeMap = {
798
452
  sm: "small",
799
453
  md: "small",
@@ -862,7 +516,7 @@ function getInitials(name) {
862
516
  }
863
517
 
864
518
  // src/components/ui/avatar/Avatar.tsx
865
- var sizeStyles5 = {
519
+ var sizeStyles3 = {
866
520
  xs: { container: "w-6 h-6", text: "text-xs", image: "w-6 h-6" },
867
521
  sm: { container: "w-8 h-8", text: "text-xs", image: "w-8 h-8" },
868
522
  md: { container: "w-10 h-10", text: "text-sm", image: "w-10 h-10" },
@@ -879,7 +533,7 @@ function Avatar({
879
533
  className,
880
534
  ...props
881
535
  }) {
882
- const styles2 = sizeStyles5[size];
536
+ const styles2 = sizeStyles3[size];
883
537
  const hasImage = source !== void 0;
884
538
  const resolvedFallback = fallback ?? (colorFromName ? getInitials(colorFromName) : void 0);
885
539
  const nameColor = colorFromName ? avatarColor(colorFromName) : void 0;
@@ -931,7 +585,7 @@ function AvatarGroup({
931
585
  size = "md",
932
586
  className
933
587
  }) {
934
- const childArray = React24.Children.toArray(children);
588
+ const childArray = React23.Children.toArray(children);
935
589
  const visibleChildren = max ? childArray.slice(0, max) : childArray;
936
590
  const remainingCount = max ? Math.max(0, childArray.length - max) : 0;
937
591
  return /* @__PURE__ */ jsxs(View, { className: cn("flex-row", className), children: [
@@ -942,7 +596,7 @@ function AvatarGroup({
942
596
  "border-2 border-surface-base rounded-full",
943
597
  index > 0 && "-ml-2"
944
598
  ),
945
- children: React24.isValidElement(child) ? React24.cloneElement(child, { size }) : child
599
+ children: React23.isValidElement(child) ? React23.cloneElement(child, { size }) : child
946
600
  },
947
601
  index
948
602
  )),
@@ -952,9 +606,9 @@ function AvatarGroup({
952
606
  className: cn(
953
607
  "border-2 border-surface-base rounded-full -ml-2",
954
608
  "items-center justify-center bg-surface-raised",
955
- sizeStyles5[size].container
609
+ sizeStyles3[size].container
956
610
  ),
957
- children: /* @__PURE__ */ jsxs(Text, { className: cn("font-semibold text-text-secondary", sizeStyles5[size].text), children: [
611
+ children: /* @__PURE__ */ jsxs(Text, { className: cn("font-semibold text-text-secondary", sizeStyles3[size].text), children: [
958
612
  "+",
959
613
  remainingCount
960
614
  ] })
@@ -980,7 +634,7 @@ function Divider({
980
634
  }
981
635
  );
982
636
  }
983
- var sizeStyles6 = {
637
+ var sizeStyles4 = {
984
638
  sm: { box: "w-4 h-4", icon: "w-2.5 h-2.5", label: "text-sm" },
985
639
  md: { box: "w-5 h-5", icon: "w-3 h-3", label: "text-base" },
986
640
  lg: { box: "w-6 h-6", icon: "w-3.5 h-3.5", label: "text-lg" }
@@ -998,7 +652,7 @@ var Checkbox = forwardRef(function Checkbox2({
998
652
  className,
999
653
  ...props
1000
654
  }, ref) {
1001
- const styles2 = sizeStyles6[size];
655
+ const styles2 = sizeStyles4[size];
1002
656
  const handlePress = () => {
1003
657
  if (!isDisabled) {
1004
658
  onCheckedChange?.(!isChecked);
@@ -1066,7 +720,7 @@ function CheckboxGroup({
1066
720
  )
1067
721
  ] });
1068
722
  }
1069
- var sizeStyles7 = {
723
+ var sizeStyles5 = {
1070
724
  sm: { track: "w-8 h-4", thumb: "w-3 h-3", translate: "translate-x-4" },
1071
725
  md: { track: "w-10 h-5", thumb: "w-4 h-4", translate: "translate-x-5" },
1072
726
  lg: { track: "w-12 h-6", thumb: "w-5 h-5", translate: "translate-x-6" }
@@ -1081,7 +735,7 @@ var Switch = forwardRef(function Switch2({
1081
735
  className,
1082
736
  ...props
1083
737
  }, ref) {
1084
- const styles2 = sizeStyles7[size];
738
+ const styles2 = sizeStyles5[size];
1085
739
  const handlePress = () => {
1086
740
  if (!isDisabled) {
1087
741
  onCheckedChange?.(!isChecked);
@@ -1131,7 +785,7 @@ var Switch = forwardRef(function Switch2({
1131
785
  );
1132
786
  });
1133
787
  var ModalContext = createContext({ size: "md", scrollBehavior: "outside" });
1134
- var sizeStyles8 = {
788
+ var sizeStyles6 = {
1135
789
  xs: "max-w-xs",
1136
790
  sm: "max-w-sm",
1137
791
  md: "max-w-md",
@@ -1198,7 +852,7 @@ function ModalContent({ children, className }) {
1198
852
  {
1199
853
  className: cn(
1200
854
  "bg-surface-elevated rounded-lg shadow-xl w-full",
1201
- sizeStyles8[size],
855
+ sizeStyles6[size],
1202
856
  className
1203
857
  ),
1204
858
  children
@@ -1264,7 +918,7 @@ function Skeleton({
1264
918
  style,
1265
919
  ...props
1266
920
  }) {
1267
- const variantStyles5 = {
921
+ const variantStyles4 = {
1268
922
  text: "h-4 rounded",
1269
923
  circle: "rounded-full",
1270
924
  rect: "",
@@ -1289,7 +943,7 @@ function Skeleton({
1289
943
  accessibilityLabel: "Loading...",
1290
944
  className: cn(
1291
945
  "bg-interactive-disabled",
1292
- variantStyles5[variant],
946
+ variantStyles4[variant],
1293
947
  animationStyles[animation],
1294
948
  className
1295
949
  ),
@@ -1412,7 +1066,7 @@ function Tabs({
1412
1066
  }
1413
1067
  function TabList({ children, className }) {
1414
1068
  const { variant, orientation } = useContext(TabsContext);
1415
- const variantStyles5 = {
1069
+ const variantStyles4 = {
1416
1070
  line: orientation === "horizontal" ? "border-b border-border" : "border-r border-border",
1417
1071
  enclosed: "bg-surface-raised rounded-lg p-1",
1418
1072
  "soft-rounded": "bg-surface-raised rounded-full p-1"
@@ -1422,12 +1076,12 @@ function TabList({ children, className }) {
1422
1076
  {
1423
1077
  className: cn(
1424
1078
  orientation === "horizontal" ? "flex-row" : "flex-col",
1425
- variantStyles5[variant],
1079
+ variantStyles4[variant],
1426
1080
  className
1427
1081
  ),
1428
- children: React24.Children.map(children, (child, index) => {
1429
- if (React24.isValidElement(child)) {
1430
- return React24.cloneElement(child, { index });
1082
+ children: React23.Children.map(children, (child, index) => {
1083
+ if (React23.isValidElement(child)) {
1084
+ return React23.cloneElement(child, { index });
1431
1085
  }
1432
1086
  return child;
1433
1087
  })
@@ -1455,7 +1109,7 @@ function Tab({
1455
1109
  const { activeIndex, setActiveIndex, variant, orientation } = useContext(TabsContext);
1456
1110
  const isActive = activeIndex === index;
1457
1111
  const baseStyles = "font-medium text-sm transition-colors";
1458
- const variantStyles5 = {
1112
+ const variantStyles4 = {
1459
1113
  line: cn(
1460
1114
  "px-4 py-2",
1461
1115
  orientation === "horizontal" ? "-mb-px border-b-2" : "-mr-px border-r-2",
@@ -1479,7 +1133,7 @@ function Tab({
1479
1133
  onPress: () => setActiveIndex(index),
1480
1134
  className: cn(
1481
1135
  baseStyles,
1482
- variantStyles5[variant],
1136
+ variantStyles4[variant],
1483
1137
  isDisabled && "opacity-50 cursor-not-allowed",
1484
1138
  className
1485
1139
  ),
@@ -1498,8 +1152,8 @@ function Tab({
1498
1152
  }
1499
1153
  function TabPanels({ children, className }) {
1500
1154
  const { activeIndex } = useContext(TabsContext);
1501
- return /* @__PURE__ */ jsx(View, { className: cn("flex-1", className), children: React24.Children.map(children, (child, index) => {
1502
- if (React24.isValidElement(child) && index === activeIndex) {
1155
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-1", className), children: React23.Children.map(children, (child, index) => {
1156
+ if (React23.isValidElement(child) && index === activeIndex) {
1503
1157
  return child;
1504
1158
  }
1505
1159
  return null;
@@ -1508,7 +1162,7 @@ function TabPanels({ children, className }) {
1508
1162
  function TabPanel({ children, className }) {
1509
1163
  return /* @__PURE__ */ jsx(View, { className: cn("py-4", className), children });
1510
1164
  }
1511
- var colorStyles2 = {
1165
+ var colorStyles = {
1512
1166
  default: {
1513
1167
  solid: "bg-neutral-600 text-white",
1514
1168
  subtle: "bg-neutral-100 text-neutral-700 dark:bg-neutral-800 dark:text-neutral-200",
@@ -1545,7 +1199,7 @@ var colorStyles2 = {
1545
1199
  outline: "border border-status-info text-status-info"
1546
1200
  }
1547
1201
  };
1548
- var sizeStyles9 = {
1202
+ var sizeStyles7 = {
1549
1203
  sm: { container: "px-2 py-0.5 rounded", text: "text-xs", deleteButton: "ml-1 -mr-0.5" },
1550
1204
  md: { container: "px-3 py-1 rounded-md", text: "text-sm", deleteButton: "ml-1.5 -mr-1" },
1551
1205
  lg: { container: "px-4 py-1.5 rounded-md", text: "text-base", deleteButton: "ml-2 -mr-1" }
@@ -1562,7 +1216,7 @@ function Chip({
1562
1216
  children,
1563
1217
  ...props
1564
1218
  }) {
1565
- const sizes = sizeStyles9[size];
1219
+ const sizes = sizeStyles7[size];
1566
1220
  const isClickable = !!onPress;
1567
1221
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
1568
1222
  leftElement && /* @__PURE__ */ jsx(View, { className: "mr-1.5", children: leftElement }),
@@ -1588,7 +1242,7 @@ function Chip({
1588
1242
  const baseClassName = cn(
1589
1243
  "flex-row items-center",
1590
1244
  sizes.container,
1591
- colorStyles2[color][variant],
1245
+ colorStyles[color][variant],
1592
1246
  isClickable && "web:cursor-pointer web:hover:opacity-80 active:opacity-70",
1593
1247
  isDisabled && "opacity-50 cursor-not-allowed",
1594
1248
  className
@@ -1608,7 +1262,7 @@ function Chip({
1608
1262
  }
1609
1263
  return /* @__PURE__ */ jsx(View, { className: baseClassName, ...props, children: content });
1610
1264
  }
1611
- var colorStyles3 = {
1265
+ var colorStyles2 = {
1612
1266
  default: "text-text-link",
1613
1267
  primary: "text-brand-primary",
1614
1268
  secondary: "text-brand-secondary",
@@ -1646,7 +1300,7 @@ function Link({
1646
1300
  {
1647
1301
  className: cn(
1648
1302
  "font-medium",
1649
- colorStyles3[color],
1303
+ colorStyles2[color],
1650
1304
  underlineStyles[underline],
1651
1305
  isDisabled && "opacity-50 cursor-not-allowed",
1652
1306
  "web:cursor-pointer active:opacity-70",
@@ -1899,9 +1553,9 @@ function Accordion({
1899
1553
  return newSet;
1900
1554
  });
1901
1555
  };
1902
- return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { openIndices, toggleIndex, allowMultiple }, children: /* @__PURE__ */ jsx(View, { className: cn("w-full divide-y divide-border", className), ...props, children: React24.Children.map(children, (child, index) => {
1903
- if (React24.isValidElement(child)) {
1904
- return React24.cloneElement(child, { index });
1556
+ return /* @__PURE__ */ jsx(AccordionContext.Provider, { value: { openIndices, toggleIndex, allowMultiple }, children: /* @__PURE__ */ jsx(View, { className: cn("w-full divide-y divide-border", className), ...props, children: React23.Children.map(children, (child, index) => {
1557
+ if (React23.isValidElement(child)) {
1558
+ return React23.cloneElement(child, { index });
1905
1559
  }
1906
1560
  return child;
1907
1561
  }) }) });
@@ -1909,9 +1563,9 @@ function Accordion({
1909
1563
  function AccordionItem({ index = 0, children, className }) {
1910
1564
  const { openIndices, toggleIndex } = useContext(AccordionContext);
1911
1565
  const isOpen = openIndices.has(index);
1912
- return /* @__PURE__ */ jsx(View, { className, children: React24.Children.map(children, (child) => {
1913
- if (React24.isValidElement(child)) {
1914
- return React24.cloneElement(child, {
1566
+ return /* @__PURE__ */ jsx(View, { className, children: React23.Children.map(children, (child) => {
1567
+ if (React23.isValidElement(child)) {
1568
+ return React23.cloneElement(child, {
1915
1569
  isOpen,
1916
1570
  onToggle: () => toggleIndex(index)
1917
1571
  });
@@ -1954,7 +1608,7 @@ function Breadcrumbs({
1954
1608
  children,
1955
1609
  ...props
1956
1610
  }) {
1957
- const items = React24.Children.toArray(children);
1611
+ const items = React23.Children.toArray(children);
1958
1612
  let displayItems = items;
1959
1613
  if (maxItems && items.length > maxItems) {
1960
1614
  const firstItem = items[0];
@@ -2451,7 +2105,7 @@ var ToolbarButtonContext = createContext({
2451
2105
  var BUTTON_BG = "#3C3C3C";
2452
2106
  var MENU_BG = "#2C2C2C";
2453
2107
  var hoverColors = getHoverColors(BUTTON_BG, "medium");
2454
- var sizeStyles10 = {
2108
+ var sizeStyles8 = {
2455
2109
  sm: "px-2 py-1 min-h-[26px]",
2456
2110
  md: "px-2.5 py-1 min-h-[30px]",
2457
2111
  lg: "px-3 py-1.5 min-h-[36px]"
@@ -2528,7 +2182,7 @@ function ToolbarButton({
2528
2182
  "flex-row items-center justify-center rounded",
2529
2183
  "web:transition-all web:duration-150 web:cursor-pointer",
2530
2184
  // Size
2531
- sizeStyles10[size],
2185
+ sizeStyles8[size],
2532
2186
  // Disabled
2533
2187
  isDisabled && "opacity-40 web:cursor-default web:pointer-events-none",
2534
2188
  className
@@ -2540,7 +2194,7 @@ function ToolbarButton({
2540
2194
  }
2541
2195
  ],
2542
2196
  children: [
2543
- icon && /* @__PURE__ */ jsx(View, { className: "w-5 h-5 items-center justify-center", children: React24.isValidElement(icon) ? React24.cloneElement(icon, {
2197
+ icon && /* @__PURE__ */ jsx(View, { className: "w-5 h-5 items-center justify-center", children: React23.isValidElement(icon) ? React23.cloneElement(icon, {
2544
2198
  size: 20,
2545
2199
  width: 20,
2546
2200
  height: 20,
@@ -2679,7 +2333,7 @@ var sizeConfig = {
2679
2333
  md: { outer: "w-5 h-5", inner: "w-2.5 h-2.5", text: "text-base" },
2680
2334
  lg: { outer: "w-6 h-6", inner: "w-3 h-3", text: "text-lg" }
2681
2335
  };
2682
- var colorStyles4 = {
2336
+ var colorStyles3 = {
2683
2337
  primary: { checked: "border-brand-primary bg-brand-primary", unchecked: "border-border-strong" },
2684
2338
  secondary: { checked: "border-brand-secondary bg-brand-secondary", unchecked: "border-border-strong" },
2685
2339
  success: { checked: "border-status-success bg-status-success", unchecked: "border-border-strong" },
@@ -2704,7 +2358,7 @@ function Radio({
2704
2358
  const color = radioColor ?? groupColor ?? "primary";
2705
2359
  const isChecked = selectedValue === value;
2706
2360
  const { outer, inner, text } = sizeConfig[size];
2707
- const { checked, unchecked } = colorStyles4[color];
2361
+ const { checked, unchecked } = colorStyles3[color];
2708
2362
  const handlePress = () => {
2709
2363
  if (!isDisabled) {
2710
2364
  onChange(value);
@@ -2742,7 +2396,7 @@ function Radio({
2742
2396
  }
2743
2397
  );
2744
2398
  }
2745
- var sizeStyles11 = {
2399
+ var sizeStyles9 = {
2746
2400
  left: {
2747
2401
  sm: "w-64",
2748
2402
  md: "w-80",
@@ -2817,7 +2471,7 @@ function Drawer({
2817
2471
  className: cn(
2818
2472
  "absolute bg-surface-elevated shadow-2xl",
2819
2473
  placementStyles[placement],
2820
- sizeStyles11[placement][size],
2474
+ sizeStyles9[placement][size],
2821
2475
  className
2822
2476
  ),
2823
2477
  accessibilityRole: "dialog",
@@ -2888,12 +2542,12 @@ var colorVarMap = {
2888
2542
  warning: "var(--color-status-warning)",
2889
2543
  info: "var(--color-status-info)"
2890
2544
  };
2891
- var sizeStyles12 = {
2545
+ var sizeStyles10 = {
2892
2546
  sm: "h-1",
2893
2547
  md: "h-2",
2894
2548
  lg: "h-3"
2895
2549
  };
2896
- var colorStyles5 = {
2550
+ var colorStyles4 = {
2897
2551
  primary: "bg-brand-primary",
2898
2552
  secondary: "bg-brand-secondary",
2899
2553
  success: "bg-status-success",
@@ -2936,7 +2590,7 @@ function Progress({
2936
2590
  "rounded-full overflow-hidden",
2937
2591
  trackWidth ? void 0 : "w-full",
2938
2592
  trackColorStyles[color],
2939
- sizeStyles12[size]
2593
+ sizeStyles10[size]
2940
2594
  ),
2941
2595
  style: trackWidth ? { width: trackWidth } : void 0,
2942
2596
  accessibilityRole: "progressbar",
@@ -2950,7 +2604,7 @@ function Progress({
2950
2604
  {
2951
2605
  className: cn(
2952
2606
  "h-full rounded-full",
2953
- !customColor && colorStyles5[color],
2607
+ !customColor && colorStyles4[color],
2954
2608
  isIndeterminate && "animate-pulse w-1/3"
2955
2609
  ),
2956
2610
  style: {
@@ -3066,14 +2720,14 @@ function ProgressSteps({
3066
2720
  }) {
3067
2721
  const { dot, connector } = stepSizeStyles[size];
3068
2722
  return /* @__PURE__ */ jsxs(View, { className: cn("w-full", className), ...props, children: [
3069
- /* @__PURE__ */ jsx(View, { className: "flex-row items-center", children: Array.from({ length: totalSteps }).map((_, index) => /* @__PURE__ */ jsxs(React24.Fragment, { children: [
2723
+ /* @__PURE__ */ jsx(View, { className: "flex-row items-center", children: Array.from({ length: totalSteps }).map((_, index) => /* @__PURE__ */ jsxs(React23.Fragment, { children: [
3070
2724
  /* @__PURE__ */ jsx(
3071
2725
  View,
3072
2726
  {
3073
2727
  className: cn(
3074
2728
  "rounded-full",
3075
2729
  dot,
3076
- index <= currentStep ? colorStyles5[color] : "bg-border-strong"
2730
+ index <= currentStep ? colorStyles4[color] : "bg-border-strong"
3077
2731
  )
3078
2732
  }
3079
2733
  ),
@@ -3083,7 +2737,7 @@ function ProgressSteps({
3083
2737
  className: cn(
3084
2738
  "flex-1 mx-1",
3085
2739
  connector,
3086
- index < currentStep ? colorStyles5[color] : "bg-border-strong"
2740
+ index < currentStep ? colorStyles4[color] : "bg-border-strong"
3087
2741
  )
3088
2742
  }
3089
2743
  )
@@ -3483,12 +3137,12 @@ function Autocomplete({
3483
3137
  )
3484
3138
  ] });
3485
3139
  }
3486
- var sizeStyles13 = {
3140
+ var sizeStyles11 = {
3487
3141
  sm: { icon: "w-3.5 h-3.5 text-xs", text: "text-xs" },
3488
3142
  md: { icon: "w-4 h-4 text-sm", text: "text-sm" },
3489
3143
  lg: { icon: "w-5 h-5 text-base", text: "text-base" }
3490
3144
  };
3491
- var colorStyles6 = {
3145
+ var colorStyles5 = {
3492
3146
  default: "text-text-tertiary",
3493
3147
  primary: "text-brand-primary",
3494
3148
  secondary: "text-text-secondary",
@@ -3527,7 +3181,7 @@ function HelpTip({
3527
3181
  }) {
3528
3182
  const [internalIsOpen, setInternalIsOpen] = useState(false);
3529
3183
  const isOpen = controlledIsOpen ?? internalIsOpen;
3530
- const { icon: iconSize, text: textSize } = sizeStyles13[size];
3184
+ const { icon: iconSize, text: textSize } = sizeStyles11[size];
3531
3185
  const handlePress = () => {
3532
3186
  if (controlledIsOpen === void 0) {
3533
3187
  setInternalIsOpen((prev) => !prev);
@@ -3556,12 +3210,12 @@ function HelpTip({
3556
3210
  className: cn(
3557
3211
  "items-center justify-center rounded-full",
3558
3212
  "border border-current",
3559
- colorStyles6[color],
3213
+ colorStyles5[color],
3560
3214
  iconSize,
3561
3215
  "web:hover:opacity-80 web:cursor-help",
3562
3216
  iconClassName
3563
3217
  ),
3564
- children: /* @__PURE__ */ jsx(Text, { className: cn("font-semibold", iconSize, colorStyles6[color]), children: iconMap[icon] })
3218
+ children: /* @__PURE__ */ jsx(Text, { className: cn("font-semibold", iconSize, colorStyles5[color]), children: iconMap[icon] })
3565
3219
  }
3566
3220
  ),
3567
3221
  isOpen && /* @__PURE__ */ jsxs(
@@ -3631,7 +3285,7 @@ function FormField({
3631
3285
  }) {
3632
3286
  const isInvalid = !!errorMessage;
3633
3287
  const isHorizontal = orientation === "horizontal";
3634
- const fieldId = React24.useId();
3288
+ const fieldId = React23.useId();
3635
3289
  const helperId = `${fieldId}-helper`;
3636
3290
  const errorId = `${fieldId}-error`;
3637
3291
  return /* @__PURE__ */ jsxs(
@@ -3672,10 +3326,10 @@ function FormField({
3672
3326
  }
3673
3327
  ),
3674
3328
  /* @__PURE__ */ jsxs(View, { className: cn(isHorizontal && "flex-1"), children: [
3675
- React24.Children.map(children, (child) => {
3676
- if (React24.isValidElement(child)) {
3329
+ React23.Children.map(children, (child) => {
3330
+ if (React23.isValidElement(child)) {
3677
3331
  const childProps = child.props;
3678
- return React24.cloneElement(child, {
3332
+ return React23.cloneElement(child, {
3679
3333
  accessibilityHint: errorMessage || helperText || childProps.accessibilityHint,
3680
3334
  accessibilityState: {
3681
3335
  ...childProps.accessibilityState,
@@ -3946,7 +3600,7 @@ function ListItemDivider({ inset = true, className, ...props }) {
3946
3600
  }
3947
3601
  );
3948
3602
  }
3949
- var variantColorStyles2 = {
3603
+ var variantColorStyles = {
3950
3604
  subtle: {
3951
3605
  default: "bg-surface-raised border-border-subtle text-text-secondary",
3952
3606
  primary: "bg-brand-primary/10 border-brand-primary/25 text-brand-primary",
@@ -3966,7 +3620,7 @@ var variantColorStyles2 = {
3966
3620
  info: "border-status-info text-status-info"
3967
3621
  }
3968
3622
  };
3969
- var sizeStyles14 = {
3623
+ var sizeStyles12 = {
3970
3624
  xs: { container: "px-1 py-px", text: "text-[9px]" },
3971
3625
  sm: { container: "px-2 py-0.5", text: "text-[10px]" },
3972
3626
  md: { container: "px-2 py-1", text: "text-[10px]" }
@@ -3985,13 +3639,13 @@ function Pill({
3985
3639
  const containerClasses = cn(
3986
3640
  "flex-row items-center gap-1 border self-start shrink-0",
3987
3641
  rounded ? "rounded-full" : "rounded",
3988
- variantColorStyles2[variant][color],
3989
- sizeStyles14[size].container,
3642
+ variantColorStyles[variant][color],
3643
+ sizeStyles12[size].container,
3990
3644
  className
3991
3645
  );
3992
3646
  const textClasses = cn(
3993
3647
  "font-heading font-semibold",
3994
- sizeStyles14[size].text,
3648
+ sizeStyles12[size].text,
3995
3649
  "text-inherit"
3996
3650
  );
3997
3651
  const content = /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -4003,7 +3657,7 @@ function Pill({
4003
3657
  }
4004
3658
  return /* @__PURE__ */ jsx(View, { className: containerClasses, ...props, children: content });
4005
3659
  }
4006
- var variantStyles4 = {
3660
+ var variantStyles3 = {
4007
3661
  h1: "font-heading text-5xl font-bold leading-tight",
4008
3662
  h2: "font-heading text-4xl font-bold leading-tight",
4009
3663
  h3: "font-heading text-3xl font-bold leading-tight",
@@ -4018,7 +3672,7 @@ var variantStyles4 = {
4018
3672
  overline: "font-body text-xs font-semibold uppercase tracking-widest leading-relaxed",
4019
3673
  button: "font-sans text-sm font-semibold leading-relaxed"
4020
3674
  };
4021
- var colorStyles7 = {
3675
+ var colorStyles6 = {
4022
3676
  primary: "text-text-primary",
4023
3677
  secondary: "text-text-secondary",
4024
3678
  tertiary: "text-text-tertiary",
@@ -4074,8 +3728,8 @@ function Typography({
4074
3728
  accessibilityRole: isHeading ? "header" : "text",
4075
3729
  numberOfLines: numLines,
4076
3730
  className: cn(
4077
- variantStyles4[variant],
4078
- color !== "inherit" && colorStyles7[color],
3731
+ variantStyles3[variant],
3732
+ color !== "inherit" && colorStyles6[color],
4079
3733
  align && alignStyles2[align],
4080
3734
  shouldTruncate && "truncate",
4081
3735
  marginBottomStyles[mb],
@@ -4249,7 +3903,7 @@ function Table({
4249
3903
  selectable,
4250
3904
  allRowIds: rowIds
4251
3905
  },
4252
- children: /* @__PURE__ */ jsx(View, { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx(View, { className: "w-full min-w-full", children: isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, { rowCount: loadingRowCount }) : children }) }) })
3906
+ children: /* @__PURE__ */ jsx(View, { className: cn("w-full", className), ...props, children: /* @__PURE__ */ jsx(ScrollView, { horizontal: true, showsHorizontalScrollIndicator: false, children: /* @__PURE__ */ jsx(View, { role: "table", className: "w-full min-w-full", children: isLoading ? /* @__PURE__ */ jsx(TableLoadingSkeleton, { rowCount: loadingRowCount }) : children }) }) })
4253
3907
  }
4254
3908
  );
4255
3909
  }
@@ -4257,14 +3911,14 @@ function TableHeader({ children, className }) {
4257
3911
  return /* @__PURE__ */ jsx(
4258
3912
  View,
4259
3913
  {
4260
- accessibilityRole: "none",
3914
+ role: "rowgroup",
4261
3915
  className: cn("bg-background-subtle rounded-t-lg", className),
4262
3916
  children
4263
3917
  }
4264
3918
  );
4265
3919
  }
4266
3920
  function TableBody({ children, className }) {
4267
- return /* @__PURE__ */ jsx(View, { accessibilityRole: "none", className, children });
3921
+ return /* @__PURE__ */ jsx(View, { role: "rowgroup", className, children });
4268
3922
  }
4269
3923
  function TableRow({
4270
3924
  isSelected = false,
@@ -4276,7 +3930,7 @@ function TableRow({
4276
3930
  return /* @__PURE__ */ jsx(
4277
3931
  View,
4278
3932
  {
4279
- accessibilityRole: "none",
3933
+ role: "row",
4280
3934
  className: cn(
4281
3935
  "flex-row border-b border-divider",
4282
3936
  isHoverable && "web:hover:bg-interactive-hover",
@@ -4300,6 +3954,7 @@ function TableHeaderCell({
4300
3954
  const { sortColumn, sortDirection, onSort } = useContext(TableContext);
4301
3955
  const isSorted = sortKey && sortColumn === sortKey;
4302
3956
  const isSortable = !!sortKey && !!onSort;
3957
+ const ariaSort = isSorted ? sortDirection === "asc" ? "ascending" : sortDirection === "desc" ? "descending" : "none" : "none";
4303
3958
  const handlePress = (e) => {
4304
3959
  if (isSortable && sortKey) {
4305
3960
  onSort(sortKey);
@@ -4326,26 +3981,34 @@ function TableHeaderCell({
4326
3981
  ] });
4327
3982
  if (isSortable) {
4328
3983
  return /* @__PURE__ */ jsx(
4329
- Pressable,
3984
+ View,
4330
3985
  {
4331
- accessibilityRole: "button",
4332
- accessibilityLabel: `Sort by ${children}`,
4333
- onPress: handlePress,
3986
+ role: "columnheader",
3987
+ "aria-sort": ariaSort,
4334
3988
  style: width ? { width } : { flex: 1 },
4335
- className: cn(
4336
- "flex-row items-center px-4 py-3",
4337
- alignStyles3[align],
4338
- "web:hover:bg-interactive-hover active:bg-interactive-active",
4339
- className
4340
- ),
4341
- ...props,
4342
- children: content
3989
+ children: /* @__PURE__ */ jsx(
3990
+ Pressable,
3991
+ {
3992
+ accessibilityRole: "button",
3993
+ accessibilityLabel: `Sort by ${children}`,
3994
+ onPress: handlePress,
3995
+ className: cn(
3996
+ "flex-row items-center px-4 py-3",
3997
+ alignStyles3[align],
3998
+ "web:hover:bg-interactive-hover active:bg-interactive-active",
3999
+ className
4000
+ ),
4001
+ ...props,
4002
+ children: content
4003
+ }
4004
+ )
4343
4005
  }
4344
4006
  );
4345
4007
  }
4346
4008
  return /* @__PURE__ */ jsx(
4347
4009
  View,
4348
4010
  {
4011
+ role: "columnheader",
4349
4012
  style: width ? { width } : { flex: 1 },
4350
4013
  className: cn(
4351
4014
  "flex-row items-center px-4 py-3",
@@ -4371,6 +4034,7 @@ function TableCell({
4371
4034
  return /* @__PURE__ */ jsx(
4372
4035
  View,
4373
4036
  {
4037
+ role: "cell",
4374
4038
  style: width ? { width } : { flex: 1 },
4375
4039
  className: cn(
4376
4040
  "justify-center px-4 py-3.5",
@@ -4579,11 +4243,11 @@ function Stepper({
4579
4243
  className
4580
4244
  ),
4581
4245
  ...props,
4582
- children: React24.Children.map(children, (child, index) => {
4583
- if (React24.isValidElement(child)) {
4246
+ children: React23.Children.map(children, (child, index) => {
4247
+ if (React23.isValidElement(child)) {
4584
4248
  return /* @__PURE__ */ jsxs(Fragment, { children: [
4585
- React24.cloneElement(child, { index }),
4586
- index < React24.Children.count(children) - 1 && /* @__PURE__ */ jsx(StepConnector, { index })
4249
+ React23.cloneElement(child, { index }),
4250
+ index < React23.Children.count(children) - 1 && /* @__PURE__ */ jsx(StepConnector, { index })
4587
4251
  ] });
4588
4252
  }
4589
4253
  return child;
@@ -4625,9 +4289,9 @@ function Step({ index = 0, status, className, children }) {
4625
4289
  orientation === "horizontal" ? "items-center" : "flex-row items-start",
4626
4290
  className
4627
4291
  ),
4628
- children: React24.Children.map(children, (child) => {
4629
- if (React24.isValidElement(child)) {
4630
- return React24.cloneElement(child, {
4292
+ children: React23.Children.map(children, (child) => {
4293
+ if (React23.isValidElement(child)) {
4294
+ return React23.cloneElement(child, {
4631
4295
  status: derivedStatus,
4632
4296
  index
4633
4297
  });
@@ -4689,7 +4353,7 @@ function StepContent({ status = "upcoming", className, children }) {
4689
4353
  if (status !== "active") return null;
4690
4354
  return /* @__PURE__ */ jsx(View, { className: cn("ml-11 mt-2 pb-4", className), children });
4691
4355
  }
4692
- var colorStyles8 = {
4356
+ var colorStyles7 = {
4693
4357
  primary: "text-text-primary",
4694
4358
  secondary: "text-text-secondary",
4695
4359
  tertiary: "text-text-tertiary",
@@ -4820,10 +4484,10 @@ function DateTime({
4820
4484
  ...props
4821
4485
  }) {
4822
4486
  if (value === null || value === void 0) {
4823
- return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles8[color], className), ...props, children: fallback });
4487
+ return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles7[color], className), ...props, children: fallback });
4824
4488
  }
4825
4489
  const formattedDate = formatDate(value, format, isUTC);
4826
- return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles8[color], className), ...props, children: formattedDate });
4490
+ return /* @__PURE__ */ jsx(Text, { className: cn(colorStyles7[color], className), ...props, children: formattedDate });
4827
4491
  }
4828
4492
  function formatDateTime(value, format = "datetime", isUTC = false, fallback = "-") {
4829
4493
  if (value === null || value === void 0) {
@@ -4870,8 +4534,8 @@ function MetricGroup({
4870
4534
  children,
4871
4535
  ...props
4872
4536
  }) {
4873
- const items = React24.Children.toArray(children);
4874
- return /* @__PURE__ */ jsx(View, { className: cn("flex-row items-center", className), ...props, children: items.map((child, i) => /* @__PURE__ */ jsxs(React24.Fragment, { children: [
4537
+ const items = React23.Children.toArray(children);
4538
+ return /* @__PURE__ */ jsx(View, { className: cn("flex-row items-center", className), ...props, children: items.map((child, i) => /* @__PURE__ */ jsxs(React23.Fragment, { children: [
4875
4539
  /* @__PURE__ */ jsx(View, { className: "flex-1 items-center", children: child }),
4876
4540
  i < items.length - 1 && /* @__PURE__ */ jsx(
4877
4541
  View,
@@ -5127,161 +4791,6 @@ function PrBadge({
5127
4791
  }
5128
4792
  return badge;
5129
4793
  }
5130
- var solidVariantColors = {
5131
- success: "#14B8A6",
5132
- warning: "#FFB020",
5133
- error: "#D14343",
5134
- neutral: "#6B7280"
5135
- };
5136
- var ringVariantStyles = {
5137
- "on-track": {
5138
- backgroundColor: "rgba(20,184,166,0.15)",
5139
- borderWidth: 1,
5140
- borderColor: "rgba(20,184,166,0.3)"
5141
- },
5142
- deviation: {
5143
- backgroundColor: "rgba(245,158,11,0.15)",
5144
- borderWidth: 1,
5145
- borderColor: "rgba(245,158,11,0.25)"
5146
- },
5147
- future: {
5148
- backgroundColor: "rgba(107,114,128,0.1)",
5149
- borderWidth: 1,
5150
- borderStyle: "dashed",
5151
- borderColor: "rgba(107,114,128,0.2)"
5152
- }
5153
- };
5154
- var glowStyles = {
5155
- success: { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
5156
- warning: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
5157
- error: { boxShadow: "0 0 4px rgba(239,68,68,0.4)" },
5158
- neutral: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" },
5159
- "on-track": { boxShadow: "0 0 4px rgba(20,184,166,0.4)" },
5160
- deviation: { boxShadow: "0 0 4px rgba(245,158,11,0.4)" },
5161
- future: { boxShadow: "0 0 4px rgba(107,114,128,0.4)" }
5162
- };
5163
- var iconChars = {
5164
- check: "\u2713",
5165
- exclamation: "!",
5166
- dash: "\u2014"
5167
- };
5168
- var iconColors2 = {
5169
- success: "#0A5C52",
5170
- warning: "#6B4000",
5171
- error: "#5C1A1A",
5172
- neutral: "#D1D5DB",
5173
- "on-track": "#14B8A6",
5174
- deviation: "#FFB020",
5175
- future: "#6B7280"
5176
- };
5177
- var sizeDimensions = {
5178
- sm: { size: 8, showIcon: false },
5179
- md: { size: 18, showIcon: true }
5180
- };
5181
- function isSolidVariant(variant) {
5182
- return variant in solidVariantColors;
5183
- }
5184
- function StatusDot({
5185
- variant,
5186
- icon,
5187
- size = "sm",
5188
- glow,
5189
- label,
5190
- className,
5191
- ...props
5192
- }) {
5193
- const config = sizeDimensions[size];
5194
- const solid = isSolidVariant(variant);
5195
- const ring = ringVariantStyles[variant];
5196
- const glowStyle = glow ? glowStyles[variant] : null;
5197
- const dot = /* @__PURE__ */ jsx(
5198
- View,
5199
- {
5200
- style: [
5201
- {
5202
- width: config.size,
5203
- height: config.size,
5204
- borderRadius: 9999,
5205
- alignItems: "center",
5206
- justifyContent: "center",
5207
- flexShrink: 0
5208
- },
5209
- solid ? { backgroundColor: solidVariantColors[variant] } : void 0,
5210
- ring ? ring : void 0,
5211
- glowStyle ? glowStyle : void 0
5212
- ],
5213
- accessibilityRole: "image",
5214
- accessibilityLabel: `${variant} status`,
5215
- testID: "status-dot",
5216
- children: config.showIcon && icon && /* @__PURE__ */ jsx(
5217
- Text,
5218
- {
5219
- style: {
5220
- fontSize: 11,
5221
- lineHeight: 11,
5222
- fontWeight: "900",
5223
- color: iconColors2[variant]
5224
- },
5225
- accessibilityElementsHidden: true,
5226
- children: iconChars[icon]
5227
- }
5228
- )
5229
- }
5230
- );
5231
- if (label) {
5232
- return /* @__PURE__ */ jsxs(
5233
- View,
5234
- {
5235
- className,
5236
- style: { flexDirection: "row", alignItems: "center", gap: 6 },
5237
- accessibilityLabel: `${variant} status: ${label}`,
5238
- ...props,
5239
- children: [
5240
- /* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: dot }),
5241
- /* @__PURE__ */ jsx(
5242
- Text,
5243
- {
5244
- style: { fontSize: 12, lineHeight: 16, color: "#9CA3AF" },
5245
- accessibilityElementsHidden: true,
5246
- children: label
5247
- }
5248
- )
5249
- ]
5250
- }
5251
- );
5252
- }
5253
- return /* @__PURE__ */ jsx(View, { className, ...props, children: dot });
5254
- }
5255
-
5256
- // src/theme/workout-tokens.ts
5257
- var WORKOUT_TOKENS = {
5258
- // BodyMap volume heatmap scale (drive dynamic SVG fills, so inline values).
5259
- // Maps weekly-volume status against MEV/MAV/MRV landmarks to a fill color.
5260
- heatmap: {
5261
- none: "#E0E0E0",
5262
- // gray — no training data
5263
- under: "#4A90D9",
5264
- // cool blue — below MEV
5265
- maintenance: "#F5C842",
5266
- // warm yellow — MEV to MAV
5267
- productive: "#4CAF50",
5268
- // green — MAV to MRV
5269
- approaching: "#FFA502",
5270
- // orange — near MRV
5271
- over: "#FF6B35"
5272
- // red-orange — over MRV
5273
- },
5274
- // Border colors (use inline to avoid 'border' class pitfall)
5275
- border: {
5276
- default: "#1F1F1F",
5277
- strong: "#2C2C2C"},
5278
- // Surface colors for inline use
5279
- surface: {
5280
- raised: "#1C1C1C",
5281
- elevated: "#191919"
5282
- }};
5283
-
5284
- // src/components/custom/Workout/PlaceholderStrip.tsx
5285
4794
  function SingleStrip({
5286
4795
  width,
5287
4796
  className,
@@ -5297,7 +4806,7 @@ function SingleStrip({
5297
4806
  backgroundColor: "transparent",
5298
4807
  borderWidth: 1,
5299
4808
  borderStyle: "dashed",
5300
- borderColor: WORKOUT_TOKENS.border.strong,
4809
+ borderColor: "var(--color-border-strong)",
5301
4810
  borderRadius: 1,
5302
4811
  opacity: 0.5
5303
4812
  },
@@ -5337,7 +4846,7 @@ function SegmentedStrip({
5337
4846
  backgroundColor: "transparent",
5338
4847
  borderWidth: 1,
5339
4848
  borderStyle: "dashed",
5340
- borderColor: WORKOUT_TOKENS.border.strong,
4849
+ borderColor: "var(--color-border-strong)",
5341
4850
  borderRadius: 1,
5342
4851
  minWidth: 4
5343
4852
  },
@@ -5359,9 +4868,49 @@ function PlaceholderStrip({
5359
4868
  }
5360
4869
  return /* @__PURE__ */ jsx(SingleStrip, { ...props });
5361
4870
  }
5362
- var INTER = "Inter, sans-serif";
5363
- var TEXT_TERTIARY = "#6B7280";
5364
- var phaseColors = {
4871
+
4872
+ // src/utils/workout-format.ts
4873
+ function roundRpe(rpe) {
4874
+ return Math.round(rpe * 2) / 2;
4875
+ }
4876
+ function rpeColor(rpe) {
4877
+ if (rpe >= 9.5) return WORKOUT_TOKENS.scale.red;
4878
+ if (rpe >= 8.5) return WORKOUT_TOKENS.scale.orange;
4879
+ if (rpe >= 7) return WORKOUT_TOKENS.scale.yellow;
4880
+ return WORKOUT_TOKENS.scale.green;
4881
+ }
4882
+ function roundWeight(weight) {
4883
+ return Math.round(weight);
4884
+ }
4885
+ function formatVelocity(velocity) {
4886
+ return velocity.toFixed(2);
4887
+ }
4888
+ function roundTempo(tempo) {
4889
+ return tempo.map((v) => Math.round(v * 10) / 10);
4890
+ }
4891
+ function formatSignedPct(ratio) {
4892
+ const pct = Math.round(ratio * 100);
4893
+ return `${pct > 0 ? "+" : ""}${pct}%`;
4894
+ }
4895
+ function formatPrescription(p) {
4896
+ if (p == null) return null;
4897
+ let reps = null;
4898
+ if (p.repsLow != null && p.repsHigh != null) {
4899
+ reps = p.repsLow === p.repsHigh ? `${p.repsLow}` : `${p.repsLow}\u2013${p.repsHigh}`;
4900
+ } else if (p.repsLow != null) {
4901
+ reps = `${p.repsLow}`;
4902
+ }
4903
+ const weight = p.weightLbs != null ? `${p.weightLbs} lb` : null;
4904
+ const head = [reps, weight].filter((s) => s != null).join(" @ ");
4905
+ const rpe = p.rpe != null ? `RPE ${p.rpe}` : null;
4906
+ const full = [head.length > 0 ? head : null, rpe].filter((s) => s != null).join(" \xB7 ");
4907
+ return full.length > 0 ? full : null;
4908
+ }
4909
+
4910
+ // src/components/custom/Workout/TempoDisplay.tsx
4911
+ var INTER = "Inter, sans-serif";
4912
+ var TEXT_TERTIARY = "#6B7280";
4913
+ var phaseColors = {
5365
4914
  eccentric: "#FFB020",
5366
4915
  // status-warning (amber)
5367
4916
  pauseBottom: TEXT_TERTIARY,
@@ -5414,7 +4963,7 @@ function TempoDisplay({
5414
4963
  ...props
5415
4964
  }) {
5416
4965
  const [showTooltip, setShowTooltip] = useState(false);
5417
- const [eccentric, pauseBottom, concentric, pauseTop] = tempo;
4966
+ const [eccentric, pauseBottom, concentric, pauseTop] = roundTempo(tempo);
5418
4967
  const isSm = size === "sm";
5419
4968
  const fontSize = isSm ? 9 : 11;
5420
4969
  const monoColor = TEXT_TERTIARY;
@@ -5922,12 +5471,7 @@ function WorkoutPill({
5922
5471
  }
5923
5472
  return pill;
5924
5473
  }
5925
- var VEL_COLORS = {
5926
- green: "#2ed573",
5927
- yellow: "#ffd43b",
5928
- orange: "#ffa502",
5929
- red: "#ff4757"
5930
- };
5474
+ var VEL_COLORS = WORKOUT_TOKENS.scale;
5931
5475
  function getVelocityZoneColor(velocity) {
5932
5476
  if (velocity >= 1) return "vel-green";
5933
5477
  if (velocity >= 0.75) return "vel-yellow";
@@ -6065,7 +5609,7 @@ function VelocityStrip({
6065
5609
  paddingBottom: expanded ? 24 : 0,
6066
5610
  paddingHorizontal: expanded ? 6 : 0,
6067
5611
  paddingVertical: expanded ? void 0 : 8,
6068
- backgroundColor: expanded ? "#1C1C1C" : "transparent",
5612
+ backgroundColor: expanded ? "var(--color-surface-raised)" : "transparent",
6069
5613
  overflow: expanded ? "visible" : "hidden"
6070
5614
  }
6071
5615
  ],
@@ -6080,7 +5624,7 @@ function VelocityStrip({
6080
5624
  style: { flexDirection: "row", flex: 1, gap: 2, alignItems: "flex-end" },
6081
5625
  children: velocities.map((v, i) => {
6082
5626
  const zone = getVelocityZoneColor(v);
6083
- const barHeightPct = Math.round(v / (maxVelocity * 1.15) * 100);
5627
+ const barHeightPct = maxVelocity > 0 ? Math.round(v / (maxVelocity * 1.15) * 100) : 0;
6084
5628
  const bar = /* @__PURE__ */ jsxs(
6085
5629
  View,
6086
5630
  {
@@ -6089,9 +5633,9 @@ function VelocityStrip({
6089
5633
  expanded && /* @__PURE__ */ jsx(Animated.View, { style: { opacity: labelOpacity, alignItems: "center", position: "absolute", top: -13, left: 0, right: 0 }, accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(
6090
5634
  Text,
6091
5635
  {
6092
- style: { fontSize: 8, fontWeight: "600", color: "#9CA3AF" },
5636
+ style: { fontSize: 8, fontWeight: "600", color: "var(--color-text-secondary)" },
6093
5637
  testID: `velocity-label-${i}`,
6094
- children: v.toFixed(2)
5638
+ children: formatVelocity(v)
6095
5639
  }
6096
5640
  ) }),
6097
5641
  /* @__PURE__ */ jsx(
@@ -6107,7 +5651,7 @@ function VelocityStrip({
6107
5651
  },
6108
5652
  testID: `velocity-bar-${i}`,
6109
5653
  accessibilityRole: "image",
6110
- accessibilityLabel: `Rep ${i + 1}: ${v.toFixed(2)} meters per second`
5654
+ accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second`
6111
5655
  }
6112
5656
  )
6113
5657
  ]
@@ -6121,7 +5665,7 @@ function VelocityStrip({
6121
5665
  style: { flex: 1, height: "100%" },
6122
5666
  onPress: () => onRepPress(i, v),
6123
5667
  accessibilityRole: "button",
6124
- accessibilityLabel: `Rep ${i + 1}: ${v.toFixed(2)} meters per second, tap for details`,
5668
+ accessibilityLabel: `Rep ${i + 1}: ${formatVelocity(v)} meters per second, tap for details`,
6125
5669
  testID: `velocity-bar-pressable-${i}`,
6126
5670
  children: bar
6127
5671
  },
@@ -6151,7 +5695,7 @@ function VelocityStrip({
6151
5695
  {
6152
5696
  style: {
6153
5697
  fontSize: 10,
6154
- color: "#9CA3AF",
5698
+ color: "var(--color-text-secondary)",
6155
5699
  fontFamily: "Inter, sans-serif"
6156
5700
  },
6157
5701
  children: [
@@ -6159,7 +5703,7 @@ function VelocityStrip({
6159
5703
  " ",
6160
5704
  "\xB7",
6161
5705
  " ",
6162
- meanVelocity.toFixed(2),
5706
+ formatVelocity(meanVelocity),
6163
5707
  " m/s"
6164
5708
  ]
6165
5709
  }
@@ -6169,7 +5713,7 @@ function VelocityStrip({
6169
5713
  {
6170
5714
  style: {
6171
5715
  fontSize: 10,
6172
- color: "#9CA3AF",
5716
+ color: "var(--color-text-secondary)",
6173
5717
  fontFamily: "Inter, sans-serif",
6174
5718
  ...getLossStyle(loss)
6175
5719
  },
@@ -6279,166 +5823,9 @@ function MuscleGroupChip({
6279
5823
  }
6280
5824
  return content;
6281
5825
  }
6282
- var BRAND_PRIMARY = "#FF7900";
6283
- function normalizeData(data, height) {
6284
- if (data.length === 0) return [];
6285
- const min = Math.min(...data);
6286
- const max = Math.max(...data);
6287
- const range = max - min || 1;
6288
- return data.map((v) => height - (v - min) / range * height);
6289
- }
6290
- function normalizeValue(value, data, height) {
6291
- const min = Math.min(...data);
6292
- const max = Math.max(...data);
6293
- const range = max - min || 1;
6294
- return height - (value - min) / range * height;
6295
- }
6296
- function Sparkline({
6297
- data,
6298
- width = 80,
6299
- height = 30,
6300
- color,
6301
- showDots = false,
6302
- referenceLines,
6303
- highlightLast = false,
6304
- className,
6305
- ...props
6306
- }) {
6307
- if (data.length === 0) {
6308
- return /* @__PURE__ */ jsx(
6309
- View,
6310
- {
6311
- style: { width, height },
6312
- className,
6313
- testID: "sparkline-empty",
6314
- accessibilityLabel: "Sparkline chart, no data",
6315
- ...props
6316
- }
6317
- );
6318
- }
6319
- const resolvedColor = color ?? BRAND_PRIMARY;
6320
- const normalized = normalizeData(data, height);
6321
- const stepX = data.length > 1 ? width / (data.length - 1) : 0;
6322
- const dotSize = 3;
6323
- const highlightSize = 6;
6324
- return /* @__PURE__ */ jsxs(
6325
- View,
6326
- {
6327
- style: { width, height, position: "relative" },
6328
- className: cn(className),
6329
- accessibilityRole: "image",
6330
- accessibilityLabel: `Sparkline chart with ${data.length} data points`,
6331
- testID: "sparkline",
6332
- ...props,
6333
- children: [
6334
- referenceLines?.map((line, i) => {
6335
- const y = normalizeValue(line.value, data, height);
6336
- return /* @__PURE__ */ jsx(
6337
- View,
6338
- {
6339
- style: [
6340
- {
6341
- position: "absolute",
6342
- top: y,
6343
- left: 0,
6344
- right: 0,
6345
- opacity: 0.6
6346
- },
6347
- line.dashed ? {
6348
- height: 0,
6349
- borderStyle: "dashed",
6350
- borderTopWidth: 1,
6351
- borderTopColor: line.color
6352
- } : {
6353
- height: 1,
6354
- backgroundColor: line.color
6355
- }
6356
- ],
6357
- accessibilityElementsHidden: true,
6358
- testID: `sparkline-reference-${i}`,
6359
- children: line.label && /* @__PURE__ */ jsx(
6360
- Text,
6361
- {
6362
- style: {
6363
- position: "absolute",
6364
- right: 0,
6365
- top: -10,
6366
- fontSize: 7,
6367
- color: line.color,
6368
- opacity: 1
6369
- },
6370
- testID: `sparkline-reference-label-${i}`,
6371
- children: line.label
6372
- }
6373
- )
6374
- },
6375
- `ref-${i}`
6376
- );
6377
- }),
6378
- normalized.map((y, i) => {
6379
- if (i === 0) return null;
6380
- const prevY = normalized[i - 1];
6381
- const x1 = (i - 1) * stepX;
6382
- const x2 = i * stepX;
6383
- const dx = x2 - x1;
6384
- const dy = y - prevY;
6385
- const length = Math.sqrt(dx * dx + dy * dy);
6386
- const angle = Math.atan2(dy, dx) * (180 / Math.PI);
6387
- return /* @__PURE__ */ jsx(
6388
- View,
6389
- {
6390
- style: {
6391
- position: "absolute",
6392
- left: x1,
6393
- top: prevY,
6394
- width: length,
6395
- height: 1.5,
6396
- backgroundColor: resolvedColor,
6397
- transformOrigin: "0 0",
6398
- transform: [{ rotate: `${angle}deg` }]
6399
- },
6400
- accessibilityElementsHidden: true,
6401
- testID: `sparkline-segment-${i}`
6402
- },
6403
- `line-${i}`
6404
- );
6405
- }),
6406
- (showDots || highlightLast) && normalized.map((y, i) => {
6407
- const isLast = i === data.length - 1;
6408
- const shouldShow = showDots || highlightLast && isLast;
6409
- if (!shouldShow) return null;
6410
- const size = highlightLast && isLast ? highlightSize : dotSize;
6411
- return /* @__PURE__ */ jsx(
6412
- View,
6413
- {
6414
- style: {
6415
- position: "absolute",
6416
- left: i * stepX - size / 2,
6417
- top: y - size / 2,
6418
- width: size,
6419
- height: size,
6420
- borderRadius: size / 2,
6421
- backgroundColor: resolvedColor
6422
- },
6423
- accessibilityElementsHidden: true,
6424
- testID: `sparkline-dot-${i}`
6425
- },
6426
- `dot-${i}`
6427
- );
6428
- })
6429
- ]
6430
- }
6431
- );
6432
- }
6433
- function getRPEColor(rpe) {
6434
- if (rpe >= 9.5) return "#ff4757";
6435
- if (rpe >= 8.5) return "#ffa502";
6436
- if (rpe >= 7) return "#ffd43b";
6437
- return "#2ed573";
6438
- }
6439
5826
  function formatAccessibilityLabel(setNumber, reps, weight, unit) {
6440
5827
  const repsText = reps != null ? `${reps} reps` : "no reps";
6441
- const weightText = weight != null ? `at ${weight} ${unit}` : "";
5828
+ const weightText = weight != null ? `at ${roundWeight(weight)} ${unit}` : "";
6442
5829
  return `Set ${setNumber}: ${repsText}${weightText ? ` ${weightText}` : ""}`;
6443
5830
  }
6444
5831
  function SetRow({
@@ -6516,7 +5903,7 @@ function SetRow({
6516
5903
  fontSize: 13,
6517
5904
  fontWeight: "600",
6518
5905
  fontFamily: "Inter, sans-serif",
6519
- color: "#9CA3AF"
5906
+ color: "var(--color-text-secondary)"
6520
5907
  },
6521
5908
  children: setNumber
6522
5909
  }
@@ -6534,9 +5921,9 @@ function SetRow({
6534
5921
  style: {
6535
5922
  fontSize: 12,
6536
5923
  fontFamily: "Inter, sans-serif",
6537
- color: "#9CA3AF"
5924
+ color: "var(--color-text-secondary)"
6538
5925
  },
6539
- children: previous ? `${previous.reps} x ${previous.weight}` : "\u2014"
5926
+ children: previous ? `${previous.reps} x ${roundWeight(previous.weight)}` : "\u2014"
6540
5927
  }
6541
5928
  )
6542
5929
  }
@@ -6553,7 +5940,7 @@ function SetRow({
6553
5940
  fontSize: 13,
6554
5941
  fontStyle: "italic",
6555
5942
  fontFamily: "Inter, sans-serif",
6556
- color: "#6B7280"
5943
+ color: "var(--color-text-tertiary)"
6557
5944
  },
6558
5945
  testID: "set-row-target-reps",
6559
5946
  children: targets.reps
@@ -6565,7 +5952,7 @@ function SetRow({
6565
5952
  fontSize: 14,
6566
5953
  fontWeight: "600",
6567
5954
  fontFamily: "Inter, sans-serif",
6568
- color: reps != null ? "#F3F4F6" : "#6B7280"
5955
+ color: reps != null ? "var(--color-text-primary)" : "var(--color-text-tertiary)"
6569
5956
  },
6570
5957
  children: reps != null ? reps : "\u2014"
6571
5958
  }
@@ -6584,10 +5971,10 @@ function SetRow({
6584
5971
  fontSize: 13,
6585
5972
  fontStyle: "italic",
6586
5973
  fontFamily: "Inter, sans-serif",
6587
- color: "#6B7280"
5974
+ color: "var(--color-text-tertiary)"
6588
5975
  },
6589
5976
  testID: "set-row-target-weight",
6590
- children: targets.weight
5977
+ children: roundWeight(targets.weight)
6591
5978
  }
6592
5979
  ) : /* @__PURE__ */ jsx(
6593
5980
  Text,
@@ -6596,9 +5983,9 @@ function SetRow({
6596
5983
  fontSize: 14,
6597
5984
  fontWeight: "600",
6598
5985
  fontFamily: "Inter, sans-serif",
6599
- color: weight != null ? "#F3F4F6" : "#6B7280"
5986
+ color: weight != null ? "var(--color-text-primary)" : "var(--color-text-tertiary)"
6600
5987
  },
6601
- children: weight != null ? weight : "\u2014"
5988
+ children: weight != null ? roundWeight(weight) : "\u2014"
6602
5989
  }
6603
5990
  )
6604
5991
  }
@@ -6615,9 +6002,9 @@ function SetRow({
6615
6002
  fontSize: 13,
6616
6003
  fontWeight: "600",
6617
6004
  fontFamily: "Inter, sans-serif",
6618
- color: rpe != null ? getRPEColor(rpe) : "#6B7280"
6005
+ color: rpe != null ? rpeColor(rpe) : "var(--color-text-tertiary)"
6619
6006
  },
6620
- children: rpe != null ? rpe : "\u2014"
6007
+ children: rpe != null ? roundRpe(rpe) : "\u2014"
6621
6008
  }
6622
6009
  )
6623
6010
  }
@@ -6660,16 +6047,16 @@ function SetRow({
6660
6047
  }
6661
6048
  );
6662
6049
  }
6663
- var BRAND_PRIMARY2 = "#FF7900";
6664
- var TEXT_PRIMARY = "#F3F4F6";
6665
- var TEXT_TERTIARY2 = "#6B7280";
6050
+ var BRAND_PRIMARY = "#FF7900";
6051
+ var TEXT_PRIMARY = "var(--color-text-primary)";
6052
+ var TEXT_TERTIARY2 = "var(--color-text-tertiary)";
6666
6053
  var inputStyle = {
6667
6054
  fontSize: 14,
6668
6055
  fontWeight: "600",
6669
6056
  fontFamily: "Inter, sans-serif",
6670
- backgroundColor: WORKOUT_TOKENS.surface.raised,
6057
+ backgroundColor: "var(--color-surface-raised)",
6671
6058
  borderWidth: 1,
6672
- borderColor: WORKOUT_TOKENS.border.strong,
6059
+ borderColor: "var(--color-border-strong)",
6673
6060
  borderRadius: 6,
6674
6061
  textAlign: "center",
6675
6062
  color: TEXT_PRIMARY,
@@ -6696,9 +6083,9 @@ function InputBar({
6696
6083
  {
6697
6084
  style: {
6698
6085
  width: "100%",
6699
- backgroundColor: WORKOUT_TOKENS.surface.elevated,
6086
+ backgroundColor: "var(--color-surface-elevated)",
6700
6087
  borderTopWidth: 1,
6701
- borderTopColor: WORKOUT_TOKENS.border.default,
6088
+ borderTopColor: "var(--color-border-default)",
6702
6089
  paddingTop: 10,
6703
6090
  paddingHorizontal: 16,
6704
6091
  paddingBottom: 12,
@@ -6791,7 +6178,7 @@ function InputBar({
6791
6178
  onPress: onRecord,
6792
6179
  disabled: !canRecord,
6793
6180
  style: ({ pressed }) => ({
6794
- backgroundColor: BRAND_PRIMARY2,
6181
+ backgroundColor: BRAND_PRIMARY,
6795
6182
  borderRadius: 8,
6796
6183
  paddingVertical: 10,
6797
6184
  paddingHorizontal: 16,
@@ -6818,7 +6205,7 @@ function InputBar({
6818
6205
  }
6819
6206
  );
6820
6207
  }
6821
- var BRAND_PRIMARY3 = "#FF7900";
6208
+ var BRAND_PRIMARY2 = "#FF7900";
6822
6209
  function RestTimer({
6823
6210
  totalSeconds,
6824
6211
  elapsedMs,
@@ -6833,15 +6220,16 @@ function RestTimer({
6833
6220
  const minutes = Math.floor(remainingSec / 60);
6834
6221
  const seconds = remainingSec % 60;
6835
6222
  const timeDisplay = `${minutes}:${String(seconds).padStart(2, "0")}`;
6836
- const progressPct = Math.min(100, elapsedMs / (totalSeconds * 1e3) * 100);
6223
+ const totalMs = totalSeconds * 1e3;
6224
+ const progressPct = totalMs > 0 ? Math.min(100, elapsedMs / totalMs * 100) : 100;
6837
6225
  return /* @__PURE__ */ jsxs(
6838
6226
  View,
6839
6227
  {
6840
6228
  style: {
6841
6229
  width: "100%",
6842
- backgroundColor: WORKOUT_TOKENS.surface.raised,
6230
+ backgroundColor: "var(--color-surface-raised)",
6843
6231
  borderTopWidth: 1,
6844
- borderTopColor: WORKOUT_TOKENS.border.default,
6232
+ borderTopColor: "var(--color-border-default)",
6845
6233
  paddingVertical: 12,
6846
6234
  paddingHorizontal: 16
6847
6235
  },
@@ -6869,7 +6257,7 @@ function RestTimer({
6869
6257
  fontWeight: "600",
6870
6258
  textTransform: "uppercase",
6871
6259
  letterSpacing: 1,
6872
- color: "#9CA3AF"
6260
+ color: "var(--color-text-secondary)"
6873
6261
  },
6874
6262
  testID: "rest-timer-label",
6875
6263
  children: "REST"
@@ -6881,7 +6269,7 @@ function RestTimer({
6881
6269
  style: {
6882
6270
  fontSize: 11,
6883
6271
  fontFamily: "Inter, sans-serif",
6884
- color: "#6B7280",
6272
+ color: "var(--color-text-tertiary)",
6885
6273
  marginTop: 2
6886
6274
  },
6887
6275
  testID: "rest-timer-next-set",
@@ -6896,7 +6284,7 @@ function RestTimer({
6896
6284
  fontSize: 28,
6897
6285
  fontFamily: '"Space Grotesk", sans-serif',
6898
6286
  fontWeight: "700",
6899
- color: "#F3F4F6",
6287
+ color: "var(--color-text-primary)",
6900
6288
  fontVariant: ["tabular-nums"],
6901
6289
  letterSpacing: -0.5
6902
6290
  },
@@ -6912,7 +6300,7 @@ function RestTimer({
6912
6300
  {
6913
6301
  style: {
6914
6302
  height: 3,
6915
- backgroundColor: WORKOUT_TOKENS.border.default,
6303
+ backgroundColor: "var(--color-border-default)",
6916
6304
  borderRadius: 2,
6917
6305
  marginBottom: 12
6918
6306
  },
@@ -6922,7 +6310,7 @@ function RestTimer({
6922
6310
  {
6923
6311
  style: {
6924
6312
  height: "100%",
6925
- backgroundColor: BRAND_PRIMARY3,
6313
+ backgroundColor: BRAND_PRIMARY2,
6926
6314
  borderRadius: 2,
6927
6315
  width: `${progressPct}%`
6928
6316
  },
@@ -6952,7 +6340,7 @@ function RestTimer({
6952
6340
  fontSize: 11,
6953
6341
  fontFamily: "Inter, sans-serif",
6954
6342
  fontWeight: "600",
6955
- color: "#9CA3AF"
6343
+ color: "var(--color-text-secondary)"
6956
6344
  },
6957
6345
  children: "+30s"
6958
6346
  }
@@ -6979,7 +6367,7 @@ function RestTimer({
6979
6367
  fontSize: 11,
6980
6368
  fontFamily: "Inter, sans-serif",
6981
6369
  fontWeight: "600",
6982
- color: BRAND_PRIMARY3
6370
+ color: BRAND_PRIMARY2
6983
6371
  },
6984
6372
  children: "Skip"
6985
6373
  }
@@ -6992,10 +6380,21 @@ function RestTimer({
6992
6380
  );
6993
6381
  }
6994
6382
  var COLORS = {
6995
- textPrimary: "#F3F4F6",
6996
- textSecondary: "#9CA3AF",
6997
- textTertiary: "#6B7280"};
6998
- var COLUMN_HEADERS = ["SET", "PREV", "REPS", "LBS", "RPE"];
6383
+ // Theme-aware tokens: text foregrounds and this card's own surfaces/borders
6384
+ // must flip together so text stays readable in both light and dark. The
6385
+ // expanded/pressed surfaces are self-owned here (not from a themed Card), so
6386
+ // hardcoding dark values would leave dark-on-dark once the text flips.
6387
+ // react-native-web passes the CSS var through to the inline style.
6388
+ textPrimary: "var(--color-text-primary)",
6389
+ textSecondary: "var(--color-text-secondary)",
6390
+ textTertiary: "var(--color-text-tertiary)",
6391
+ surfaceRaised: "var(--color-surface-raised)",
6392
+ surfaceElevated: "var(--color-surface-elevated)",
6393
+ borderDefault: "var(--color-border-default)"
6394
+ };
6395
+ function buildColumnHeaders(unit) {
6396
+ return ["SET", "PREV", "REPS", unit.toUpperCase(), "RPE"];
6397
+ }
6999
6398
  function getSupersetBorderRadius(position) {
7000
6399
  switch (position) {
7001
6400
  case "first":
@@ -7036,7 +6435,7 @@ function getSupersetMargin(position) {
7036
6435
  }
7037
6436
  function formatSummary(summary) {
7038
6437
  if (!summary) return "";
7039
- return `${summary.sets}\xD7${summary.reps} @ ${summary.weight} ${summary.unit}`;
6438
+ return `${summary.sets}\xD7${summary.reps} @ ${roundWeight(summary.weight)} ${summary.unit}`;
7040
6439
  }
7041
6440
  function formatAccessibilityLabel2(name, summary, prescription) {
7042
6441
  if (summary) return `${name}, ${formatSummary(summary)}`;
@@ -7074,7 +6473,7 @@ function CollapsedCard({
7074
6473
  padding: 12,
7075
6474
  paddingHorizontal: 14,
7076
6475
  cursor: "pointer",
7077
- backgroundColor: pressed ? WORKOUT_TOKENS.surface.raised : "transparent",
6476
+ backgroundColor: pressed ? COLORS.surfaceRaised : "transparent",
7078
6477
  ...borderRadius,
7079
6478
  ...supersetMargin
7080
6479
  },
@@ -7115,7 +6514,7 @@ function CollapsedCard({
7115
6514
  e1rm && /* @__PURE__ */ jsx(
7116
6515
  WeightBadge,
7117
6516
  {
7118
- value: e1rm.value,
6517
+ value: roundWeight(e1rm.value),
7119
6518
  unit: e1rm.unit,
7120
6519
  size: "sm",
7121
6520
  showIcon: false,
@@ -7170,13 +6569,15 @@ function ExpandedCard({
7170
6569
  }) {
7171
6570
  const borderRadius = getSupersetBorderRadius(supersetPosition);
7172
6571
  const supersetMargin = getSupersetMargin(supersetPosition);
6572
+ const unit = summary?.unit ?? sets?.[0]?.unit ?? "lbs";
6573
+ const columnHeaders = buildColumnHeaders(unit);
7173
6574
  return /* @__PURE__ */ jsxs(
7174
6575
  View,
7175
6576
  {
7176
6577
  style: {
7177
- backgroundColor: WORKOUT_TOKENS.surface.elevated,
6578
+ backgroundColor: COLORS.surfaceElevated,
7178
6579
  borderWidth: 1,
7179
- borderColor: WORKOUT_TOKENS.border.default,
6580
+ borderColor: COLORS.borderDefault,
7180
6581
  ...borderRadius,
7181
6582
  ...supersetMargin
7182
6583
  },
@@ -7199,7 +6600,7 @@ function ExpandedCard({
7199
6600
  paddingHorizontal: 14,
7200
6601
  paddingBottom: 10,
7201
6602
  borderBottomWidth: 1,
7202
- borderBottomColor: WORKOUT_TOKENS.border.default
6603
+ borderBottomColor: COLORS.borderDefault
7203
6604
  },
7204
6605
  children: [
7205
6606
  /* @__PURE__ */ jsx(
@@ -7232,7 +6633,7 @@ function ExpandedCard({
7232
6633
  e1rm && /* @__PURE__ */ jsx(
7233
6634
  WeightBadge,
7234
6635
  {
7235
- value: e1rm.value,
6636
+ value: roundWeight(e1rm.value),
7236
6637
  unit: e1rm.unit,
7237
6638
  size: "sm",
7238
6639
  showIcon: false,
@@ -7256,7 +6657,7 @@ function ExpandedCard({
7256
6657
  paddingBottom: 4
7257
6658
  },
7258
6659
  testID: "exercise-card-column-headers",
7259
- children: COLUMN_HEADERS.map((header, i) => {
6660
+ children: columnHeaders.map((header, i) => {
7260
6661
  const widths = [36, void 0, 44, 56, 36];
7261
6662
  const width = widths[i];
7262
6663
  const isFlex = width === void 0;
@@ -7422,7 +6823,7 @@ function SupersetWrapper({
7422
6823
  }
7423
6824
  );
7424
6825
  }
7425
- var BRAND_PRIMARY4 = "#FF7900";
6826
+ var BRAND_PRIMARY3 = "#FF7900";
7426
6827
  var segmentBgColors = {
7427
6828
  completed: "rgba(20,184,166,0.3)",
7428
6829
  current: "rgba(255,121,0,0.5)",
@@ -7450,10 +6851,11 @@ function MesoSegment({ meso, isActive, onPress }) {
7450
6851
  }).start();
7451
6852
  };
7452
6853
  const progress = meso.status === "current" ? clampProgress(meso.currentWeek, meso.weekCount) : 0;
6854
+ const segmentFlex = Math.max(1, meso.weekCount);
7453
6855
  return /* @__PURE__ */ jsx(
7454
6856
  Pressable,
7455
6857
  {
7456
- style: { flex: meso.weekCount },
6858
+ style: { flex: segmentFlex },
7457
6859
  onPress: () => onPress(meso.id),
7458
6860
  onPressIn: handlePressIn,
7459
6861
  onPressOut: handlePressOut,
@@ -7473,7 +6875,7 @@ function MesoSegment({ meso, isActive, onPress }) {
7473
6875
  },
7474
6876
  isActive ? {
7475
6877
  borderWidth: 2,
7476
- borderColor: BRAND_PRIMARY4,
6878
+ borderColor: BRAND_PRIMARY3,
7477
6879
  transform: [{ scale: 1.02 }, { scale: pressScale }]
7478
6880
  } : void 0
7479
6881
  ],
@@ -7487,7 +6889,7 @@ function MesoSegment({ meso, isActive, onPress }) {
7487
6889
  top: 0,
7488
6890
  bottom: 0,
7489
6891
  width: `${progress * 100}%`,
7490
- backgroundColor: BRAND_PRIMARY4
6892
+ backgroundColor: BRAND_PRIMARY3
7491
6893
  },
7492
6894
  testID: `meso-segment-fill-${meso.id}`
7493
6895
  }
@@ -7528,7 +6930,7 @@ function MesoProgressBar({
7528
6930
  }
7529
6931
  );
7530
6932
  }
7531
- var BRAND_PRIMARY5 = "#FF7900";
6933
+ var BRAND_PRIMARY4 = "#FF7900";
7532
6934
  function WeekRow({
7533
6935
  weekNumber,
7534
6936
  totalWeeks,
@@ -7553,7 +6955,7 @@ function WeekRow({
7553
6955
  if (isCurrent) {
7554
6956
  rowStyle.backgroundColor = "rgba(255,121,0,0.04)";
7555
6957
  rowStyle.borderLeftWidth = 2;
7556
- rowStyle.borderLeftColor = BRAND_PRIMARY5;
6958
+ rowStyle.borderLeftColor = BRAND_PRIMARY4;
7557
6959
  }
7558
6960
  return /* @__PURE__ */ jsxs(
7559
6961
  View,
@@ -7577,7 +6979,7 @@ function WeekRow({
7577
6979
  width: 6,
7578
6980
  height: 6,
7579
6981
  borderRadius: 3,
7580
- backgroundColor: BRAND_PRIMARY5
6982
+ backgroundColor: BRAND_PRIMARY4
7581
6983
  },
7582
6984
  accessibilityElementsHidden: true,
7583
6985
  testID: "week-row-current-dot"
@@ -7590,7 +6992,7 @@ function WeekRow({
7590
6992
  fontSize: 13,
7591
6993
  fontWeight: "700",
7592
6994
  fontFamily: "Inter, sans-serif",
7593
- color: isCurrent ? BRAND_PRIMARY5 : "#F3F4F6"
6995
+ color: isCurrent ? BRAND_PRIMARY4 : "var(--color-text-primary)"
7594
6996
  },
7595
6997
  accessibilityElementsHidden: true,
7596
6998
  children: `W${weekNumber}`
@@ -7630,9 +7032,11 @@ function WeekRow({
7630
7032
  );
7631
7033
  }
7632
7034
  var COLORS2 = {
7633
- textPrimary: "#F3F4F6",
7634
- textSecondary: "#9CA3AF",
7635
- textTertiary: "#6B7280",
7035
+ // Theme-aware foregrounds: resolve to a readable color in both light and dark
7036
+ // (react-native-web passes the CSS var through to the inline style).
7037
+ textPrimary: "var(--color-text-primary)",
7038
+ textSecondary: "var(--color-text-secondary)",
7039
+ textTertiary: "var(--color-text-tertiary)",
7636
7040
  statusSuccess: "#14B8A6",
7637
7041
  brandPrimary: "#FF7900",
7638
7042
  borderDefault: "#1F1F1F",
@@ -7776,13 +7180,13 @@ function WorkoutCard({
7776
7180
  }
7777
7181
  );
7778
7182
  }
7779
- var BRAND_PRIMARY6 = "#FF7900";
7183
+ var BRAND_PRIMARY5 = "#FF7900";
7780
7184
  var BRAND_PRIMARY_DARK = "#C45E00";
7781
7185
  var BRAND_PRIMARY_LIGHT = "#FFB066";
7782
7186
  var BORDER_DEFAULT = "#1F1F1F";
7783
- var TEXT_PRIMARY2 = "#F3F4F6";
7784
- var TEXT_SECONDARY = "#9CA3AF";
7785
- var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY6, BRAND_PRIMARY_LIGHT];
7187
+ var TEXT_PRIMARY2 = "var(--color-text-primary)";
7188
+ var TEXT_SECONDARY = "var(--color-text-secondary)";
7189
+ var ACCENT_STOPS = [BRAND_PRIMARY_DARK, BRAND_PRIMARY5, BRAND_PRIMARY_LIGHT];
7786
7190
  function heatmapColor(percentage) {
7787
7191
  const clamped = Math.max(0, Math.min(100, percentage));
7788
7192
  const opacity = 0.12 + clamped / 100 * 0.78;
@@ -7817,7 +7221,7 @@ function MesoCard({
7817
7221
  }, [highlighted, highlight]);
7818
7222
  const borderColor = highlight.interpolate({
7819
7223
  inputRange: [0, 1],
7820
- outputRange: [BORDER_DEFAULT, BRAND_PRIMARY6]
7224
+ outputRange: [BORDER_DEFAULT, BRAND_PRIMARY5]
7821
7225
  });
7822
7226
  const header = /* @__PURE__ */ jsxs(View, { style: { paddingHorizontal: 14, paddingTop: 12, paddingBottom: 10 }, testID: "meso-card-body", children: [
7823
7227
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 8 }, testID: "meso-card-header", children: [
@@ -7877,7 +7281,7 @@ function MesoCard({
7877
7281
  {
7878
7282
  variant: "outline",
7879
7283
  elevation: 2,
7880
- borderColor: highlighted ? BRAND_PRIMARY6 : BORDER_DEFAULT,
7284
+ borderColor: highlighted ? BRAND_PRIMARY5 : BORDER_DEFAULT,
7881
7285
  className,
7882
7286
  style: [
7883
7287
  { borderColor },
@@ -7934,14 +7338,14 @@ function MesoCard({
7934
7338
  }
7935
7339
  ) });
7936
7340
  }
7937
- var BRAND_PRIMARY7 = "#FF7900";
7341
+ var BRAND_PRIMARY6 = "#FF7900";
7938
7342
  var RECENT_BORDER = "rgba(255,176,32,0.3)";
7939
7343
  var RECENT_GLOW = "0 0 12px rgba(255,176,32,0.06)";
7940
- var SURFACE_RAISED = "#1C1C1C";
7941
- var BORDER_DEFAULT2 = "#1F1F1F";
7942
- var TEXT_PRIMARY3 = "#F3F4F6";
7943
- var TEXT_SECONDARY2 = "#9CA3AF";
7944
- var TEXT_TERTIARY3 = "#6B7280";
7344
+ var SURFACE_RAISED = "var(--color-surface-raised)";
7345
+ var BORDER_DEFAULT2 = "var(--color-border-default)";
7346
+ var TEXT_PRIMARY3 = "var(--color-text-primary)";
7347
+ var TEXT_SECONDARY2 = "var(--color-text-secondary)";
7348
+ var TEXT_TERTIARY3 = "var(--color-text-tertiary)";
7945
7349
  var TYPE_LABELS = {
7946
7350
  e1rm: "e1RM",
7947
7351
  weight: "Weight",
@@ -7981,7 +7385,7 @@ function PrRecordRow({ record, index }) {
7981
7385
  },
7982
7386
  testID: `pr-history-modal-record-${index}`,
7983
7387
  children: [
7984
- /* @__PURE__ */ jsx(Star, { size: 16, color: BRAND_PRIMARY7, fill: BRAND_PRIMARY7, strokeWidth: 2 }),
7388
+ /* @__PURE__ */ jsx(Star, { size: 16, color: BRAND_PRIMARY6, fill: BRAND_PRIMARY6, strokeWidth: 2 }),
7985
7389
  /* @__PURE__ */ jsx(
7986
7390
  Text,
7987
7391
  {
@@ -8125,13 +7529,13 @@ function PrHistoryModal({
8125
7529
  }
8126
7530
  );
8127
7531
  }
8128
- var BRAND_PRIMARY8 = "#FF7900";
7532
+ var BRAND_PRIMARY7 = "#FF7900";
8129
7533
  var BRAND_PRIMARY_SUBTLE = "rgba(255,121,0,0.12)";
8130
7534
  var STATUS_SUCCESS = "#14B8A6";
8131
7535
  var STATUS_WARNING = "#FFB020";
8132
7536
  var STATUS_ERROR = "#D14343";
8133
- var TEXT_PRIMARY4 = "#F3F4F6";
8134
- var TEXT_SECONDARY3 = "#9CA3AF";
7537
+ var TEXT_PRIMARY4 = "var(--color-text-primary)";
7538
+ var TEXT_SECONDARY3 = "var(--color-text-secondary)";
8135
7539
  var EMOJI_SETS = {
8136
7540
  sleep: ["\u{1F634}", "\u{1F610}", "\u{1F642}", "\u{1F60A}", "\u{1F929}"],
8137
7541
  soreness: ["\u{1F635}", "\u{1F623}", "\u{1F610}", "\u{1F642}", "\u{1F4AA}"],
@@ -8193,8 +7597,8 @@ function EmojiSlider({ factor }) {
8193
7597
  paddingVertical: 8,
8194
7598
  borderRadius: 8,
8195
7599
  borderWidth: 1,
8196
- borderColor: selected ? BRAND_PRIMARY8 : WORKOUT_TOKENS.border.default,
8197
- backgroundColor: selected ? BRAND_PRIMARY_SUBTLE : WORKOUT_TOKENS.surface.raised,
7600
+ borderColor: selected ? BRAND_PRIMARY7 : "var(--color-border-default)",
7601
+ backgroundColor: selected ? BRAND_PRIMARY_SUBTLE : "var(--color-surface-raised)",
8198
7602
  opacity: selected ? 1 : pressed ? 0.8 : 0.55,
8199
7603
  transform: [{ scale: selected ? 1.06 : 1 }]
8200
7604
  }),
@@ -8221,7 +7625,7 @@ function ScoreGauge({ score }) {
8221
7625
  borderRadius: 30,
8222
7626
  borderWidth: 4,
8223
7627
  borderColor: color,
8224
- backgroundColor: WORKOUT_TOKENS.surface.raised,
7628
+ backgroundColor: "var(--color-surface-raised)",
8225
7629
  alignItems: "center",
8226
7630
  justifyContent: "center"
8227
7631
  },
@@ -8246,8 +7650,8 @@ function WarmUpCard({ validation }) {
8246
7650
  padding: 12,
8247
7651
  borderRadius: 8,
8248
7652
  borderWidth: 1,
8249
- borderColor: WORKOUT_TOKENS.border.default,
8250
- backgroundColor: WORKOUT_TOKENS.surface.raised
7653
+ borderColor: "var(--color-border-default)",
7654
+ backgroundColor: "var(--color-surface-raised)"
8251
7655
  },
8252
7656
  testID: "readiness-check-warmup",
8253
7657
  children: [
@@ -8307,7 +7711,7 @@ function ReadinessCheck({
8307
7711
  marginTop: 16,
8308
7712
  width: "100%",
8309
7713
  alignItems: "center",
8310
- backgroundColor: BRAND_PRIMARY8,
7714
+ backgroundColor: BRAND_PRIMARY7,
8311
7715
  borderRadius: 8,
8312
7716
  paddingVertical: 12,
8313
7717
  opacity: pressed ? 0.8 : 1
@@ -8317,480 +7721,116 @@ function ReadinessCheck({
8317
7721
  )
8318
7722
  ] }) });
8319
7723
  }
8320
- var BRAND_PRIMARY9 = "#FF7900";
8321
- var BRAND_PRIMARY_DARK2 = "#C45E00";
8322
- var BRAND_PRIMARY_LIGHT2 = "#FFB066";
8323
- var TEXT_PRIMARY5 = "#F3F4F6";
8324
- var TEXT_SECONDARY4 = "#9CA3AF";
8325
- var TEXT_TERTIARY4 = "#6B7280";
8326
- var SUCCESS = "#14B8A6";
8327
- var WARNING = "#FFB020";
8328
- var ERROR = "#D14343";
8329
- var ACCENT_STOPS2 = [BRAND_PRIMARY_DARK2, BRAND_PRIMARY9, BRAND_PRIMARY_LIGHT2];
8330
- var CARD_GRADIENT = "linear-gradient(135deg, #191919 0%, rgba(25,25,25,0.95) 100%)";
8331
- var GAUGE_GRADIENT = "linear-gradient(90deg, rgba(20,184,166,0.25) 0%, rgba(255,176,32,0.25) 50%, rgba(209,67,67,0.25) 100%)";
8332
- var STATUS_VARIANTS = {
8333
- success: { bg: "rgba(20,184,166,0.15)", border: "rgba(20,184,166,0.3)", text: SUCCESS },
8334
- warning: { bg: "rgba(255,176,32,0.15)", border: "rgba(255,176,32,0.3)", text: WARNING },
8335
- error: { bg: "rgba(209,67,67,0.15)", border: "rgba(209,67,67,0.25)", text: ERROR }
8336
- };
8337
- function clamp012(value) {
8338
- if (!Number.isFinite(value)) return 0;
8339
- if (value < 0) return 0;
8340
- if (value > 1) return 1;
8341
- return value;
7724
+ var BRAND_PRIMARY8 = "#FF7900";
7725
+ var TEXT_PRIMARY5 = "var(--color-text-primary)";
7726
+ var TEXT_SECONDARY4 = "var(--color-text-secondary)";
7727
+ var TEXT_TERTIARY4 = "var(--color-text-tertiary)";
7728
+ var BORDER_STRONG = "var(--color-border-strong)";
7729
+ var STATUS_SUCCESS2 = "#14B8A6";
7730
+ var STATUS_ERROR2 = "#D14343";
7731
+ var STATUS_WARNING2 = "#FFB020";
7732
+ var GRID_LINE = "rgba(255,255,255,0.06)";
7733
+ var TOOLTIP_BG = "var(--color-surface-elevated)";
7734
+ var SUCCESS_PILL_BG = "rgba(20,184,166,0.10)";
7735
+ var SUCCESS_PILL_BORDER = "rgba(20,184,166,0.20)";
7736
+ var ERROR_PILL_BG = "rgba(209,67,67,0.10)";
7737
+ var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
7738
+ var PLOT_LEFT = 26;
7739
+ var TOOLTIP_WIDTH = 124;
7740
+ function timeOf(dateStr) {
7741
+ const t = Date.parse(dateStr);
7742
+ return Number.isNaN(t) ? 0 : t;
8342
7743
  }
8343
- function getGaugeZoneColor(level) {
8344
- if (level >= 0.7) return ERROR;
8345
- if (level >= 0.4) return WARNING;
8346
- return SUCCESS;
8347
- }
8348
- function renderCoachingText(text, highlights) {
8349
- if (!highlights || highlights.length === 0) return text;
8350
- const escaped = highlights.filter(Boolean).map((h) => h.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8351
- if (escaped.length === 0) return text;
8352
- const regex = new RegExp(`(${escaped.join("|")})`, "g");
8353
- return text.split(regex).map(
8354
- (part, index) => highlights.includes(part) ? /* @__PURE__ */ jsx(
8355
- Text,
8356
- {
8357
- style: { fontWeight: "700", color: TEXT_PRIMARY5 },
8358
- children: part
8359
- },
8360
- `${part}-${index}`
8361
- ) : /* @__PURE__ */ jsx(Fragment$1, { children: part }, `t-${index}`)
8362
- );
7744
+ function formatValue(value) {
7745
+ return `${Math.round(value)}`;
8363
7746
  }
8364
- function StatusPill({ badge }) {
8365
- const colors = STATUS_VARIANTS[badge.variant];
8366
- return /* @__PURE__ */ jsxs(
8367
- View,
8368
- {
8369
- className: "flex-row items-center",
8370
- style: {
8371
- gap: 5,
8372
- paddingVertical: 3,
8373
- paddingHorizontal: 8,
8374
- borderRadius: 4,
8375
- borderWidth: 1,
8376
- backgroundColor: colors.bg,
8377
- borderColor: colors.border
8378
- },
8379
- testID: "meso-status-card-badge",
8380
- children: [
8381
- /* @__PURE__ */ jsx(View, { accessibilityElementsHidden: true, children: /* @__PURE__ */ jsx(StatusDot, { variant: badge.variant, size: "sm" }) }),
8382
- /* @__PURE__ */ jsx(
8383
- Text,
8384
- {
8385
- style: {
8386
- fontSize: 10,
8387
- fontFamily: "Inter, sans-serif",
8388
- fontWeight: "700",
8389
- letterSpacing: 0.3,
8390
- color: colors.text
8391
- },
8392
- children: badge.label
8393
- }
8394
- )
8395
- ]
8396
- }
7747
+ function buildGeometry(data, projection, boundaries, width, height) {
7748
+ const values = [...data, ...projection].map((p) => p.e1rm);
7749
+ if (data.length === 0) {
7750
+ return {
7751
+ hasData: false,
7752
+ toX: () => 0,
7753
+ toY: () => 0,
7754
+ actual: [],
7755
+ projection: [],
7756
+ gridLines: [],
7757
+ boundaries: []
7758
+ };
7759
+ }
7760
+ const times = [
7761
+ ...data.map((p) => timeOf(p.date)),
7762
+ ...projection.map((p) => timeOf(p.date)),
7763
+ ...boundaries.map((b) => timeOf(b.date))
7764
+ ];
7765
+ const tMin = Math.min(...times);
7766
+ const tMaxRaw = Math.max(...times);
7767
+ const tMax = tMaxRaw === tMin ? tMin + 1 : tMaxRaw;
7768
+ const yMin = Math.min(...values);
7769
+ const yMax = Math.max(...values);
7770
+ const range = yMax - yMin || Math.max(1, yMax * 0.1);
7771
+ const padV = range * 0.15;
7772
+ const domainMin = yMin - padV;
7773
+ const domainMax = yMax + padV;
7774
+ const innerW = Math.max(1, width - PLOT_LEFT);
7775
+ const toX = (time) => PLOT_LEFT + (time - tMin) / (tMax - tMin) * innerW;
7776
+ const toY = (value) => height - (value - domainMin) / (domainMax - domainMin) * height;
7777
+ const project = (points) => points.map((point, index) => ({
7778
+ x: toX(timeOf(point.date)),
7779
+ y: toY(point.e1rm),
7780
+ point,
7781
+ index
7782
+ }));
7783
+ const tickValues = Array.from(
7784
+ new Set([yMax, (yMin + yMax) / 2, yMin].map((v) => Math.round(v)))
8397
7785
  );
7786
+ const gridLines = tickValues.map((v) => ({ y: toY(v), label: formatValue(v) }));
7787
+ return {
7788
+ hasData: true,
7789
+ toX,
7790
+ toY,
7791
+ actual: project(data),
7792
+ projection: project(projection),
7793
+ gridLines,
7794
+ boundaries: boundaries.map((b) => ({
7795
+ x: toX(timeOf(b.date)),
7796
+ label: b.label
7797
+ }))
7798
+ };
8398
7799
  }
8399
- function MetricCell({ metric }) {
8400
- return /* @__PURE__ */ jsxs(View, { style: { width: "48%" }, testID: "meso-status-card-metric", children: [
8401
- /* @__PURE__ */ jsx(
8402
- Text,
8403
- {
8404
- style: {
8405
- fontSize: 10,
8406
- fontFamily: "Inter, sans-serif",
8407
- fontWeight: "600",
8408
- letterSpacing: 0.5,
8409
- textTransform: "uppercase",
8410
- color: TEXT_TERTIARY4
8411
- },
8412
- children: metric.label
8413
- }
8414
- ),
8415
- /* @__PURE__ */ jsx(
8416
- Text,
8417
- {
8418
- style: {
8419
- marginTop: 2,
8420
- fontSize: 13,
8421
- fontFamily: "Inter, sans-serif",
8422
- fontWeight: "600",
8423
- color: TEXT_PRIMARY5
8424
- },
8425
- children: metric.value
8426
- }
8427
- )
8428
- ] });
7800
+ function computeTrend(data, boundaries) {
7801
+ if (data.length < 2) return { percent: 0, positive: true };
7802
+ let series = data;
7803
+ if (boundaries.length > 0) {
7804
+ const lastBoundary = Math.max(...boundaries.map((b) => timeOf(b.date)));
7805
+ const filtered = data.filter((p) => timeOf(p.date) >= lastBoundary);
7806
+ if (filtered.length < 2) return { percent: 0, positive: true };
7807
+ series = filtered;
7808
+ }
7809
+ const first = series[0].e1rm;
7810
+ const last = series[series.length - 1].e1rm;
7811
+ const percent = first ? (last - first) / first * 100 : 0;
7812
+ return { percent, positive: percent >= 0 };
8429
7813
  }
8430
- function Gauge({ gauge }) {
8431
- const level = clamp012(gauge.level);
8432
- const percentage = Math.round(level * 100);
8433
- const markerColor = getGaugeZoneColor(level);
8434
- return /* @__PURE__ */ jsxs(
8435
- View,
8436
- {
8437
- style: { gap: 6 },
8438
- accessibilityRole: "progressbar",
8439
- accessibilityValue: { min: 0, max: 100, now: percentage },
8440
- accessibilityLabel: `${gauge.label}: ${percentage}%`,
8441
- "aria-valuenow": percentage,
8442
- "aria-valuemin": 0,
8443
- "aria-valuemax": 100,
8444
- testID: "meso-status-card-gauge",
8445
- children: [
8446
- /* @__PURE__ */ jsxs(
8447
- View,
8448
- {
8449
- className: "flex-row items-center justify-between",
8450
- accessibilityElementsHidden: true,
8451
- children: [
8452
- /* @__PURE__ */ jsx(
8453
- Text,
8454
- {
8455
- style: {
8456
- fontSize: 10,
8457
- fontFamily: "Inter, sans-serif",
8458
- fontWeight: "500",
8459
- letterSpacing: 0.5,
8460
- textTransform: "uppercase",
8461
- color: TEXT_SECONDARY4
8462
- },
8463
- children: gauge.label
8464
- }
8465
- ),
8466
- gauge.sublabel != null && /* @__PURE__ */ jsx(
8467
- Text,
8468
- {
8469
- style: {
8470
- fontSize: 10,
8471
- fontFamily: "Inter, sans-serif",
8472
- fontWeight: "500",
8473
- color: TEXT_TERTIARY4
8474
- },
8475
- children: gauge.sublabel
8476
- }
8477
- )
8478
- ]
8479
- }
8480
- ),
8481
- /* @__PURE__ */ jsxs(
8482
- View,
8483
- {
8484
- style: {
8485
- height: 8,
8486
- borderRadius: 4,
8487
- position: "relative",
8488
- backgroundImage: GAUGE_GRADIENT
8489
- },
8490
- accessibilityElementsHidden: true,
8491
- children: [
8492
- /* @__PURE__ */ jsx(
8493
- View,
8494
- {
8495
- style: {
8496
- position: "absolute",
8497
- left: "50%",
8498
- top: 0,
8499
- bottom: 0,
8500
- width: 1,
8501
- marginLeft: -0.5,
8502
- backgroundColor: "rgba(255,255,255,0.3)"
8503
- },
8504
- testID: "meso-status-card-gauge-center"
8505
- }
8506
- ),
8507
- /* @__PURE__ */ jsx(
8508
- View,
8509
- {
8510
- style: {
8511
- position: "absolute",
8512
- left: `${percentage}%`,
8513
- top: -3,
8514
- marginLeft: -7,
8515
- width: 14,
8516
- height: 14,
8517
- borderRadius: 9999,
8518
- borderWidth: 2,
8519
- borderColor: TEXT_PRIMARY5,
8520
- backgroundColor: markerColor,
8521
- boxShadow: "0 0 4px rgba(0,0,0,0.5)"
8522
- },
8523
- testID: "meso-status-card-gauge-marker"
8524
- }
8525
- )
8526
- ]
8527
- }
8528
- )
8529
- ]
8530
- }
8531
- );
8532
- }
8533
- function MesoStatusCard({
8534
- mesoName,
8535
- mesoSubtitle,
8536
- statusBadge,
8537
- metrics,
8538
- gauges,
8539
- coaching,
8540
- nextTarget,
8541
- className,
8542
- ...props
8543
- }) {
8544
- return /* @__PURE__ */ jsxs(
8545
- Card,
8546
- {
8547
- variant: "outline",
8548
- elevation: 1,
8549
- borderColor: BRAND_PRIMARY_DARK2,
8550
- className,
8551
- style: {
8552
- borderColor: BRAND_PRIMARY_DARK2,
8553
- borderWidth: 1,
8554
- backgroundImage: CARD_GRADIENT
8555
- },
8556
- role: "article",
8557
- "aria-label": `Mesocycle status for ${mesoName}`,
8558
- testID: "meso-status-card",
8559
- ...props,
8560
- children: [
8561
- /* @__PURE__ */ jsx(
8562
- View,
8563
- {
8564
- className: "flex-row",
8565
- style: { position: "absolute", top: 0, left: 0, right: 0, height: 3, zIndex: 1 },
8566
- accessibilityElementsHidden: true,
8567
- testID: "meso-status-card-accent",
8568
- children: ACCENT_STOPS2.map((color) => /* @__PURE__ */ jsx(View, { style: { flex: 1, backgroundColor: color } }, color))
8569
- }
8570
- ),
8571
- /* @__PURE__ */ jsxs(View, { style: { padding: 14, gap: 14 }, testID: "meso-status-card-body", children: [
8572
- /* @__PURE__ */ jsxs(View, { testID: "meso-status-card-header", children: [
8573
- /* @__PURE__ */ jsxs(
8574
- View,
8575
- {
8576
- className: "flex-row items-center justify-between",
8577
- style: { gap: 8 },
8578
- children: [
8579
- /* @__PURE__ */ jsx(
8580
- Text,
8581
- {
8582
- style: {
8583
- flexShrink: 1,
8584
- fontSize: 15,
8585
- fontFamily: '"Space Grotesk", sans-serif',
8586
- fontWeight: "700",
8587
- color: TEXT_PRIMARY5
8588
- },
8589
- testID: "meso-status-card-name",
8590
- children: mesoName
8591
- }
8592
- ),
8593
- /* @__PURE__ */ jsx(StatusPill, { badge: statusBadge })
8594
- ]
8595
- }
8596
- ),
8597
- /* @__PURE__ */ jsx(
8598
- Text,
8599
- {
8600
- style: {
8601
- marginTop: 4,
8602
- fontSize: 12,
8603
- fontFamily: "Inter, sans-serif",
8604
- color: TEXT_SECONDARY4
8605
- },
8606
- testID: "meso-status-card-subtitle",
8607
- children: mesoSubtitle
8608
- }
8609
- )
8610
- ] }),
8611
- metrics.length > 0 && /* @__PURE__ */ jsx(
8612
- View,
8613
- {
8614
- className: "flex-row flex-wrap",
8615
- style: { gap: 8 },
8616
- testID: "meso-status-card-metrics",
8617
- children: metrics.map((metric, index) => /* @__PURE__ */ jsx(MetricCell, { metric }, `${metric.label}-${index}`))
8618
- }
8619
- ),
8620
- gauges.length > 0 && /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "meso-status-card-gauges", children: gauges.map((gauge, index) => /* @__PURE__ */ jsx(Gauge, { gauge }, `${gauge.label}-${index}`)) }),
8621
- coaching != null && /* @__PURE__ */ jsx(
8622
- View,
8623
- {
8624
- style: {
8625
- backgroundColor: "rgba(255,176,32,0.06)",
8626
- borderWidth: 1,
8627
- borderColor: "rgba(255,176,32,0.15)",
8628
- borderRadius: 8,
8629
- paddingVertical: 10,
8630
- paddingHorizontal: 12
8631
- },
8632
- testID: "meso-status-card-coaching",
8633
- children: /* @__PURE__ */ jsx(
8634
- Text,
8635
- {
8636
- style: {
8637
- fontSize: 12,
8638
- lineHeight: 17,
8639
- fontFamily: "Inter, sans-serif",
8640
- color: TEXT_SECONDARY4
8641
- },
8642
- children: renderCoachingText(coaching.text, coaching.highlights)
8643
- }
8644
- )
8645
- }
8646
- ),
8647
- nextTarget != null && /* @__PURE__ */ jsxs(
8648
- View,
8649
- {
8650
- className: "flex-row items-center",
8651
- style: {
8652
- gap: 8,
8653
- backgroundColor: "rgba(20,184,166,0.06)",
8654
- borderWidth: 1,
8655
- borderColor: "rgba(20,184,166,0.2)",
8656
- borderRadius: 8,
8657
- paddingVertical: 10,
8658
- paddingHorizontal: 12
8659
- },
8660
- testID: "meso-status-card-next-target",
8661
- children: [
8662
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 14, color: SUCCESS }, accessibilityElementsHidden: true, children: nextTarget.icon }),
8663
- /* @__PURE__ */ jsx(
8664
- Text,
8665
- {
8666
- style: {
8667
- flexShrink: 1,
8668
- fontSize: 12,
8669
- fontFamily: "Inter, sans-serif",
8670
- fontWeight: "600",
8671
- color: SUCCESS
8672
- },
8673
- children: nextTarget.text
8674
- }
8675
- )
8676
- ]
8677
- }
8678
- )
8679
- ] })
8680
- ]
8681
- }
8682
- );
8683
- }
8684
- var BRAND_PRIMARY10 = "#FF7900";
8685
- var TEXT_PRIMARY6 = "#F3F4F6";
8686
- var TEXT_SECONDARY5 = "#9CA3AF";
8687
- var TEXT_TERTIARY5 = "#6B7280";
8688
- var BORDER_STRONG = "#2C2C2C";
8689
- var STATUS_SUCCESS2 = "#14B8A6";
8690
- var STATUS_ERROR2 = "#D14343";
8691
- var STATUS_WARNING2 = "#FFB020";
8692
- var GRID_LINE = "rgba(255,255,255,0.06)";
8693
- var TOOLTIP_BG = "rgba(28,28,28,0.95)";
8694
- var SUCCESS_PILL_BG = "rgba(20,184,166,0.10)";
8695
- var SUCCESS_PILL_BORDER = "rgba(20,184,166,0.20)";
8696
- var ERROR_PILL_BG = "rgba(209,67,67,0.10)";
8697
- var ERROR_PILL_BORDER = "rgba(209,67,67,0.20)";
8698
- var PLOT_LEFT = 26;
8699
- var TOOLTIP_WIDTH = 124;
8700
- function timeOf(dateStr) {
8701
- const t = Date.parse(dateStr);
8702
- return Number.isNaN(t) ? 0 : t;
8703
- }
8704
- function formatValue(value) {
8705
- return `${Math.round(value)}`;
8706
- }
8707
- function buildGeometry(data, projection, boundaries, width, height) {
8708
- const values = [...data, ...projection].map((p) => p.e1rm);
8709
- if (data.length === 0) {
8710
- return {
8711
- hasData: false,
8712
- toX: () => 0,
8713
- toY: () => 0,
8714
- actual: [],
8715
- projection: [],
8716
- gridLines: [],
8717
- boundaries: []
8718
- };
8719
- }
8720
- const times = [
8721
- ...data.map((p) => timeOf(p.date)),
8722
- ...projection.map((p) => timeOf(p.date)),
8723
- ...boundaries.map((b) => timeOf(b.date))
8724
- ];
8725
- const tMin = Math.min(...times);
8726
- const tMaxRaw = Math.max(...times);
8727
- const tMax = tMaxRaw === tMin ? tMin + 1 : tMaxRaw;
8728
- const yMin = Math.min(...values);
8729
- const yMax = Math.max(...values);
8730
- const range = yMax - yMin || Math.max(1, yMax * 0.1);
8731
- const padV = range * 0.15;
8732
- const domainMin = yMin - padV;
8733
- const domainMax = yMax + padV;
8734
- const innerW = Math.max(1, width - PLOT_LEFT);
8735
- const toX = (time) => PLOT_LEFT + (time - tMin) / (tMax - tMin) * innerW;
8736
- const toY = (value) => height - (value - domainMin) / (domainMax - domainMin) * height;
8737
- const project = (points) => points.map((point, index) => ({
8738
- x: toX(timeOf(point.date)),
8739
- y: toY(point.e1rm),
8740
- point,
8741
- index
8742
- }));
8743
- const tickValues = Array.from(
8744
- new Set([yMax, (yMin + yMax) / 2, yMin].map((v) => Math.round(v)))
8745
- );
8746
- const gridLines = tickValues.map((v) => ({ y: toY(v), label: formatValue(v) }));
8747
- return {
8748
- hasData: true,
8749
- toX,
8750
- toY,
8751
- actual: project(data),
8752
- projection: project(projection),
8753
- gridLines,
8754
- boundaries: boundaries.map((b) => ({
8755
- x: toX(timeOf(b.date)),
8756
- label: b.label
8757
- }))
8758
- };
8759
- }
8760
- function computeTrend(data, boundaries) {
8761
- if (data.length < 2) return { percent: 0, positive: true };
8762
- let series = data;
8763
- if (boundaries.length > 0) {
8764
- const lastBoundary = Math.max(...boundaries.map((b) => timeOf(b.date)));
8765
- const filtered = data.filter((p) => timeOf(p.date) >= lastBoundary);
8766
- if (filtered.length < 2) return { percent: 0, positive: true };
8767
- series = filtered;
8768
- }
8769
- const first = series[0].e1rm;
8770
- const last = series[series.length - 1].e1rm;
8771
- const percent = first ? (last - first) / first * 100 : 0;
8772
- return { percent, positive: percent >= 0 };
8773
- }
8774
- function ChartLine({
8775
- coords,
8776
- color,
8777
- strokeWidth,
8778
- dashed,
8779
- testID
8780
- }) {
8781
- return /* @__PURE__ */ jsx(Fragment, { children: coords.map((c, i) => {
8782
- if (i === 0) return null;
8783
- const prev = coords[i - 1];
8784
- const dx = c.x - prev.x;
8785
- const dy = c.y - prev.y;
8786
- const length = Math.sqrt(dx * dx + dy * dy);
8787
- const angle = Math.atan2(dy, dx) * (180 / Math.PI);
8788
- return /* @__PURE__ */ jsx(
8789
- View,
8790
- {
8791
- testID,
8792
- accessibilityElementsHidden: true,
8793
- style: [
7814
+ function ChartLine({
7815
+ coords,
7816
+ color,
7817
+ strokeWidth,
7818
+ dashed,
7819
+ testID
7820
+ }) {
7821
+ return /* @__PURE__ */ jsx(Fragment, { children: coords.map((c, i) => {
7822
+ if (i === 0) return null;
7823
+ const prev = coords[i - 1];
7824
+ const dx = c.x - prev.x;
7825
+ const dy = c.y - prev.y;
7826
+ const length = Math.sqrt(dx * dx + dy * dy);
7827
+ const angle = Math.atan2(dy, dx) * (180 / Math.PI);
7828
+ return /* @__PURE__ */ jsx(
7829
+ View,
7830
+ {
7831
+ testID,
7832
+ accessibilityElementsHidden: true,
7833
+ style: [
8794
7834
  {
8795
7835
  position: "absolute",
8796
7836
  left: prev.x,
@@ -8871,7 +7911,7 @@ function StrengthTrendChart({
8871
7911
  alignItems: "center",
8872
7912
  justifyContent: "center"
8873
7913
  },
8874
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY5 }, children: "No strength data yet" })
7914
+ children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY4 }, children: "No strength data yet" })
8875
7915
  }
8876
7916
  )
8877
7917
  }
@@ -8923,7 +7963,7 @@ function StrengthTrendChart({
8923
7963
  textAlign: "right",
8924
7964
  fontSize: 9,
8925
7965
  fontFamily: "Inter, sans-serif",
8926
- color: TEXT_TERTIARY5
7966
+ color: TEXT_TERTIARY4
8927
7967
  },
8928
7968
  children: line.label
8929
7969
  }
@@ -8966,7 +8006,7 @@ function StrengthTrendChart({
8966
8006
  ChartLine,
8967
8007
  {
8968
8008
  coords: geometry.projection,
8969
- color: TEXT_TERTIARY5,
8009
+ color: TEXT_TERTIARY4,
8970
8010
  strokeWidth: 2,
8971
8011
  dashed: true,
8972
8012
  testID: "strength-trend-chart-projection-segment"
@@ -8976,7 +8016,7 @@ function StrengthTrendChart({
8976
8016
  ChartLine,
8977
8017
  {
8978
8018
  coords: geometry.actual,
8979
- color: BRAND_PRIMARY10,
8019
+ color: BRAND_PRIMARY8,
8980
8020
  strokeWidth: 2.5,
8981
8021
  testID: "strength-trend-chart-actual-segment"
8982
8022
  }
@@ -9029,7 +8069,7 @@ function StrengthTrendChart({
9029
8069
  width: 8,
9030
8070
  height: 8,
9031
8071
  borderRadius: 1,
9032
- backgroundColor: BRAND_PRIMARY10
8072
+ backgroundColor: BRAND_PRIMARY8
9033
8073
  }
9034
8074
  },
9035
8075
  `point-${c.index}`
@@ -9064,7 +8104,7 @@ function StrengthTrendChart({
9064
8104
  style: {
9065
8105
  fontSize: 10,
9066
8106
  fontFamily: "Inter, sans-serif",
9067
- color: TEXT_TERTIARY5
8107
+ color: TEXT_TERTIARY4
9068
8108
  },
9069
8109
  children: selectedCoord.point.sessionLabel ?? selectedCoord.point.date
9070
8110
  }
@@ -9077,7 +8117,7 @@ function StrengthTrendChart({
9077
8117
  fontSize: 13,
9078
8118
  fontFamily: "Inter, sans-serif",
9079
8119
  fontWeight: "700",
9080
- color: TEXT_PRIMARY6
8120
+ color: TEXT_PRIMARY5
9081
8121
  },
9082
8122
  children: `${formatValue(selectedCoord.point.e1rm)} ${unit}`
9083
8123
  }
@@ -9117,7 +8157,7 @@ function StrengthTrendChart({
9117
8157
  textAlign: "center",
9118
8158
  fontSize: 10,
9119
8159
  fontFamily: "Inter, sans-serif",
9120
- color: TEXT_TERTIARY5
8160
+ color: TEXT_TERTIARY4
9121
8161
  },
9122
8162
  children: boundary.label
9123
8163
  },
@@ -9160,8 +8200,8 @@ function StrengthTrendChart({
9160
8200
  testID: "strength-trend-chart-legend",
9161
8201
  children: [
9162
8202
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 5 }, children: [
9163
- /* @__PURE__ */ jsx(View, { style: { width: 14, height: 2.5, borderRadius: 1.5, backgroundColor: BRAND_PRIMARY10 } }),
9164
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY5 }, children: "Actual" })
8203
+ /* @__PURE__ */ jsx(View, { style: { width: 14, height: 2.5, borderRadius: 1.5, backgroundColor: BRAND_PRIMARY8 } }),
8204
+ /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY4 }, children: "Actual" })
9165
8205
  ] }),
9166
8206
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 5 }, children: [
9167
8207
  /* @__PURE__ */ jsx(
@@ -9172,15 +8212,15 @@ function StrengthTrendChart({
9172
8212
  height: 0,
9173
8213
  borderTopWidth: 2,
9174
8214
  borderStyle: "dashed",
9175
- borderTopColor: TEXT_TERTIARY5
8215
+ borderTopColor: TEXT_TERTIARY4
9176
8216
  }
9177
8217
  }
9178
8218
  ),
9179
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY5 }, children: "Projected" })
8219
+ /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY4 }, children: "Projected" })
9180
8220
  ] }),
9181
8221
  /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 5 }, children: [
9182
8222
  /* @__PURE__ */ jsx(Text, { style: { fontSize: 12, color: STATUS_WARNING2 }, children: "\u2605" }),
9183
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY5 }, children: "PR" })
8223
+ /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY4 }, children: "PR" })
9184
8224
  ] })
9185
8225
  ]
9186
8226
  }
@@ -9193,7 +8233,7 @@ var STATUS_SUCCESS3 = "#14B8A6";
9193
8233
  var STATUS_WARNING3 = "#FFB020";
9194
8234
  var STATUS_INFO = "#2196F3";
9195
8235
  var DOT_BORDER = "#F3F4F6";
9196
- var TEXT_TERTIARY6 = "#6B7280";
8236
+ var TEXT_TERTIARY5 = "var(--color-text-tertiary)";
9197
8237
  var BAND_FILL = "rgba(20,184,166,0.1)";
9198
8238
  var BAND_EDGE = "rgba(20,184,166,0.45)";
9199
8239
  var PROJECTION_FILL = "rgba(20,184,166,0.05)";
@@ -9482,7 +8522,7 @@ function CapacityBandChart({
9482
8522
  textAlign: "center",
9483
8523
  fontSize: 9,
9484
8524
  fontFamily: "Inter, sans-serif",
9485
- color: TEXT_TERTIARY6,
8525
+ color: TEXT_TERTIARY5,
9486
8526
  transform: [{ rotate: "-90deg" }]
9487
8527
  },
9488
8528
  accessibilityElementsHidden: true,
@@ -9504,7 +8544,7 @@ function CapacityBandChart({
9504
8544
  textAlign: "center",
9505
8545
  fontSize: 10,
9506
8546
  fontFamily: "Inter, sans-serif",
9507
- color: TEXT_TERTIARY6
8547
+ color: TEXT_TERTIARY5
9508
8548
  },
9509
8549
  accessibilityElementsHidden: true,
9510
8550
  importantForAccessibility: "no-hide-descendants",
@@ -9566,847 +8606,674 @@ function CapacityBandChart({
9566
8606
  }
9567
8607
  );
9568
8608
  }
9569
-
9570
- // src/components/custom/Workout/muscleTaxonomy.ts
9571
- var MuscleGroup = /* @__PURE__ */ ((MuscleGroup4) => {
9572
- MuscleGroup4["CHEST"] = "chest";
9573
- MuscleGroup4["FRONT_DELTS"] = "front_delts";
9574
- MuscleGroup4["SIDE_DELTS"] = "side_delts";
9575
- MuscleGroup4["TRICEPS"] = "triceps";
9576
- MuscleGroup4["LATS"] = "lats";
9577
- MuscleGroup4["UPPER_BACK"] = "upper_back";
9578
- MuscleGroup4["REAR_DELTS"] = "rear_delts";
9579
- MuscleGroup4["BICEPS"] = "biceps";
9580
- MuscleGroup4["FOREARMS"] = "forearms";
9581
- MuscleGroup4["QUADS"] = "quads";
9582
- MuscleGroup4["HAMSTRINGS"] = "hamstrings";
9583
- MuscleGroup4["GLUTES"] = "glutes";
9584
- MuscleGroup4["CALVES"] = "calves";
9585
- MuscleGroup4["ABS"] = "abs";
9586
- MuscleGroup4["OBLIQUES"] = "obliques";
9587
- return MuscleGroup4;
9588
- })(MuscleGroup || {});
9589
- var SimpleMuscleGroup = /* @__PURE__ */ ((SimpleMuscleGroup3) => {
9590
- SimpleMuscleGroup3["CHEST"] = "chest";
9591
- SimpleMuscleGroup3["BACK"] = "back";
9592
- SimpleMuscleGroup3["SHOULDERS"] = "shoulders";
9593
- SimpleMuscleGroup3["BICEPS"] = "biceps";
9594
- SimpleMuscleGroup3["TRICEPS"] = "triceps";
9595
- SimpleMuscleGroup3["LEGS"] = "legs";
9596
- SimpleMuscleGroup3["CORE"] = "core";
9597
- SimpleMuscleGroup3["FOREARMS"] = "forearms";
9598
- return SimpleMuscleGroup3;
9599
- })(SimpleMuscleGroup || {});
9600
- var SIMPLE_TO_DETAILED = {
9601
- ["chest" /* CHEST */]: ["chest" /* CHEST */],
9602
- ["back" /* BACK */]: ["lats" /* LATS */, "upper_back" /* UPPER_BACK */],
9603
- ["shoulders" /* SHOULDERS */]: [
9604
- "front_delts" /* FRONT_DELTS */,
9605
- "side_delts" /* SIDE_DELTS */,
9606
- "rear_delts" /* REAR_DELTS */
9607
- ],
9608
- ["biceps" /* BICEPS */]: ["biceps" /* BICEPS */],
9609
- ["triceps" /* TRICEPS */]: ["triceps" /* TRICEPS */],
9610
- ["legs" /* LEGS */]: [
9611
- "quads" /* QUADS */,
9612
- "hamstrings" /* HAMSTRINGS */,
9613
- "glutes" /* GLUTES */,
9614
- "calves" /* CALVES */
9615
- ],
9616
- ["core" /* CORE */]: ["abs" /* ABS */, "obliques" /* OBLIQUES */],
9617
- ["forearms" /* FOREARMS */]: ["forearms" /* FOREARMS */]
8609
+ var SURFACE_ELEVATED = "var(--color-surface-elevated)";
8610
+ var BORDER_DEFAULT3 = "var(--color-border-default)";
8611
+ var BRAND_PRIMARY9 = "#FF7900";
8612
+ var TEXT_PRIMARY6 = "var(--color-text-primary)";
8613
+ var TEXT_TERTIARY6 = "var(--color-text-tertiary)";
8614
+ var PAGE_BG = "var(--color-background-base)";
8615
+ var WORKOUT_PILL_STATUS = {
8616
+ completed: "completed",
8617
+ today: "current",
8618
+ upcoming: "upcoming"
9618
8619
  };
9619
- var DETAILED_TO_SIMPLE = Object.entries(
9620
- SIMPLE_TO_DETAILED
9621
- ).reduce(
9622
- (acc, [simple, groups]) => {
9623
- for (const group of groups) {
9624
- acc[group] = simple;
9625
- }
9626
- return acc;
9627
- },
9628
- {}
9629
- );
9630
- var MUSCLE_TO_CATEGORY = {
9631
- ["chest" /* CHEST */]: "push",
9632
- ["front_delts" /* FRONT_DELTS */]: "push",
9633
- ["side_delts" /* SIDE_DELTS */]: "push",
9634
- ["triceps" /* TRICEPS */]: "push",
9635
- ["lats" /* LATS */]: "pull",
9636
- ["upper_back" /* UPPER_BACK */]: "pull",
9637
- ["rear_delts" /* REAR_DELTS */]: "pull",
9638
- ["biceps" /* BICEPS */]: "pull",
9639
- ["forearms" /* FOREARMS */]: "pull",
9640
- ["quads" /* QUADS */]: "legs",
9641
- ["hamstrings" /* HAMSTRINGS */]: "legs",
9642
- ["glutes" /* GLUTES */]: "legs",
9643
- ["calves" /* CALVES */]: "legs",
9644
- ["abs" /* ABS */]: "core",
9645
- ["obliques" /* OBLIQUES */]: "core"
9646
- };
9647
- var MUSCLE_TO_SVG_SLUGS = {
9648
- ["chest" /* CHEST */]: ["chest"],
9649
- ["front_delts" /* FRONT_DELTS */]: ["deltoids"],
9650
- ["side_delts" /* SIDE_DELTS */]: ["deltoids"],
9651
- ["rear_delts" /* REAR_DELTS */]: ["deltoids"],
9652
- ["triceps" /* TRICEPS */]: ["triceps"],
9653
- ["lats" /* LATS */]: ["upper-back"],
9654
- ["upper_back" /* UPPER_BACK */]: ["upper-back", "trapezius"],
9655
- ["biceps" /* BICEPS */]: ["biceps"],
9656
- ["forearms" /* FOREARMS */]: ["forearm"],
9657
- ["quads" /* QUADS */]: ["quadriceps"],
9658
- ["hamstrings" /* HAMSTRINGS */]: ["hamstring"],
9659
- ["glutes" /* GLUTES */]: ["gluteal"],
9660
- ["calves" /* CALVES */]: ["calves"],
9661
- ["abs" /* ABS */]: ["abs"],
9662
- ["obliques" /* OBLIQUES */]: ["obliques"]
9663
- };
9664
- var MUSCLE_DISPLAY_NAMES = {
9665
- ["chest" /* CHEST */]: "Chest",
9666
- ["front_delts" /* FRONT_DELTS */]: "Front Delts",
9667
- ["side_delts" /* SIDE_DELTS */]: "Side Delts",
9668
- ["rear_delts" /* REAR_DELTS */]: "Rear Delts",
9669
- ["triceps" /* TRICEPS */]: "Triceps",
9670
- ["lats" /* LATS */]: "Lats",
9671
- ["upper_back" /* UPPER_BACK */]: "Upper Back",
9672
- ["biceps" /* BICEPS */]: "Biceps",
9673
- ["forearms" /* FOREARMS */]: "Forearms",
9674
- ["quads" /* QUADS */]: "Quads",
9675
- ["hamstrings" /* HAMSTRINGS */]: "Hamstrings",
9676
- ["glutes" /* GLUTES */]: "Glutes",
9677
- ["calves" /* CALVES */]: "Calves",
9678
- ["abs" /* ABS */]: "Abs",
9679
- ["obliques" /* OBLIQUES */]: "Obliques"
9680
- };
9681
- var SIMPLE_DISPLAY_NAMES = {
9682
- ["chest" /* CHEST */]: "Chest",
9683
- ["back" /* BACK */]: "Back",
9684
- ["shoulders" /* SHOULDERS */]: "Shoulders",
9685
- ["biceps" /* BICEPS */]: "Biceps",
9686
- ["triceps" /* TRICEPS */]: "Triceps",
9687
- ["legs" /* LEGS */]: "Legs",
9688
- ["core" /* CORE */]: "Core",
9689
- ["forearms" /* FOREARMS */]: "Forearms"
9690
- };
9691
- var DEFAULT_VOLUME_LANDMARKS = {
9692
- ["chest" /* CHEST */]: { mev: 8, mav: 14, mrv: 20 },
9693
- ["lats" /* LATS */]: { mev: 8, mav: 14, mrv: 20 },
9694
- ["upper_back" /* UPPER_BACK */]: { mev: 6, mav: 12, mrv: 18 },
9695
- ["front_delts" /* FRONT_DELTS */]: { mev: 2, mav: 6, mrv: 10 },
9696
- ["side_delts" /* SIDE_DELTS */]: { mev: 6, mav: 14, mrv: 22 },
9697
- ["rear_delts" /* REAR_DELTS */]: { mev: 6, mav: 12, mrv: 18 },
9698
- ["biceps" /* BICEPS */]: { mev: 4, mav: 10, mrv: 18 },
9699
- ["triceps" /* TRICEPS */]: { mev: 4, mav: 8, mrv: 14 },
9700
- ["forearms" /* FOREARMS */]: { mev: 2, mav: 6, mrv: 12 },
9701
- ["quads" /* QUADS */]: { mev: 6, mav: 12, mrv: 18 },
9702
- ["hamstrings" /* HAMSTRINGS */]: { mev: 4, mav: 10, mrv: 16 },
9703
- ["glutes" /* GLUTES */]: { mev: 4, mav: 10, mrv: 16 },
9704
- ["calves" /* CALVES */]: { mev: 6, mav: 10, mrv: 16 },
9705
- ["abs" /* ABS */]: { mev: 0, mav: 8, mrv: 16 },
9706
- ["obliques" /* OBLIQUES */]: { mev: 0, mav: 6, mrv: 12 }
9707
- };
9708
- var VOLUME_STATUS_LABELS = {
9709
- under: "under-trained",
9710
- maintenance: "maintenance",
9711
- productive: "productive",
9712
- over: "over-reaching"
9713
- };
9714
- var STATUS_SEVERITY = {
9715
- under: 1,
9716
- maintenance: 2,
9717
- productive: 3,
9718
- over: 4
9719
- };
9720
- function getHeatmapColor(status, intensity = 0) {
9721
- const heatmap = WORKOUT_TOKENS.heatmap;
9722
- switch (status) {
9723
- case "under":
9724
- return heatmap.under;
9725
- case "maintenance":
9726
- return heatmap.maintenance;
9727
- case "productive":
9728
- return intensity >= 0.85 ? heatmap.approaching : heatmap.productive;
9729
- case "over":
9730
- return heatmap.over;
9731
- default:
9732
- return heatmap.none;
8620
+ function deriveNavLevel(selection) {
8621
+ if (selection.workoutId != null) return "workout";
8622
+ if (selection.weekNumber != null) return "week";
8623
+ return "meso";
8624
+ }
8625
+ function toProgressBarMesos(mesos) {
8626
+ return mesos.map(({ id, name, weekCount, status, currentWeek }) => ({
8627
+ id,
8628
+ name,
8629
+ weekCount,
8630
+ status,
8631
+ currentWeek
8632
+ }));
8633
+ }
8634
+ function findMeso(mesos, id) {
8635
+ if (id == null) return null;
8636
+ return mesos.find((meso) => meso.id === id) ?? null;
8637
+ }
8638
+ function findWeek(meso, weekNumber) {
8639
+ if (meso == null || weekNumber == null) return null;
8640
+ return meso.weeks.find((week) => week.weekNumber === weekNumber) ?? null;
8641
+ }
8642
+ function findWorkout(week, workoutId) {
8643
+ if (week == null || workoutId == null) return null;
8644
+ return week.workouts.find((workout) => workout.id === workoutId) ?? null;
8645
+ }
8646
+ function buildBreadcrumbs(meso, weekNumber, workout) {
8647
+ const crumbs = [{ key: "meso", label: meso.name, level: "meso" }];
8648
+ if (weekNumber != null) {
8649
+ crumbs.push({ key: "week", label: `Week ${weekNumber}`, level: "week" });
8650
+ }
8651
+ if (workout != null) {
8652
+ crumbs.push({ key: "workout", label: workout.name, level: "workout" });
9733
8653
  }
8654
+ return crumbs;
9734
8655
  }
9735
- function isMoreSevere(a, b) {
9736
- return STATUS_SEVERITY[a] >= STATUS_SEVERITY[b];
9737
- }
9738
- var SLUG_TO_PRIMARY_MUSCLE = {
9739
- chest: "chest" /* CHEST */,
9740
- deltoids: "side_delts" /* SIDE_DELTS */,
9741
- triceps: "triceps" /* TRICEPS */,
9742
- "upper-back": "lats" /* LATS */,
9743
- trapezius: "upper_back" /* UPPER_BACK */,
9744
- biceps: "biceps" /* BICEPS */,
9745
- forearm: "forearms" /* FOREARMS */,
9746
- quadriceps: "quads" /* QUADS */,
9747
- hamstring: "hamstrings" /* HAMSTRINGS */,
9748
- gluteal: "glutes" /* GLUTES */,
9749
- calves: "calves" /* CALVES */,
9750
- abs: "abs" /* ABS */,
9751
- obliques: "obliques" /* OBLIQUES */
9752
- };
9753
-
9754
- // src/components/custom/Workout/BodyMap.tsx
9755
- var Body = BodyHighlighter.default ?? BodyHighlighter;
9756
- var OUTLINE_FILL = "rgba(255,255,255,0.08)";
9757
- var OUTLINE_BORDER = "rgba(255,255,255,0.12)";
9758
- var BODY_SCALE = 0.8;
9759
- var TEXT_PRIMARY7 = "#F3F4F6";
9760
- var TEXT_SECONDARY6 = "#9CA3AF";
9761
- function buildSlugParts(data) {
9762
- const bySlug = /* @__PURE__ */ new Map();
9763
- for (const d of data) {
9764
- for (const slug of MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []) {
9765
- const existing = bySlug.get(slug);
9766
- if (!existing || isMoreSevere(d.volumeStatus, existing.status)) {
9767
- bySlug.set(slug, { status: d.volumeStatus, intensity: d.intensity });
9768
- }
8656
+ function Breadcrumbs2({ crumbs, onNavigate }) {
8657
+ return /* @__PURE__ */ jsx(
8658
+ View,
8659
+ {
8660
+ className: "flex-row items-center flex-wrap",
8661
+ style: { gap: 4 },
8662
+ testID: "program-planning-page-breadcrumbs",
8663
+ children: crumbs.map((crumb, index) => {
8664
+ const isLast = index === crumbs.length - 1;
8665
+ return /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 4 }, children: [
8666
+ index > 0 && /* @__PURE__ */ jsx(Text, { style: { fontSize: 12, color: TEXT_TERTIARY6 }, children: "\u203A" }),
8667
+ /* @__PURE__ */ jsx(
8668
+ Pressable,
8669
+ {
8670
+ onPress: () => onNavigate(crumb.level),
8671
+ disabled: isLast,
8672
+ accessibilityRole: "button",
8673
+ testID: `program-planning-page-crumb-${crumb.key}`,
8674
+ children: /* @__PURE__ */ jsx(
8675
+ Text,
8676
+ {
8677
+ style: {
8678
+ fontSize: 12,
8679
+ fontFamily: "Inter, sans-serif",
8680
+ fontWeight: isLast ? "700" : "500",
8681
+ color: isLast ? TEXT_PRIMARY6 : BRAND_PRIMARY9
8682
+ },
8683
+ children: crumb.label
8684
+ }
8685
+ )
8686
+ }
8687
+ )
8688
+ ] }, crumb.key);
8689
+ })
9769
8690
  }
9770
- }
9771
- return Array.from(bySlug.entries()).map(([slug, v]) => ({
9772
- slug,
9773
- color: getHeatmapColor(v.status, v.intensity)
8691
+ );
8692
+ }
8693
+ function toWeekRow(week, meso, onSelectWeek) {
8694
+ const workouts = week.workouts.map((workout) => ({
8695
+ name: workout.name,
8696
+ status: WORKOUT_PILL_STATUS[workout.status],
8697
+ onPress: () => onSelectWeek(week.weekNumber)
9774
8698
  }));
8699
+ return {
8700
+ weekNumber: week.weekNumber,
8701
+ totalWeeks: meso.weekCount,
8702
+ workouts,
8703
+ intensityLevel: week.intensityLevel,
8704
+ intensityThreshold: week.intensityThreshold,
8705
+ isCurrent: week.isCurrent ?? week.weekNumber === meso.currentWeek,
8706
+ isDeload: week.isDeload
8707
+ };
9775
8708
  }
9776
- function buildSimpleLegend(data) {
9777
- const bySimple = /* @__PURE__ */ new Map();
9778
- for (const d of data) {
9779
- const simple = DETAILED_TO_SIMPLE[d.muscleGroup];
9780
- const existing = bySimple.get(simple);
9781
- if (!existing) {
9782
- bySimple.set(simple, {
9783
- key: simple,
9784
- name: SIMPLE_DISPLAY_NAMES[simple],
9785
- status: d.volumeStatus,
9786
- intensity: d.intensity,
9787
- sets: d.weeklySets,
9788
- muscle: d.muscleGroup
9789
- });
9790
- continue;
9791
- }
9792
- existing.sets += d.weeklySets;
9793
- existing.intensity = Math.max(existing.intensity, d.intensity);
9794
- if (isMoreSevere(d.volumeStatus, existing.status)) {
9795
- existing.status = d.volumeStatus;
9796
- existing.muscle = d.muscleGroup;
9797
- }
9798
- }
9799
- return Array.from(bySimple.values());
9800
- }
9801
- function buildDetailedLegend(data) {
9802
- return data.map((d) => ({
9803
- key: d.muscleGroup,
9804
- name: MUSCLE_DISPLAY_NAMES[d.muscleGroup],
9805
- status: d.volumeStatus,
9806
- intensity: d.intensity,
9807
- sets: d.weeklySets,
9808
- muscle: d.muscleGroup
8709
+ function MesoLevel({ mesos, activeMesoId, onSelectMeso, onSelectWeek }) {
8710
+ return /* @__PURE__ */ jsx(View, { style: { gap: 12 }, testID: "program-planning-page-meso-level", children: mesos.map((meso) => {
8711
+ const expanded = meso.id === activeMesoId;
8712
+ return /* @__PURE__ */ jsx(
8713
+ MesoCard,
8714
+ {
8715
+ name: meso.name,
8716
+ goal: meso.goal,
8717
+ split: meso.split,
8718
+ weekRange: meso.weekRange,
8719
+ currentWeek: meso.currentWeek,
8720
+ totalWeeks: meso.weekCount,
8721
+ weeks: expanded ? meso.weeks.map((week) => toWeekRow(week, meso, onSelectWeek)) : [],
8722
+ volumeHeatmap: meso.volumeHeatmap,
8723
+ expanded,
8724
+ onToggle: () => onSelectMeso(meso.id),
8725
+ highlighted: expanded
8726
+ },
8727
+ meso.id
8728
+ );
8729
+ }) });
8730
+ }
8731
+ function WeekLevel({ week, onSelectWorkout }) {
8732
+ return /* @__PURE__ */ jsx(View, { style: { gap: 10 }, testID: "program-planning-page-week-level", children: week.workouts.map((workout) => /* @__PURE__ */ jsx(
8733
+ WorkoutCard,
8734
+ {
8735
+ name: workout.name,
8736
+ date: workout.date,
8737
+ duration: workout.duration,
8738
+ status: workout.status,
8739
+ muscleGroups: workout.muscleGroups,
8740
+ totalSets: workout.totalSets,
8741
+ totalVolume: workout.totalVolume,
8742
+ unit: workout.unit,
8743
+ exercises: workout.exercises,
8744
+ expanded: false,
8745
+ onToggle: () => onSelectWorkout(workout.id)
8746
+ },
8747
+ workout.id
8748
+ )) });
8749
+ }
8750
+ function WorkoutLevel({ workout, expandedExercise, onToggleExercise }) {
8751
+ const exercises = workout.exercises.map((exercise, index) => ({
8752
+ ...exercise,
8753
+ state: exercise.state === "upcoming" ? exercise.state : index === expandedExercise ? "expanded" : "collapsed",
8754
+ onToggle: () => onToggleExercise(index)
9809
8755
  }));
8756
+ return /* @__PURE__ */ jsx(View, { testID: "program-planning-page-workout-level", children: /* @__PURE__ */ jsx(
8757
+ WorkoutCard,
8758
+ {
8759
+ name: workout.name,
8760
+ date: workout.date,
8761
+ duration: workout.duration,
8762
+ status: workout.status,
8763
+ muscleGroups: workout.muscleGroups,
8764
+ totalSets: workout.totalSets,
8765
+ totalVolume: workout.totalVolume,
8766
+ unit: workout.unit,
8767
+ exercises,
8768
+ expanded: true,
8769
+ onToggle: () => void 0
8770
+ }
8771
+ ) });
9810
8772
  }
9811
- function BodyMap({
9812
- data,
9813
- view,
9814
- onViewChange,
9815
- onMusclePress,
9816
- highlightedMuscle,
9817
- mode = "detailed",
8773
+ function ProgramPlanningPage({
8774
+ title = "Program Plan",
8775
+ mesos,
9818
8776
  className,
9819
8777
  ...props
9820
8778
  }) {
9821
- const slugParts = useMemo(() => buildSlugParts(data), [data]);
9822
- const legend = useMemo(
9823
- () => mode === "simple" ? buildSimpleLegend(data) : buildDetailedLegend(data),
9824
- [data, mode]
9825
- );
9826
- const [highlight] = useState(() => new Animated.Value(highlightedMuscle ? 1 : 0));
9827
- useEffect(() => {
9828
- const animation = Animated.timing(highlight, {
9829
- toValue: highlightedMuscle ? 1 : 0,
9830
- duration: 250,
9831
- easing: Easing.out(Easing.ease),
9832
- useNativeDriver: false
9833
- });
9834
- animation.start();
9835
- return () => animation.stop();
9836
- }, [highlightedMuscle, highlight]);
9837
- const scale = highlight.interpolate({ inputRange: [0, 1], outputRange: [1, 1.02] });
9838
- const glowColor = highlightedMuscle ? getHeatmapColor(
9839
- data.find((d) => d.muscleGroup === highlightedMuscle)?.volumeStatus,
9840
- data.find((d) => d.muscleGroup === highlightedMuscle)?.intensity ?? 0
9841
- ) : null;
9842
- const handleBodyPress = (part) => {
9843
- if (!onMusclePress || !part.slug) return;
9844
- const fromData = data.find(
9845
- (d) => (MUSCLE_TO_SVG_SLUGS[d.muscleGroup] ?? []).includes(part.slug)
9846
- );
9847
- const muscle = fromData?.muscleGroup ?? SLUG_TO_PRIMARY_MUSCLE[part.slug];
9848
- if (muscle) onMusclePress(muscle);
8779
+ const [activeMesoId, setActiveMesoId] = useState(mesos[0]?.id ?? null);
8780
+ const [selectedWeek, setSelectedWeek] = useState(null);
8781
+ const [selectedWorkoutId, setSelectedWorkoutId] = useState(null);
8782
+ const [expandedExercise, setExpandedExercise] = useState(null);
8783
+ const progressMesos = useMemo(() => toProgressBarMesos(mesos), [mesos]);
8784
+ const activeMeso = findMeso(mesos, activeMesoId);
8785
+ const level = deriveNavLevel({ weekNumber: selectedWeek, workoutId: selectedWorkoutId });
8786
+ const activeWeek = findWeek(activeMeso, selectedWeek);
8787
+ const activeWorkout = findWorkout(activeWeek, selectedWorkoutId);
8788
+ const selectMeso = (id) => {
8789
+ setActiveMesoId(id);
8790
+ setSelectedWeek(null);
8791
+ setSelectedWorkoutId(null);
9849
8792
  };
9850
- return /* @__PURE__ */ jsxs(View, { className: cn(className), testID: "body-map", ...props, children: [
9851
- /* @__PURE__ */ jsx(ViewToggle, { view, onViewChange }),
9852
- /* @__PURE__ */ jsx(
9853
- Animated.View,
9854
- {
9855
- style: [
8793
+ const selectWeek = (weekNumber) => {
8794
+ setSelectedWeek(weekNumber);
8795
+ setSelectedWorkoutId(null);
8796
+ setExpandedExercise(null);
8797
+ };
8798
+ const selectWorkout = (id) => {
8799
+ setSelectedWorkoutId(id);
8800
+ setExpandedExercise(null);
8801
+ };
8802
+ const toggleExercise = (index) => setExpandedExercise((current) => current === index ? null : index);
8803
+ const navigateTo = (target) => {
8804
+ if (target === "meso") selectMeso(activeMesoId ?? mesos[0]?.id);
8805
+ else if (target === "week" && selectedWeek != null) selectWeek(selectedWeek);
8806
+ };
8807
+ return /* @__PURE__ */ jsx(
8808
+ View,
8809
+ {
8810
+ className,
8811
+ style: { width: 390, backgroundColor: PAGE_BG },
8812
+ accessibilityRole: "main",
8813
+ "aria-label": title,
8814
+ testID: "program-planning-page",
8815
+ ...props,
8816
+ children: /* @__PURE__ */ jsxs(View, { style: { padding: 16, gap: 14 }, testID: "program-planning-page-content", children: [
8817
+ /* @__PURE__ */ jsx(
8818
+ Text,
9856
8819
  {
9857
- width: 200 * BODY_SCALE,
9858
- alignSelf: "center",
9859
- transform: [{ scale }]
9860
- },
9861
- glowColor ? { boxShadow: `0 0 14px 2px ${glowColor}` } : void 0
9862
- ],
9863
- "aria-hidden": true,
9864
- accessibilityElementsHidden: true,
9865
- importantForAccessibility: "no-hide-descendants",
9866
- testID: "body-map-svg",
9867
- children: /* @__PURE__ */ jsx(
9868
- Body,
8820
+ accessibilityRole: "header",
8821
+ style: {
8822
+ fontSize: 20,
8823
+ fontFamily: '"Space Grotesk", sans-serif',
8824
+ fontWeight: "700",
8825
+ color: TEXT_PRIMARY6
8826
+ },
8827
+ testID: "program-planning-page-title",
8828
+ children: title
8829
+ }
8830
+ ),
8831
+ /* @__PURE__ */ jsx(View, { style: { marginHorizontal: -16 }, children: /* @__PURE__ */ jsx(
8832
+ MesoProgressBar,
9869
8833
  {
9870
- side: view,
9871
- data: slugParts,
9872
- scale: BODY_SCALE,
9873
- gender: "male",
9874
- defaultFill: OUTLINE_FILL,
9875
- border: OUTLINE_BORDER,
9876
- onBodyPartPress: handleBodyPress
8834
+ mesos: progressMesos,
8835
+ activeMesoId,
8836
+ onMesoPress: selectMeso
9877
8837
  }
9878
- )
9879
- }
9880
- ),
9881
- legend.length === 0 ? /* @__PURE__ */ jsx(
9882
- Text,
9883
- {
9884
- style: {
9885
- marginTop: 8,
9886
- fontSize: 12,
9887
- color: TEXT_SECONDARY6,
9888
- textAlign: "center",
9889
- fontFamily: "Inter, sans-serif"
9890
- },
9891
- testID: "body-map-empty",
9892
- children: "No training data"
9893
- }
9894
- ) : /* @__PURE__ */ jsx(
9895
- View,
9896
- {
9897
- className: "flex-row flex-wrap",
9898
- style: { marginTop: 10, gap: 6, justifyContent: "center" },
9899
- testID: "body-map-legend",
9900
- children: legend.map((entry) => /* @__PURE__ */ jsx(
9901
- MuscleButton,
8838
+ ) }),
8839
+ activeMeso != null && /* @__PURE__ */ jsx(
8840
+ Breadcrumbs2,
9902
8841
  {
9903
- entry,
9904
- highlighted: highlightedMuscle === entry.muscle,
9905
- onMusclePress
9906
- },
9907
- entry.key
9908
- ))
9909
- }
9910
- )
9911
- ] });
8842
+ crumbs: buildBreadcrumbs(activeMeso, selectedWeek, activeWorkout),
8843
+ onNavigate: navigateTo
8844
+ }
8845
+ ),
8846
+ /* @__PURE__ */ jsxs(
8847
+ View,
8848
+ {
8849
+ style: {
8850
+ backgroundColor: SURFACE_ELEVATED,
8851
+ borderWidth: 1,
8852
+ borderColor: BORDER_DEFAULT3,
8853
+ borderRadius: 12,
8854
+ padding: 12
8855
+ },
8856
+ testID: "program-planning-page-body",
8857
+ children: [
8858
+ level === "meso" && /* @__PURE__ */ jsx(
8859
+ MesoLevel,
8860
+ {
8861
+ mesos,
8862
+ activeMesoId,
8863
+ onSelectMeso: selectMeso,
8864
+ onSelectWeek: selectWeek
8865
+ }
8866
+ ),
8867
+ level === "week" && activeWeek != null && /* @__PURE__ */ jsx(WeekLevel, { week: activeWeek, onSelectWorkout: selectWorkout }),
8868
+ level === "workout" && activeWorkout != null && /* @__PURE__ */ jsx(
8869
+ WorkoutLevel,
8870
+ {
8871
+ workout: activeWorkout,
8872
+ expandedExercise,
8873
+ onToggleExercise: toggleExercise
8874
+ }
8875
+ )
8876
+ ]
8877
+ }
8878
+ )
8879
+ ] })
8880
+ }
8881
+ );
8882
+ }
8883
+ var SURFACE_ELEVATED2 = "var(--color-surface-elevated)";
8884
+ var BORDER_DEFAULT4 = "var(--color-border-default)";
8885
+ var BRAND_PRIMARY10 = "#FF7900";
8886
+ var TEXT_PRIMARY7 = "var(--color-text-primary)";
8887
+ var TEXT_SECONDARY5 = "var(--color-text-secondary)";
8888
+ var TEXT_TERTIARY7 = "var(--color-text-tertiary)";
8889
+ var PAGE_BG2 = "var(--color-background-base)";
8890
+ var CHART_WIDTH = 326;
8891
+ var CHART_HEIGHT = 150;
8892
+ var EXERCISE_DETAIL_TABS = [
8893
+ { key: "progress", label: "Progress" },
8894
+ { key: "history", label: "History" },
8895
+ { key: "advanced", label: "Advanced" }
8896
+ ];
8897
+ function deriveExerciseStats(entries) {
8898
+ let bestE1rm = null;
8899
+ let prCount = 0;
8900
+ for (const entry of entries) {
8901
+ if (entry.e1rm != null && (bestE1rm == null || entry.e1rm.value > bestE1rm)) {
8902
+ bestE1rm = entry.e1rm.value;
8903
+ }
8904
+ if (entry.isPR) prCount += 1;
8905
+ }
8906
+ return { sessions: entries.length, bestE1rm, prCount };
8907
+ }
8908
+ function toExerciseCardProps(entry, expanded, onToggle) {
8909
+ return {
8910
+ name: entry.title,
8911
+ state: expanded ? "expanded" : "collapsed",
8912
+ onToggle,
8913
+ summary: entry.summary,
8914
+ e1rm: entry.e1rm,
8915
+ isPR: entry.isPR,
8916
+ tempo: entry.tempo,
8917
+ sets: expanded ? entry.sets : void 0
8918
+ };
9912
8919
  }
9913
- function ViewToggle({ view, onViewChange }) {
8920
+ function summarizeVbt(sets) {
8921
+ const allReps = sets.flatMap((set) => set.velocities);
8922
+ const meanVelocity = calculateMeanVelocity(allReps);
8923
+ let velocityLoss = 0;
8924
+ for (const set of sets) {
8925
+ velocityLoss = Math.max(velocityLoss, calculateVelocityLoss(set.velocities));
8926
+ }
8927
+ return { meanVelocity, velocityLoss };
8928
+ }
8929
+ function TabBar({ active, onSelect }) {
9914
8930
  return /* @__PURE__ */ jsx(
9915
8931
  View,
9916
8932
  {
9917
- className: "flex-row self-center",
9918
- style: { gap: 4, marginBottom: 8 },
9919
- testID: "body-map-view-toggle",
9920
- children: ["front", "back"].map((side) => {
9921
- const active = view === side;
8933
+ className: "flex-row",
8934
+ style: {
8935
+ borderBottomWidth: 1,
8936
+ borderBottomColor: BORDER_DEFAULT4
8937
+ },
8938
+ accessibilityRole: "tablist",
8939
+ testID: "exercise-detail-page-tabs",
8940
+ children: EXERCISE_DETAIL_TABS.map(({ key, label }) => {
8941
+ const isActive = key === active;
9922
8942
  return /* @__PURE__ */ jsx(
9923
8943
  Pressable,
9924
8944
  {
9925
- onPress: () => onViewChange?.(side),
9926
- accessibilityRole: "button",
9927
- accessibilityLabel: `Show ${side} view`,
9928
- "aria-pressed": active,
9929
- disabled: !onViewChange,
8945
+ onPress: () => onSelect(key),
8946
+ accessibilityRole: "tab",
8947
+ accessibilityState: { selected: isActive },
9930
8948
  style: {
9931
- paddingHorizontal: 12,
9932
- paddingVertical: 4,
9933
- borderRadius: 9999,
9934
- backgroundColor: active ? "rgba(255,121,0,0.16)" : "transparent",
9935
- borderWidth: 1,
9936
- borderColor: active ? "#FF7900" : WORKOUT_TOKENS.border.strong
8949
+ flex: 1,
8950
+ alignItems: "center",
8951
+ paddingVertical: 10,
8952
+ borderBottomWidth: 2,
8953
+ borderBottomColor: isActive ? BRAND_PRIMARY10 : "transparent"
9937
8954
  },
9938
- testID: `body-map-toggle-${side}`,
8955
+ testID: `exercise-detail-page-tab-${key}`,
9939
8956
  children: /* @__PURE__ */ jsx(
9940
8957
  Text,
9941
8958
  {
9942
8959
  style: {
9943
- fontSize: 12,
8960
+ fontSize: 13,
9944
8961
  fontFamily: "Inter, sans-serif",
9945
- fontWeight: active ? "700" : "500",
9946
- color: active ? "#FF7900" : TEXT_SECONDARY6,
9947
- textTransform: "capitalize"
8962
+ fontWeight: isActive ? "700" : "500",
8963
+ color: isActive ? TEXT_PRIMARY7 : TEXT_TERTIARY7
9948
8964
  },
9949
- children: side
8965
+ children: label
9950
8966
  }
9951
8967
  )
9952
8968
  },
9953
- side
8969
+ key
9954
8970
  );
9955
8971
  })
9956
8972
  }
9957
8973
  );
9958
8974
  }
9959
- function MuscleButton({ entry, highlighted, onMusclePress }) {
9960
- const dotColor = getHeatmapColor(entry.status, entry.intensity);
9961
- const label = `${entry.name}, ${VOLUME_STATUS_LABELS[entry.status]}, ${entry.sets} sets this week`;
8975
+ var STAT_CARDS = [
8976
+ { key: "sessions", label: "Sessions" },
8977
+ { key: "bestE1rm", label: "Best e1RM" },
8978
+ { key: "prCount", label: "PRs" }
8979
+ ];
8980
+ function StatStrip({ stats, unit }) {
8981
+ return /* @__PURE__ */ jsx(View, { className: "flex-row", style: { gap: 8 }, testID: "exercise-detail-page-stats", children: STAT_CARDS.map(({ key, label }) => {
8982
+ const raw = stats[key];
8983
+ const value = key === "bestE1rm" ? raw == null ? "\u2014" : `${raw} ${unit}` : `${raw}`;
8984
+ return /* @__PURE__ */ jsxs(
8985
+ View,
8986
+ {
8987
+ style: {
8988
+ flex: 1,
8989
+ padding: 12,
8990
+ borderRadius: 10,
8991
+ backgroundColor: SURFACE_ELEVATED2,
8992
+ borderWidth: 1,
8993
+ borderColor: BORDER_DEFAULT4
8994
+ },
8995
+ testID: `exercise-detail-page-stat-${key}`,
8996
+ children: [
8997
+ /* @__PURE__ */ jsx(
8998
+ Text,
8999
+ {
9000
+ style: {
9001
+ fontSize: 18,
9002
+ fontFamily: '"Space Grotesk", sans-serif',
9003
+ fontWeight: "700",
9004
+ color: TEXT_PRIMARY7
9005
+ },
9006
+ children: value
9007
+ }
9008
+ ),
9009
+ /* @__PURE__ */ jsx(
9010
+ Text,
9011
+ {
9012
+ style: {
9013
+ marginTop: 2,
9014
+ fontSize: 10,
9015
+ fontFamily: "Inter, sans-serif",
9016
+ fontWeight: "600",
9017
+ letterSpacing: 0.4,
9018
+ textTransform: "uppercase",
9019
+ color: TEXT_TERTIARY7
9020
+ },
9021
+ children: label
9022
+ }
9023
+ )
9024
+ ]
9025
+ },
9026
+ key
9027
+ );
9028
+ }) });
9029
+ }
9030
+ function SectionCard({
9031
+ title,
9032
+ children,
9033
+ testID
9034
+ }) {
9962
9035
  return /* @__PURE__ */ jsxs(
9963
- Pressable,
9036
+ View,
9964
9037
  {
9965
- onPress: () => onMusclePress?.(entry.muscle),
9966
- accessibilityRole: "button",
9967
- accessibilityLabel: label,
9968
- "aria-pressed": highlighted,
9969
9038
  style: {
9970
- flexDirection: "row",
9971
- alignItems: "center",
9972
- gap: 5,
9973
- paddingHorizontal: 8,
9974
- paddingVertical: 3,
9975
- borderRadius: 9999,
9039
+ backgroundColor: SURFACE_ELEVATED2,
9976
9040
  borderWidth: 1,
9977
- borderColor: highlighted ? "#FF7900" : WORKOUT_TOKENS.border.default,
9978
- backgroundColor: WORKOUT_TOKENS.surface.raised
9041
+ borderColor: BORDER_DEFAULT4,
9042
+ borderRadius: 12,
9043
+ padding: 12,
9044
+ gap: 10
9979
9045
  },
9980
- testID: `body-map-muscle-${entry.key}`,
9046
+ testID,
9981
9047
  children: [
9982
- /* @__PURE__ */ jsx(
9983
- View,
9984
- {
9985
- style: { width: 7, height: 7, borderRadius: 9999, backgroundColor: dotColor },
9986
- accessibilityElementsHidden: true,
9987
- testID: `body-map-muscle-dot-${entry.key}`
9988
- }
9989
- ),
9990
9048
  /* @__PURE__ */ jsx(
9991
9049
  Text,
9992
9050
  {
9993
9051
  style: {
9994
9052
  fontSize: 11,
9995
9053
  fontFamily: "Inter, sans-serif",
9996
- fontWeight: "500",
9997
- color: TEXT_PRIMARY7
9054
+ fontWeight: "600",
9055
+ letterSpacing: 0.6,
9056
+ textTransform: "uppercase",
9057
+ color: TEXT_TERTIARY7
9998
9058
  },
9999
- accessibilityElementsHidden: true,
10000
- children: entry.name
9059
+ children: title
10001
9060
  }
10002
- )
9061
+ ),
9062
+ children
10003
9063
  ]
10004
9064
  }
10005
9065
  );
10006
9066
  }
10007
- var SURFACE_ELEVATED = WORKOUT_TOKENS.surface.elevated;
10008
- var SURFACE_RAISED2 = WORKOUT_TOKENS.surface.raised;
10009
- var BORDER_STRONG2 = WORKOUT_TOKENS.border.strong;
10010
- var BORDER_DEFAULT3 = WORKOUT_TOKENS.border.default;
10011
- var BRAND_PRIMARY11 = "#FF7900";
10012
- var TEXT_PRIMARY8 = "#F3F4F6";
10013
- var TEXT_SECONDARY7 = "#9CA3AF";
10014
- var TEXT_TERTIARY7 = "#6B7280";
10015
- var VOLUME_GRADIENT = "linear-gradient(90deg, #2196F3 0%, #14B8A6 50%, #D14343 100%)";
10016
- var SLIDE_OFFSET = 400;
10017
- var BACKDROP_OPACITY = 0.4;
10018
- var STATUS_BADGE_COLOR = {
10019
- under: "info",
10020
- maintenance: "warning",
10021
- productive: "success",
10022
- over: "error"
10023
- };
10024
- function clamp013(value) {
10025
- if (value < 0) return 0;
10026
- if (value > 1) return 1;
10027
- return value;
9067
+ function EntryList({ entries, expandedId, onToggle, emptyLabel, testID }) {
9068
+ if (entries.length === 0) {
9069
+ return /* @__PURE__ */ jsx(
9070
+ Text,
9071
+ {
9072
+ style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY7 },
9073
+ testID: `${testID}-empty`,
9074
+ children: emptyLabel
9075
+ }
9076
+ );
9077
+ }
9078
+ return /* @__PURE__ */ jsx(View, { style: { gap: 8 }, testID, children: entries.map((entry) => /* @__PURE__ */ jsx(
9079
+ ExerciseCard,
9080
+ {
9081
+ ...toExerciseCardProps(entry, entry.id === expandedId, () => onToggle(entry.id))
9082
+ },
9083
+ entry.id
9084
+ )) });
10028
9085
  }
10029
- function markerFraction(weeklySets, { mev, mrv }) {
10030
- const span = mrv - mev;
10031
- if (span <= 0) return weeklySets >= mrv ? 1 : 0;
10032
- return clamp013((weeklySets - mev) / span);
9086
+ function VbtBreakdown({ sets }) {
9087
+ return /* @__PURE__ */ jsx(View, { style: { gap: 10 }, testID: "exercise-detail-page-vbt-breakdown", children: sets.map((set) => {
9088
+ const mean = calculateMeanVelocity(set.velocities);
9089
+ const loss = calculateVelocityLoss(set.velocities);
9090
+ return /* @__PURE__ */ jsxs(
9091
+ View,
9092
+ {
9093
+ className: "flex-row items-center",
9094
+ style: { gap: 10 },
9095
+ testID: "exercise-detail-page-vbt-set",
9096
+ children: [
9097
+ /* @__PURE__ */ jsx(
9098
+ Text,
9099
+ {
9100
+ style: {
9101
+ width: 44,
9102
+ fontSize: 11,
9103
+ fontFamily: "Inter, sans-serif",
9104
+ fontWeight: "600",
9105
+ color: TEXT_SECONDARY5
9106
+ },
9107
+ children: set.label
9108
+ }
9109
+ ),
9110
+ /* @__PURE__ */ jsx(View, { className: "flex-1", style: { height: 8, justifyContent: "center" }, children: /* @__PURE__ */ jsx(VelocityStrip, { velocities: set.velocities, variant: "mini" }) }),
9111
+ /* @__PURE__ */ jsx(
9112
+ Text,
9113
+ {
9114
+ style: {
9115
+ fontSize: 11,
9116
+ fontFamily: "Inter, sans-serif",
9117
+ fontVariant: ["tabular-nums"],
9118
+ color: TEXT_TERTIARY7
9119
+ },
9120
+ children: `${mean.toFixed(2)} \xB7 -${loss}%`
9121
+ }
9122
+ )
9123
+ ]
9124
+ },
9125
+ set.label
9126
+ );
9127
+ }) });
10033
9128
  }
10034
- function BodyMapDetailPanel({
10035
- muscleGroup,
10036
- displayName,
10037
- weeklySets,
10038
- landmarks,
10039
- volumeStatus,
10040
- lastTrained,
10041
- weeklyHistory,
10042
- contributingExercises,
10043
- upcomingExercises,
10044
- isOpen,
10045
- visible,
10046
- onClose,
10047
- onViewExercises,
10048
- ...props
10049
- }) {
10050
- const open = isOpen ?? visible ?? false;
10051
- const [translateY] = useState(() => new Animated.Value(SLIDE_OFFSET));
10052
- const [backdrop] = useState(() => new Animated.Value(0));
10053
- useEffect(() => {
10054
- if (!open) return;
10055
- const animation = Animated.parallel([
10056
- Animated.timing(translateY, {
10057
- toValue: 0,
10058
- duration: 400,
10059
- easing: Easing.out(Easing.ease),
10060
- useNativeDriver: false
10061
- }),
10062
- Animated.timing(backdrop, {
10063
- toValue: BACKDROP_OPACITY,
10064
- duration: 300,
10065
- easing: Easing.out(Easing.ease),
10066
- useNativeDriver: false
10067
- })
10068
- ]);
10069
- animation.start();
10070
- return () => animation.stop();
10071
- }, [open, translateY, backdrop]);
10072
- if (!open) return null;
10073
- const dialogLabel = `${displayName} volume details`;
10074
- const markerLeft = markerFraction(weeklySets, landmarks) * 100;
10075
- const hasContributing = (contributingExercises?.length ?? 0) > 0;
10076
- const hasUpcoming = (upcomingExercises?.length ?? 0) > 0;
10077
- return /* @__PURE__ */ jsxs(
9129
+ function VbtSummaryRow({ summary }) {
9130
+ const cells = [
9131
+ { label: "Mean Velocity", value: `${summary.meanVelocity.toFixed(2)} m/s` },
9132
+ { label: "Peak Vel. Loss", value: `-${summary.velocityLoss}%` }
9133
+ ];
9134
+ return /* @__PURE__ */ jsx(View, { className: "flex-row", style: { gap: 8 }, testID: "exercise-detail-page-vbt-summary", children: cells.map((cell) => /* @__PURE__ */ jsxs(
10078
9135
  View,
10079
9136
  {
10080
- style: { position: "absolute", top: 0, left: 0, right: 0, bottom: 0, justifyContent: "flex-end" },
10081
- testID: "body-map-detail-panel-root",
9137
+ style: {
9138
+ flex: 1,
9139
+ padding: 12,
9140
+ borderRadius: 10,
9141
+ backgroundColor: SURFACE_ELEVATED2,
9142
+ borderWidth: 1,
9143
+ borderColor: BORDER_DEFAULT4
9144
+ },
10082
9145
  children: [
10083
9146
  /* @__PURE__ */ jsx(
10084
- Animated.View,
9147
+ Text,
10085
9148
  {
10086
9149
  style: {
10087
- position: "absolute",
10088
- top: 0,
10089
- left: 0,
10090
- right: 0,
10091
- bottom: 0,
10092
- backgroundColor: "#000000",
10093
- opacity: backdrop
9150
+ fontSize: 16,
9151
+ fontFamily: '"Space Grotesk", sans-serif',
9152
+ fontWeight: "700",
9153
+ color: TEXT_PRIMARY7
10094
9154
  },
10095
- testID: "body-map-detail-panel-backdrop-anim",
10096
- children: /* @__PURE__ */ jsx(
10097
- Pressable,
10098
- {
10099
- onPress: onClose,
10100
- accessibilityRole: "button",
10101
- accessibilityLabel: `Close ${displayName} details`,
10102
- style: { flex: 1 },
10103
- testID: "body-map-detail-panel-backdrop"
10104
- }
10105
- )
9155
+ children: cell.value
10106
9156
  }
10107
9157
  ),
10108
- /* @__PURE__ */ jsxs(
10109
- Animated.View,
9158
+ /* @__PURE__ */ jsx(
9159
+ Text,
10110
9160
  {
10111
- accessibilityRole: "dialog",
10112
- accessibilityLabel: dialogLabel,
10113
- "aria-label": dialogLabel,
10114
9161
  style: {
10115
- backgroundColor: SURFACE_ELEVATED,
10116
- borderTopLeftRadius: 16,
10117
- borderTopRightRadius: 16,
10118
- maxHeight: "88%",
10119
- transform: [{ translateY }]
9162
+ marginTop: 2,
9163
+ fontSize: 10,
9164
+ fontFamily: "Inter, sans-serif",
9165
+ fontWeight: "600",
9166
+ letterSpacing: 0.4,
9167
+ textTransform: "uppercase",
9168
+ color: TEXT_TERTIARY7
10120
9169
  },
10121
- testID: "body-map-detail-panel",
10122
- ...props,
9170
+ children: cell.label
9171
+ }
9172
+ )
9173
+ ]
9174
+ },
9175
+ cell.label
9176
+ )) });
9177
+ }
9178
+ function ExerciseDetailPage({
9179
+ exercise,
9180
+ meso,
9181
+ trend,
9182
+ progression,
9183
+ history,
9184
+ vbt,
9185
+ className,
9186
+ ...props
9187
+ }) {
9188
+ const [tab, setTab] = useState("progress");
9189
+ const [expandedProgressId, setExpandedProgressId] = useState(null);
9190
+ const [expandedHistoryId, setExpandedHistoryId] = useState(null);
9191
+ const stats = useMemo(() => deriveExerciseStats(history), [history]);
9192
+ const vbtSummary = useMemo(() => summarizeVbt(vbt.sets), [vbt.sets]);
9193
+ const toggle = (setId) => (id) => setId((current) => current === id ? null : id);
9194
+ return /* @__PURE__ */ jsx(
9195
+ View,
9196
+ {
9197
+ className,
9198
+ style: { width: 390, backgroundColor: PAGE_BG2 },
9199
+ accessibilityRole: "main",
9200
+ "aria-label": exercise.name,
9201
+ testID: "exercise-detail-page",
9202
+ ...props,
9203
+ children: /* @__PURE__ */ jsxs(View, { style: { padding: 16, gap: 14 }, testID: "exercise-detail-page-content", children: [
9204
+ /* @__PURE__ */ jsxs(
9205
+ View,
9206
+ {
9207
+ className: "flex-row items-start justify-between",
9208
+ style: { gap: 8 },
9209
+ testID: "exercise-detail-page-header",
10123
9210
  children: [
10124
- /* @__PURE__ */ jsx(
10125
- Pressable,
10126
- {
10127
- onPress: onClose,
10128
- accessibilityRole: "button",
10129
- accessibilityLabel: `Close ${displayName} details`,
10130
- hitSlop: 12,
10131
- style: { alignSelf: "center", paddingVertical: 8 },
10132
- testID: "body-map-detail-panel-handle",
10133
- children: /* @__PURE__ */ jsx(
10134
- View,
10135
- {
10136
- style: { width: 40, height: 4, borderRadius: 2, backgroundColor: BORDER_STRONG2 },
10137
- accessibilityElementsHidden: true
10138
- }
10139
- )
10140
- }
10141
- ),
10142
- /* @__PURE__ */ jsxs(
10143
- ScrollView,
9211
+ /* @__PURE__ */ jsxs(View, { style: { flexShrink: 1 }, children: [
9212
+ /* @__PURE__ */ jsx(
9213
+ Text,
9214
+ {
9215
+ accessibilityRole: "header",
9216
+ style: {
9217
+ fontSize: 20,
9218
+ fontFamily: '"Space Grotesk", sans-serif',
9219
+ fontWeight: "700",
9220
+ color: TEXT_PRIMARY7
9221
+ },
9222
+ testID: "exercise-detail-page-title",
9223
+ children: exercise.name
9224
+ }
9225
+ ),
9226
+ /* @__PURE__ */ jsx(
9227
+ Text,
9228
+ {
9229
+ style: {
9230
+ marginTop: 2,
9231
+ fontSize: 12,
9232
+ fontFamily: "Inter, sans-serif",
9233
+ color: TEXT_SECONDARY5
9234
+ },
9235
+ testID: "exercise-detail-page-subtitle",
9236
+ children: exercise.subtitle
9237
+ }
9238
+ )
9239
+ ] }),
9240
+ exercise.currentE1rm != null && /* @__PURE__ */ jsxs(
9241
+ View,
10144
9242
  {
10145
- style: { paddingHorizontal: 16 },
10146
- contentContainerStyle: { paddingBottom: 20 },
10147
- testID: "body-map-detail-panel-scroll",
9243
+ style: {
9244
+ paddingVertical: 4,
9245
+ paddingHorizontal: 10,
9246
+ borderRadius: 6,
9247
+ backgroundColor: "rgba(255,121,0,0.10)",
9248
+ borderWidth: 1,
9249
+ borderColor: "rgba(255,121,0,0.25)"
9250
+ },
9251
+ testID: "exercise-detail-page-e1rm",
10148
9252
  children: [
10149
- /* @__PURE__ */ jsxs(
10150
- View,
10151
- {
10152
- className: "flex-row items-center justify-between",
10153
- style: { gap: 8, paddingTop: 4, paddingBottom: 4 },
10154
- testID: "body-map-detail-panel-header",
10155
- children: [
10156
- /* @__PURE__ */ jsxs(View, { className: "flex-row items-center", style: { gap: 8, flexShrink: 1 }, children: [
10157
- /* @__PURE__ */ jsx(
10158
- Text,
10159
- {
10160
- accessibilityRole: "header",
10161
- style: {
10162
- fontSize: 16,
10163
- fontFamily: '"Space Grotesk", sans-serif',
10164
- fontWeight: "700",
10165
- color: TEXT_PRIMARY8
10166
- },
10167
- testID: "body-map-detail-panel-title",
10168
- children: displayName
10169
- }
10170
- ),
10171
- /* @__PURE__ */ jsx(
10172
- Badge,
10173
- {
10174
- variant: "subtle",
10175
- color: STATUS_BADGE_COLOR[volumeStatus],
10176
- size: "sm",
10177
- testID: "body-map-detail-panel-status-badge",
10178
- children: VOLUME_STATUS_LABELS[volumeStatus]
10179
- }
10180
- )
10181
- ] }),
10182
- /* @__PURE__ */ jsx(
10183
- Pressable,
10184
- {
10185
- onPress: onClose,
10186
- accessibilityRole: "button",
10187
- accessibilityLabel: `Close ${displayName} details`,
10188
- hitSlop: 8,
10189
- style: { padding: 4, margin: -4 },
10190
- testID: "body-map-detail-panel-close",
10191
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 22, lineHeight: 22, color: TEXT_SECONDARY7 }, children: "\xD7" })
10192
- }
10193
- )
10194
- ]
10195
- }
10196
- ),
10197
- lastTrained != null && /* @__PURE__ */ jsx(
9253
+ /* @__PURE__ */ jsx(
10198
9254
  Text,
10199
9255
  {
10200
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY7 },
10201
- testID: "body-map-detail-panel-last-trained",
10202
- children: `Last trained ${lastTrained}`
9256
+ style: {
9257
+ fontSize: 9,
9258
+ fontFamily: "Inter, sans-serif",
9259
+ fontWeight: "600",
9260
+ letterSpacing: 0.4,
9261
+ textTransform: "uppercase",
9262
+ color: TEXT_TERTIARY7
9263
+ },
9264
+ children: "e1RM"
10203
9265
  }
10204
9266
  ),
10205
- /* @__PURE__ */ jsxs(View, { style: { marginTop: 16 }, testID: "body-map-detail-panel-volume", children: [
10206
- /* @__PURE__ */ jsxs(
10207
- View,
10208
- {
10209
- className: "flex-row items-center justify-between",
10210
- style: { marginBottom: 6 },
10211
- accessibilityElementsHidden: true,
10212
- children: [
10213
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY7 }, children: `MEV ${landmarks.mev}` }),
10214
- /* @__PURE__ */ jsx(Text, { style: { fontSize: 10, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_TERTIARY7 }, children: `MRV ${landmarks.mrv}` })
10215
- ]
10216
- }
10217
- ),
10218
- /* @__PURE__ */ jsxs(
10219
- View,
10220
- {
10221
- style: { height: 14, justifyContent: "center" },
10222
- accessibilityRole: "progressbar",
10223
- accessibilityValue: { min: landmarks.mev, max: landmarks.mrv, now: weeklySets },
10224
- accessibilityLabel: `${weeklySets} weekly sets, between MEV ${landmarks.mev} and MRV ${landmarks.mrv}`,
10225
- "aria-valuenow": weeklySets,
10226
- "aria-valuemin": landmarks.mev,
10227
- "aria-valuemax": landmarks.mrv,
10228
- testID: "body-map-detail-panel-volume-bar",
10229
- children: [
10230
- /* @__PURE__ */ jsx(
10231
- View,
10232
- {
10233
- style: { height: 8, borderRadius: 4, backgroundImage: VOLUME_GRADIENT },
10234
- accessibilityElementsHidden: true
10235
- }
10236
- ),
10237
- /* @__PURE__ */ jsx(
10238
- View,
10239
- {
10240
- style: {
10241
- position: "absolute",
10242
- left: `${markerLeft}%`,
10243
- marginLeft: -7,
10244
- width: 14,
10245
- height: 14,
10246
- borderRadius: 7,
10247
- borderWidth: 2,
10248
- borderColor: TEXT_PRIMARY8,
10249
- backgroundColor: SURFACE_ELEVATED,
10250
- boxShadow: "0 0 4px rgba(0,0,0,0.5)"
10251
- },
10252
- accessibilityElementsHidden: true,
10253
- testID: "body-map-detail-panel-volume-marker"
10254
- }
10255
- )
10256
- ]
10257
- }
10258
- )
10259
- ] }),
10260
- /* @__PURE__ */ jsxs(View, { className: "flex-row items-baseline", style: { marginTop: 14, gap: 4 }, children: [
10261
- /* @__PURE__ */ jsx(
10262
- Text,
10263
- {
10264
- style: {
10265
- fontSize: 24,
10266
- fontFamily: '"Space Grotesk", sans-serif',
10267
- fontWeight: "700",
10268
- color: TEXT_PRIMARY8
10269
- },
10270
- testID: "body-map-detail-panel-set-count",
10271
- children: weeklySets
10272
- }
10273
- ),
10274
- /* @__PURE__ */ jsx(
10275
- Text,
10276
- {
10277
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY7 },
10278
- testID: "body-map-detail-panel-mrv-suffix",
10279
- children: `/ ${landmarks.mrv} MRV`
10280
- }
10281
- )
10282
- ] }),
10283
- weeklyHistory != null && weeklyHistory.length > 0 && /* @__PURE__ */ jsxs(View, { style: { marginTop: 14 }, testID: "body-map-detail-panel-sparkline", children: [
10284
- /* @__PURE__ */ jsx(
10285
- Text,
10286
- {
10287
- style: {
10288
- fontSize: 10,
10289
- fontFamily: "Inter, sans-serif",
10290
- fontWeight: "600",
10291
- color: TEXT_TERTIARY7,
10292
- marginBottom: 6
10293
- },
10294
- accessibilityElementsHidden: true,
10295
- children: "VOLUME TREND"
10296
- }
10297
- ),
10298
- /* @__PURE__ */ jsx(Sparkline, { data: weeklyHistory, width: 80, height: 30, highlightLast: true })
10299
- ] }),
10300
- hasContributing && /* @__PURE__ */ jsxs(View, { style: { marginTop: 16 }, testID: "body-map-detail-panel-contributing", children: [
10301
- /* @__PURE__ */ jsx(
10302
- Text,
10303
- {
10304
- style: {
10305
- fontSize: 10,
10306
- fontFamily: "Inter, sans-serif",
10307
- fontWeight: "600",
10308
- color: TEXT_TERTIARY7,
10309
- marginBottom: 8
10310
- },
10311
- children: "CONTRIBUTING EXERCISES"
10312
- }
10313
- ),
10314
- contributingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
10315
- View,
10316
- {
10317
- className: "flex-row items-center justify-between",
10318
- style: {
10319
- gap: 10,
10320
- paddingVertical: 8,
10321
- paddingHorizontal: 12,
10322
- marginBottom: 6,
10323
- borderRadius: 8,
10324
- backgroundColor: SURFACE_RAISED2,
10325
- borderWidth: 1,
10326
- borderColor: BORDER_DEFAULT3
10327
- },
10328
- testID: `body-map-detail-panel-contributing-${index}`,
10329
- children: [
10330
- /* @__PURE__ */ jsx(
10331
- Text,
10332
- {
10333
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY8 },
10334
- testID: `body-map-detail-panel-contributing-${index}-name`,
10335
- children: exercise.name
10336
- }
10337
- ),
10338
- /* @__PURE__ */ jsx(
10339
- Text,
10340
- {
10341
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_SECONDARY7 },
10342
- testID: `body-map-detail-panel-contributing-${index}-detail`,
10343
- children: `${exercise.sets} sets \xB7 ${Math.round(exercise.contributionWeight * 100)}%`
10344
- }
10345
- )
10346
- ]
10347
- },
10348
- `${exercise.name}-${index}`
10349
- ))
10350
- ] }),
10351
- hasUpcoming && /* @__PURE__ */ jsxs(View, { style: { marginTop: 16 }, testID: "body-map-detail-panel-upcoming", children: [
10352
- /* @__PURE__ */ jsx(
10353
- Text,
10354
- {
10355
- style: {
10356
- fontSize: 10,
10357
- fontFamily: "Inter, sans-serif",
10358
- fontWeight: "600",
10359
- color: TEXT_TERTIARY7,
10360
- marginBottom: 8
10361
- },
10362
- children: "UPCOMING"
10363
- }
10364
- ),
10365
- upcomingExercises.map((exercise, index) => /* @__PURE__ */ jsxs(
10366
- View,
10367
- {
10368
- className: "flex-row items-center justify-between",
10369
- style: { gap: 10, paddingVertical: 6 },
10370
- testID: `body-map-detail-panel-upcoming-${index}`,
10371
- children: [
10372
- /* @__PURE__ */ jsx(
10373
- Text,
10374
- {
10375
- style: { flex: 1, fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "600", color: TEXT_PRIMARY8 },
10376
- testID: `body-map-detail-panel-upcoming-${index}-name`,
10377
- children: exercise.name
10378
- }
10379
- ),
10380
- /* @__PURE__ */ jsx(
10381
- Text,
10382
- {
10383
- style: { fontSize: 12, fontFamily: "Inter, sans-serif", color: TEXT_TERTIARY7 },
10384
- testID: `body-map-detail-panel-upcoming-${index}-detail`,
10385
- children: `${exercise.workoutName} \xB7 ${exercise.sets} sets`
10386
- }
10387
- )
10388
- ]
10389
- },
10390
- `${exercise.name}-${index}`
10391
- ))
10392
- ] }),
10393
- onViewExercises != null && /* @__PURE__ */ jsx(
10394
- Pressable,
9267
+ /* @__PURE__ */ jsx(
9268
+ Text,
10395
9269
  {
10396
- onPress: onViewExercises,
10397
- accessibilityRole: "button",
10398
- accessibilityLabel: `View ${displayName} exercises`,
10399
9270
  style: {
10400
- marginTop: 16,
10401
- paddingVertical: 10,
10402
- borderRadius: 8,
10403
- alignItems: "center",
10404
- backgroundColor: "rgba(255,121,0,0.12)",
10405
- borderWidth: 1,
10406
- borderColor: "rgba(255,121,0,0.3)"
9271
+ fontSize: 15,
9272
+ fontFamily: '"Space Grotesk", sans-serif',
9273
+ fontWeight: "700",
9274
+ color: BRAND_PRIMARY10
10407
9275
  },
10408
- testID: "body-map-detail-panel-view-exercises",
10409
- children: /* @__PURE__ */ jsx(Text, { style: { fontSize: 13, fontFamily: "Inter, sans-serif", fontWeight: "700", color: BRAND_PRIMARY11 }, children: "View exercises" })
9276
+ children: `${exercise.currentE1rm} ${exercise.unit}`
10410
9277
  }
10411
9278
  )
10412
9279
  ]
@@ -10414,6 +9281,346 @@ function BodyMapDetailPanel({
10414
9281
  )
10415
9282
  ]
10416
9283
  }
9284
+ ),
9285
+ /* @__PURE__ */ jsx(TabBar, { active: tab, onSelect: setTab }),
9286
+ tab === "progress" && /* @__PURE__ */ jsxs(View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-progress", children: [
9287
+ /* @__PURE__ */ jsx(MesoStatusCard, { ...meso }),
9288
+ /* @__PURE__ */ jsx(StatStrip, { stats, unit: exercise.unit }),
9289
+ /* @__PURE__ */ jsx(SectionCard, { title: "Strength Trend", testID: "exercise-detail-page-trend", children: /* @__PURE__ */ jsx(
9290
+ StrengthTrendChart,
9291
+ {
9292
+ data: trend.data,
9293
+ projection: trend.projection,
9294
+ mesoBoundaries: trend.mesoBoundaries,
9295
+ width: CHART_WIDTH,
9296
+ height: CHART_HEIGHT,
9297
+ unit: exercise.unit,
9298
+ animateOnMount: false
9299
+ }
9300
+ ) }),
9301
+ /* @__PURE__ */ jsx(SectionCard, { title: "Week-by-Week", testID: "exercise-detail-page-progression", children: /* @__PURE__ */ jsx(
9302
+ EntryList,
9303
+ {
9304
+ entries: progression,
9305
+ expandedId: expandedProgressId,
9306
+ onToggle: toggle(setExpandedProgressId),
9307
+ emptyLabel: "No progression logged yet",
9308
+ testID: "exercise-detail-page-progression-list"
9309
+ }
9310
+ ) })
9311
+ ] }),
9312
+ tab === "history" && /* @__PURE__ */ jsx(View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-history", children: /* @__PURE__ */ jsx(SectionCard, { title: "All Sessions", testID: "exercise-detail-page-history", children: /* @__PURE__ */ jsx(
9313
+ EntryList,
9314
+ {
9315
+ entries: history,
9316
+ expandedId: expandedHistoryId,
9317
+ onToggle: toggle(setExpandedHistoryId),
9318
+ emptyLabel: "No sessions logged yet",
9319
+ testID: "exercise-detail-page-history-list"
9320
+ }
9321
+ ) }) }),
9322
+ tab === "advanced" && /* @__PURE__ */ jsxs(View, { style: { gap: 14 }, testID: "exercise-detail-page-panel-advanced", children: [
9323
+ /* @__PURE__ */ jsx(SectionCard, { title: "Capacity Band", testID: "exercise-detail-page-capacity", children: /* @__PURE__ */ jsx(
9324
+ CapacityBandChart,
9325
+ {
9326
+ band: vbt.band,
9327
+ workouts: vbt.workouts,
9328
+ projection: vbt.projection,
9329
+ width: CHART_WIDTH,
9330
+ height: CHART_HEIGHT
9331
+ }
9332
+ ) }),
9333
+ /* @__PURE__ */ jsx(VbtSummaryRow, { summary: vbtSummary }),
9334
+ /* @__PURE__ */ jsx(SectionCard, { title: "Velocity Breakdown", testID: "exercise-detail-page-velocity", children: /* @__PURE__ */ jsx(VbtBreakdown, { sets: vbt.sets }) })
9335
+ ] })
9336
+ ] })
9337
+ }
9338
+ );
9339
+ }
9340
+ var SURFACE_ELEVATED3 = "var(--color-surface-elevated)";
9341
+ var BORDER_DEFAULT5 = "var(--color-border-default)";
9342
+ var BRAND_PRIMARY11 = "#FF7900";
9343
+ var TEXT_PRIMARY8 = "var(--color-text-primary)";
9344
+ var TEXT_SECONDARY6 = "var(--color-text-secondary)";
9345
+ var TEXT_TERTIARY8 = "var(--color-text-tertiary)";
9346
+ var PAGE_BG3 = "var(--color-background-base)";
9347
+ function countCompletedSets(exercise) {
9348
+ if (exercise.setVelocities != null) return exercise.setVelocities.length;
9349
+ if (exercise.status === "completed") return exercise.totalPlannedSets;
9350
+ return 0;
9351
+ }
9352
+ function deriveWorkoutProgress(exercises) {
9353
+ let completedExercises = 0;
9354
+ let completedSets = 0;
9355
+ let totalSets = 0;
9356
+ for (const exercise of exercises) {
9357
+ if (exercise.status === "completed") completedExercises += 1;
9358
+ completedSets += countCompletedSets(exercise);
9359
+ totalSets += exercise.totalPlannedSets;
9360
+ }
9361
+ return {
9362
+ completedExercises,
9363
+ totalExercises: exercises.length,
9364
+ completedSets,
9365
+ totalSets,
9366
+ fraction: totalSets === 0 ? 0 : completedSets / totalSets
9367
+ };
9368
+ }
9369
+ function findActiveExercise(exercises) {
9370
+ return exercises.find((exercise) => exercise.status === "active") ?? null;
9371
+ }
9372
+ function statusToCardState(status, focused) {
9373
+ if (status === "upcoming") return "upcoming";
9374
+ return focused ? "expanded" : "collapsed";
9375
+ }
9376
+ function toActiveCardProps(exercise, focused, onToggle, supersetPosition = null, supersetColor) {
9377
+ const state = statusToCardState(exercise.status, focused);
9378
+ return {
9379
+ name: exercise.name,
9380
+ state,
9381
+ onToggle,
9382
+ summary: exercise.summary,
9383
+ e1rm: exercise.e1rm,
9384
+ isPR: exercise.isPR,
9385
+ tempo: exercise.tempo,
9386
+ setVelocities: exercise.setVelocities,
9387
+ totalPlannedSets: exercise.totalPlannedSets,
9388
+ sets: state === "expanded" ? exercise.sets : void 0,
9389
+ prescription: exercise.prescription,
9390
+ previousBest: exercise.previousBest,
9391
+ supersetPosition,
9392
+ supersetColor
9393
+ };
9394
+ }
9395
+ function groupExercises(exercises, supersets) {
9396
+ const byId = new Map(supersets.map((superset) => [superset.id, superset]));
9397
+ const groups = [];
9398
+ for (const exercise of exercises) {
9399
+ const superset = exercise.supersetId != null ? byId.get(exercise.supersetId) : void 0;
9400
+ const last = groups[groups.length - 1];
9401
+ if (superset != null && last?.type === "superset" && last.superset.id === superset.id) {
9402
+ last.exercises.push(exercise);
9403
+ } else if (superset != null) {
9404
+ groups.push({ type: "superset", superset, exercises: [exercise] });
9405
+ } else {
9406
+ groups.push({ type: "single", exercise });
9407
+ }
9408
+ }
9409
+ return groups;
9410
+ }
9411
+ function supersetPositionAt(index, length) {
9412
+ if (length === 1) return null;
9413
+ if (index === 0) return "first";
9414
+ if (index === length - 1) return "last";
9415
+ return "middle";
9416
+ }
9417
+ function WorkoutHeader({
9418
+ title,
9419
+ subtitle,
9420
+ progress
9421
+ }) {
9422
+ return /* @__PURE__ */ jsxs(View, { style: { gap: 10 }, testID: "active-workout-page-header", children: [
9423
+ /* @__PURE__ */ jsxs(View, { className: "flex-row items-start justify-between", style: { gap: 8 }, children: [
9424
+ /* @__PURE__ */ jsxs(View, { style: { flexShrink: 1 }, children: [
9425
+ /* @__PURE__ */ jsx(
9426
+ Text,
9427
+ {
9428
+ accessibilityRole: "header",
9429
+ style: {
9430
+ fontSize: 20,
9431
+ fontFamily: '"Space Grotesk", sans-serif',
9432
+ fontWeight: "700",
9433
+ color: TEXT_PRIMARY8
9434
+ },
9435
+ testID: "active-workout-page-title",
9436
+ children: title
9437
+ }
9438
+ ),
9439
+ subtitle != null && /* @__PURE__ */ jsx(
9440
+ Text,
9441
+ {
9442
+ style: {
9443
+ marginTop: 2,
9444
+ fontSize: 12,
9445
+ fontFamily: "Inter, sans-serif",
9446
+ color: TEXT_SECONDARY6
9447
+ },
9448
+ testID: "active-workout-page-subtitle",
9449
+ children: subtitle
9450
+ }
9451
+ )
9452
+ ] }),
9453
+ /* @__PURE__ */ jsxs(View, { style: { alignItems: "flex-end" }, testID: "active-workout-page-progress-count", children: [
9454
+ /* @__PURE__ */ jsx(
9455
+ Text,
9456
+ {
9457
+ style: {
9458
+ fontSize: 15,
9459
+ fontFamily: '"Space Grotesk", sans-serif',
9460
+ fontWeight: "700",
9461
+ color: BRAND_PRIMARY11,
9462
+ fontVariant: ["tabular-nums"]
9463
+ },
9464
+ children: `${progress.completedExercises}/${progress.totalExercises}`
9465
+ }
9466
+ ),
9467
+ /* @__PURE__ */ jsx(
9468
+ Text,
9469
+ {
9470
+ style: {
9471
+ fontSize: 10,
9472
+ fontFamily: "Inter, sans-serif",
9473
+ fontWeight: "600",
9474
+ letterSpacing: 0.4,
9475
+ textTransform: "uppercase",
9476
+ color: TEXT_TERTIARY8
9477
+ },
9478
+ children: `${progress.completedSets}/${progress.totalSets} sets`
9479
+ }
9480
+ )
9481
+ ] })
9482
+ ] }),
9483
+ /* @__PURE__ */ jsx(
9484
+ View,
9485
+ {
9486
+ style: { height: 4, backgroundColor: BORDER_DEFAULT5, borderRadius: 2 },
9487
+ testID: "active-workout-page-progress-track",
9488
+ children: /* @__PURE__ */ jsx(
9489
+ View,
9490
+ {
9491
+ style: {
9492
+ height: "100%",
9493
+ width: `${Math.round(progress.fraction * 100)}%`,
9494
+ backgroundColor: BRAND_PRIMARY11,
9495
+ borderRadius: 2
9496
+ },
9497
+ testID: "active-workout-page-progress-fill"
9498
+ }
9499
+ )
9500
+ }
9501
+ )
9502
+ ] });
9503
+ }
9504
+ function ExerciseList({ groups, focusedId, onToggle }) {
9505
+ return /* @__PURE__ */ jsx(View, { style: { gap: 10 }, testID: "active-workout-page-exercises", children: groups.map((group) => {
9506
+ if (group.type === "single") {
9507
+ return /* @__PURE__ */ jsx(
9508
+ View,
9509
+ {
9510
+ style: {
9511
+ backgroundColor: SURFACE_ELEVATED3,
9512
+ borderWidth: 1,
9513
+ borderColor: BORDER_DEFAULT5,
9514
+ borderRadius: 12
9515
+ },
9516
+ children: /* @__PURE__ */ jsx(
9517
+ ExerciseCard,
9518
+ {
9519
+ ...toActiveCardProps(
9520
+ group.exercise,
9521
+ group.exercise.id === focusedId,
9522
+ () => onToggle(group.exercise.id)
9523
+ )
9524
+ }
9525
+ )
9526
+ },
9527
+ group.exercise.id
9528
+ );
9529
+ }
9530
+ return /* @__PURE__ */ jsx(
9531
+ SupersetWrapper,
9532
+ {
9533
+ label: group.superset.label,
9534
+ color: group.superset.color,
9535
+ children: group.exercises.map((exercise, index) => /* @__PURE__ */ jsx(
9536
+ ExerciseCard,
9537
+ {
9538
+ ...toActiveCardProps(
9539
+ exercise,
9540
+ exercise.id === focusedId,
9541
+ () => onToggle(exercise.id),
9542
+ supersetPositionAt(index, group.exercises.length),
9543
+ group.superset.color
9544
+ )
9545
+ },
9546
+ exercise.id
9547
+ ))
9548
+ },
9549
+ group.superset.id
9550
+ );
9551
+ }) });
9552
+ }
9553
+ function ActiveWorkoutPage({
9554
+ title = "Active Workout",
9555
+ subtitle,
9556
+ exercises,
9557
+ supersets = [],
9558
+ input,
9559
+ rest,
9560
+ initialResting = false,
9561
+ className,
9562
+ ...props
9563
+ }) {
9564
+ const active = findActiveExercise(exercises);
9565
+ const [focusedId, setFocusedId] = useState(active?.id ?? null);
9566
+ const [resting, setResting] = useState(initialResting);
9567
+ const [reps, setReps] = useState(input?.reps ?? "");
9568
+ const [weight, setWeight] = useState(input?.weight ?? "");
9569
+ const progress = useMemo(() => deriveWorkoutProgress(exercises), [exercises]);
9570
+ const groups = useMemo(() => groupExercises(exercises, supersets), [exercises, supersets]);
9571
+ const toggleFocus = (id) => setFocusedId((current) => current === id ? null : id);
9572
+ const nextSetNumber = active != null ? countCompletedSets(active) + 1 : 1;
9573
+ const canRecord = reps.trim() !== "" && weight.trim() !== "";
9574
+ const showRest = resting && rest != null;
9575
+ const showInput = !showRest && active != null;
9576
+ return /* @__PURE__ */ jsxs(
9577
+ View,
9578
+ {
9579
+ className,
9580
+ style: { position: "relative", width: 390, backgroundColor: PAGE_BG3 },
9581
+ accessibilityRole: "main",
9582
+ "aria-label": title,
9583
+ testID: "active-workout-page",
9584
+ ...props,
9585
+ children: [
9586
+ /* @__PURE__ */ jsxs(View, { style: { padding: 16, gap: 14 }, testID: "active-workout-page-content", children: [
9587
+ /* @__PURE__ */ jsx(WorkoutHeader, { title, subtitle, progress }),
9588
+ /* @__PURE__ */ jsx(ExerciseList, { groups, focusedId, onToggle: toggleFocus })
9589
+ ] }),
9590
+ (showRest || showInput) && /* @__PURE__ */ jsx(
9591
+ View,
9592
+ {
9593
+ style: { borderTopWidth: 1, borderTopColor: BORDER_DEFAULT5 },
9594
+ testID: "active-workout-page-bottom-bar",
9595
+ children: showRest && rest != null ? /* @__PURE__ */ jsx(
9596
+ RestTimer,
9597
+ {
9598
+ totalSeconds: rest.totalSeconds,
9599
+ elapsedMs: rest.elapsedMs,
9600
+ nextSetInfo: rest.nextSetInfo,
9601
+ onSkip: () => setResting(false),
9602
+ onAddTime: () => void 0,
9603
+ visible: true
9604
+ }
9605
+ ) : active != null && /* @__PURE__ */ jsx(
9606
+ InputBar,
9607
+ {
9608
+ exerciseName: active.name,
9609
+ setNumber: nextSetNumber,
9610
+ totalSets: active.totalPlannedSets,
9611
+ reps,
9612
+ weight,
9613
+ unit: active.unit,
9614
+ onRepsChange: setReps,
9615
+ onWeightChange: setWeight,
9616
+ onRecord: () => {
9617
+ if (rest != null) setResting(true);
9618
+ },
9619
+ canRecord,
9620
+ visible: true
9621
+ }
9622
+ )
9623
+ }
10417
9624
  )
10418
9625
  ]
10419
9626
  }
@@ -10736,7 +9943,7 @@ var DEFAULT_THRESHOLDS = [
10736
9943
  var ARC_START = 135;
10737
9944
  var ARC_SWEEP = 270;
10738
9945
  var SEGMENTS = 40;
10739
- function clamp014(n) {
9946
+ function clamp012(n) {
10740
9947
  if (Number.isNaN(n)) return 0;
10741
9948
  return Math.max(0, Math.min(1, n));
10742
9949
  }
@@ -10768,7 +9975,7 @@ function buildTicks(fill, size, activeColor) {
10768
9975
  };
10769
9976
  });
10770
9977
  }
10771
- function Gauge2({
9978
+ function Gauge({
10772
9979
  value,
10773
9980
  min = 0,
10774
9981
  max = 100,
@@ -10781,7 +9988,7 @@ function Gauge2({
10781
9988
  ...props
10782
9989
  }) {
10783
9990
  const span = max - min || 1;
10784
- const fill = clamp014((value - min) / span);
9991
+ const fill = clamp012((value - min) / span);
10785
9992
  const activeColor = (f) => color ?? bandColor(f, thresholds, min, max);
10786
9993
  const ticks = buildTicks(fill, size, activeColor);
10787
9994
  const displayColor = color ?? bandColor(fill, thresholds, min, max);
@@ -10975,6 +10182,6 @@ function composeValidators(...validators) {
10975
10182
  };
10976
10183
  }
10977
10184
 
10978
- export { Accordion, AccordionButton, AccordionItem, AccordionPanel, Alert, AlertDescription, AlertTitle, Autocomplete, Avatar, AvatarBadge, AvatarGroup, Badge, BadgeText, BaseBadge, BodyMap, BodyMapDetailPanel, BreadcrumbItem, Breadcrumbs, Button, ButtonIcon, ButtonSpinner, ButtonText, CapacityBandChart, Caption, Card, CardContent, CardDescription, CardFooter, CardHeader, CardSkeleton, CardTitle, Checkbox, CheckboxGroup, Chip, CircularProgress, Collapse, CollapseButton, CollapseContent, DEFAULT_VOLUME_LANDMARKS, DETAILED_TO_SIMPLE, DataRow, DateTime, DeviationBar, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, EmptyState, ExerciseCard, FormActions, FormField, FormRow, FormSection, Gauge2 as Gauge, HStack, Heading, HelpTip, IconBox, Indicator, Input, InputBar, InputGroup, IntensityBar, Label, LabelWithHelp, Link, ListItem, ListItemContent, ListItemDivider, ListItemIcon, ListItemTrailing, MUSCLE_DISPLAY_NAMES, MUSCLE_TO_CATEGORY, MUSCLE_TO_SVG_SLUGS, Menu, MenuDivider, MenuGroup, MenuItem, MenuList, MenuTrigger, MesoCard, MesoProgressBar, MesoStatusCard, Metric, MetricGroup, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalTitle, MuscleGroup, MuscleGroupChip, Overline, Paragraph, PasswordInput, Pill, PlaceholderStrip, Popover, PopoverCloseButton, PopoverContent, PopoverTrigger, PrBadge, PrHistoryModal, Progress, ProgressSteps, Radio, RadioGroup, ReadinessCheck, RestTimer, SIMPLE_DISPLAY_NAMES, SIMPLE_TO_DETAILED, Scatter, Section, SectionContent, SectionHeader, Select, SetRow, Sidebar, SidebarContent, SidebarDivider, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, SimpleMuscleGroup, Skeleton, SkeletonCard, SkeletonCircle, SkeletonListItem, SkeletonText, Sparkline, Spinner, Stack, StatusDot, StepContent, StepIndicator, StepLabel, Stepper, Step as StepperStep, StrengthTrendChart, SupersetWrapper, Surface, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TablePagination, TableRow, Tabs, TempoDisplay, Toast, ToastProvider, ToolbarButton, ToolbarButtonGroup, Tooltip, Treemap, Typography, VOLUME_STATUS_LABELS, VStack, VelocityStrip, WeekRow, WeightBadge, WorkoutCard, WorkoutPill, alpha, calculateMeanVelocity, calculateVelocityLoss, cn, composeValidators, createFieldId, formatDateTime, getContrastText, getFieldAriaProps, getFieldValidationProps, getHeatmapColor, getLuminance, getResultColor, getStatusColor, getVelocityZoneColor, getVelocityZoneName, hasMaxLength, hasMinLength, isEmpty, isValidEmail, useTable, useToast, useToolbarButton, validationRules };
10185
+ export { Accordion, AccordionButton, AccordionItem, AccordionPanel, ActiveWorkoutPage, Alert, AlertDescription, AlertTitle, Autocomplete, Avatar, AvatarBadge, AvatarGroup, BaseBadge, BreadcrumbItem, Breadcrumbs, Button, ButtonIcon, ButtonSpinner, ButtonText, CapacityBandChart, Caption, Checkbox, CheckboxGroup, Chip, CircularProgress, Collapse, CollapseButton, CollapseContent, DataRow, DateTime, DeviationBar, Divider, Drawer, DrawerBody, DrawerFooter, DrawerHeader, EXERCISE_DETAIL_TABS, EmptyState, ExerciseCard, ExerciseDetailPage, FormActions, FormField, FormRow, FormSection, Gauge, HStack, Heading, HelpTip, IconBox, Input, InputBar, InputGroup, IntensityBar, Label, LabelWithHelp, Link, ListItem, ListItemContent, ListItemDivider, ListItemIcon, ListItemTrailing, Menu, MenuDivider, MenuGroup, MenuItem, MenuList, MenuTrigger, MesoCard, MesoProgressBar, Metric, MetricGroup, Modal, ModalBody, ModalCloseButton, ModalContent, ModalFooter, ModalHeader, ModalTitle, MuscleGroupChip, Overline, Paragraph, PasswordInput, Pill, PlaceholderStrip, Popover, PopoverCloseButton, PopoverContent, PopoverTrigger, PrBadge, PrHistoryModal, ProgramPlanningPage, Progress, ProgressSteps, Radio, RadioGroup, ReadinessCheck, RestTimer, Scatter, Section, SectionContent, SectionHeader, Select, SetRow, Sidebar, SidebarContent, SidebarDivider, SidebarFooter, SidebarHeader, SidebarItem, SidebarSection, Skeleton, SkeletonCard, SkeletonCircle, SkeletonListItem, SkeletonText, Spinner, Stack, StepContent, StepIndicator, StepLabel, Stepper, Step as StepperStep, StrengthTrendChart, SupersetWrapper, Surface, Switch, Tab, TabList, TabPanel, TabPanels, Table, TableBody, TableCell, TableHeader, TableHeaderCell, TablePagination, TableRow, Tabs, TempoDisplay, Toast, ToastProvider, ToolbarButton, ToolbarButtonGroup, Tooltip, Treemap, Typography, VStack, VelocityStrip, WeekRow, WeightBadge, WorkoutCard, WorkoutPill, alpha, buildBreadcrumbs, calculateMeanVelocity, calculateVelocityLoss, composeValidators, countCompletedSets, createFieldId, deriveExerciseStats, deriveNavLevel, deriveWorkoutProgress, findActiveExercise, findMeso, findWeek, findWorkout, formatDateTime, formatPrescription, formatSignedPct, formatVelocity, getContrastText, getFieldAriaProps, getFieldValidationProps, getLuminance, getResultColor, getStatusColor, getVelocityZoneColor, getVelocityZoneName, groupExercises, hasMaxLength, hasMinLength, isEmpty, isValidEmail, roundRpe, roundTempo, roundWeight, rpeColor, statusToCardState, summarizeVbt, toActiveCardProps, toExerciseCardProps, toProgressBarMesos, useTable, useToast, useToolbarButton, validationRules };
10979
10186
  //# sourceMappingURL=index.mjs.map
10980
10187
  //# sourceMappingURL=index.mjs.map