@burdenoff/microfe-mybodyshield 2026.705.1 → 2026.705.2

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 (44) hide show
  1. package/dist/mybodyshield/components/DataTable.js +8 -4
  2. package/dist/mybodyshield/components/DataTable.js.map +1 -1
  3. package/dist/mybodyshield/components/EvidenceUpload.js +92 -4
  4. package/dist/mybodyshield/components/EvidenceUpload.js.map +1 -0
  5. package/dist/mybodyshield/components/FileLink.js +35 -2
  6. package/dist/mybodyshield/components/FileLink.js.map +1 -0
  7. package/dist/mybodyshield/components/MybDiscussion.js +107 -6
  8. package/dist/mybodyshield/components/MybDiscussion.js.map +1 -0
  9. package/dist/mybodyshield/components/MybTags.js +148 -4
  10. package/dist/mybodyshield/components/MybTags.js.map +1 -0
  11. package/dist/mybodyshield/components/Pagination.js.map +1 -1
  12. package/dist/mybodyshield/components/UserSearchSelect.js +148 -0
  13. package/dist/mybodyshield/components/UserSearchSelect.js.map +1 -0
  14. package/dist/mybodyshield/components/index.js +1 -0
  15. package/dist/mybodyshield/hooks/index.js +1 -0
  16. package/dist/mybodyshield/hooks/useMyBodyShieldApi.js +47 -27
  17. package/dist/mybodyshield/hooks/useMyBodyShieldApi.js.map +1 -1
  18. package/dist/mybodyshield/hooks/useMybComments.js +44 -2
  19. package/dist/mybodyshield/hooks/useMybComments.js.map +1 -0
  20. package/dist/mybodyshield/hooks/useMybFiles.js +80 -3
  21. package/dist/mybodyshield/hooks/useMybFiles.js.map +1 -0
  22. package/dist/mybodyshield/hooks/useMybTags.js +88 -2
  23. package/dist/mybodyshield/hooks/useMybTags.js.map +1 -0
  24. package/dist/mybodyshield/hooks/useMybUsers.js +36 -0
  25. package/dist/mybodyshield/hooks/useMybUsers.js.map +1 -0
  26. package/dist/mybodyshield/pages/DashboardPage.js +41 -36
  27. package/dist/mybodyshield/pages/DashboardPage.js.map +1 -1
  28. package/dist/mybodyshield/pages/_shared/visuals.js +15 -9
  29. package/dist/mybodyshield/pages/_shared/visuals.js.map +1 -1
  30. package/dist/mybodyshield/pages/coaching/CoachingPage.js +171 -147
  31. package/dist/mybodyshield/pages/coaching/CoachingPage.js.map +1 -1
  32. package/dist/mybodyshield/pages/goals/GoalsPage.js +0 -8
  33. package/dist/mybodyshield/pages/goals/GoalsPage.js.map +1 -1
  34. package/dist/mybodyshield/pages/nutrition/NutritionPage.js +352 -278
  35. package/dist/mybodyshield/pages/nutrition/NutritionPage.js.map +1 -1
  36. package/dist/mybodyshield/pages/programs/ProgramDetailPage.js +600 -296
  37. package/dist/mybodyshield/pages/programs/ProgramDetailPage.js.map +1 -1
  38. package/dist/mybodyshield/pages/progress/ProgressPage.js +88 -51
  39. package/dist/mybodyshield/pages/progress/ProgressPage.js.map +1 -1
  40. package/dist/mybodyshield/pages/train/SessionDetailPage.js +146 -126
  41. package/dist/mybodyshield/pages/train/SessionDetailPage.js.map +1 -1
  42. package/dist/mybodyshield/pages/train/SessionsPage.js +1 -4
  43. package/dist/mybodyshield/pages/train/SessionsPage.js.map +1 -1
  44. package/package.json +2 -2
@@ -95,7 +95,13 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
95
95
  children: e
96
96
  })]
97
97
  }, e))
