@alfadocs/ui-kit 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/notes-panel-CCz0J140.js +370 -0
- package/dist/_chunks/sparkline-DJtZBe7O.js +501 -0
- package/dist/agent-catalog.json +27 -1
- package/dist/agent-i18n/en.json +4 -2
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/notes-panel/notes-panel.d.ts +45 -2
- package/dist/components/sparkline/index.js +1 -1
- package/dist/components/sparkline/sparkline.d.ts +24 -0
- package/dist/host-compat.css +4 -1
- package/dist/i18n/locales/ar.d.ts +2 -0
- package/dist/i18n/locales/ar.js +2 -0
- package/dist/i18n/locales/de.d.ts +2 -0
- package/dist/i18n/locales/de.js +2 -0
- package/dist/i18n/locales/el.d.ts +2 -0
- package/dist/i18n/locales/el.js +2 -0
- package/dist/i18n/locales/en.d.ts +2 -0
- package/dist/i18n/locales/en.js +2 -0
- package/dist/i18n/locales/es.d.ts +2 -0
- package/dist/i18n/locales/es.js +2 -0
- package/dist/i18n/locales/fr.d.ts +2 -0
- package/dist/i18n/locales/fr.js +2 -0
- package/dist/i18n/locales/hi.d.ts +2 -0
- package/dist/i18n/locales/hi.js +2 -0
- package/dist/i18n/locales/it.d.ts +2 -0
- package/dist/i18n/locales/it.js +2 -0
- package/dist/i18n/locales/ja.d.ts +2 -0
- package/dist/i18n/locales/ja.js +2 -0
- package/dist/i18n/locales/nl.d.ts +2 -0
- package/dist/i18n/locales/nl.js +2 -0
- package/dist/i18n/locales/pl.d.ts +2 -0
- package/dist/i18n/locales/pl.js +2 -0
- package/dist/i18n/locales/pt.d.ts +2 -0
- package/dist/i18n/locales/pt.js +2 -0
- package/dist/i18n/locales/ro.d.ts +2 -0
- package/dist/i18n/locales/ro.js +2 -0
- package/dist/i18n/locales/ru.d.ts +2 -0
- package/dist/i18n/locales/ru.js +2 -0
- package/dist/i18n/locales/sq.d.ts +2 -0
- package/dist/i18n/locales/sq.js +2 -0
- package/dist/i18n/locales/sv.d.ts +2 -0
- package/dist/i18n/locales/sv.js +2 -0
- package/dist/i18n/locales/tr.d.ts +2 -0
- package/dist/i18n/locales/tr.js +2 -0
- package/dist/i18n/locales/zh.d.ts +2 -0
- package/dist/i18n/locales/zh.js +2 -0
- package/dist/index.js +2 -2
- package/dist/locales/ar.json +2 -0
- package/dist/locales/de.json +2 -0
- package/dist/locales/el.json +2 -0
- package/dist/locales/en.json +2 -0
- package/dist/locales/es.json +2 -0
- package/dist/locales/fr.json +2 -0
- package/dist/locales/hi.json +2 -0
- package/dist/locales/it.json +2 -0
- package/dist/locales/ja.json +2 -0
- package/dist/locales/nl.json +2 -0
- package/dist/locales/pl.json +2 -0
- package/dist/locales/pt.json +2 -0
- package/dist/locales/ro.json +2 -0
- package/dist/locales/ru.json +2 -0
- package/dist/locales/sq.json +2 -0
- package/dist/locales/sv.json +2 -0
- package/dist/locales/tr.json +2 -0
- package/dist/locales/zh.json +2 -0
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
- package/dist/_chunks/notes-panel-CTcOLLVo.js +0 -324
- package/dist/_chunks/sparkline-DLq7xwic.js +0 -394
|
@@ -0,0 +1,501 @@
|
|
|
1
|
+
import { jsx as d, jsxs as D } from "react/jsx-runtime";
|
|
2
|
+
import { forwardRef as oe, useId as de, useMemo as A, useRef as S, useState as Z, useEffect as P, useImperativeHandle as ce } from "react";
|
|
3
|
+
import { c as E } from "./index-D2ZczOXr.js";
|
|
4
|
+
import { useTranslation as le } from "react-i18next";
|
|
5
|
+
import ue from "react-apexcharts";
|
|
6
|
+
import U from "apexcharts";
|
|
7
|
+
import { g as J, u as pe } from "./apexcharts-theme-B_AxGC_h.js";
|
|
8
|
+
import { m as me } from "./annotation-marker-CsUJGZjQ.js";
|
|
9
|
+
import { u as he } from "./registry-DvAUVLHh.js";
|
|
10
|
+
function fe(n) {
|
|
11
|
+
if (n.length < 2)
|
|
12
|
+
return { slope: 0, direction: "steady" };
|
|
13
|
+
const r = n.length, c = (r - 1) / 2, s = n.reduce((a, i) => a + i, 0) / r;
|
|
14
|
+
let o = 0, h = 0;
|
|
15
|
+
for (let a = 0; a < r; a++) {
|
|
16
|
+
const i = a - c;
|
|
17
|
+
o += i * (n[a] - s), h += i * i;
|
|
18
|
+
}
|
|
19
|
+
const p = h === 0 ? 0 : o / h, y = 0.01 * (Math.max(...n) - Math.min(...n) || 1), m = Math.abs(p) < y ? "steady" : p > 0 ? "increasing" : "decreasing";
|
|
20
|
+
return { slope: p, direction: m };
|
|
21
|
+
}
|
|
22
|
+
const ge = {
|
|
23
|
+
id: "sparkline",
|
|
24
|
+
capabilities: [],
|
|
25
|
+
state: {},
|
|
26
|
+
actions: {
|
|
27
|
+
update_series: {
|
|
28
|
+
// Replacing the rendered series mutates what the chart displays — write,
|
|
29
|
+
// not read.
|
|
30
|
+
safety: "write",
|
|
31
|
+
argsType: "{ data: number[] }",
|
|
32
|
+
argsSchema: {
|
|
33
|
+
type: "object",
|
|
34
|
+
properties: {
|
|
35
|
+
data: {
|
|
36
|
+
type: "array",
|
|
37
|
+
items: { type: "number" },
|
|
38
|
+
description: "The new data points to render."
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
required: ["data"]
|
|
42
|
+
},
|
|
43
|
+
idempotent: !0,
|
|
44
|
+
descriptionKey: "ui.agent.sparkline.actions.updateSeries",
|
|
45
|
+
description: "Replace the sparkline data without remounting.",
|
|
46
|
+
invoke: (n, r) => {
|
|
47
|
+
n.updateSeries(r.data);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
export_png: {
|
|
51
|
+
// Pure getter — returns an image of the current chart, no state change.
|
|
52
|
+
safety: "read",
|
|
53
|
+
returns: "string",
|
|
54
|
+
returnsSchema: {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "A PNG image of the sparkline encoded as a data URI."
|
|
57
|
+
},
|
|
58
|
+
descriptionKey: "ui.agent.sparkline.actions.exportPng",
|
|
59
|
+
description: "Return a PNG data URI of the sparkline.",
|
|
60
|
+
invoke: (n) => n.dataURI()
|
|
61
|
+
},
|
|
62
|
+
select_annotation: {
|
|
63
|
+
// Routes the host somewhere — the same thing a pointer press on the
|
|
64
|
+
// annotation's band does. Nothing in the chart changes, but the host's
|
|
65
|
+
// surface does, so it is not a read.
|
|
66
|
+
safety: "write",
|
|
67
|
+
argsType: "{ annotationId: string }",
|
|
68
|
+
argsSchema: {
|
|
69
|
+
type: "object",
|
|
70
|
+
properties: {
|
|
71
|
+
annotationId: {
|
|
72
|
+
type: "string",
|
|
73
|
+
description: "The annotation's id, as carried by data-annotation-hit-id on the pressable band. The decorative drawn marker carries the same value as data-annotation-id, but is not selectable."
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
required: ["annotationId"]
|
|
77
|
+
},
|
|
78
|
+
idempotent: !0,
|
|
79
|
+
descriptionKey: "ui.agent.sparkline.actions.selectAnnotation",
|
|
80
|
+
description: "Select a drawn annotation, as pressing its band would. No-op unless the host wired onAnnotationSelect and the id names an annotation that is currently drawn.",
|
|
81
|
+
invoke: (n, r) => {
|
|
82
|
+
n.selectAnnotation(r.annotationId);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
domHooks: {
|
|
87
|
+
root: { attr: "data-component", value: "sparkline" },
|
|
88
|
+
instanceId: {
|
|
89
|
+
attr: "data-component-id",
|
|
90
|
+
sourceProp: "id",
|
|
91
|
+
description: "Sourced from the id prop."
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}, Q = E("ds:relative ds:inline-block ds:w-full", {
|
|
95
|
+
variants: {
|
|
96
|
+
size: {
|
|
97
|
+
xs: "ds:h-6",
|
|
98
|
+
sm: "ds:h-8",
|
|
99
|
+
md: "ds:h-10",
|
|
100
|
+
// Applied when an explicit `height` prop is given: the wrapper
|
|
101
|
+
// grows with the svg instead of clipping at the size's fixed height.
|
|
102
|
+
auto: ""
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
defaultVariants: { size: "md" }
|
|
106
|
+
}), X = E("", {
|
|
107
|
+
variants: {
|
|
108
|
+
tone: {
|
|
109
|
+
neutral: "ds:[--annotation-color:var(--muted-foreground)]",
|
|
110
|
+
info: "ds:[--annotation-color:var(--info)]",
|
|
111
|
+
success: "ds:[--annotation-color:var(--success)]",
|
|
112
|
+
/* `--warning-readable`, not `--warning`: a 1.5px dashed line is a
|
|
113
|
+
* non-text graphic (WCAG 1.4.11, 3:1), and yellow-500 is ~1.6:1 on a
|
|
114
|
+
* light card. The token aliases back to `--warning` in dark. */
|
|
115
|
+
warning: "ds:[--annotation-color:var(--warning-readable)]",
|
|
116
|
+
error: "ds:[--annotation-color:var(--destructive)]",
|
|
117
|
+
accent: "ds:[--annotation-color:var(--accent)]"
|
|
118
|
+
}
|
|
119
|
+
},
|
|
120
|
+
defaultVariants: { tone: "neutral" }
|
|
121
|
+
}), ve = E(
|
|
122
|
+
"ds:pointer-events-none ds:absolute ds:inset-x-[2px]",
|
|
123
|
+
{
|
|
124
|
+
variants: {
|
|
125
|
+
size: {
|
|
126
|
+
xs: "ds:inset-y-[-10px]",
|
|
127
|
+
sm: "ds:inset-y-[-6px]",
|
|
128
|
+
md: "ds:inset-y-[-2px]",
|
|
129
|
+
auto: "ds:inset-y-0"
|
|
130
|
+
}
|
|
131
|
+
},
|
|
132
|
+
defaultVariants: { size: "md" }
|
|
133
|
+
}
|
|
134
|
+
), ye = {
|
|
135
|
+
increasing: "↑",
|
|
136
|
+
decreasing: "↓",
|
|
137
|
+
steady: "→"
|
|
138
|
+
}, be = {
|
|
139
|
+
xs: 24,
|
|
140
|
+
sm: 32,
|
|
141
|
+
md: 40
|
|
142
|
+
}, k = 2, Y = 2.5, ke = 44;
|
|
143
|
+
function we(n, r) {
|
|
144
|
+
const c = n.map((s) => ({
|
|
145
|
+
annotation: s,
|
|
146
|
+
centre: ee(s.position) * r
|
|
147
|
+
})).sort((s, o) => s.centre - o.centre);
|
|
148
|
+
return c.map((s, o) => {
|
|
149
|
+
const h = c[o - 1], p = c[o + 1], w = h ? (h.centre + s.centre) / 2 : 0, y = p ? (s.centre + p.centre) / 2 : r, m = Math.max(0, w), a = Math.min(r, y), i = Math.min(ke, Math.max(0, a - m)), x = Math.min(
|
|
150
|
+
Math.max(s.centre - i / 2, m),
|
|
151
|
+
a - i
|
|
152
|
+
);
|
|
153
|
+
return { annotation: s.annotation, x, width: i };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
function ee(n) {
|
|
157
|
+
return Number.isFinite(n) ? Math.min(1, Math.max(0, n)) : 0;
|
|
158
|
+
}
|
|
159
|
+
function xe(n) {
|
|
160
|
+
return n.filter((r) => r != null);
|
|
161
|
+
}
|
|
162
|
+
function Ie() {
|
|
163
|
+
return typeof window < "u" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
164
|
+
}
|
|
165
|
+
const Ne = oe(
|
|
166
|
+
({
|
|
167
|
+
id: n,
|
|
168
|
+
data: r,
|
|
169
|
+
variant: c = "line",
|
|
170
|
+
size: s = "md",
|
|
171
|
+
label: o,
|
|
172
|
+
color: h,
|
|
173
|
+
showEndpoint: p = !1,
|
|
174
|
+
showTooltip: w = !1,
|
|
175
|
+
width: y,
|
|
176
|
+
height: m,
|
|
177
|
+
annotations: a,
|
|
178
|
+
onAnnotationSelect: i,
|
|
179
|
+
className: x,
|
|
180
|
+
...V
|
|
181
|
+
}, te) => {
|
|
182
|
+
var q;
|
|
183
|
+
const { t: f, i18n: $ } = le(), j = de(), b = A(
|
|
184
|
+
() => `sparkline-${j.replace(/[^a-zA-Z0-9-_]/g, "")}`,
|
|
185
|
+
[j]
|
|
186
|
+
), I = S(null), [O, ne] = Z(0), l = A(() => xe(r), [r]), { direction: C } = fe(l), B = A(() => {
|
|
187
|
+
const e = a && a.length > 0 ? f("sparkline.annotations", {
|
|
188
|
+
list: a.map((v) => v.label).join(", ")
|
|
189
|
+
}) : "", t = (v) => e ? `${v}. ${e}` : v;
|
|
190
|
+
if (l.length === 0)
|
|
191
|
+
return t(f("sparkline.noData", "No data"));
|
|
192
|
+
const u = (v) => new Intl.NumberFormat($.language).format(v), g = f(`sparkline.direction.${C}`), R = {
|
|
193
|
+
min: u(Math.min(...l)),
|
|
194
|
+
max: u(Math.max(...l)),
|
|
195
|
+
current: u(l[l.length - 1]),
|
|
196
|
+
direction: g
|
|
197
|
+
};
|
|
198
|
+
return t(o ? f("sparkline.summary", { label: o, ...R }) : f("sparkline.summaryNoLabel", R));
|
|
199
|
+
}, [l, a, o, C, $.language, f]), [N, ae] = Z(
|
|
200
|
+
() => {
|
|
201
|
+
try {
|
|
202
|
+
return J();
|
|
203
|
+
} catch {
|
|
204
|
+
return {};
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
);
|
|
208
|
+
P(() => {
|
|
209
|
+
let e;
|
|
210
|
+
const t = new MutationObserver(() => {
|
|
211
|
+
clearTimeout(e), e = setTimeout(() => {
|
|
212
|
+
try {
|
|
213
|
+
ae(J());
|
|
214
|
+
} catch {
|
|
215
|
+
}
|
|
216
|
+
}, 50);
|
|
217
|
+
});
|
|
218
|
+
return t.observe(document.documentElement, {
|
|
219
|
+
attributes: !0,
|
|
220
|
+
attributeFilter: ["class"]
|
|
221
|
+
}), () => {
|
|
222
|
+
clearTimeout(e), t.disconnect();
|
|
223
|
+
};
|
|
224
|
+
}, []), P(() => {
|
|
225
|
+
const e = I.current;
|
|
226
|
+
if (!e) return;
|
|
227
|
+
const t = new ResizeObserver((u) => {
|
|
228
|
+
const g = u[0];
|
|
229
|
+
g && ne(Math.floor(g.contentRect.width));
|
|
230
|
+
});
|
|
231
|
+
return t.observe(e), () => t.disconnect();
|
|
232
|
+
}, []), pe(I);
|
|
233
|
+
const M = S(i);
|
|
234
|
+
P(() => {
|
|
235
|
+
M.current = i;
|
|
236
|
+
}, [i]);
|
|
237
|
+
const F = S(a);
|
|
238
|
+
F.current = a;
|
|
239
|
+
const z = A(
|
|
240
|
+
() => ({
|
|
241
|
+
updateSeries(e) {
|
|
242
|
+
var t;
|
|
243
|
+
(t = U.getChartByID(b)) == null || t.updateSeries([{ data: e }]);
|
|
244
|
+
},
|
|
245
|
+
updateOptions(e) {
|
|
246
|
+
var t;
|
|
247
|
+
(t = U.getChartByID(b)) == null || t.updateOptions(e);
|
|
248
|
+
},
|
|
249
|
+
async dataURI() {
|
|
250
|
+
const e = U.getChartByID(b);
|
|
251
|
+
return e ? (await e.dataURI()).imgURI : "";
|
|
252
|
+
},
|
|
253
|
+
selectAnnotation(e) {
|
|
254
|
+
var u, g;
|
|
255
|
+
(u = F.current) != null && u.some((R) => R.id === e) && ((g = M.current) == null || g.call(M, e));
|
|
256
|
+
}
|
|
257
|
+
}),
|
|
258
|
+
[b]
|
|
259
|
+
);
|
|
260
|
+
ce(te, () => z, [z]), he(ge, z, n);
|
|
261
|
+
const _ = h ?? ((q = N.colors) == null ? void 0 : q[0]) ?? "currentColor";
|
|
262
|
+
if (l.length === 0)
|
|
263
|
+
return /* @__PURE__ */ d(
|
|
264
|
+
"div",
|
|
265
|
+
{
|
|
266
|
+
ref: I,
|
|
267
|
+
role: "img",
|
|
268
|
+
"aria-label": B,
|
|
269
|
+
dir: "ltr",
|
|
270
|
+
className: Q({
|
|
271
|
+
size: m !== void 0 ? "auto" : s,
|
|
272
|
+
className: x
|
|
273
|
+
}),
|
|
274
|
+
"data-component": "sparkline",
|
|
275
|
+
"data-component-id": n,
|
|
276
|
+
...V
|
|
277
|
+
}
|
|
278
|
+
);
|
|
279
|
+
const G = Ie(), H = r.length > l.length, L = H ? r.flatMap((e, t) => e == null ? [] : [{ x: t, y: e }]) : l, re = {
|
|
280
|
+
...N,
|
|
281
|
+
chart: {
|
|
282
|
+
...N.chart,
|
|
283
|
+
id: b,
|
|
284
|
+
type: c,
|
|
285
|
+
sparkline: { enabled: !0 },
|
|
286
|
+
toolbar: { show: !1 },
|
|
287
|
+
animations: {
|
|
288
|
+
enabled: !G,
|
|
289
|
+
// A gapped series is re-rendered as {x, y} pairs, and Apex's
|
|
290
|
+
// update tween interpolates between the old and new paths point by
|
|
291
|
+
// point. Across a width change the two have different lengths and
|
|
292
|
+
// the tween emits `d="… NaN …"` for a few frames. The finished
|
|
293
|
+
// render is correct either way; switching the tween off keeps the
|
|
294
|
+
// console clean.
|
|
295
|
+
dynamicAnimation: { enabled: !G && !H }
|
|
296
|
+
},
|
|
297
|
+
zoom: { enabled: !1 },
|
|
298
|
+
parentHeightOffset: 0
|
|
299
|
+
},
|
|
300
|
+
colors: [_],
|
|
301
|
+
stroke: {
|
|
302
|
+
curve: "smooth",
|
|
303
|
+
width: c === "bar" ? 0 : 2
|
|
304
|
+
},
|
|
305
|
+
fill: {
|
|
306
|
+
opacity: c === "area" ? 0.15 : 1
|
|
307
|
+
},
|
|
308
|
+
xaxis: {
|
|
309
|
+
crosshairs: { show: !1 },
|
|
310
|
+
// Pin the extent to the slot count so a gap at either end still holds
|
|
311
|
+
// its place — otherwise the plot would rescale to the measurements
|
|
312
|
+
// and the annotation fractions would no longer mean the same thing.
|
|
313
|
+
...H ? { type: "numeric", min: 0, max: r.length - 1 } : {}
|
|
314
|
+
},
|
|
315
|
+
tooltip: { enabled: w },
|
|
316
|
+
markers: p ? {
|
|
317
|
+
size: [0],
|
|
318
|
+
discrete: [
|
|
319
|
+
{
|
|
320
|
+
// An index into the SERIES, whose holes have already been
|
|
321
|
+
// removed — so this is the last MEASURED point, never a slot
|
|
322
|
+
// the parameter was not measured at.
|
|
323
|
+
seriesIndex: 0,
|
|
324
|
+
dataPointIndex: L.length - 1,
|
|
325
|
+
fillColor: _,
|
|
326
|
+
strokeColor: _,
|
|
327
|
+
size: 4
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
} : { size: 0 },
|
|
331
|
+
grid: {
|
|
332
|
+
...N.grid,
|
|
333
|
+
show: !1,
|
|
334
|
+
// ApexCharts grid.padding uses physical keys (not CSS logical properties).
|
|
335
|
+
// The chart wrapper enforces dir="ltr" so these always resolve correctly.
|
|
336
|
+
padding: {
|
|
337
|
+
top: k,
|
|
338
|
+
right: k,
|
|
339
|
+
bottom: k,
|
|
340
|
+
left: k
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}, se = y ?? (O > 0 ? O : "100%"), ie = m ?? be[s ?? "md"], T = a != null && a.length ? a : void 0, W = O - k * 2, K = i && T && W > 0 ? we(T, W) : void 0;
|
|
344
|
+
return /* @__PURE__ */ D(
|
|
345
|
+
"div",
|
|
346
|
+
{
|
|
347
|
+
ref: I,
|
|
348
|
+
role: "img",
|
|
349
|
+
"aria-label": B,
|
|
350
|
+
dir: "ltr",
|
|
351
|
+
className: Q({
|
|
352
|
+
size: m !== void 0 ? "auto" : s,
|
|
353
|
+
className: x
|
|
354
|
+
}),
|
|
355
|
+
"data-component": "sparkline",
|
|
356
|
+
"data-component-id": n,
|
|
357
|
+
...V,
|
|
358
|
+
children: [
|
|
359
|
+
/* @__PURE__ */ d(
|
|
360
|
+
ue,
|
|
361
|
+
{
|
|
362
|
+
type: c,
|
|
363
|
+
series: [{ data: L }],
|
|
364
|
+
options: re,
|
|
365
|
+
width: se,
|
|
366
|
+
height: ie,
|
|
367
|
+
"aria-hidden": "true"
|
|
368
|
+
}
|
|
369
|
+
),
|
|
370
|
+
T && /* Drawn over the plot rather than through ApexCharts' own xaxis
|
|
371
|
+
annotations: a fraction of the measured extent is the one
|
|
372
|
+
positioning rule that survives series of different lengths, which
|
|
373
|
+
is what makes a column of sparklines share an x. */
|
|
374
|
+
/* The inset lives on a div: an <svg> is a replaced element, so
|
|
375
|
+
left+right do not size it and it would fall back to its intrinsic
|
|
376
|
+
300px. The div is the plot box; the svg fills it. The 2px MUST
|
|
377
|
+
equal PLOT_EDGE_PADDING — Tailwind needs a static literal, so the
|
|
378
|
+
two cannot share one source; change them together or the first and
|
|
379
|
+
last annotation drift off the first and last data point. */
|
|
380
|
+
/* @__PURE__ */ d("div", { className: "ds:pointer-events-none ds:absolute ds:inset-y-0 ds:inset-x-[2px]", children: /* @__PURE__ */ d(
|
|
381
|
+
"svg",
|
|
382
|
+
{
|
|
383
|
+
"aria-hidden": "true",
|
|
384
|
+
focusable: "false",
|
|
385
|
+
"data-testid": "sparkline-annotations",
|
|
386
|
+
className: "ds:size-full",
|
|
387
|
+
children: T.map((e) => {
|
|
388
|
+
const t = ee(e.position);
|
|
389
|
+
return (
|
|
390
|
+
/* A nested viewport placed at a percentage of the plot: the
|
|
391
|
+
one positioning rule that needs no measurement, so a column
|
|
392
|
+
of sparklines shares an x whatever their widths. */
|
|
393
|
+
/* @__PURE__ */ D(
|
|
394
|
+
"svg",
|
|
395
|
+
{
|
|
396
|
+
x: `${t * 100}%`,
|
|
397
|
+
y: "0",
|
|
398
|
+
width: "1",
|
|
399
|
+
height: "100%",
|
|
400
|
+
overflow: "visible",
|
|
401
|
+
"data-annotation-id": e.id,
|
|
402
|
+
"data-annotation-position": t,
|
|
403
|
+
className: X({ tone: e.tone }),
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ d(
|
|
406
|
+
"line",
|
|
407
|
+
{
|
|
408
|
+
x1: 0,
|
|
409
|
+
x2: 0,
|
|
410
|
+
y1: 0,
|
|
411
|
+
y2: "100%",
|
|
412
|
+
className: "ds:[stroke:var(--annotation-color)] ds:[stroke-dasharray:2_3] ds:[stroke-width:1]"
|
|
413
|
+
}
|
|
414
|
+
),
|
|
415
|
+
/* @__PURE__ */ d(
|
|
416
|
+
"path",
|
|
417
|
+
{
|
|
418
|
+
d: me(
|
|
419
|
+
e.shape ?? "diamond",
|
|
420
|
+
0,
|
|
421
|
+
Y,
|
|
422
|
+
Y
|
|
423
|
+
),
|
|
424
|
+
className: "ds:[fill:var(--annotation-color)]"
|
|
425
|
+
}
|
|
426
|
+
)
|
|
427
|
+
]
|
|
428
|
+
},
|
|
429
|
+
e.id
|
|
430
|
+
)
|
|
431
|
+
);
|
|
432
|
+
})
|
|
433
|
+
}
|
|
434
|
+
) }),
|
|
435
|
+
K && i && /* Sized in px, not percentages: 44px is a measurement, not a
|
|
436
|
+
fraction of a box the reader can resize. `pointer-events-none`
|
|
437
|
+
holds all the way down to the bands, so the only live pixels are
|
|
438
|
+
the 44px each annotation owns. */
|
|
439
|
+
/* @__PURE__ */ d(
|
|
440
|
+
"div",
|
|
441
|
+
{
|
|
442
|
+
className: ve({
|
|
443
|
+
size: m !== void 0 ? "auto" : s
|
|
444
|
+
}),
|
|
445
|
+
children: /* @__PURE__ */ d(
|
|
446
|
+
"svg",
|
|
447
|
+
{
|
|
448
|
+
"aria-hidden": "true",
|
|
449
|
+
focusable: "false",
|
|
450
|
+
"data-testid": "sparkline-annotation-hits",
|
|
451
|
+
className: "ds:size-full",
|
|
452
|
+
children: K.map(({ annotation: e, x: t, width: u }) => /* @__PURE__ */ D(
|
|
453
|
+
"g",
|
|
454
|
+
{
|
|
455
|
+
"data-annotation-hit-id": e.id,
|
|
456
|
+
onClick: () => i(e.id),
|
|
457
|
+
className: `ds:group ds:pointer-events-auto ds:cursor-pointer ${X(
|
|
458
|
+
{ tone: e.tone }
|
|
459
|
+
)}`,
|
|
460
|
+
children: [
|
|
461
|
+
/* @__PURE__ */ d("title", { children: f("sparkline.annotationAction", {
|
|
462
|
+
label: e.label
|
|
463
|
+
}) }),
|
|
464
|
+
/* @__PURE__ */ d(
|
|
465
|
+
"rect",
|
|
466
|
+
{
|
|
467
|
+
x: t,
|
|
468
|
+
y: 0,
|
|
469
|
+
width: u,
|
|
470
|
+
height: "100%",
|
|
471
|
+
className: "ds:[fill:var(--annotation-color)] ds:opacity-0 ds:transition-opacity ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:group-hover:opacity-20"
|
|
472
|
+
}
|
|
473
|
+
)
|
|
474
|
+
]
|
|
475
|
+
},
|
|
476
|
+
e.id
|
|
477
|
+
))
|
|
478
|
+
}
|
|
479
|
+
)
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
p && /* @__PURE__ */ d(
|
|
483
|
+
"span",
|
|
484
|
+
{
|
|
485
|
+
"aria-hidden": "true",
|
|
486
|
+
className: "ds:pointer-events-none ds:absolute ds:end-0 ds:top-0 ds:text-[length:var(--font-size-xs)] ds:leading-none",
|
|
487
|
+
children: ye[C]
|
|
488
|
+
}
|
|
489
|
+
)
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
Ne.displayName = "Sparkline";
|
|
496
|
+
export {
|
|
497
|
+
Ne as S,
|
|
498
|
+
ge as s,
|
|
499
|
+
fe as u
|
|
500
|
+
};
|
|
501
|
+
//# sourceMappingURL=sparkline-DJtZBe7O.js.map
|
package/dist/agent-catalog.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"packageVersion": "1.
|
|
3
|
+
"packageVersion": "1.2.0",
|
|
4
4
|
"components": [
|
|
5
5
|
{
|
|
6
6
|
"kind": "component",
|
|
@@ -6720,6 +6720,12 @@
|
|
|
6720
6720
|
"type": "boolean",
|
|
6721
6721
|
"description": "Whether the current user may write clinical notes (the practice_add_clinical_note permission gate).",
|
|
6722
6722
|
"descriptionKey": "ui.agent.notesPanel.state.canAddClinical"
|
|
6723
|
+
},
|
|
6724
|
+
{
|
|
6725
|
+
"name": "currentNoteId",
|
|
6726
|
+
"type": "string | null",
|
|
6727
|
+
"description": "Id of the note the host has addressed — the one marked, scrolled to and focused. Null when none is. An id only, never note content.",
|
|
6728
|
+
"descriptionKey": "ui.agent.notesPanel.state.currentNoteId"
|
|
6723
6729
|
}
|
|
6724
6730
|
],
|
|
6725
6731
|
"actions": [
|
|
@@ -11099,6 +11105,26 @@
|
|
|
11099
11105
|
},
|
|
11100
11106
|
"description": "Return a PNG data URI of the sparkline.",
|
|
11101
11107
|
"descriptionKey": "ui.agent.sparkline.actions.exportPng"
|
|
11108
|
+
},
|
|
11109
|
+
{
|
|
11110
|
+
"name": "select_annotation",
|
|
11111
|
+
"safety": "write",
|
|
11112
|
+
"argsType": "{ annotationId: string }",
|
|
11113
|
+
"argsSchema": {
|
|
11114
|
+
"type": "object",
|
|
11115
|
+
"properties": {
|
|
11116
|
+
"annotationId": {
|
|
11117
|
+
"type": "string",
|
|
11118
|
+
"description": "The annotation's id, as carried by data-annotation-hit-id on the pressable band. The decorative drawn marker carries the same value as data-annotation-id, but is not selectable."
|
|
11119
|
+
}
|
|
11120
|
+
},
|
|
11121
|
+
"required": [
|
|
11122
|
+
"annotationId"
|
|
11123
|
+
]
|
|
11124
|
+
},
|
|
11125
|
+
"idempotent": true,
|
|
11126
|
+
"description": "Select a drawn annotation, as pressing its band would. No-op unless the host wired onAnnotationSelect and the id names an annotation that is currently drawn.",
|
|
11127
|
+
"descriptionKey": "ui.agent.sparkline.actions.selectAnnotation"
|
|
11102
11128
|
}
|
|
11103
11129
|
],
|
|
11104
11130
|
"domHooks": {
|
package/dist/agent-i18n/en.json
CHANGED
|
@@ -688,7 +688,8 @@
|
|
|
688
688
|
"notesPanel": {
|
|
689
689
|
"state": {
|
|
690
690
|
"notes": "Timeline note ids + pinned / flagged / clinical flags. Never the note body or author (both PHI).",
|
|
691
|
-
"canAddClinical": "Whether the current user may write clinical notes (the practice_add_clinical_note permission gate)."
|
|
691
|
+
"canAddClinical": "Whether the current user may write clinical notes (the practice_add_clinical_note permission gate).",
|
|
692
|
+
"currentNoteId": "Id of the note the host has addressed — the one marked, scrolled to and focused. Null when none is. An id only, never note content."
|
|
692
693
|
},
|
|
693
694
|
"actions": {
|
|
694
695
|
"addNote": "Compose and commit a new note. A clinical note requires the clinical-note permission (read canAddClinical first).",
|
|
@@ -1137,7 +1138,8 @@
|
|
|
1137
1138
|
"sparkline": {
|
|
1138
1139
|
"actions": {
|
|
1139
1140
|
"updateSeries": "Replace the sparkline data without remounting.",
|
|
1140
|
-
"exportPng": "Return a PNG data URI of the sparkline."
|
|
1141
|
+
"exportPng": "Return a PNG data URI of the sparkline.",
|
|
1142
|
+
"selectAnnotation": "Select a drawn annotation, as pressing its band would. No-op unless the host wired onAnnotationSelect and the id names an annotation that is currently drawn."
|
|
1141
1143
|
}
|
|
1142
1144
|
},
|
|
1143
1145
|
"stepperAccordion": {
|
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { type HTMLAttributes, type ReactNode } from 'react';
|
|
2
2
|
import type { ClinicalNoteCardProps } from '../clinical-note-card';
|
|
3
3
|
import type { RichTextEditorProps, RichTextEditorToolbar, RedactorFactory } from '../rich-text-editor';
|
|
4
|
-
/**
|
|
5
|
-
|
|
4
|
+
/**
|
|
5
|
+
* One note in the panel — the data subset of `ClinicalNoteCard`.
|
|
6
|
+
*
|
|
7
|
+
* `aria-label` names the card for assistive tech. Set it whenever a row is not
|
|
8
|
+
* a clinical note: the card's fallback name is "Clinical note", so an entry
|
|
9
|
+
* that is something else (a dated event, an import) is announced as one.
|
|
10
|
+
*/
|
|
11
|
+
export type NotesPanelNote = Pick<ClinicalNoteCardProps, 'id' | 'dateIso' | 'createdAtIso' | 'author' | 'clinical' | 'attachedTo' | 'content' | 'contentFormat' | 'pinned' | 'flagged' | 'aria-label'>;
|
|
6
12
|
/**
|
|
7
13
|
* Curated agent handle for NotesPanel. Reads the note timeline's STRUCTURE
|
|
8
14
|
* (ids + pinned / flagged / clinical flags — never the note body or author,
|
|
@@ -21,6 +27,8 @@ export interface NotesPanelHandle {
|
|
|
21
27
|
canAddNote: () => boolean;
|
|
22
28
|
/** Whether clinical notes may be written (the permission gate). */
|
|
23
29
|
canAddClinical: () => boolean;
|
|
30
|
+
/** Id of the note the host has addressed, or null when none is. */
|
|
31
|
+
getCurrentNoteId: () => string | null;
|
|
24
32
|
/** Commit a new note with explicit content (mirrors the composer's submit). */
|
|
25
33
|
addNote: (submission: NotesPanelSubmission) => void;
|
|
26
34
|
/** Toggle a note's pinned state (mirrors onTogglePin). */
|
|
@@ -45,6 +53,41 @@ export interface NotesPanelProps extends Omit<HTMLAttributes<HTMLElement>, 'titl
|
|
|
45
53
|
notes: NotesPanelNote[];
|
|
46
54
|
/** Commit a new note. Omit to hide the composer (read-only timeline). */
|
|
47
55
|
onAddNote?: (submission: NotesPanelSubmission) => void;
|
|
56
|
+
/**
|
|
57
|
+
* The note the reader ASKED for, addressed by id from somewhere else in the
|
|
58
|
+
* record — a marker in a chart, a row in a grid, an agent. The panel marks
|
|
59
|
+
* it, scrolls it to the middle of its own scroll region and moves focus to
|
|
60
|
+
* it, and renders it unclamped so the thing that was asked for is readable
|
|
61
|
+
* in full without a second click.
|
|
62
|
+
*
|
|
63
|
+
* Opening a panel is not the same as answering a question: a rail's
|
|
64
|
+
* `setActiveTool` moves no focus and announces nothing, so a control whose
|
|
65
|
+
* name promises "in the notes panel" produces no perceivable change for a
|
|
66
|
+
* keyboard or screen-reader reader unless the panel lands them on the note.
|
|
67
|
+
* That is what this prop is for; without it, a host has to reach into the
|
|
68
|
+
* panel's DOM to do the same job.
|
|
69
|
+
*
|
|
70
|
+
* Marked on three channels, never colour alone (WCAG 1.4.1): a solid
|
|
71
|
+
* inline-start bar the other notes do not have, a tinted gutter, and
|
|
72
|
+
* `aria-current` plus a visually-hidden sentence naming the mark.
|
|
73
|
+
*
|
|
74
|
+
* Ids that match no note are ignored. To address the SAME note twice — the
|
|
75
|
+
* reader pressing the same marker again after scrolling away — bump
|
|
76
|
+
* `currentNoteKey` alongside it; this prop alone is a value, not a request.
|
|
77
|
+
*/
|
|
78
|
+
currentNoteId?: string;
|
|
79
|
+
/**
|
|
80
|
+
* Bump on every address to re-scroll and re-focus the note in `currentNoteId`
|
|
81
|
+
* even when the id has not changed.
|
|
82
|
+
*
|
|
83
|
+
* Addressing is a request, not a value: a reader who presses the same marker
|
|
84
|
+
* a second time (having scrolled away, or having moved focus off the note) is
|
|
85
|
+
* asking to be taken back, and a control whose name promises the notes panel
|
|
86
|
+
* must do something perceivable every time it is pressed. Without this the
|
|
87
|
+
* second press is inert — the panel is already showing that note, so nothing
|
|
88
|
+
* re-runs. Hosts increment a counter in the same handler that opens the tool.
|
|
89
|
+
*/
|
|
90
|
+
currentNoteKey?: string | number;
|
|
48
91
|
/**
|
|
49
92
|
* `'rich'` (default) mounts the kit `RichTextEditor` (Redactor; degrades to a
|
|
50
93
|
* textarea where Redactor is absent). `'plain'` keeps a simple `TextArea` for
|
|
@@ -9,6 +9,10 @@ export interface SparklineHandle {
|
|
|
9
9
|
updateSeries: (data: (number | null)[]) => void;
|
|
10
10
|
updateOptions: (opts: ApexCharts.ApexOptions) => void;
|
|
11
11
|
dataURI: () => Promise<string>;
|
|
12
|
+
/** Fire the host's annotation handler for `id`, as a pointer press on that
|
|
13
|
+
* annotation's band would. No-op when the sparkline is not selectable, or
|
|
14
|
+
* when `id` names no currently drawn annotation. */
|
|
15
|
+
selectAnnotation: (id: string) => void;
|
|
12
16
|
}
|
|
13
17
|
/** Semantic tint for an annotation. Decorative reinforcement of `shape` —
|
|
14
18
|
* never the only channel carrying which event this is. */
|
|
@@ -66,6 +70,26 @@ export interface SparklineProps extends Omit<HTMLAttributes<HTMLDivElement>, 'ro
|
|
|
66
70
|
/** Vertical reference lines dropped across the plot. Omitted = none, so
|
|
67
71
|
* every existing consumer is unaffected. */
|
|
68
72
|
annotations?: readonly SparklineAnnotation[];
|
|
73
|
+
/**
|
|
74
|
+
* Make the drawn annotations POINTER-selectable — a press anywhere in an
|
|
75
|
+
* annotation's 44px band calls this with its `id`. Omitted (the default, and
|
|
76
|
+
* what every consumer before 1.1.0 gets) leaves them decorative, which is
|
|
77
|
+
* what a dashboard sparkline wants: a trend thumbnail should not be a click
|
|
78
|
+
* target.
|
|
79
|
+
*
|
|
80
|
+
* NOT a keyboard route, and deliberately so. The sparkline is `role="img"`,
|
|
81
|
+
* whose descendants are not exposed to assistive technology at all, so a
|
|
82
|
+
* focusable control drawn inside it would be a tab stop with no accessible
|
|
83
|
+
* name. The host MUST therefore already offer a keyboard control that does
|
|
84
|
+
* the same thing for the same annotation (WCAG 2.1.1) — this is a pointer
|
|
85
|
+
* shortcut to that control, never the only way in.
|
|
86
|
+
*
|
|
87
|
+
* The 44px band is delivered by the `size` variants only. Pass an explicit
|
|
88
|
+
* `height` and the pointer layer falls back to the drawn height, so
|
|
89
|
+
* `height={20}` yields a 20px-tall target — below even WCAG 2.5.8. Under
|
|
90
|
+
* `.theme-accessible`, where `--min-target-size` is 48px, the band stays 44.
|
|
91
|
+
*/
|
|
92
|
+
onAnnotationSelect?: (annotationId: string) => void;
|
|
69
93
|
}
|
|
70
94
|
export declare const Sparkline: import("react").ForwardRefExoticComponent<SparklineProps & import("react").RefAttributes<SparklineHandle>>;
|
|
71
95
|
export {};
|