@burdenoff/microfe-mybodyshield 2026.821.2 → 2026.830.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/mybodyshield/MyBodyShieldRoot.d.ts.map +1 -1
  2. package/dist/mybodyshield/MyBodyShieldRoot.js +54 -56
  3. package/dist/mybodyshield/MyBodyShieldRoot.js.map +1 -1
  4. package/dist/mybodyshield/MyBodyShieldRoutes.d.ts.map +1 -1
  5. package/dist/mybodyshield/MyBodyShieldRoutes.js +121 -62
  6. package/dist/mybodyshield/MyBodyShieldRoutes.js.map +1 -1
  7. package/dist/mybodyshield/components/EvidenceUpload.d.ts.map +1 -1
  8. package/dist/mybodyshield/components/EvidenceUpload.js +46 -45
  9. package/dist/mybodyshield/components/EvidenceUpload.js.map +1 -1
  10. package/dist/mybodyshield/components/FileLink.d.ts.map +1 -1
  11. package/dist/mybodyshield/components/FileLink.js +27 -18
  12. package/dist/mybodyshield/components/FileLink.js.map +1 -1
  13. package/dist/mybodyshield/components/MybDiscussion.d.ts +1 -1
  14. package/dist/mybodyshield/components/MybDiscussion.d.ts.map +1 -1
  15. package/dist/mybodyshield/components/MybDiscussion.js +59 -58
  16. package/dist/mybodyshield/components/MybDiscussion.js.map +1 -1
  17. package/dist/mybodyshield/components/MybTags.d.ts +1 -1
  18. package/dist/mybodyshield/components/MybTags.d.ts.map +1 -1
  19. package/dist/mybodyshield/components/MybTags.js +83 -74
  20. package/dist/mybodyshield/components/MybTags.js.map +1 -1
  21. package/dist/mybodyshield/components/PageDisabled.d.ts.map +1 -1
  22. package/dist/mybodyshield/components/PageDisabled.js +16 -11
  23. package/dist/mybodyshield/components/PageDisabled.js.map +1 -1
  24. package/dist/mybodyshield/components/Pagination.d.ts.map +1 -1
  25. package/dist/mybodyshield/components/Pagination.js +36 -27
  26. package/dist/mybodyshield/components/Pagination.js.map +1 -1
  27. package/dist/mybodyshield/components/StateViews.d.ts.map +1 -1
  28. package/dist/mybodyshield/components/StateViews.js +42 -34
  29. package/dist/mybodyshield/components/StateViews.js.map +1 -1
  30. package/dist/mybodyshield/components/UserSearchSelect.d.ts.map +1 -1
  31. package/dist/mybodyshield/components/UserSearchSelect.js +66 -68
  32. package/dist/mybodyshield/components/UserSearchSelect.js.map +1 -1
  33. package/dist/mybodyshield/hooks/index.d.ts +1 -0
  34. package/dist/mybodyshield/hooks/index.d.ts.map +1 -1
  35. package/dist/mybodyshield/hooks/index.js +1 -0
  36. package/dist/mybodyshield/hooks/useTr.d.ts +5 -0
  37. package/dist/mybodyshield/hooks/useTr.d.ts.map +1 -0
  38. package/dist/mybodyshield/hooks/useTr.js +12 -0
  39. package/dist/mybodyshield/hooks/useTr.js.map +1 -0
  40. package/dist/mybodyshield/pages/DashboardPage.d.ts.map +1 -1
  41. package/dist/mybodyshield/pages/DashboardPage.js +157 -136
  42. package/dist/mybodyshield/pages/DashboardPage.js.map +1 -1
  43. package/dist/mybodyshield/pages/SettingsPage.d.ts.map +1 -1
  44. package/dist/mybodyshield/pages/SettingsPage.js +50 -59
  45. package/dist/mybodyshield/pages/SettingsPage.js.map +1 -1
  46. package/dist/mybodyshield/pages/_shared/visuals.d.ts +2 -1
  47. package/dist/mybodyshield/pages/_shared/visuals.d.ts.map +1 -1
  48. package/dist/mybodyshield/pages/_shared/visuals.js +91 -81
  49. package/dist/mybodyshield/pages/_shared/visuals.js.map +1 -1
  50. package/dist/mybodyshield/pages/ai/AiControlsPage.d.ts.map +1 -1
  51. package/dist/mybodyshield/pages/ai/AiControlsPage.js +279 -231
  52. package/dist/mybodyshield/pages/ai/AiControlsPage.js.map +1 -1
  53. package/dist/mybodyshield/pages/coaching/CoachingPage.d.ts.map +1 -1
  54. package/dist/mybodyshield/pages/coaching/CoachingPage.js +349 -258
  55. package/dist/mybodyshield/pages/coaching/CoachingPage.js.map +1 -1
  56. package/dist/mybodyshield/pages/goals/GoalsPage.d.ts.map +1 -1
  57. package/dist/mybodyshield/pages/goals/GoalsPage.js +247 -251
  58. package/dist/mybodyshield/pages/goals/GoalsPage.js.map +1 -1
  59. package/dist/mybodyshield/pages/insights/InsightsCharts.d.ts.map +1 -1
  60. package/dist/mybodyshield/pages/insights/InsightsCharts.js +216 -213
  61. package/dist/mybodyshield/pages/insights/InsightsCharts.js.map +1 -1
  62. package/dist/mybodyshield/pages/insights/InsightsPage.d.ts.map +1 -1
  63. package/dist/mybodyshield/pages/insights/InsightsPage.js +327 -220
  64. package/dist/mybodyshield/pages/insights/InsightsPage.js.map +1 -1
  65. package/dist/mybodyshield/pages/nutrition/NutritionPage.d.ts.map +1 -1
  66. package/dist/mybodyshield/pages/nutrition/NutritionPage.js +575 -529
  67. package/dist/mybodyshield/pages/nutrition/NutritionPage.js.map +1 -1
  68. package/dist/mybodyshield/pages/programs/ProgramDetailPage.d.ts.map +1 -1
  69. package/dist/mybodyshield/pages/programs/ProgramDetailPage.js +333 -275
  70. package/dist/mybodyshield/pages/programs/ProgramDetailPage.js.map +1 -1
  71. package/dist/mybodyshield/pages/programs/ProgramsPage.d.ts.map +1 -1
  72. package/dist/mybodyshield/pages/programs/ProgramsPage.js +258 -253
  73. package/dist/mybodyshield/pages/programs/ProgramsPage.js.map +1 -1
  74. package/dist/mybodyshield/pages/progress/ProgressPage.d.ts.map +1 -1
  75. package/dist/mybodyshield/pages/progress/ProgressPage.js +271 -254
  76. package/dist/mybodyshield/pages/progress/ProgressPage.js.map +1 -1
  77. package/dist/mybodyshield/pages/recovery/RecoveryPage.d.ts.map +1 -1
  78. package/dist/mybodyshield/pages/recovery/RecoveryPage.js +206 -200
  79. package/dist/mybodyshield/pages/recovery/RecoveryPage.js.map +1 -1
  80. package/dist/mybodyshield/pages/train/SessionDetailPage.d.ts.map +1 -1
  81. package/dist/mybodyshield/pages/train/SessionDetailPage.js +327 -294
  82. package/dist/mybodyshield/pages/train/SessionDetailPage.js.map +1 -1
  83. package/dist/mybodyshield/pages/train/SessionsPage.d.ts.map +1 -1
  84. package/dist/mybodyshield/pages/train/SessionsPage.js +180 -163
  85. package/dist/mybodyshield/pages/train/SessionsPage.js.map +1 -1
  86. package/dist/mybodyshield/utils/i18n.d.ts +1 -2
  87. package/dist/mybodyshield/utils/i18n.d.ts.map +1 -1
  88. package/dist/mybodyshield/utils/i18n.js +15 -0
  89. package/dist/mybodyshield/utils/i18n.js.map +1 -0
  90. package/package.json +1 -1
@@ -1,149 +1,158 @@
1
1
  import { useMybAssignTag as e, useMybCreateAndAssignTag as t, useMybEntityTags as n, useMybRemoveTagAssignment as r, useMybTagSearch as i } from "../hooks/useMybTags.js";
