@burdenoff/microfe-mybodyshield 2026.827.1 → 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.
- package/dist/mybodyshield/MyBodyShieldRoot.d.ts.map +1 -1
- package/dist/mybodyshield/MyBodyShieldRoot.js +54 -56
- package/dist/mybodyshield/MyBodyShieldRoot.js.map +1 -1
- package/dist/mybodyshield/MyBodyShieldRoutes.d.ts.map +1 -1
- package/dist/mybodyshield/MyBodyShieldRoutes.js +121 -62
- package/dist/mybodyshield/MyBodyShieldRoutes.js.map +1 -1
- package/dist/mybodyshield/components/EvidenceUpload.d.ts.map +1 -1
- package/dist/mybodyshield/components/EvidenceUpload.js +46 -45
- package/dist/mybodyshield/components/EvidenceUpload.js.map +1 -1
- package/dist/mybodyshield/components/FileLink.d.ts.map +1 -1
- package/dist/mybodyshield/components/FileLink.js +27 -18
- package/dist/mybodyshield/components/FileLink.js.map +1 -1
- package/dist/mybodyshield/components/MybDiscussion.d.ts +1 -1
- package/dist/mybodyshield/components/MybDiscussion.d.ts.map +1 -1
- package/dist/mybodyshield/components/MybDiscussion.js +59 -58
- package/dist/mybodyshield/components/MybDiscussion.js.map +1 -1
- package/dist/mybodyshield/components/MybTags.d.ts +1 -1
- package/dist/mybodyshield/components/MybTags.d.ts.map +1 -1
- package/dist/mybodyshield/components/MybTags.js +83 -74
- package/dist/mybodyshield/components/MybTags.js.map +1 -1
- package/dist/mybodyshield/components/PageDisabled.d.ts.map +1 -1
- package/dist/mybodyshield/components/PageDisabled.js +16 -11
- package/dist/mybodyshield/components/PageDisabled.js.map +1 -1
- package/dist/mybodyshield/components/Pagination.d.ts.map +1 -1
- package/dist/mybodyshield/components/Pagination.js +36 -27
- package/dist/mybodyshield/components/Pagination.js.map +1 -1
- package/dist/mybodyshield/components/StateViews.d.ts.map +1 -1
- package/dist/mybodyshield/components/StateViews.js +42 -34
- package/dist/mybodyshield/components/StateViews.js.map +1 -1
- package/dist/mybodyshield/components/UserSearchSelect.d.ts.map +1 -1
- package/dist/mybodyshield/components/UserSearchSelect.js +66 -68
- package/dist/mybodyshield/components/UserSearchSelect.js.map +1 -1
- package/dist/mybodyshield/hooks/index.d.ts +1 -0
- package/dist/mybodyshield/hooks/index.d.ts.map +1 -1
- package/dist/mybodyshield/hooks/index.js +1 -0
- package/dist/mybodyshield/hooks/useTr.d.ts +5 -0
- package/dist/mybodyshield/hooks/useTr.d.ts.map +1 -0
- package/dist/mybodyshield/hooks/useTr.js +12 -0
- package/dist/mybodyshield/hooks/useTr.js.map +1 -0
- package/dist/mybodyshield/pages/DashboardPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/DashboardPage.js +157 -136
- package/dist/mybodyshield/pages/DashboardPage.js.map +1 -1
- package/dist/mybodyshield/pages/SettingsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/SettingsPage.js +50 -59
- package/dist/mybodyshield/pages/SettingsPage.js.map +1 -1
- package/dist/mybodyshield/pages/_shared/visuals.d.ts +2 -1
- package/dist/mybodyshield/pages/_shared/visuals.d.ts.map +1 -1
- package/dist/mybodyshield/pages/_shared/visuals.js +91 -81
- package/dist/mybodyshield/pages/_shared/visuals.js.map +1 -1
- package/dist/mybodyshield/pages/ai/AiControlsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/ai/AiControlsPage.js +255 -266
- package/dist/mybodyshield/pages/ai/AiControlsPage.js.map +1 -1
- package/dist/mybodyshield/pages/coaching/CoachingPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/coaching/CoachingPage.js +321 -301
- package/dist/mybodyshield/pages/coaching/CoachingPage.js.map +1 -1
- package/dist/mybodyshield/pages/goals/GoalsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/goals/GoalsPage.js +247 -251
- package/dist/mybodyshield/pages/goals/GoalsPage.js.map +1 -1
- package/dist/mybodyshield/pages/insights/InsightsCharts.d.ts.map +1 -1
- package/dist/mybodyshield/pages/insights/InsightsCharts.js +216 -213
- package/dist/mybodyshield/pages/insights/InsightsCharts.js.map +1 -1
- package/dist/mybodyshield/pages/insights/InsightsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/insights/InsightsPage.js +290 -284
- package/dist/mybodyshield/pages/insights/InsightsPage.js.map +1 -1
- package/dist/mybodyshield/pages/nutrition/NutritionPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/nutrition/NutritionPage.js +575 -529
- package/dist/mybodyshield/pages/nutrition/NutritionPage.js.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramDetailPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramDetailPage.js +333 -275
- package/dist/mybodyshield/pages/programs/ProgramDetailPage.js.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/programs/ProgramsPage.js +258 -253
- package/dist/mybodyshield/pages/programs/ProgramsPage.js.map +1 -1
- package/dist/mybodyshield/pages/progress/ProgressPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/progress/ProgressPage.js +271 -254
- package/dist/mybodyshield/pages/progress/ProgressPage.js.map +1 -1
- package/dist/mybodyshield/pages/recovery/RecoveryPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/recovery/RecoveryPage.js +206 -200
- package/dist/mybodyshield/pages/recovery/RecoveryPage.js.map +1 -1
- package/dist/mybodyshield/pages/train/SessionDetailPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/train/SessionDetailPage.js +327 -294
- package/dist/mybodyshield/pages/train/SessionDetailPage.js.map +1 -1
- package/dist/mybodyshield/pages/train/SessionsPage.d.ts.map +1 -1
- package/dist/mybodyshield/pages/train/SessionsPage.js +180 -163
- package/dist/mybodyshield/pages/train/SessionsPage.js.map +1 -1
- package/dist/mybodyshield/utils/i18n.d.ts +1 -2
- package/dist/mybodyshield/utils/i18n.d.ts.map +1 -1
- package/dist/mybodyshield/utils/i18n.js +15 -0
- package/dist/mybodyshield/utils/i18n.js.map +1 -0
- 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
|
|
4
|
-
import { Loader2 as
|
|
5
|
-
import { Fragment as
|
|
6
|
-
import { Button as
|
|
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
|
|
9
|
-
let C = n(
|
|
10
|
-
|
|
11
|
-
let e = setTimeout(() => M
|
|
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
|
-
}, [
|
|
14
|
-
let
|
|
15
|
-
|
|
16
|
-
},
|
|
17
|
-
|
|
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
|
|
20
|
+
await D.mutateAsync(e), K(), j(!1);
|
|
20
21
|
} catch (e) {
|
|
21
|
-
|
|
22
|
+
L(e instanceof Error ? e.message : w("mybodyshield.components.tags.addFailed", "Failed to add tag."));
|
|
22
23
|
}
|
|
23
|
-
},
|
|
24
|
-
if (
|
|
25
|
-
|
|
24
|
+
}, J = async () => {
|
|
25
|
+
if (V) {
|
|
26
|
+
L(null);
|
|
26
27
|
try {
|
|
27
|
-
await
|
|
28
|
+
await k.mutateAsync(V), K(), j(!1);
|
|
28
29
|
} catch (e) {
|
|
29
|
-
|
|
30
|
+
L(e instanceof Error ? e.message : w("mybodyshield.components.tags.createFailed", "Failed to create tag."));
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
},
|
|
33
|
-
|
|
33
|
+
}, Y = async (e) => {
|
|
34
|
+
L(null);
|
|
34
35
|
try {
|
|
35
|
-
await
|
|
36
|
+
await O.mutateAsync(e);
|
|
36
37
|
} catch (e) {
|
|
37
|
-
|
|
38
|
+
L(e instanceof Error ? e.message : w("mybodyshield.components.tags.removeFailed", "Failed to remove tag."));
|
|
38
39
|
}
|
|
39
40
|
};
|
|
40
|
-
return /* @__PURE__ */
|
|
41
|
-
/* @__PURE__ */
|
|
41
|
+
return /* @__PURE__ */ m("div", { children: [
|
|
42
|
+
/* @__PURE__ */ p("p", {
|
|
42
43
|
className: "mb-1.5 text-xs text-text-tertiary",
|
|
43
|
-
children:
|
|
44
|
+
children: T
|
|
44
45
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
46
|
+
/* @__PURE__ */ m("div", {
|
|
46
47
|
className: "flex flex-wrap items-center gap-2",
|
|
47
|
-
children: [
|
|
48
|
+
children: [E.isLoading ? /* @__PURE__ */ m("span", {
|
|
48
49
|
className: "inline-flex items-center gap-1.5 text-sm text-text-tertiary",
|
|
49
|
-
children: [
|
|
50
|
-
|
|
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__ */
|
|
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__ */
|
|
58
|
-
/* @__PURE__ */
|
|
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__ */
|
|
67
|
+
/* @__PURE__ */ p("button", {
|
|
63
68
|
type: "button",
|
|
64
|
-
onClick: () =>
|
|
65
|
-
disabled:
|
|
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__ */
|
|
73
|
+
children: /* @__PURE__ */ p(d, { className: "h-3 w-3" })
|
|
69
74
|
})
|
|
70
75
|
]
|
|
71
|
-
}, e.id)), /* @__PURE__ */
|
|
72
|
-
open:
|
|
76
|
+
}, e.id)), /* @__PURE__ */ m(_, {
|
|
77
|
+
open: A,
|
|
73
78
|
onOpenChange: (e) => {
|
|
74
|
-
|
|
79
|
+
j(e), e || K();
|
|
75
80
|
},
|
|
76
|
-
children: [/* @__PURE__ */
|
|
81
|
+
children: [/* @__PURE__ */ p(y, {
|
|
77
82
|
asChild: !0,
|
|
78
|
-
children: /* @__PURE__ */
|
|
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: [
|
|
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__ */
|
|
93
|
+
}), /* @__PURE__ */ m(v, {
|
|
85
94
|
align: "start",
|
|
86
95
|
className: "w-64 p-2",
|
|
87
|
-
children: [/* @__PURE__ */
|
|
96
|
+
children: [/* @__PURE__ */ p(g, {
|
|
88
97
|
autoFocus: !0,
|
|
89
|
-
value:
|
|
90
|
-
onChange: (e) =>
|
|
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__ */
|
|
102
|
+
}), /* @__PURE__ */ p("div", {
|
|
94
103
|
className: "mt-2 max-h-56 overflow-y-auto",
|
|
95
|
-
children:
|
|
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: [
|
|
98
|
-
|
|
99
|
-
|
|
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: () =>
|
|
102
|
-
disabled:
|
|
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__ */
|
|
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__ */
|
|
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
|
-
|
|
126
|
+
W && /* @__PURE__ */ m("button", {
|
|
114
127
|
type: "button",
|
|
115
|
-
onClick:
|
|
116
|
-
disabled:
|
|
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__ */
|
|
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
|
-
!
|
|
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
|
-
|
|
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
|
-
|
|
149
|
+
I && /* @__PURE__ */ p("p", {
|
|
141
150
|
className: "mt-1.5 text-xs text-status-error-text",
|
|
142
|
-
children:
|
|
151
|
+
children: I
|
|
143
152
|
})
|
|
144
153
|
] });
|
|
145
154
|
}
|
|
146
155
|
//#endregion
|
|
147
|
-
export {
|
|
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;
|
|
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 {
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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 {
|
|
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
|
|
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;
|
|
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 {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
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
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
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__ */
|
|
24
|
+
/* @__PURE__ */ a(o, {
|
|
24
25
|
variant: "outline",
|
|
25
26
|
size: "sm",
|
|
26
|
-
onClick: () =>
|
|
27
|
-
disabled:
|
|
28
|
-
"aria-label": "Previous page",
|
|
29
|
-
children: [
|
|
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:
|
|
38
|
+
children: p("mybodyshield.pagination.page", "Page {{page}}", { page: s + 1 })
|
|
34
39
|
}),
|
|
35
|
-
/* @__PURE__ */
|
|
40
|
+
/* @__PURE__ */ a(o, {
|
|
36
41
|
variant: "outline",
|
|
37
42
|
size: "sm",
|
|
38
|
-
onClick: () =>
|
|
39
|
-
disabled: !
|
|
40
|
-
"aria-label": "Next page",
|
|
41
|
-
children: [
|
|
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 {
|
|
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
|
|
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;
|
|
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 {
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
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
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
className: "
|
|
10
|
-
children:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
className: "
|
|
21
|
-
children:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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__ */
|
|
41
|
+
children: [/* @__PURE__ */ i("div", {
|
|
34
42
|
className: "mb-3 flex items-end justify-between gap-3",
|
|
35
|
-
children: [/* @__PURE__ */
|
|
43
|
+
children: [/* @__PURE__ */ i("div", { children: [/* @__PURE__ */ r("h2", {
|
|
36
44
|
className: "text-base font-semibold text-text-primary",
|
|
37
45
|
children: t
|
|
38
|
-
}),
|
|
46
|
+
}), n && /* @__PURE__ */ r("p", {
|
|
39
47
|
className: "mt-0.5 text-sm text-text-secondary",
|
|
40
|
-
children:
|
|
41
|
-
})] }), a && /* @__PURE__ */
|
|
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 {
|
|
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
|
|
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;
|
|
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"}
|