98
- }), D = {
98
+ });
99
+ function D(e, t) {
100
+ return new Proxy(e, { get(e, n) {
101
+ return e[n] ?? e[t];
102
+ } });
103
+ }
104
+ var O = D({
99
105
  STRENGTH: {
100
106
  icon: i,
101
107
  tint: "var(--color-accent-primary)"
@@ -120,7 +126,7 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
120
126
  icon: l,
121
127
  tint: "var(--color-status-success-text)"
122
128
  }
123
- }, O = {
129
+ }, "STRENGTH"), k = D({
124
130
  CHEST: { tint: "var(--color-accent-primary)" },
125
131
  BACK: { tint: "var(--color-accent-teal)" },
126
132
  LEGS: { tint: "var(--color-status-warning-text)" },
@@ -128,7 +134,7 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
128
134
  ARMS: { tint: "var(--color-accent-primary)" },
129
135
  CORE: { tint: "var(--color-status-success-text)" },
130
136
  FULL_BODY: { tint: "var(--color-text-secondary)" }
131
- }, k = {
137
+ }, "FULL_BODY"), A = D({
132
138
  WEIGHT_LOSS: {
133
139
  icon: h,
134
140
  tint: "var(--color-accent-teal)"
@@ -153,7 +159,7 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
153
159
  icon: p,
154
160
  tint: "var(--color-text-secondary)"
155
161
  }
156
- }, A = {
162
+ }, "GENERAL_FITNESS"), j = D({
157
163
  WEIGHT: {
158
164
  icon: v,
159
165
  tint: "var(--color-accent-primary)",
@@ -194,7 +200,7 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
194
200
  tint: "var(--color-accent-teal)",
195
201
  unit: "cm"
196
202
  }
197
- }, j = {
203
+ }, "WEIGHT"), M = D({
198
204
  SLEEP: {
199
205
  icon: n,
200
206
  tint: "var(--color-accent-primary)",
@@ -220,14 +226,14 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
220
226
  tint: "var(--color-accent-teal)",
221
227
  label: "Mood"
222
228
  }
223
- }, M = ({ icon: t, tint: n = "var(--color-accent-teal)", className: r }) => /* @__PURE__ */ b("span", {
229
+ }, "READINESS"), N = ({ icon: t, tint: n = "var(--color-accent-teal)", className: r }) => /* @__PURE__ */ b("span", {
224
230
  className: e("flex size-9 shrink-0 items-center justify-center rounded-lg", r),
225
231
  style: {
226
232
  backgroundColor: `color-mix(in srgb, ${n} 16%, transparent)`,
227
233
  color: n
228
234
  },
229
235
  children: t
230
- }), N = ({ delta: t, unit: n = "", goodDirection: r = "up" }) => {
236
+ }), P = ({ delta: t, unit: n = "", goodDirection: r = "up" }) => {
231
237
  if (!Number.isFinite(t) || t === 0) return /* @__PURE__ */ x("span", {
232
238
  className: "text-xs text-text-tertiary",
233
239
  children: ["±0", n]
@@ -243,13 +249,13 @@ var S = ({ value: t, color: n = "var(--color-accent-teal)", height: r = 8, class
243
249
  ]
244
250
  });
245
251
  };
246
- function P(e) {
252
+ function F(e) {
247
253
  let t = e.targetValue - e.baselineValue;
248
254
  if (t === 0) return e.currentValue >= e.targetValue ? 100 : 0;
249
255
  let n = (e.currentValue - e.baselineValue) / t * 100;
250
256
  return Math.max(0, Math.min(100, n));
251
257
  }
252
258
  //#endregion
253
- export { k as GOAL_TYPE_META, M as IconChip, A as METRIC_META, O as MUSCLE_META, T as MacroBar, E as MacroLegend, S as Meter, C as ProgressRing, j as RECOVERY_META, N as TrendPill, D as WORKOUT_TYPE_META, P as computeGoalProgress };
259
+ export { A as GOAL_TYPE_META, N as IconChip, j as METRIC_META, k as MUSCLE_META, T as MacroBar, E as MacroLegend, S as Meter, C as ProgressRing, M as RECOVERY_META, P as TrendPill, O as WORKOUT_TYPE_META, F as computeGoalProgress };
254
260
 
255
261
  //# sourceMappingURL=visuals.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"visuals.js","names":[],"sources":["../../../../src/mybodyshield/pages/_shared/visuals.tsx"],"sourcesContent":["/**\n * Shared fitness-domain visual helpers.\n * @module mybodyshield/pages/_shared\n *\n * Token-driven (no raw colors) SVG/CSS visual primitives + domain icon/tint\n * maps reused across the MyBodyShield pages. Everything reads fe-libs semantic\n * tokens so light/dark themes and custom themes work automatically.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport {\n Dumbbell,\n HeartPulse,\n Timer,\n Activity,\n StretchHorizontal,\n Flower2,\n Moon,\n Weight,\n Ruler,\n Percent,\n Heart,\n TrendingDown,\n TrendingUp,\n Zap,\n Waves,\n Target,\n Sparkles,\n Brain,\n BedDouble,\n Gauge,\n Smile,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport type {\n MybBodyMetricType,\n MybGoalType,\n MybMuscleGroup,\n MybRecoveryMetric,\n MybWorkoutType,\n} from '../../types';\n\n// ============================================================================\n// Meter — a horizontal progress bar with a token-driven fill\n// ============================================================================\n\nexport const Meter: FC<{\n /** 0–100 percentage. */\n value: number;\n /** CSS color for the fill (default: accent-teal). */\n color?: string;\n height?: number;\n className?: string;\n}> = ({ value, color = 'var(--color-accent-teal)', height = 8, className }) => {\n const pct = Math.max(0, Math.min(100, value));\n return (\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"progressbar\"\n aria-valuenow={Math.round(pct)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-500 ease-out\"\n style={{ width: `${pct}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n\n// ============================================================================\n// ProgressRing — a circular progress indicator (goal progress, readiness)\n// ============================================================================\n\nexport const ProgressRing: FC<{\n value: number;\n size?: number;\n stroke?: number;\n color?: string;\n trackColor?: string;\n children?: ReactNode;\n className?: string;\n}> = ({\n value,\n size = 96,\n stroke = 9,\n color = 'var(--color-accent-teal)',\n trackColor = 'var(--color-bg-sunken)',\n children,\n className,\n}) => {\n const pct = Math.max(0, Math.min(100, value));\n const r = (size - stroke) / 2;\n const c = 2 * Math.PI * r;\n const offset = c - (pct / 100) * c;\n return (\n <div\n className={cn('relative inline-flex items-center justify-center', className)}\n style={{ width: size, height: size }}\n >\n <svg width={size} height={size} className=\"-rotate-90\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke={trackColor}\n strokeWidth={stroke}\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke={color}\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n strokeDasharray={c}\n strokeDashoffset={offset}\n className=\"transition-[stroke-dashoffset] duration-700 ease-out\"\n />\n </svg>\n {children != null && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">{children}</div>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// MacroBar — a stacked protein/carbs/fat bar (grams → proportion)\n// ============================================================================\n\nexport const MACRO_HUE = {\n protein: 'var(--color-accent-teal)',\n carbs: 'var(--color-status-warning-text)',\n fat: 'var(--color-accent-primary)',\n} as const;\n\nexport const MacroBar: FC<{\n proteinG: number;\n carbsG: number;\n fatG: number;\n height?: number;\n className?: string;\n}> = ({ proteinG, carbsG, fatG, height = 8, className }) => {\n const total = Math.max(1, proteinG + carbsG + fatG);\n const seg = (g: number) => `${(g / total) * 100}%`;\n return (\n <div\n className={cn('flex w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n >\n <div style={{ width: seg(proteinG), backgroundColor: MACRO_HUE.protein }} />\n <div style={{ width: seg(carbsG), backgroundColor: MACRO_HUE.carbs }} />\n <div style={{ width: seg(fatG), backgroundColor: MACRO_HUE.fat }} />\n </div>\n );\n};\n\nexport const MacroLegend: FC<{ className?: string }> = ({ className }) => (\n <div className={cn('flex flex-wrap items-center gap-3 text-xs text-text-tertiary', className)}>\n {(['protein', 'carbs', 'fat'] as const).map((k) => (\n <span key={k} className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full\" style={{ backgroundColor: MACRO_HUE[k] }} />\n <span className=\"capitalize\">{k}</span>\n </span>\n ))}\n </div>\n);\n\n// ============================================================================\n// Domain icon + tint maps (semantic tokens only)\n// ============================================================================\n\nexport const WORKOUT_TYPE_META: Record<MybWorkoutType, { icon: typeof Dumbbell; tint: string }> = {\n STRENGTH: { icon: Dumbbell, tint: 'var(--color-accent-primary)' },\n CARDIO: { icon: HeartPulse, tint: 'var(--color-status-warning-text)' },\n HIIT: { icon: Zap, tint: 'var(--color-status-error-text)' },\n MOBILITY: { icon: StretchHorizontal, tint: 'var(--color-accent-teal)' },\n YOGA: { icon: Flower2, tint: 'var(--color-accent-teal)' },\n RECOVERY: { icon: Moon, tint: 'var(--color-status-success-text)' },\n};\n\nexport const MUSCLE_META: Record<MybMuscleGroup, { tint: string }> = {\n CHEST: { tint: 'var(--color-accent-primary)' },\n BACK: { tint: 'var(--color-accent-teal)' },\n LEGS: { tint: 'var(--color-status-warning-text)' },\n SHOULDERS: { tint: 'var(--color-status-error-text)' },\n ARMS: { tint: 'var(--color-accent-primary)' },\n CORE: { tint: 'var(--color-status-success-text)' },\n FULL_BODY: { tint: 'var(--color-text-secondary)' },\n};\n\nexport const GOAL_TYPE_META: Record<MybGoalType, { icon: typeof Target; tint: string }> = {\n WEIGHT_LOSS: { icon: TrendingDown, tint: 'var(--color-accent-teal)' },\n MUSCLE_GAIN: { icon: Dumbbell, tint: 'var(--color-accent-primary)' },\n STRENGTH: { icon: Weight, tint: 'var(--color-status-error-text)' },\n ENDURANCE: { icon: Activity, tint: 'var(--color-status-warning-text)' },\n MOBILITY: { icon: StretchHorizontal, tint: 'var(--color-accent-teal)' },\n GENERAL_FITNESS: { icon: Sparkles, tint: 'var(--color-text-secondary)' },\n};\n\nexport const METRIC_META: Record<\n MybBodyMetricType,\n { icon: typeof Weight; tint: string; unit: string }\n> = {\n WEIGHT: { icon: Weight, tint: 'var(--color-accent-primary)', unit: 'kg' },\n BODY_FAT: { icon: Percent, tint: 'var(--color-status-warning-text)', unit: '%' },\n RESTING_HEART_RATE: { icon: Heart, tint: 'var(--color-status-error-text)', unit: 'bpm' },\n WAIST: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n CHEST: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n HIPS: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n ARM: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n THIGH: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n};\n\nexport const RECOVERY_META: Record<\n MybRecoveryMetric,\n { icon: typeof Gauge; tint: string; label: string }\n> = {\n SLEEP: { icon: BedDouble, tint: 'var(--color-accent-primary)', label: 'Sleep' },\n READINESS: { icon: Gauge, tint: 'var(--color-status-success-text)', label: 'Readiness' },\n SORENESS: { icon: Waves, tint: 'var(--color-status-warning-text)', label: 'Soreness' },\n STRESS: { icon: Brain, tint: 'var(--color-status-error-text)', label: 'Stress' },\n MOOD: { icon: Smile, tint: 'var(--color-accent-teal)', label: 'Mood' },\n};\n\n// ============================================================================\n// Small helpers\n// ============================================================================\n\n/** Circular icon chip with a soft tinted background. */\nexport const IconChip: FC<{ icon: ReactNode; tint?: string; className?: string }> = ({\n icon,\n tint = 'var(--color-accent-teal)',\n className,\n}) => (\n <span\n className={cn('flex size-9 shrink-0 items-center justify-center rounded-lg', className)}\n style={{ backgroundColor: `color-mix(in srgb, ${tint} 16%, transparent)`, color: tint }}\n >\n {icon}\n </span>\n);\n\n/** A small trend delta pill (up/down/flat) with semantic color. */\nexport const TrendPill: FC<{ delta: number; unit?: string; goodDirection?: 'up' | 'down' }> = ({\n delta,\n unit = '',\n goodDirection = 'up',\n}) => {\n if (!Number.isFinite(delta) || delta === 0) {\n return <span className=\"text-xs text-text-tertiary\">±0{unit}</span>;\n }\n const up = delta > 0;\n const good = goodDirection === 'up' ? up : !up;\n const Icon = up ? TrendingUp : TrendingDown;\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 text-xs font-medium tabular-nums',\n good ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {up ? '+' : ''}\n {delta.toFixed(1)}\n {unit}\n </span>\n );\n};\n\n/** Compute a goal's completion percentage from baseline → target → current. */\nexport function computeGoalProgress(goal: {\n baselineValue: number;\n targetValue: number;\n currentValue: number;\n}): number {\n const span = goal.targetValue - goal.baselineValue;\n if (span === 0) return goal.currentValue >= goal.targetValue ? 100 : 0;\n const done = ((goal.currentValue - goal.baselineValue) / span) * 100;\n return Math.max(0, Math.min(100, done));\n}\n\nexport { Timer };\n"],"mappings":"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"}
1
+ {"version":3,"file":"visuals.js","names":[],"sources":["../../../../src/mybodyshield/pages/_shared/visuals.tsx"],"sourcesContent":["/**\n * Shared fitness-domain visual helpers.\n * @module mybodyshield/pages/_shared\n *\n * Token-driven (no raw colors) SVG/CSS visual primitives + domain icon/tint\n * maps reused across the MyBodyShield pages. Everything reads fe-libs semantic\n * tokens so light/dark themes and custom themes work automatically.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport {\n Dumbbell,\n HeartPulse,\n Timer,\n Activity,\n StretchHorizontal,\n Flower2,\n Moon,\n Weight,\n Ruler,\n Percent,\n Heart,\n TrendingDown,\n TrendingUp,\n Zap,\n Waves,\n Target,\n Sparkles,\n Brain,\n BedDouble,\n Gauge,\n Smile,\n} from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport type {\n MybBodyMetricType,\n MybGoalType,\n MybMuscleGroup,\n MybRecoveryMetric,\n MybWorkoutType,\n} from '../../types';\n\n// ============================================================================\n// Meter — a horizontal progress bar with a token-driven fill\n// ============================================================================\n\nexport const Meter: FC<{\n /** 0–100 percentage. */\n value: number;\n /** CSS color for the fill (default: accent-teal). */\n color?: string;\n height?: number;\n className?: string;\n}> = ({ value, color = 'var(--color-accent-teal)', height = 8, className }) => {\n const pct = Math.max(0, Math.min(100, value));\n return (\n <div\n className={cn('w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n role=\"progressbar\"\n aria-valuenow={Math.round(pct)}\n aria-valuemin={0}\n aria-valuemax={100}\n >\n <div\n className=\"h-full rounded-full transition-[width] duration-500 ease-out\"\n style={{ width: `${pct}%`, backgroundColor: color }}\n />\n </div>\n );\n};\n\n// ============================================================================\n// ProgressRing — a circular progress indicator (goal progress, readiness)\n// ============================================================================\n\nexport const ProgressRing: FC<{\n value: number;\n size?: number;\n stroke?: number;\n color?: string;\n trackColor?: string;\n children?: ReactNode;\n className?: string;\n}> = ({\n value,\n size = 96,\n stroke = 9,\n color = 'var(--color-accent-teal)',\n trackColor = 'var(--color-bg-sunken)',\n children,\n className,\n}) => {\n const pct = Math.max(0, Math.min(100, value));\n const r = (size - stroke) / 2;\n const c = 2 * Math.PI * r;\n const offset = c - (pct / 100) * c;\n return (\n <div\n className={cn('relative inline-flex items-center justify-center', className)}\n style={{ width: size, height: size }}\n >\n <svg width={size} height={size} className=\"-rotate-90\">\n <circle\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke={trackColor}\n strokeWidth={stroke}\n />\n <circle\n cx={size / 2}\n cy={size / 2}\n r={r}\n fill=\"none\"\n stroke={color}\n strokeWidth={stroke}\n strokeLinecap=\"round\"\n strokeDasharray={c}\n strokeDashoffset={offset}\n className=\"transition-[stroke-dashoffset] duration-700 ease-out\"\n />\n </svg>\n {children != null && (\n <div className=\"absolute inset-0 flex flex-col items-center justify-center\">{children}</div>\n )}\n </div>\n );\n};\n\n// ============================================================================\n// MacroBar — a stacked protein/carbs/fat bar (grams → proportion)\n// ============================================================================\n\nexport const MACRO_HUE = {\n protein: 'var(--color-accent-teal)',\n carbs: 'var(--color-status-warning-text)',\n fat: 'var(--color-accent-primary)',\n} as const;\n\nexport const MacroBar: FC<{\n proteinG: number;\n carbsG: number;\n fatG: number;\n height?: number;\n className?: string;\n}> = ({ proteinG, carbsG, fatG, height = 8, className }) => {\n const total = Math.max(1, proteinG + carbsG + fatG);\n const seg = (g: number) => `${(g / total) * 100}%`;\n return (\n <div\n className={cn('flex w-full overflow-hidden rounded-full bg-bg-sunken', className)}\n style={{ height }}\n >\n <div style={{ width: seg(proteinG), backgroundColor: MACRO_HUE.protein }} />\n <div style={{ width: seg(carbsG), backgroundColor: MACRO_HUE.carbs }} />\n <div style={{ width: seg(fatG), backgroundColor: MACRO_HUE.fat }} />\n </div>\n );\n};\n\nexport const MacroLegend: FC<{ className?: string }> = ({ className }) => (\n <div className={cn('flex flex-wrap items-center gap-3 text-xs text-text-tertiary', className)}>\n {(['protein', 'carbs', 'fat'] as const).map((k) => (\n <span key={k} className=\"inline-flex items-center gap-1.5\">\n <span className=\"size-2 rounded-full\" style={{ backgroundColor: MACRO_HUE[k] }} />\n <span className=\"capitalize\">{k}</span>\n </span>\n ))}\n </div>\n);\n\n// ============================================================================\n// Domain icon + tint maps (semantic tokens only)\n// ============================================================================\n\n/**\n * Wrap an enum→meta map so an unknown server enum value (svc stores enums as\n * TEXT, so a value outside the client union is plausible) resolves to a safe\n * fallback entry instead of `undefined` — accessing `.icon`/`.tint`/`.label` on\n * `undefined` would otherwise crash the whole page.\n */\nfunction metaWithFallback<K extends string, V>(\n source: Record<K, V>,\n fallback: NoInfer<K>\n): Record<K, V> {\n return new Proxy(source, {\n get(target, prop: string) {\n return (target as Record<string, V>)[prop] ?? target[fallback];\n },\n }) as Record<K, V>;\n}\n\nconst WORKOUT_TYPE_META_SOURCE: Record<MybWorkoutType, { icon: typeof Dumbbell; tint: string }> = {\n STRENGTH: { icon: Dumbbell, tint: 'var(--color-accent-primary)' },\n CARDIO: { icon: HeartPulse, tint: 'var(--color-status-warning-text)' },\n HIIT: { icon: Zap, tint: 'var(--color-status-error-text)' },\n MOBILITY: { icon: StretchHorizontal, tint: 'var(--color-accent-teal)' },\n YOGA: { icon: Flower2, tint: 'var(--color-accent-teal)' },\n RECOVERY: { icon: Moon, tint: 'var(--color-status-success-text)' },\n};\nexport const WORKOUT_TYPE_META = metaWithFallback(WORKOUT_TYPE_META_SOURCE, 'STRENGTH');\n\nconst MUSCLE_META_SOURCE: Record<MybMuscleGroup, { tint: string }> = {\n CHEST: { tint: 'var(--color-accent-primary)' },\n BACK: { tint: 'var(--color-accent-teal)' },\n LEGS: { tint: 'var(--color-status-warning-text)' },\n SHOULDERS: { tint: 'var(--color-status-error-text)' },\n ARMS: { tint: 'var(--color-accent-primary)' },\n CORE: { tint: 'var(--color-status-success-text)' },\n FULL_BODY: { tint: 'var(--color-text-secondary)' },\n};\nexport const MUSCLE_META = metaWithFallback(MUSCLE_META_SOURCE, 'FULL_BODY');\n\nconst GOAL_TYPE_META_SOURCE: Record<MybGoalType, { icon: typeof Target; tint: string }> = {\n WEIGHT_LOSS: { icon: TrendingDown, tint: 'var(--color-accent-teal)' },\n MUSCLE_GAIN: { icon: Dumbbell, tint: 'var(--color-accent-primary)' },\n STRENGTH: { icon: Weight, tint: 'var(--color-status-error-text)' },\n ENDURANCE: { icon: Activity, tint: 'var(--color-status-warning-text)' },\n MOBILITY: { icon: StretchHorizontal, tint: 'var(--color-accent-teal)' },\n GENERAL_FITNESS: { icon: Sparkles, tint: 'var(--color-text-secondary)' },\n};\nexport const GOAL_TYPE_META = metaWithFallback(GOAL_TYPE_META_SOURCE, 'GENERAL_FITNESS');\n\nconst METRIC_META_SOURCE: Record<\n MybBodyMetricType,\n { icon: typeof Weight; tint: string; unit: string }\n> = {\n WEIGHT: { icon: Weight, tint: 'var(--color-accent-primary)', unit: 'kg' },\n BODY_FAT: { icon: Percent, tint: 'var(--color-status-warning-text)', unit: '%' },\n RESTING_HEART_RATE: { icon: Heart, tint: 'var(--color-status-error-text)', unit: 'bpm' },\n WAIST: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n CHEST: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n HIPS: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n ARM: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n THIGH: { icon: Ruler, tint: 'var(--color-accent-teal)', unit: 'cm' },\n};\nexport const METRIC_META = metaWithFallback(METRIC_META_SOURCE, 'WEIGHT');\n\nconst RECOVERY_META_SOURCE: Record<\n MybRecoveryMetric,\n { icon: typeof Gauge; tint: string; label: string }\n> = {\n SLEEP: { icon: BedDouble, tint: 'var(--color-accent-primary)', label: 'Sleep' },\n READINESS: { icon: Gauge, tint: 'var(--color-status-success-text)', label: 'Readiness' },\n SORENESS: { icon: Waves, tint: 'var(--color-status-warning-text)', label: 'Soreness' },\n STRESS: { icon: Brain, tint: 'var(--color-status-error-text)', label: 'Stress' },\n MOOD: { icon: Smile, tint: 'var(--color-accent-teal)', label: 'Mood' },\n};\nexport const RECOVERY_META = metaWithFallback(RECOVERY_META_SOURCE, 'READINESS');\n\n// ============================================================================\n// Small helpers\n// ============================================================================\n\n/** Circular icon chip with a soft tinted background. */\nexport const IconChip: FC<{ icon: ReactNode; tint?: string; className?: string }> = ({\n icon,\n tint = 'var(--color-accent-teal)',\n className,\n}) => (\n <span\n className={cn('flex size-9 shrink-0 items-center justify-center rounded-lg', className)}\n style={{ backgroundColor: `color-mix(in srgb, ${tint} 16%, transparent)`, color: tint }}\n >\n {icon}\n </span>\n);\n\n/** A small trend delta pill (up/down/flat) with semantic color. */\nexport const TrendPill: FC<{ delta: number; unit?: string; goodDirection?: 'up' | 'down' }> = ({\n delta,\n unit = '',\n goodDirection = 'up',\n}) => {\n if (!Number.isFinite(delta) || delta === 0) {\n return <span className=\"text-xs text-text-tertiary\">±0{unit}</span>;\n }\n const up = delta > 0;\n const good = goodDirection === 'up' ? up : !up;\n const Icon = up ? TrendingUp : TrendingDown;\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1 text-xs font-medium tabular-nums',\n good ? 'text-status-success-text' : 'text-status-error-text'\n )}\n >\n <Icon className=\"h-3.5 w-3.5\" />\n {up ? '+' : ''}\n {delta.toFixed(1)}\n {unit}\n </span>\n );\n};\n\n/** Compute a goal's completion percentage from baseline → target → current. */\nexport function computeGoalProgress(goal: {\n baselineValue: number;\n targetValue: number;\n currentValue: number;\n}): number {\n const span = goal.targetValue - goal.baselineValue;\n if (span === 0) return goal.currentValue >= goal.targetValue ? 100 : 0;\n const done = ((goal.currentValue - goal.baselineValue) / span) * 100;\n return Math.max(0, Math.min(100, done));\n}\n\nexport { Timer };\n"],"mappings":"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"}