2
+ import { useTr as a } from "../hooks/useTr.js";
2
3
  import "../hooks/index.js";
3
- import { useEffect as a, useState as o } from "react";
4
- import { Loader2 as s, Plus as c, Tag as l, X as u } from "lucide-react";
5
- import { Fragment as d, jsx as f, jsxs as p } from "react/jsx-runtime";
6
- import { Button as m, Input as h, Popover as g, PopoverContent as _, PopoverTrigger as v, Spinner as y } from "@burdenoff/fe-libs/ui";
4
+ import { useEffect as o, useState as s } from "react";
5
+ import { Loader2 as c, Plus as l, Tag as u, X as d } from "lucide-react";
6
+ import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
7
+ import { Button as h, Input as g, Popover as _, PopoverContent as v, PopoverTrigger as y, Spinner as b } from "@burdenoff/fe-libs/ui";
7
8
  //#region src/mybodyshield/components/MybTags.tsx
8
- function b({ entityType: b, entityId: x, label: S = "Tags" }) {
9
- let C = n(b, x), w = e(b, x), T = r(b, x), E = t(b, x), [D, O] = o(!1), [k, A] = o(""), [j, M] = o(""), [N, P] = o(null);
10
- a(() => {
11
- let e = setTimeout(() => M(k), 250);
9
+ function x({ entityType: x, entityId: S, label: C }) {
10
+ let w = a(), T = C ?? w("mybodyshield.components.tags.label", "Tags"), E = n(x, S), D = e(x, S), O = r(x, S), k = t(x, S), [A, j] = s(!1), [M, N] = s(""), [P, F] = s(""), [I, L] = s(null);
11
+ o(() => {
12
+ let e = setTimeout(() => F(M), 250);
12
13
  return () => clearTimeout(e);
13
- }, [k]);
14
- let F = i(j), I = C.data ?? [], L = new Set(I.map((e) => e.tag.id)), R = j.trim(), z = (F.data ?? []).filter((e) => !L.has(e.id)), B = R.length > 0 && [...I.map((e) => e.tag.label), ...(F.data ?? []).map((e) => e.label)].some((e) => e.toLowerCase() === R.toLowerCase()), V = R.length > 0 && !B, H = w.isPending || E.isPending, U = () => {
15
- A(""), M(""), P(null);
16
- }, W = async (e) => {
17
- P(null);
14
+ }, [M]);
15
+ let R = i(P), z = E.data ?? [], B = new Set(z.map((e) => e.tag.id)), V = P.trim(), H = (R.data ?? []).filter((e) => !B.has(e.id)), U = V.length > 0 && [...z.map((e) => e.tag.label), ...(R.data ?? []).map((e) => e.label)].some((e) => e.toLowerCase() === V.toLowerCase()), W = V.length > 0 && !U, G = D.isPending || k.isPending, K = () => {
16
+ N(""), F(""), L(null);
17
+ }, q = async (e) => {
18
+ L(null);
18
19
  try {
19
- await w.mutateAsync(e), U(), O(!1);
20
+ await D.mutateAsync(e), K(), j(!1);
20
21
  } catch (e) {
21
- P(e instanceof Error ? e.message : "Failed to add tag.");
22
+ L(e instanceof Error ? e.message : w("mybodyshield.components.tags.addFailed", "Failed to add tag."));
22
23
  }
23
- }, G = async () => {
24
- if (R) {
25
- P(null);
24
+ }, J = async () => {
25
+ if (V) {
26
+ L(null);
26
27
  try {
27
- await E.mutateAsync(R), U(), O(!1);
28
+ await k.mutateAsync(V), K(), j(!1);
28
29
  } catch (e) {
29
- P(e instanceof Error ? e.message : "Failed to create tag.");
30
+ L(e instanceof Error ? e.message : w("mybodyshield.components.tags.createFailed", "Failed to create tag."));
30
31
  }
31
32
  }
32
- }, K = async (e) => {
33
- P(null);
33
+ }, Y = async (e) => {
34
+ L(null);
34
35
  try {
35
- await T.mutateAsync(e);
36
+ await O.mutateAsync(e);
36
37
  } catch (e) {
37
- P(e instanceof Error ? e.message : "Failed to remove tag.");
38
+ L(e instanceof Error ? e.message : w("mybodyshield.components.tags.removeFailed", "Failed to remove tag."));
38
39
  }
39
40
  };
40
- return /* @__PURE__ */ p("div", { children: [
41
- /* @__PURE__ */ f("p", {
41
+ return /* @__PURE__ */ m("div", { children: [
42
+ /* @__PURE__ */ p("p", {
42
43
  className: "mb-1.5 text-xs text-text-tertiary",
43
- children: S
44
+ children: T
44
45
  }),
45
- /* @__PURE__ */ p("div", {
46
+ /* @__PURE__ */ m("div", {
46
47
  className: "flex flex-wrap items-center gap-2",
47
- children: [C.isLoading ? /* @__PURE__ */ p("span", {
48
+ children: [E.isLoading ? /* @__PURE__ */ m("span", {
48
49
  className: "inline-flex items-center gap-1.5 text-sm text-text-tertiary",
49
- children: [/* @__PURE__ */ f(s, { className: "h-3.5 w-3.5 animate-spin" }), " Loading tags…"]
50
- }) : I.map((e) => /* @__PURE__ */ p("span", {
50
+ children: [
51
+ /* @__PURE__ */ p(c, { className: "h-3.5 w-3.5 animate-spin" }),
52
+ " ",
53
+ w("mybodyshield.components.tags.loading", "Loading tags…")
54
+ ]
55
+ }) : z.map((e) => /* @__PURE__ */ m("span", {
51
56
  className: "inline-flex items-center gap-1.5 rounded-full border border-border-seam bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary",
52
57
  children: [
53
- e.tag.color ? /* @__PURE__ */ f("span", {
58
+ e.tag.color ? /* @__PURE__ */ p("span", {
54
59
  className: "h-2 w-2 shrink-0 rounded-full",
55
60
  style: { backgroundColor: e.tag.color },
56
61
  "aria-hidden": !0
57
- }) : /* @__PURE__ */ f(l, { className: "h-3 w-3 text-text-tertiary" }),
58
- /* @__PURE__ */ f("span", {
62
+ }) : /* @__PURE__ */ p(u, { className: "h-3 w-3 text-text-tertiary" }),
63
+ /* @__PURE__ */ p("span", {
59
64
  className: "max-w-[10rem] truncate",
60
65
  children: e.tag.label
61
66
  }),
62
- /* @__PURE__ */ f("button", {
67
+ /* @__PURE__ */ p("button", {
63
68
  type: "button",
64
- onClick: () => K(e.id),
65
- disabled: T.isPending,
69
+ onClick: () => Y(e.id),
70
+ disabled: O.isPending,
66
71
  "aria-label": `Remove tag ${e.tag.label}`,
67
72
  className: "rounded-full p-0.5 text-text-tertiary hover:bg-bg-canvas hover:text-text-primary",
68
- children: /* @__PURE__ */ f(u, { className: "h-3 w-3" })
73
+ children: /* @__PURE__ */ p(d, { className: "h-3 w-3" })
69
74
  })
70
75
  ]
71
- }, e.id)), /* @__PURE__ */ p(g, {
72
- open: D,
76
+ }, e.id)), /* @__PURE__ */ m(_, {
77
+ open: A,
73
78
  onOpenChange: (e) => {
74
- O(e), e || U();
79
+ j(e), e || K();
75
80
  },
76
- children: [/* @__PURE__ */ f(v, {
81
+ children: [/* @__PURE__ */ p(y, {
77
82
  asChild: !0,
78
- children: /* @__PURE__ */ p(m, {
83
+ children: /* @__PURE__ */ m(h, {
79
84
  size: "sm",
80
85
  variant: "outline",
81
86
  className: "h-7 gap-1 px-2 text-xs",
82
- children: [/* @__PURE__ */ f(c, { className: "h-3.5 w-3.5" }), " Add tag"]
87
+ children: [
88
+ /* @__PURE__ */ p(l, { className: "h-3.5 w-3.5" }),
89
+ " ",
90
+ w("mybodyshield.components.tags.add", "Add tag")
91
+ ]
83
92
  })
84
- }), /* @__PURE__ */ p(_, {
93
+ }), /* @__PURE__ */ m(v, {
85
94
  align: "start",
86
95
  className: "w-64 p-2",
87
- children: [/* @__PURE__ */ f(h, {
96
+ children: [/* @__PURE__ */ p(g, {
88
97
  autoFocus: !0,
89
- value: k,
90
- onChange: (e) => A(e.target.value),
91
- placeholder: "Search or create a tag…",
98
+ value: M,
99
+ onChange: (e) => N(e.target.value),
100
+ placeholder: w("mybodyshield.components.tags.searchPlaceholder", "Search or create a tag…"),
92
101
  className: "h-8"
93
- }), /* @__PURE__ */ f("div", {
102
+ }), /* @__PURE__ */ p("div", {
94
103
  className: "mt-2 max-h-56 overflow-y-auto",
95
- children: F.isFetching && R.length > 0 ? /* @__PURE__ */ p("div", {
104
+ children: R.isFetching && V.length > 0 ? /* @__PURE__ */ m("div", {
96
105
  className: "flex items-center gap-2 px-1 py-2 text-sm text-text-tertiary",
97
- children: [/* @__PURE__ */ f(y, { size: "sm" }), " Searching…"]
98
- }) : /* @__PURE__ */ p(d, { children: [
99
- z.map((e) => /* @__PURE__ */ p("button", {
106
+ children: [
107
+ /* @__PURE__ */ p(b, { size: "sm" }),
108
+ " ",
109
+ w("mybodyshield.common.searching", "Searching…")
110
+ ]
111
+ }) : /* @__PURE__ */ m(f, { children: [
112
+ H.map((e) => /* @__PURE__ */ m("button", {
100
113
  type: "button",
101
- onClick: () => W(e.id),
102
- disabled: H,
114
+ onClick: () => q(e.id),
115
+ disabled: G,
103
116
  className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-text-secondary hover:bg-bg-sunken disabled:opacity-60",
104
- children: [e.color ? /* @__PURE__ */ f("span", {
117
+ children: [e.color ? /* @__PURE__ */ p("span", {
105
118
  className: "h-2 w-2 shrink-0 rounded-full",
106
119
  style: { backgroundColor: e.color },
107
120
  "aria-hidden": !0
108
- }) : /* @__PURE__ */ f(l, { className: "h-3.5 w-3.5 text-text-tertiary" }), /* @__PURE__ */ f("span", {
121
+ }) : /* @__PURE__ */ p(u, { className: "h-3.5 w-3.5 text-text-tertiary" }), /* @__PURE__ */ p("span", {
109
122
  className: "truncate",
110
123
  children: e.label
111
124
  })]
112
125
  }, e.id)),
113
- V && /* @__PURE__ */ p("button", {
126
+ W && /* @__PURE__ */ m("button", {
114
127
  type: "button",
115
- onClick: G,
116
- disabled: H,
128
+ onClick: J,
129
+ disabled: G,
117
130
  className: "flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-action-primary-bg hover:bg-bg-sunken disabled:opacity-60",
118
- children: [/* @__PURE__ */ f(c, { className: "h-3.5 w-3.5 shrink-0" }), /* @__PURE__ */ p("span", {
131
+ children: [/* @__PURE__ */ p(l, { className: "h-3.5 w-3.5 shrink-0" }), /* @__PURE__ */ p("span", {
119
132
  className: "truncate",
120
- children: [
121
- "Create “",
122
- R,
123
- "”"
124
- ]
133
+ children: w("mybodyshield.components.tags.createLabel", "Create “{{label}}”", { label: V })
125
134
  })]
126
135
  }),
127
- !V && z.length === 0 && R.length > 0 && /* @__PURE__ */ f("p", {
136
+ !W && H.length === 0 && V.length > 0 && /* @__PURE__ */ p("p", {
128
137
  className: "px-2 py-2 text-sm text-text-tertiary",
129
- children: "Already added."
138
+ children: w("mybodyshield.components.tags.alreadyAdded", "Already added.")
130
139
  }),
131
- R.length === 0 && /* @__PURE__ */ f("p", {
140
+ V.length === 0 && /* @__PURE__ */ p("p", {
132
141
  className: "px-2 py-2 text-sm text-text-tertiary",
133
- children: "Type to search existing tags or create a new one."
142
+ children: w("mybodyshield.components.tags.typeToSearch", "Type to search existing tags or create a new one.")
134
143
  })
135
144
  ] })
136
145
  })]
137
146
  })]
138
147
  })]
139
148
  }),
140
- N && /* @__PURE__ */ f("p", {
149
+ I && /* @__PURE__ */ p("p", {
141
150
  className: "mt-1.5 text-xs text-status-error-text",
142
- children: N
151
+ children: I
143
152
  })
144
153
  ] });
145
154
  }
146
155
  //#endregion
147
- export { b as MybTags };
156
+ export { x as MybTags };
148
157
 
149
158
  //# sourceMappingURL=MybTags.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MybTags.js","names":[],"sources":["../../../src/mybodyshield/components/MybTags.tsx"],"sourcesContent":["/**\n * MybTags — a lightweight tag control for mybodyshield entities (Integration C).\n * @module mybodyshield/components/MybTags\n *\n * The mybodyshield svc exposes no tags field, so this drives the platform tag store\n * directly: `getEntityTags` (display), `searchTags` (+ `createTag`) to pick or\n * create, `assignTag`/`removeTagAssignment` to link — all via the workspace\n * gateway. No mybodyshield-svc change.\n */\n\nimport { useEffect, useState } from 'react';\nimport { Loader2, Plus, Tag as TagIcon, X } from 'lucide-react';\nimport {\n Button,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Spinner,\n} from '@burdenoff/fe-libs/ui';\nimport {\n useMybEntityTags,\n useMybTagSearch,\n useMybAssignTag,\n useMybRemoveTagAssignment,\n useMybCreateAndAssignTag,\n} from '../hooks';\n\ninterface MybTagsProps {\n entityType: string;\n entityId: string;\n label?: string;\n}\n\nexport function MybTags({ entityType, entityId, label = 'Tags' }: MybTagsProps) {\n const tags = useMybEntityTags(entityType, entityId);\n const assign = useMybAssignTag(entityType, entityId);\n const remove = useMybRemoveTagAssignment(entityType, entityId);\n const createAndAssign = useMybCreateAndAssignTag(entityType, entityId);\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [debounced, setDebounced] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebounced(query), 250);\n return () => clearTimeout(timer);\n }, [query]);\n\n const search = useMybTagSearch(debounced);\n\n const assignments = tags.data ?? [];\n const assignedIds = new Set(assignments.map((a) => a.tag.id));\n const q = debounced.trim();\n const searchResults = (search.data ?? []).filter((t) => !assignedIds.has(t.id));\n const hasExact =\n q.length > 0 &&\n [...assignments.map((a) => a.tag.label), ...(search.data ?? []).map((t) => t.label)].some(\n (l) => l.toLowerCase() === q.toLowerCase()\n );\n const showCreate = q.length > 0 && !hasExact;\n const busy = assign.isPending || createAndAssign.isPending;\n\n const resetInput = () => {\n setQuery('');\n setDebounced('');\n setError(null);\n };\n\n const handleAssign = async (tagId: string) => {\n setError(null);\n try {\n await assign.mutateAsync(tagId);\n resetInput();\n setOpen(false);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to add tag.');\n }\n };\n\n const handleCreate = async () => {\n if (!q) return;\n setError(null);\n try {\n await createAndAssign.mutateAsync(q);\n resetInput();\n setOpen(false);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to create tag.');\n }\n };\n\n const handleRemove = async (assignmentId: string) => {\n setError(null);\n try {\n await remove.mutateAsync(assignmentId);\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to remove tag.');\n }\n };\n\n return (\n <div>\n <p className=\"mb-1.5 text-xs text-text-tertiary\">{label}</p>\n <div className=\"flex flex-wrap items-center gap-2\">\n {tags.isLoading ? (\n <span className=\"inline-flex items-center gap-1.5 text-sm text-text-tertiary\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" /> Loading tags…\n </span>\n ) : (\n assignments.map((assignment) => (\n <span\n key={assignment.id}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border-seam bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary\"\n >\n {assignment.tag.color ? (\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: assignment.tag.color }}\n aria-hidden\n />\n ) : (\n <TagIcon className=\"h-3 w-3 text-text-tertiary\" />\n )}\n <span className=\"max-w-[10rem] truncate\">{assignment.tag.label}</span>\n <button\n type=\"button\"\n onClick={() => handleRemove(assignment.id)}\n disabled={remove.isPending}\n aria-label={`Remove tag ${assignment.tag.label}`}\n className=\"rounded-full p-0.5 text-text-tertiary hover:bg-bg-canvas hover:text-text-primary\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n ))\n )}\n\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) resetInput();\n }}\n >\n <PopoverTrigger asChild>\n <Button size=\"sm\" variant=\"outline\" className=\"h-7 gap-1 px-2 text-xs\">\n <Plus className=\"h-3.5 w-3.5\" /> Add tag\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-2\">\n <Input\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search or create a tag…\"\n className=\"h-8\"\n />\n <div className=\"mt-2 max-h-56 overflow-y-auto\">\n {search.isFetching && q.length > 0 ? (\n <div className=\"flex items-center gap-2 px-1 py-2 text-sm text-text-tertiary\">\n <Spinner size=\"sm\" /> Searching…\n </div>\n ) : (\n <>\n {searchResults.map((tag) => (\n <button\n key={tag.id}\n type=\"button\"\n onClick={() => handleAssign(tag.id)}\n disabled={busy}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-text-secondary hover:bg-bg-sunken disabled:opacity-60\"\n >\n {tag.color ? (\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: tag.color }}\n aria-hidden\n />\n ) : (\n <TagIcon className=\"h-3.5 w-3.5 text-text-tertiary\" />\n )}\n <span className=\"truncate\">{tag.label}</span>\n </button>\n ))}\n\n {showCreate && (\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={busy}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-action-primary-bg hover:bg-bg-sunken disabled:opacity-60\"\n >\n <Plus className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate\">Create “{q}”</span>\n </button>\n )}\n\n {!showCreate && searchResults.length === 0 && q.length > 0 && (\n <p className=\"px-2 py-2 text-sm text-text-tertiary\">Already added.</p>\n )}\n {q.length === 0 && (\n <p className=\"px-2 py-2 text-sm text-text-tertiary\">\n Type to search existing tags or create a new one.\n </p>\n )}\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n\n {error && <p className=\"mt-1.5 text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"MybTags.js","names":[],"sources":["../../../src/mybodyshield/components/MybTags.tsx"],"sourcesContent":["/**\n * MybTags — a lightweight tag control for mybodyshield entities (Integration C).\n * @module mybodyshield/components/MybTags\n *\n * The mybodyshield svc exposes no tags field, so this drives the platform tag store\n * directly: `getEntityTags` (display), `searchTags` (+ `createTag`) to pick or\n * create, `assignTag`/`removeTagAssignment` to link — all via the workspace\n * gateway. No mybodyshield-svc change.\n */\n\nimport { useEffect, useState } from 'react';\nimport { Loader2, Plus, Tag as TagIcon, X } from 'lucide-react';\nimport {\n Button,\n Input,\n Popover,\n PopoverContent,\n PopoverTrigger,\n Spinner,\n} from '@burdenoff/fe-libs/ui';\nimport {\n useMybEntityTags,\n useMybTagSearch,\n useMybAssignTag,\n useMybRemoveTagAssignment,\n useMybCreateAndAssignTag,\n useTr,\n} from '../hooks';\n\ninterface MybTagsProps {\n entityType: string;\n entityId: string;\n label?: string;\n}\n\nexport function MybTags({ entityType, entityId, label: labelProp }: MybTagsProps) {\n const t = useTr();\n const label = labelProp ?? t('mybodyshield.components.tags.label', 'Tags');\n const tags = useMybEntityTags(entityType, entityId);\n const assign = useMybAssignTag(entityType, entityId);\n const remove = useMybRemoveTagAssignment(entityType, entityId);\n const createAndAssign = useMybCreateAndAssignTag(entityType, entityId);\n\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState('');\n const [debounced, setDebounced] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n const timer = setTimeout(() => setDebounced(query), 250);\n return () => clearTimeout(timer);\n }, [query]);\n\n const search = useMybTagSearch(debounced);\n\n const assignments = tags.data ?? [];\n const assignedIds = new Set(assignments.map((a) => a.tag.id));\n const q = debounced.trim();\n const searchResults = (search.data ?? []).filter((t) => !assignedIds.has(t.id));\n const hasExact =\n q.length > 0 &&\n [...assignments.map((a) => a.tag.label), ...(search.data ?? []).map((t) => t.label)].some(\n (l) => l.toLowerCase() === q.toLowerCase()\n );\n const showCreate = q.length > 0 && !hasExact;\n const busy = assign.isPending || createAndAssign.isPending;\n\n const resetInput = () => {\n setQuery('');\n setDebounced('');\n setError(null);\n };\n\n const handleAssign = async (tagId: string) => {\n setError(null);\n try {\n await assign.mutateAsync(tagId);\n resetInput();\n setOpen(false);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t('mybodyshield.components.tags.addFailed', 'Failed to add tag.')\n );\n }\n };\n\n const handleCreate = async () => {\n if (!q) return;\n setError(null);\n try {\n await createAndAssign.mutateAsync(q);\n resetInput();\n setOpen(false);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t('mybodyshield.components.tags.createFailed', 'Failed to create tag.')\n );\n }\n };\n\n const handleRemove = async (assignmentId: string) => {\n setError(null);\n try {\n await remove.mutateAsync(assignmentId);\n } catch (err) {\n setError(\n err instanceof Error\n ? err.message\n : t('mybodyshield.components.tags.removeFailed', 'Failed to remove tag.')\n );\n }\n };\n\n return (\n <div>\n <p className=\"mb-1.5 text-xs text-text-tertiary\">{label}</p>\n <div className=\"flex flex-wrap items-center gap-2\">\n {tags.isLoading ? (\n <span className=\"inline-flex items-center gap-1.5 text-sm text-text-tertiary\">\n <Loader2 className=\"h-3.5 w-3.5 animate-spin\" />{' '}\n {t('mybodyshield.components.tags.loading', 'Loading tags…')}\n </span>\n ) : (\n assignments.map((assignment) => (\n <span\n key={assignment.id}\n className=\"inline-flex items-center gap-1.5 rounded-full border border-border-seam bg-bg-sunken px-2.5 py-1 text-xs text-text-secondary\"\n >\n {assignment.tag.color ? (\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: assignment.tag.color }}\n aria-hidden\n />\n ) : (\n <TagIcon className=\"h-3 w-3 text-text-tertiary\" />\n )}\n <span className=\"max-w-[10rem] truncate\">{assignment.tag.label}</span>\n <button\n type=\"button\"\n onClick={() => handleRemove(assignment.id)}\n disabled={remove.isPending}\n aria-label={`Remove tag ${assignment.tag.label}`}\n className=\"rounded-full p-0.5 text-text-tertiary hover:bg-bg-canvas hover:text-text-primary\"\n >\n <X className=\"h-3 w-3\" />\n </button>\n </span>\n ))\n )}\n\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) resetInput();\n }}\n >\n <PopoverTrigger asChild>\n <Button size=\"sm\" variant=\"outline\" className=\"h-7 gap-1 px-2 text-xs\">\n <Plus className=\"h-3.5 w-3.5\" /> {t('mybodyshield.components.tags.add', 'Add tag')}\n </Button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64 p-2\">\n <Input\n autoFocus\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder={t(\n 'mybodyshield.components.tags.searchPlaceholder',\n 'Search or create a tag…'\n )}\n className=\"h-8\"\n />\n <div className=\"mt-2 max-h-56 overflow-y-auto\">\n {search.isFetching && q.length > 0 ? (\n <div className=\"flex items-center gap-2 px-1 py-2 text-sm text-text-tertiary\">\n <Spinner size=\"sm\" /> {t('mybodyshield.common.searching', 'Searching…')}\n </div>\n ) : (\n <>\n {searchResults.map((tag) => (\n <button\n key={tag.id}\n type=\"button\"\n onClick={() => handleAssign(tag.id)}\n disabled={busy}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-text-secondary hover:bg-bg-sunken disabled:opacity-60\"\n >\n {tag.color ? (\n <span\n className=\"h-2 w-2 shrink-0 rounded-full\"\n style={{ backgroundColor: tag.color }}\n aria-hidden\n />\n ) : (\n <TagIcon className=\"h-3.5 w-3.5 text-text-tertiary\" />\n )}\n <span className=\"truncate\">{tag.label}</span>\n </button>\n ))}\n\n {showCreate && (\n <button\n type=\"button\"\n onClick={handleCreate}\n disabled={busy}\n className=\"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-sm text-action-primary-bg hover:bg-bg-sunken disabled:opacity-60\"\n >\n <Plus className=\"h-3.5 w-3.5 shrink-0\" />\n <span className=\"truncate\">\n {t('mybodyshield.components.tags.createLabel', 'Create “{{label}}”', {\n label: q,\n })}\n </span>\n </button>\n )}\n\n {!showCreate && searchResults.length === 0 && q.length > 0 && (\n <p className=\"px-2 py-2 text-sm text-text-tertiary\">\n {t('mybodyshield.components.tags.alreadyAdded', 'Already added.')}\n </p>\n )}\n {q.length === 0 && (\n <p className=\"px-2 py-2 text-sm text-text-tertiary\">\n {t(\n 'mybodyshield.components.tags.typeToSearch',\n 'Type to search existing tags or create a new one.'\n )}\n </p>\n )}\n </>\n )}\n </div>\n </PopoverContent>\n </Popover>\n </div>\n\n {error && <p className=\"mt-1.5 text-xs text-status-error-text\">{error}</p>}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"PageDisabled.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/PageDisabled.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAI3C,UAAU,iBAAiB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAS9C,CAAC"}
1
+ {"version":3,"file":"PageDisabled.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/PageDisabled.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAK3C,UAAU,iBAAiB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED,eAAO,MAAM,YAAY,EAAE,EAAE,CAAC,iBAAiB,CAiB9C,CAAC"}
@@ -1,17 +1,22 @@
1
1
  import { PageLayout as e } from "./PageLayout.js";
2
2
  import { EmptyState as t } from "./EmptyState.js";
3
- import { jsx as n } from "react/jsx-runtime";
3
+ import { useTr as n } from "../hooks/useTr.js";
4
+ import "../hooks/index.js";
5
+ import { jsx as r } from "react/jsx-runtime";
4
6
  //#region src/mybodyshield/components/PageDisabled.tsx
5
- var r = ({ title: r, icon: i }) => /* @__PURE__ */ n(e, {
6
- title: r,
7
- children: /* @__PURE__ */ n(t, {
8
- illustration: "empty-generic",
9
- icon: i,
10
- title: `${r} is currently unavailable`,
11
- description: "This feature has been temporarily disabled. Check back later."
12
- })
13
- });
7
+ var i = ({ title: i, icon: a }) => {
8
+ let o = n();
9
+ return /* @__PURE__ */ r(e, {
10
+ title: i,
11
+ children: /* @__PURE__ */ r(t, {
12
+ illustration: "empty-generic",
13
+ icon: a,
14
+ title: o("mybodyshield.common.pageUnavailable", "{{title}} is currently unavailable", { title: i }),
15
+ description: o("mybodyshield.common.pageDisabledDescription", "This feature has been temporarily disabled. Check back later.")
16
+ })
17
+ });
18
+ };
14
19
  //#endregion
15
- export { r as PageDisabled };
20
+ export { i as PageDisabled };
16
21
 
17
22
  //# sourceMappingURL=PageDisabled.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageDisabled.js","names":[],"sources":["../../../src/mybodyshield/components/PageDisabled.tsx"],"sourcesContent":["/**\n * PageDisabled — generic fallback when a MyBodyShield page is feature-flagged off.\n * @module mybodyshield/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { PageLayout } from './PageLayout';\nimport { EmptyState } from './EmptyState';\n\ninterface PageDisabledProps {\n title: string;\n icon?: ReactNode;\n}\n\nexport const PageDisabled: FC<PageDisabledProps> = ({ title, icon }) => (\n <PageLayout title={title}>\n <EmptyState\n illustration=\"empty-generic\"\n icon={icon}\n title={`${title} is currently unavailable`}\n description=\"This feature has been temporarily disabled. Check back later.\"\n />\n </PageLayout>\n);\n"],"mappings":";;;;AAcA,IAAa,KAAuC,EAAE,UAAO,cAC3D,kBAAC,GAAD;CAAmB;WACjB,kBAAC,GAAD;EACE,cAAa;EACP;EACN,OAAO,GAAG,EAAM;EAChB,aAAY;EACZ,CAAA;CACS,CAAA"}
1
+ {"version":3,"file":"PageDisabled.js","names":[],"sources":["../../../src/mybodyshield/components/PageDisabled.tsx"],"sourcesContent":["/**\n * PageDisabled — generic fallback when a MyBodyShield page is feature-flagged off.\n * @module mybodyshield/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { PageLayout } from './PageLayout';\nimport { EmptyState } from './EmptyState';\nimport { useTr } from '../hooks';\n\ninterface PageDisabledProps {\n title: string;\n icon?: ReactNode;\n}\n\nexport const PageDisabled: FC<PageDisabledProps> = ({ title, icon }) => {\n const t = useTr();\n return (\n <PageLayout title={title}>\n <EmptyState\n illustration=\"empty-generic\"\n icon={icon}\n title={t('mybodyshield.common.pageUnavailable', '{{title}} is currently unavailable', {\n title,\n })}\n description={t(\n 'mybodyshield.common.pageDisabledDescription',\n 'This feature has been temporarily disabled. Check back later.'\n )}\n />\n </PageLayout>\n );\n};\n"],"mappings":";;;;;;AAeA,IAAa,KAAuC,EAAE,UAAO,cAAW;CACtE,IAAM,IAAI,GAAO;AACjB,QACE,kBAAC,GAAD;EAAmB;YACjB,kBAAC,GAAD;GACE,cAAa;GACP;GACN,OAAO,EAAE,uCAAuC,sCAAsC,EACpF,UACD,CAAC;GACF,aAAa,EACX,+CACA,gEACD;GACD,CAAA;EACS,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/Pagination.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,OAAO,EACP,YAAY,EACZ,SAAS,GACV,EAAE,eAAe,sCAuCjB"}
1
+ {"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/Pagination.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,UAAU,eAAe;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,wDAAwD;IACxD,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,OAAO,EACP,YAAY,EACZ,SAAS,GACV,EAAE,eAAe,sCA0CjB"}
@@ -1,50 +1,59 @@
1
1
  import { cn as e } from "../utils/cn.js";
2
- import { ChevronLeft as t, ChevronRight as n } from "lucide-react";
3
- import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
- import { Button as a } from "@burdenoff/fe-libs/ui";
2
+ import { useTr as t } from "../hooks/useTr.js";
3
+ import "../hooks/index.js";
4
+ import { ChevronLeft as n, ChevronRight as r } from "lucide-react";
5
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
6
+ import { Button as o } from "@burdenoff/fe-libs/ui";
5
7
  //#region src/mybodyshield/components/Pagination.tsx
6
- function o({ page: o, pageSize: s, itemCount: c, hasMore: l, onPageChange: u, className: d }) {
7
- if (o === 0 && !l) return null;
8
- let f = c === 0 ? 0 : o * s + 1, p = o * s + c;
9
- return /* @__PURE__ */ i("div", {
10
- className: e("mt-4 flex flex-col items-center justify-between gap-3 sm:flex-row", d),
8
+ function s({ page: s, pageSize: c, itemCount: l, hasMore: u, onPageChange: d, className: f }) {
9
+ let p = t();
10
+ if (s === 0 && !u) return null;
11
+ let m = l === 0 ? 0 : s * c + 1, h = s * c + l;
12
+ return /* @__PURE__ */ a("div", {
13
+ className: e("mt-4 flex flex-col items-center justify-between gap-3 sm:flex-row", f),
11
14
  children: [/* @__PURE__ */ i("p", {
12
15
  className: "text-sm text-text-secondary tabular-nums",
13
16
  "aria-live": "polite",
14
- children: [
15
- "Showing ",
16
- f,
17
- "–",
18
- p
19
- ]
20
- }), /* @__PURE__ */ i("div", {
17
+ children: p("mybodyshield.pagination.showing", "Showing {{from}}–{{to}}", {
18
+ from: m,
19
+ to: h
20
+ })
21
+ }), /* @__PURE__ */ a("div", {
21
22
  className: "flex items-center gap-2",
22
23
  children: [
23
- /* @__PURE__ */ i(a, {
24
+ /* @__PURE__ */ a(o, {
24
25
  variant: "outline",
25
26
  size: "sm",
26
- onClick: () => u(o - 1),
27
- disabled: o === 0,
28
- "aria-label": "Previous page",
29
- children: [/* @__PURE__ */ r(t, { className: "mr-1 h-4 w-4" }), " Previous"]
27
+ onClick: () => d(s - 1),
28
+ disabled: s === 0,
29
+ "aria-label": p("mybodyshield.pagination.previousPage", "Previous page"),
30
+ children: [
31
+ /* @__PURE__ */ i(n, { className: "mr-1 h-4 w-4" }),
32
+ " ",
33
+ p("mybodyshield.pagination.previous", "Previous")
34
+ ]
30
35
  }),
31
36
  /* @__PURE__ */ i("span", {
32
37
  className: "min-w-[4.5rem] text-center text-sm text-text-secondary tabular-nums",
33
- children: ["Page ", o + 1]
38
+ children: p("mybodyshield.pagination.page", "Page {{page}}", { page: s + 1 })
34
39
  }),
35
- /* @__PURE__ */ i(a, {
40
+ /* @__PURE__ */ a(o, {
36
41
  variant: "outline",
37
42
  size: "sm",
38
- onClick: () => u(o + 1),
39
- disabled: !l,
40
- "aria-label": "Next page",
41
- children: ["Next ", /* @__PURE__ */ r(n, { className: "ml-1 h-4 w-4" })]
43
+ onClick: () => d(s + 1),
44
+ disabled: !u,
45
+ "aria-label": p("mybodyshield.pagination.nextPage", "Next page"),
46
+ children: [
47
+ p("mybodyshield.pagination.next", "Next"),
48
+ " ",
49
+ /* @__PURE__ */ i(r, { className: "ml-1 h-4 w-4" })
50
+ ]
42
51
  })
43
52
  ]
44
53
  })]
45
54
  });
46
55
  }
47
56
  //#endregion
48
- export { o as Pagination };
57
+ export { s as Pagination };
49
58
 
50
59
  //# sourceMappingURL=Pagination.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.js","names":[],"sources":["../../../src/mybodyshield/components/Pagination.tsx"],"sourcesContent":["/**\n * Pagination — offset-based Prev/Next control for Myb* connection lists.\n * @module mybodyshield/components\n *\n * The svc list connections return `pageInfo { cursor, hasMore }` and paginate by\n * cursor (offset is a no-op). Pages track a 0-indexed `page` for display and a\n * cursor stack for navigation; this control exposes Prev/Next, disabling Prev on\n * page 0 and Next when the server reports no more rows.\n */\n\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface PaginationProps {\n page: number;\n pageSize: number;\n /** Number of rows on the current page. */\n itemCount: number;\n /** Server flag: are there more rows after this page? */\n hasMore: boolean;\n onPageChange: (page: number) => void;\n className?: string;\n}\n\nexport function Pagination({\n page,\n pageSize,\n itemCount,\n hasMore,\n onPageChange,\n className,\n}: PaginationProps) {\n // Nothing to paginate: single page that also has no more rows.\n if (page === 0 && !hasMore) return null;\n\n const from = itemCount === 0 ? 0 : page * pageSize + 1;\n const to = page * pageSize + itemCount;\n\n return (\n <div\n className={cn('mt-4 flex flex-col items-center justify-between gap-3 sm:flex-row', className)}\n >\n <p className=\"text-sm text-text-secondary tabular-nums\" aria-live=\"polite\">\n Showing {from}–{to}\n </p>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(page - 1)}\n disabled={page === 0}\n aria-label=\"Previous page\"\n >\n <ChevronLeft className=\"mr-1 h-4 w-4\" /> Previous\n </Button>\n <span className=\"min-w-[4.5rem] text-center text-sm text-text-secondary tabular-nums\">\n Page {page + 1}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasMore}\n aria-label=\"Next page\"\n >\n Next <ChevronRight className=\"ml-1 h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;AAyBA,SAAgB,EAAW,EACzB,SACA,aACA,cACA,YACA,iBACA,gBACkB;AAElB,KAAI,MAAS,KAAK,CAAC,EAAS,QAAO;CAEnC,IAAM,IAAO,MAAc,IAAI,IAAI,IAAO,IAAW,GAC/C,IAAK,IAAO,IAAW;AAE7B,QACE,kBAAC,OAAD;EACE,WAAW,EAAG,qEAAqE,EAAU;YAD/F,CAGE,kBAAC,KAAD;GAAG,WAAU;GAA2C,aAAU;aAAlE;IAA2E;IAChE;IAAK;IAAE;IACd;MACJ,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,eAAe,EAAa,IAAO,EAAE;KACrC,UAAU,MAAS;KACnB,cAAW;eALb,CAOE,kBAAC,GAAD,EAAa,WAAU,gBAAiB,CAAA,EAAA,YACjC;;IACT,kBAAC,QAAD;KAAM,WAAU;eAAhB,CAAsF,SAC9E,IAAO,EACR;;IACP,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,eAAe,EAAa,IAAO,EAAE;KACrC,UAAU,CAAC;KACX,cAAW;eALb,CAMC,SACM,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA,CACvC;;IACL;KACF"}
1
+ {"version":3,"file":"Pagination.js","names":[],"sources":["../../../src/mybodyshield/components/Pagination.tsx"],"sourcesContent":["/**\n * Pagination — offset-based Prev/Next control for Myb* connection lists.\n * @module mybodyshield/components\n *\n * The svc list connections return `pageInfo { cursor, hasMore }` and paginate by\n * cursor (offset is a no-op). Pages track a 0-indexed `page` for display and a\n * cursor stack for navigation; this control exposes Prev/Next, disabling Prev on\n * page 0 and Next when the server reports no more rows.\n */\n\nimport { ChevronLeft, ChevronRight } from 'lucide-react';\nimport { Button } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useTr } from '../hooks';\n\ninterface PaginationProps {\n page: number;\n pageSize: number;\n /** Number of rows on the current page. */\n itemCount: number;\n /** Server flag: are there more rows after this page? */\n hasMore: boolean;\n onPageChange: (page: number) => void;\n className?: string;\n}\n\nexport function Pagination({\n page,\n pageSize,\n itemCount,\n hasMore,\n onPageChange,\n className,\n}: PaginationProps) {\n const t = useTr();\n\n // Nothing to paginate: single page that also has no more rows.\n if (page === 0 && !hasMore) return null;\n\n const from = itemCount === 0 ? 0 : page * pageSize + 1;\n const to = page * pageSize + itemCount;\n\n return (\n <div\n className={cn('mt-4 flex flex-col items-center justify-between gap-3 sm:flex-row', className)}\n >\n <p className=\"text-sm text-text-secondary tabular-nums\" aria-live=\"polite\">\n {t('mybodyshield.pagination.showing', 'Showing {{from}}–{{to}}', { from, to })}\n </p>\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(page - 1)}\n disabled={page === 0}\n aria-label={t('mybodyshield.pagination.previousPage', 'Previous page')}\n >\n <ChevronLeft className=\"mr-1 h-4 w-4\" />{' '}\n {t('mybodyshield.pagination.previous', 'Previous')}\n </Button>\n <span className=\"min-w-[4.5rem] text-center text-sm text-text-secondary tabular-nums\">\n {t('mybodyshield.pagination.page', 'Page {{page}}', { page: page + 1 })}\n </span>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => onPageChange(page + 1)}\n disabled={!hasMore}\n aria-label={t('mybodyshield.pagination.nextPage', 'Next page')}\n >\n {t('mybodyshield.pagination.next', 'Next')} <ChevronRight className=\"ml-1 h-4 w-4\" />\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;AA0BA,SAAgB,EAAW,EACzB,SACA,aACA,cACA,YACA,iBACA,gBACkB;CAClB,IAAM,IAAI,GAAO;AAGjB,KAAI,MAAS,KAAK,CAAC,EAAS,QAAO;CAEnC,IAAM,IAAO,MAAc,IAAI,IAAI,IAAO,IAAW,GAC/C,IAAK,IAAO,IAAW;AAE7B,QACE,kBAAC,OAAD;EACE,WAAW,EAAG,qEAAqE,EAAU;YAD/F,CAGE,kBAAC,KAAD;GAAG,WAAU;GAA2C,aAAU;aAC/D,EAAE,mCAAmC,2BAA2B;IAAE;IAAM;IAAI,CAAC;GAC5E,CAAA,EACJ,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,eAAe,EAAa,IAAO,EAAE;KACrC,UAAU,MAAS;KACnB,cAAY,EAAE,wCAAwC,gBAAgB;eALxE;MAOE,kBAAC,GAAD,EAAa,WAAU,gBAAiB,CAAA;MAAC;MACxC,EAAE,oCAAoC,WAAW;MAC3C;;IACT,kBAAC,QAAD;KAAM,WAAU;eACb,EAAE,gCAAgC,iBAAiB,EAAE,MAAM,IAAO,GAAG,CAAC;KAClE,CAAA;IACP,kBAAC,GAAD;KACE,SAAQ;KACR,MAAK;KACL,eAAe,EAAa,IAAO,EAAE;KACrC,UAAU,CAAC;KACX,cAAY,EAAE,oCAAoC,YAAY;eALhE;MAOG,EAAE,gCAAgC,OAAO;MAAC;MAAC,kBAAC,GAAD,EAAc,WAAU,gBAAiB,CAAA;MAC9E;;IACL;KACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"StateViews.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/StateViews.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAK3C,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAK5C,CAAC;AAEF,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CA2BxC,CAAC;AAEF,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAkBpC,CAAC"}
1
+ {"version":3,"file":"StateViews.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/StateViews.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAM3C,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,WAAW,EAAE,EAAE,CAAC,gBAAgB,CAU5C,CAAC;AAEF,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,SAAS,EAAE,EAAE,CAAC,cAAc,CA2BxC,CAAC;AAEF,UAAU,YAAY;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,OAAO,EAAE,EAAE,CAAC,YAAY,CAkBpC,CAAC"}
@@ -1,50 +1,58 @@
1
1
  import { cn as e } from "../utils/cn.js";
2
- import { AlertCircle as t } from "lucide-react";
3
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
- import { Spinner as i } from "@burdenoff/fe-libs/ui";
2
+ import { useTr as t } from "../hooks/useTr.js";
3
+ import "../hooks/index.js";
4
+ import { AlertCircle as n } from "lucide-react";
5
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
6
+ import { Spinner as a } from "@burdenoff/fe-libs/ui";
5
7
  //#region src/mybodyshield/components/StateViews.tsx
6
- var a = ({ label: t = "Loading…", className: a }) => /* @__PURE__ */ r("div", {
7
- className: e("flex min-h-[40vh] flex-col items-center justify-center gap-3", a),
8
- children: [/* @__PURE__ */ n(i, { size: "lg" }), /* @__PURE__ */ n("p", {
9
- className: "text-sm text-text-secondary",
10
- children: t
11
- })]
12
- }), o = ({ title: i = "Something went wrong", message: a, onRetry: o, className: s }) => /* @__PURE__ */ r("div", {
13
- className: e("flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center", s),
14
- children: [
15
- /* @__PURE__ */ n(t, { className: "h-10 w-10 text-status-error-text" }),
16
- /* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("h2", {
17
- className: "text-lg font-semibold text-text-primary",
18
- children: i
19
- }), a && /* @__PURE__ */ n("p", {
20
- className: "mt-1 max-w-md text-sm text-text-secondary",
21
- children: a
22
- })] }),
23
- o && /* @__PURE__ */ n("button", {
24
- type: "button",
25
- onClick: o,
26
- className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
27
- children: "Retry"
28
- })
29
- ]
30
- }), s = ({ title: t, description: i, action: a, children: o, className: s, "data-tour": c }) => /* @__PURE__ */ r("section", {
8
+ var o = ({ label: n, className: o }) => {
9
+ let s = t();
10
+ return /* @__PURE__ */ i("div", {
11
+ className: e("flex min-h-[40vh] flex-col items-center justify-center gap-3", o),
12
+ children: [/* @__PURE__ */ r(a, { size: "lg" }), /* @__PURE__ */ r("p", {
13
+ className: "text-sm text-text-secondary",
14
+ children: n ?? s("mybodyshield.common.loading", "Loading…")
15
+ })]
16
+ });
17
+ }, s = ({ title: a, message: o, onRetry: s, className: c }) => {
18
+ let l = t();
19
+ return /* @__PURE__ */ i("div", {
20
+ className: e("flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center", c),
21
+ children: [
22
+ /* @__PURE__ */ r(n, { className: "h-10 w-10 text-status-error-text" }),
23
+ /* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h2", {
24
+ className: "text-lg font-semibold text-text-primary",
25
+ children: a ?? l("mybodyshield.common.errorTitle", "Something went wrong")
26
+ }), o && /* @__PURE__ */ r("p", {
27
+ className: "mt-1 max-w-md text-sm text-text-secondary",
28
+ children: o
29
+ })] }),
30
+ s && /* @__PURE__ */ r("button", {
31
+ type: "button",
32
+ onClick: s,
33
+ className: "rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90",
34
+ children: l("mybodyshield.common.retry", "Retry")
35
+ })
36
+ ]
37
+ });
38
+ }, c = ({ title: t, description: n, action: a, children: o, className: s, "data-tour": c }) => /* @__PURE__ */ i("section", {
31
39
  "data-tour": c,
32
40
  className: e("mt-8 first:mt-0", s),
33
- children: [/* @__PURE__ */ r("div", {
41
+ children: [/* @__PURE__ */ i("div", {
34
42
  className: "mb-3 flex items-end justify-between gap-3",
35
- children: [/* @__PURE__ */ r("div", { children: [/* @__PURE__ */ n("h2", {
43
+ children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h2", {
36
44
  className: "text-base font-semibold text-text-primary",
37
45
  children: t
38
- }), i && /* @__PURE__ */ n("p", {
46
+ }), n && /* @__PURE__ */ r("p", {
39
47
  className: "mt-0.5 text-sm text-text-secondary",
40
- children: i
41
- })] }), a && /* @__PURE__ */ n("div", {
48
+ children: n
49
+ })] }), a && /* @__PURE__ */ r("div", {
42
50
  className: "shrink-0",
43
51
  children: a
44
52
  })]
45
53
  }), o]
46
54
  });
47
55
  //#endregion
48
- export { o as ErrorView, a as LoadingView, s as Section };
56
+ export { s as ErrorView, o as LoadingView, c as Section };
49
57
 
50
58
  //# sourceMappingURL=StateViews.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/mybodyshield/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module mybodyshield/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label = 'Loading…', className }) => (\n <div className={cn('flex min-h-[40vh] flex-col items-center justify-center gap-3', className)}>\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-text-secondary\">{label}</p>\n </div>\n);\n\ninterface ErrorViewProps {\n title?: string;\n message?: string;\n onRetry?: () => void;\n className?: string;\n}\n\nexport const ErrorView: FC<ErrorViewProps> = ({\n title = 'Something went wrong',\n message,\n onRetry,\n className,\n}) => (\n <div\n className={cn(\n 'flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center',\n className\n )}\n >\n <AlertCircle className=\"h-10 w-10 text-status-error-text\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">{title}</h2>\n {message && <p className=\"mt-1 max-w-md text-sm text-text-secondary\">{message}</p>}\n </div>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n Retry\n </button>\n )}\n </div>\n);\n\ninterface SectionProps {\n title: string;\n description?: string;\n action?: ReactNode;\n children: ReactNode;\n className?: string;\n 'data-tour'?: string;\n}\n\nexport const Section: FC<SectionProps> = ({\n title,\n description,\n action,\n children,\n className,\n 'data-tour': dataTour,\n}) => (\n <section data-tour={dataTour} className={cn('mt-8 first:mt-0', className)}>\n <div className=\"mb-3 flex items-end justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n {description && <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n {children}\n </section>\n);\n"],"mappings":";;;;;AAeA,IAAa,KAAqC,EAAE,WAAQ,YAAY,mBACtE,kBAAC,OAAD;CAAK,WAAW,EAAG,gEAAgE,EAAU;WAA7F,CACE,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA,EACrB,kBAAC,KAAD;EAAG,WAAU;YAA+B;EAAU,CAAA,CAClD;IAUK,KAAiC,EAC5C,WAAQ,wBACR,YACA,YACA,mBAEA,kBAAC,OAAD;CACE,WAAW,EACT,4EACA,EACD;WAJH;EAME,kBAAC,GAAD,EAAa,WAAU,oCAAqC,CAAA;EAC5D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAA2C;GAAW,CAAA,EACnE,KAAW,kBAAC,KAAD;GAAG,WAAU;aAA6C;GAAY,CAAA,CAC9E,EAAA,CAAA;EACL,KACC,kBAAC,UAAD;GACE,MAAK;GACL,SAAS;GACT,WAAU;aACX;GAEQ,CAAA;EAEP;IAYK,KAA6B,EACxC,UACA,gBACA,WACA,aACA,cACA,aAAa,QAEb,kBAAC,WAAD;CAAS,aAAW;CAAU,WAAW,EAAG,mBAAmB,EAAU;WAAzE,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAA6C;GAAW,CAAA,EACrE,KAAe,kBAAC,KAAD;GAAG,WAAU;aAAsC;GAAgB,CAAA,CAC/E,EAAA,CAAA,EACL,KAAU,kBAAC,OAAD;GAAK,WAAU;aAAY;GAAa,CAAA,CAC/C;KACL,EACO"}
1
+ {"version":3,"file":"StateViews.js","names":[],"sources":["../../../src/mybodyshield/components/StateViews.tsx"],"sourcesContent":["/**\n * Shared loading / error / section state views\n * @module mybodyshield/components\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { AlertCircle } from 'lucide-react';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\nimport { useTr } from '../hooks';\n\ninterface LoadingViewProps {\n label?: string;\n className?: string;\n}\n\nexport const LoadingView: FC<LoadingViewProps> = ({ label, className }) => {\n const t = useTr();\n return (\n <div className={cn('flex min-h-[40vh] flex-col items-center justify-center gap-3', className)}>\n <Spinner size=\"lg\" />\n <p className=\"text-sm text-text-secondary\">\n {label ?? t('mybodyshield.common.loading', 'Loading…')}\n </p>\n </div>\n );\n};\n\ninterface ErrorViewProps {\n title?: string;\n message?: string;\n onRetry?: () => void;\n className?: string;\n}\n\nexport const ErrorView: FC<ErrorViewProps> = ({ title, message, onRetry, className }) => {\n const t = useTr();\n return (\n <div\n className={cn(\n 'flex min-h-[40vh] flex-col items-center justify-center gap-4 text-center',\n className\n )}\n >\n <AlertCircle className=\"h-10 w-10 text-status-error-text\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {title ?? t('mybodyshield.common.errorTitle', 'Something went wrong')}\n </h2>\n {message && <p className=\"mt-1 max-w-md text-sm text-text-secondary\">{message}</p>}\n </div>\n {onRetry && (\n <button\n type=\"button\"\n onClick={onRetry}\n className=\"rounded-lg bg-action-primary-bg px-4 py-2 text-sm font-medium text-action-primary-text hover:opacity-90\"\n >\n {t('mybodyshield.common.retry', 'Retry')}\n </button>\n )}\n </div>\n );\n};\n\ninterface SectionProps {\n title: string;\n description?: string;\n action?: ReactNode;\n children: ReactNode;\n className?: string;\n 'data-tour'?: string;\n}\n\nexport const Section: FC<SectionProps> = ({\n title,\n description,\n action,\n children,\n className,\n 'data-tour': dataTour,\n}) => (\n <section data-tour={dataTour} className={cn('mt-8 first:mt-0', className)}>\n <div className=\"mb-3 flex items-end justify-between gap-3\">\n <div>\n <h2 className=\"text-base font-semibold text-text-primary\">{title}</h2>\n {description && <p className=\"mt-0.5 text-sm text-text-secondary\">{description}</p>}\n </div>\n {action && <div className=\"shrink-0\">{action}</div>}\n </div>\n {children}\n </section>\n);\n"],"mappings":";;;;;;;AAgBA,IAAa,KAAqC,EAAE,UAAO,mBAAgB;CACzE,IAAM,IAAI,GAAO;AACjB,QACE,kBAAC,OAAD;EAAK,WAAW,EAAG,gEAAgE,EAAU;YAA7F,CACE,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA,EACrB,kBAAC,KAAD;GAAG,WAAU;aACV,KAAS,EAAE,+BAA+B,WAAW;GACpD,CAAA,CACA;;GAWG,KAAiC,EAAE,UAAO,YAAS,YAAS,mBAAgB;CACvF,IAAM,IAAI,GAAO;AACjB,QACE,kBAAC,OAAD;EACE,WAAW,EACT,4EACA,EACD;YAJH;GAME,kBAAC,GAAD,EAAa,WAAU,oCAAqC,CAAA;GAC5D,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;IAAI,WAAU;cACX,KAAS,EAAE,kCAAkC,uBAAuB;IAClE,CAAA,EACJ,KAAW,kBAAC,KAAD;IAAG,WAAU;cAA6C;IAAY,CAAA,CAC9E,EAAA,CAAA;GACL,KACC,kBAAC,UAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;cAET,EAAE,6BAA6B,QAAQ;IACjC,CAAA;GAEP;;GAaG,KAA6B,EACxC,UACA,gBACA,WACA,aACA,cACA,aAAa,QAEb,kBAAC,WAAD;CAAS,aAAW;CAAU,WAAW,EAAG,mBAAmB,EAAU;WAAzE,CACE,kBAAC,OAAD;EAAK,WAAU;YAAf,CACE,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;GAAI,WAAU;aAA6C;GAAW,CAAA,EACrE,KAAe,kBAAC,KAAD;GAAG,WAAU;aAAsC;GAAgB,CAAA,CAC/E,EAAA,CAAA,EACL,KAAU,kBAAC,OAAD;GAAK,WAAU;aAAY;GAAa,CAAA,CAC/C;KACL,EACO"}
@@ -1 +1 @@
1
- {"version":3,"file":"UserSearchSelect.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/UserSearchSelect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAQH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,qBAAqB;IAC7B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,WAAW,EACX,QAAQ,EACR,QAAgB,EAChB,MAAsB,GACvB,EAAE,qBAAqB,+BA+HvB"}
1
+ {"version":3,"file":"UserSearchSelect.d.ts","sourceRoot":"","sources":["../../../src/mybodyshield/components/UserSearchSelect.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,UAAU,qBAAqB;IAC7B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,WAAW,EACX,QAAQ,EACR,QAAgB,EAChB,MAAsB,GACvB,EAAE,qBAAqB,+BAiJvB"}