@alfadocs/ui-kit 1.47.0 → 1.47.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.
@@ -0,0 +1,366 @@
1
+ import { jsx as A, jsxs as Y, Fragment as Ro } from "react/jsx-runtime";
2
+ import { useState as X, useCallback as b, useMemo as w, useRef as $, useContext as O, useId as vo, useEffect as To, createContext as bo, forwardRef as Co } from "react";
3
+ import { useTranslation as ho } from "react-i18next";
4
+ import { I as Z } from "./icon-button-CehAeZoP.js";
5
+ import { a as xo } from "./panel-header-D_mTdhUp.js";
6
+ import { T as yo } from "./tool-rail-CCFqDfAn.js";
7
+ import { u as W } from "./use-persistent-state-nZwZAnE9.js";
8
+ import { S as Ao } from "./star-Bf9L2Uot.js";
9
+ import { X as wo } from "./x-B5YnXwCz.js";
10
+ const So = {
11
+ id: "control-room-rail",
12
+ capabilities: ["open", "close", "select_single"],
13
+ state: {
14
+ activeToolId: {
15
+ type: "string | null",
16
+ descriptionKey: "ui.toolRail.agent.state.activeToolId",
17
+ description: "Id of the tool whose panel is currently open, or null when the rail is collapsed to its strip. No panel content is ever exposed.",
18
+ read: (t) => t.getActiveToolId()
19
+ }
20
+ },
21
+ actions: {
22
+ open: {
23
+ // Pure ephemeral panel state (open) — no data loss, no external effect.
24
+ safety: "read",
25
+ argsType: "{ id: string }",
26
+ argsSchema: {
27
+ type: "object",
28
+ properties: { id: { type: "string" } },
29
+ required: ["id"]
30
+ },
31
+ idempotent: !0,
32
+ descriptionKey: "ui.toolRail.agent.actions.open",
33
+ description: "Open the given tool's panel.",
34
+ examples: [{ args: { id: "inbox" }, note: "Open the inbox tool panel." }],
35
+ invoke: (t, s) => {
36
+ t.open(s.id);
37
+ }
38
+ },
39
+ close: {
40
+ safety: "read",
41
+ idempotent: !0,
42
+ descriptionKey: "ui.toolRail.agent.actions.close",
43
+ description: "Collapse the rail to its strip (no active tool).",
44
+ invoke: (t) => {
45
+ t.close();
46
+ }
47
+ },
48
+ select_tool: {
49
+ safety: "read",
50
+ argsType: "{ id: string | null }",
51
+ argsSchema: {
52
+ type: "object",
53
+ properties: { id: { type: ["string", "null"] } },
54
+ required: ["id"]
55
+ },
56
+ idempotent: !0,
57
+ descriptionKey: "ui.toolRail.agent.actions.selectTool",
58
+ description: "Set the active tool by id (opens its panel), or pass null to collapse.",
59
+ invoke: (t, s) => {
60
+ t.setActiveTool(s.id);
61
+ }
62
+ }
63
+ },
64
+ domHooks: {
65
+ root: {
66
+ attr: "data-component",
67
+ value: "control-room-rail",
68
+ description: "Marks the ControlRoomRail wrapper."
69
+ },
70
+ instanceId: {
71
+ attr: "data-component-id",
72
+ sourceProp: "id",
73
+ description: "Sourced from the id prop. Required to address a specific rail from the agent."
74
+ },
75
+ item: {
76
+ attr: "data-tool-id",
77
+ description: "Stable tool id emitted on each strip IconButton. The active icon also carries data-active set to its id."
78
+ }
79
+ }
80
+ }, H = bo(null);
81
+ function Xo({
82
+ globalTools: t = [],
83
+ children: s
84
+ }) {
85
+ const [l, n] = X(
86
+ () => /* @__PURE__ */ new Map()
87
+ ), f = b(
88
+ (i, a) => {
89
+ n((R) => {
90
+ const q = new Map(R);
91
+ return q.set(i, a), q;
92
+ });
93
+ },
94
+ []
95
+ ), x = b((i) => {
96
+ n((a) => {
97
+ if (!a.has(i)) return a;
98
+ const R = new Map(a);
99
+ return R.delete(i), R;
100
+ });
101
+ }, []), c = w(
102
+ () => Array.from(l.values()).flat(),
103
+ [l]
104
+ ), p = $(null), y = b((i) => {
105
+ p.current = i;
106
+ }, []), d = b((i) => {
107
+ var a;
108
+ (a = p.current) == null || a.setActiveTool(i);
109
+ }, []), m = b(() => {
110
+ var i;
111
+ (i = p.current) == null || i.setActiveTool(null);
112
+ }, []), g = w(
113
+ () => ({
114
+ globalTools: t,
115
+ contextualTools: c,
116
+ registerContextualTools: f,
117
+ unregisterContextualTools: x,
118
+ registerRail: y,
119
+ openTool: d,
120
+ closeTool: m
121
+ }),
122
+ [
123
+ t,
124
+ c,
125
+ f,
126
+ x,
127
+ y,
128
+ d,
129
+ m
130
+ ]
131
+ );
132
+ return /* @__PURE__ */ A(H.Provider, { value: g, children: s });
133
+ }
134
+ function $o(t) {
135
+ const s = O(H), l = s == null ? void 0 : s.registerContextualTools, n = s == null ? void 0 : s.unregisterContextualTools, f = vo();
136
+ To(() => {
137
+ if (!(!l || !n))
138
+ return l(f, t), () => n(f);
139
+ }, [l, n, f, t]);
140
+ }
141
+ function ko() {
142
+ const t = O(H);
143
+ return w(() => {
144
+ if (!t) return [];
145
+ const s = t.contextualTools.map((n) => ({
146
+ ...n,
147
+ scope: "contextual"
148
+ })), l = t.globalTools.map((n) => ({
149
+ ...n,
150
+ scope: "global"
151
+ }));
152
+ return [...s, ...l];
153
+ }, [t]);
154
+ }
155
+ function Do() {
156
+ const t = O(H), s = b(() => {
157
+ }, []);
158
+ return {
159
+ openTool: (t == null ? void 0 : t.openTool) ?? s,
160
+ closeTool: (t == null ? void 0 : t.closeTool) ?? s
161
+ };
162
+ }
163
+ function Mo() {
164
+ const t = O(H), s = b((l) => {
165
+ }, []);
166
+ return (t == null ? void 0 : t.registerRail) ?? s;
167
+ }
168
+ function Vo(t, s, l, n) {
169
+ const f = s.includes(t), x = l.includes(t);
170
+ if (!f && x) return { toolId: t, action: "pin" };
171
+ if (f && !x)
172
+ return n != null && n.includes(t) ? void 0 : { toolId: t, action: "unpin" };
173
+ const c = (m) => n != null && n.length ? [...n, ...m.filter((g) => !n.includes(g))] : m, p = c(s), y = c(l);
174
+ return p.length !== y.length || p.some((m, g) => y[g] !== m) ? { toolId: t, action: "reorder" } : void 0;
175
+ }
176
+ const Go = Co(function({
177
+ tools: s,
178
+ railLabel: l,
179
+ reorderable: n = !0,
180
+ favoriteIds: f,
181
+ defaultFavoriteIds: x,
182
+ pinnedFavoriteIds: c,
183
+ onFavoriteIdsChange: p,
184
+ persistFavoritesKey: y = "ui.controlRoom.favorites",
185
+ activeToolId: d,
186
+ defaultActiveToolId: m = null,
187
+ onActiveToolChange: g,
188
+ panelWidth: i,
189
+ onPanelWidthChange: a,
190
+ persistPanelWidthKey: R,
191
+ ...q
192
+ }, M) {
193
+ const { t: C } = ho(), [F, P] = X(
194
+ d ?? m ?? null
195
+ ), D = d !== void 0 ? d : F, I = b(
196
+ (o) => {
197
+ d === void 0 && P(o), g == null || g(o);
198
+ },
199
+ [d, g]
200
+ ), oo = ko(), S = s ?? oo, _ = f !== void 0, [to, eo] = W(
201
+ y,
202
+ () => x ?? S.filter((o) => o.scope === "global").map((o) => o.id),
203
+ { disabled: _ }
204
+ ), B = _ ? f : to, V = w(() => c != null && c.length ? [
205
+ ...c,
206
+ ...B.filter((o) => !c.includes(o))
207
+ ] : B, [c, B]), z = i !== void 0, [no, G] = W(R ?? "ui.controlRoom.panelWidth.unused", null, {
208
+ disabled: z || !R
209
+ }), so = z ? i : R ? no : void 0, ro = b(
210
+ (o) => {
211
+ !z && R && G(o), a == null || a(o);
212
+ },
213
+ [
214
+ z,
215
+ R,
216
+ G,
217
+ a
218
+ ]
219
+ ), v = w(() => {
220
+ const o = /* @__PURE__ */ new Map();
221
+ for (const r of S) o.set(r.id, r);
222
+ return o;
223
+ }, [S]), j = w(
224
+ () => new Set(V.filter((o) => v.has(o))),
225
+ [V, v]
226
+ ), J = (o, r) => {
227
+ const e = V.filter((T) => v.has(T)), u = r(e);
228
+ _ || eo((T) => r(T.filter((k) => v.has(k)))), p == null || p(
229
+ u,
230
+ Vo(o, e, u, c)
231
+ );
232
+ }, K = w(() => {
233
+ if (!n) return S;
234
+ const o = V.filter((e) => v.has(e)).map((e) => ({
235
+ ...v.get(e),
236
+ scope: "global",
237
+ reorderable: !0
238
+ })), r = S.filter((e) => !j.has(e.id)).map((e) => ({
239
+ ...e,
240
+ scope: "contextual",
241
+ reorderable: !0
242
+ }));
243
+ return [...o, ...r];
244
+ }, [n, S, V, v, j]), [lo, io] = X(""), L = $(!1), co = (o, r) => {
245
+ const e = r ? C("controlRoom.pinnedAnnounce", {
246
+ tool: o,
247
+ defaultValue: "Pinned {{tool}} to favourites"
248
+ }) : C("controlRoom.unpinnedAnnounce", {
249
+ tool: o,
250
+ defaultValue: "Removed {{tool}} from favourites"
251
+ });
252
+ L.current = !L.current, io(L.current ? e : `${e}​`);
253
+ }, ao = (o) => {
254
+ var r;
255
+ co(((r = v.get(o)) == null ? void 0 : r.label) ?? o, !j.has(o)), J(
256
+ o,
257
+ (e) => e.includes(o) ? e.filter((u) => u !== o) : [...e, o]
258
+ );
259
+ }, uo = (o, r) => {
260
+ var u;
261
+ const e = (u = K[o]) == null ? void 0 : u.id;
262
+ e !== void 0 && J(e, (T) => {
263
+ const k = T.filter((h) => v.has(h)), N = k.length;
264
+ if (o < N) {
265
+ if (r >= N) return k.filter((go) => go !== e);
266
+ const h = k.slice();
267
+ return h.splice(o, 1), h.splice(r, 0, e), h;
268
+ }
269
+ if (r <= N) {
270
+ const h = k.slice();
271
+ return h.splice(Math.min(r, N), 0, e), h;
272
+ }
273
+ return T;
274
+ });
275
+ }, fo = ({
276
+ tool: o,
277
+ from: r,
278
+ to: e
279
+ }) => {
280
+ const u = j.size, T = r < u;
281
+ return T && e >= u ? C("controlRoom.unpinnedAnnounce", {
282
+ tool: o.label,
283
+ defaultValue: "Removed {{tool}} from favourites"
284
+ }) : !T && e <= u ? C("controlRoom.pinnedAnnounce", {
285
+ tool: o.label,
286
+ defaultValue: "Pinned {{tool}} to favourites"
287
+ }) : T && e < u ? C("controlRoom.reorderAnnounce", {
288
+ tool: o.label,
289
+ to: e + 1,
290
+ total: u,
291
+ defaultValue: "{{tool}} moved to position {{to}} of {{total}}"
292
+ }) : "";
293
+ }, Q = $(null), U = Mo(), po = b(
294
+ (o) => {
295
+ Q.current = o, U(o), typeof M == "function" ? M(o) : M && (M.current = o);
296
+ },
297
+ [U, M]
298
+ ), E = D != null ? v.get(D) ?? null : null, mo = E ? /* @__PURE__ */ Y(Ro, { children: [
299
+ n ? (() => {
300
+ const o = j.has(E.id);
301
+ return /* @__PURE__ */ A(
302
+ Z,
303
+ {
304
+ icon: /* @__PURE__ */ A(
305
+ Ao,
306
+ {
307
+ "aria-hidden": "true",
308
+ fill: o ? "currentColor" : "none",
309
+ className: o ? "ds:text-[color:var(--accent)]" : void 0
310
+ }
311
+ ),
312
+ intent: "ghost",
313
+ size: "sm",
314
+ "aria-pressed": o,
315
+ "aria-label": C("controlRoom.favorite", {
316
+ defaultValue: "Favourite"
317
+ }),
318
+ onClick: () => ao(E.id)
319
+ }
320
+ );
321
+ })() : null,
322
+ /* @__PURE__ */ A(
323
+ Z,
324
+ {
325
+ icon: /* @__PURE__ */ A(wo, { "aria-hidden": "true" }),
326
+ intent: "ghost",
327
+ size: "sm",
328
+ "aria-label": C("controlRoom.close", { defaultValue: "Close" }),
329
+ onClick: () => {
330
+ var o;
331
+ return (o = Q.current) == null ? void 0 : o.close();
332
+ }
333
+ }
334
+ )
335
+ ] }) : null;
336
+ return /* @__PURE__ */ Y(xo, { actions: mo, children: [
337
+ /* @__PURE__ */ A(
338
+ yo,
339
+ {
340
+ ref: po,
341
+ dataComponent: "control-room-rail",
342
+ agentAdapter: So,
343
+ tools: K,
344
+ activeToolId: d,
345
+ defaultActiveToolId: m,
346
+ onActiveToolChange: I,
347
+ panelWidth: so,
348
+ onPanelWidthChange: ro,
349
+ railLabel: l ?? C("controlRoom.railLabel", { defaultValue: "Control room" }),
350
+ onReorder: n ? uo : void 0,
351
+ formatReorderAnnouncement: n ? fo : void 0,
352
+ ...q
353
+ }
354
+ ),
355
+ n ? /* @__PURE__ */ A("span", { role: "status", "aria-live": "polite", className: "ds:sr-only", children: lo }) : null
356
+ ] });
357
+ });
358
+ export {
359
+ Xo as C,
360
+ Go as a,
361
+ ko as b,
362
+ So as c,
363
+ $o as d,
364
+ Do as u
365
+ };
366
+ //# sourceMappingURL=control-room-rail-CdBOXIqX.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "packageVersion": "1.47.0",
3
+ "packageVersion": "1.47.1",
4
4
  "components": [
5
5
  {
6
6
  "kind": "component",
@@ -3,6 +3,11 @@ import { type ToolRailHandle, type ToolRailProps, type ToolRailTool } from '../t
3
3
  export type ControlRoomTool = ToolRailTool;
4
4
  /** Imperative handle — open / collapse a tool panel without the DOM. */
5
5
  export type ControlRoomRailHandle = ToolRailHandle;
6
+ /** What one favourites write did, for the tool the user acted on. */
7
+ export interface ControlRoomFavoriteChange {
8
+ toolId: string;
9
+ action: 'pin' | 'unpin' | 'reorder';
10
+ }
6
11
  export interface ControlRoomRailProps extends Omit<ToolRailProps, 'tools' | 'onReorder' | 'formatReorderAnnouncement' | 'renderToolAffordance' | 'renderPanelHeader'> {
7
12
  /**
8
13
  * Explicit tool set. Omit to read the merged global + contextual tools from
@@ -35,8 +40,10 @@ export interface ControlRoomRailProps extends Omit<ToolRailProps, 'tools' | 'onR
35
40
  * marked `scope: 'global'` (Alia, Inbox) — pinning them on top by default.
36
41
  */
37
42
  defaultFavoriteIds?: string[];
38
- /** Fires with the next favourites order whenever the user pins / reorders. */
39
- onFavoriteIdsChange?: (next: string[]) => void;
43
+ /** Fires with the next favourites order whenever the user pins / reorders.
44
+ * `change` names the tool acted on and what happened to it; it is
45
+ * absent when the write changed nothing. */
46
+ onFavoriteIdsChange?: (next: string[], change?: ControlRoomFavoriteChange) => void;
40
47
  /** localStorage key for the uncontrolled favourites. */
41
48
  persistFavoritesKey?: string;
42
49
  /**
@@ -1,5 +1,5 @@
1
1
  export { ControlRoomRail } from './control-room-rail';
2
- export type { ControlRoomRailProps, ControlRoomRailHandle, ControlRoomTool, } from './control-room-rail';
2
+ export type { ControlRoomRailProps, ControlRoomRailHandle, ControlRoomFavoriteChange, ControlRoomTool, } from './control-room-rail';
3
3
  export { controlRoomRailAgent } from './control-room-rail.agent';
4
4
  export { ControlRoomProvider, useControlRoomTools, useControlRoomMergedTools, useControlRoomActions, } from './control-room-context';
5
5
  export type { ControlRoomProviderProps } from './control-room-context';
@@ -1,4 +1,4 @@
1
- import { C as r, a as l, c as a, u as t, b as e, d as n } from "../../_chunks/control-room-rail-Cv7GpMqX.js";
1
+ import { C as r, a as l, c as a, u as t, b as e, d as n } from "../../_chunks/control-room-rail-CdBOXIqX.js";
2
2
  export {
3
3
  r as ControlRoomProvider,
4
4
  l as ControlRoomRail,
package/dist/index.js CHANGED
@@ -111,7 +111,7 @@ import { S as en } from "./_chunks/stat-Bs80Z6Yv.js";
111
111
  import { T as rn } from "./_chunks/tag-Ci3xJPcH.js";
112
112
  import { T as tn, t as nn } from "./_chunks/timeline-61AihzYz.js";
113
113
  import { T as mn } from "./_chunks/timestamp-BV2lC-wV.js";
114
- import { C as dn, a as An, c as cn, u as fn, b as gn, d as Sn } from "./_chunks/control-room-rail-Cv7GpMqX.js";
114
+ import { C as dn, a as An, c as cn, u as fn, b as gn, d as Sn } from "./_chunks/control-room-rail-CdBOXIqX.js";
115
115
  import { B as Tn, a as xn, b as un, c as Pn, d as In, e as En, f as Rn } from "./_chunks/breadcrumb-agut0PwN.js";
116
116
  import { C as _n, a as Nn, b as Dn, c as hn, d as On, e as Fn, f as Ln, g as Mn, h as yn, i as kn, j as Bn, k as vn, u as Gn } from "./_chunks/command-palette-DQl_SNEv.js";
117
117
  import { H as wn, a as Wn, b as Vn, c as Un, d as Kn, e as Yn, f as Xn, g as qn } from "./_chunks/header-3o9o9v_T.js";
@@ -244,7 +244,7 @@ import { W as MC, a as yC, w as kC } from "./_chunks/workflow-status-CuJAOuKL.js
244
244
  import { C as vC, W as GC, a as HC, b as wC, c as WC, i as VC, l as UC, m as KC, r as YC, w as XC, d as qC, e as zC, f as jC } from "./_chunks/workflow-map-DhR_h5yw.js";
245
245
  import { A as ZC, a as JC, b as $C, c as aT } from "./_chunks/alia-sidebar-CUqaJNPQ.js";
246
246
  import { A as sT, a as rT, L as oT, P as tT, S as nT, T as iT, b as pT, c as mT, d as lT, e as dT, f as AT, g as cT, h as fT, i as gT, j as ST, k as CT, l as TT, m as xT, n as uT, o as PT, p as IT, r as ET, q as RT, s as bT, t as _T, u as NT } from "./_chunks/anamnesis-summary-rows-DI-UX5r6.js";
247
- import { C as hT, a as OT, b as FT, c as LT, D as MT, d as yT, S as kT, V as BT, W as vT, e as GT, i as HT, m as wT, r as WT, u as VT, f as UT, g as KT } from "./_chunks/calendar-workspace-DDnQmiIL.js";
247
+ import { C as hT, a as OT, b as FT, c as LT, D as MT, d as yT, S as kT, V as BT, W as vT, e as GT, i as HT, m as wT, r as WT, u as VT, f as UT, g as KT } from "./_chunks/calendar-workspace-BmscntRR.js";
248
248
  import { A as XT, a as qT, b as zT, H as jT, c as QT, u as ZT } from "./_chunks/help-me-write-templates-DHIwa4xR.js";
249
249
  import { C as $T, M as ax, P as ex } from "./_chunks/marketplace-app-shell-PB89Dkk_.js";
250
250
  import { P as rx } from "./_chunks/payment-automation-upsell-BKmBXU4i.js";
@@ -1,3 +1,42 @@
1
+ /**
2
+ * Calendar pattern — the WORKSPACE ROOT.
3
+ *
4
+ * The practice agenda page the platform mounts from the kit: the grid
5
+ * and its two-strip toolbar (`calendar.surface.tsx`) beside a MINIMAL
6
+ * Control Room rail docked inline-end — up to six tools, in strip
7
+ * order: the upcoming Appointments panel (the rail's resting state and
8
+ * its default), ONE appointment editor / details tool, the waiting list,
9
+ * patient notes when in context, online bookings and the free-slot finder. Nothing else — no Inbox,
10
+ * no Alia, no patient tabs, no care plan, no tasks. The panels are the
11
+ * extracted modules from `calendar.sheets.tsx`; `calendar.host.ts`'s
12
+ * open / close seam maps onto the rail's dock, with `close()` returning
13
+ * to the Appointments panel so no path leaves an empty rail.
14
+ *
15
+ * Six is the ceiling, not the floor: `availableTools` narrows the set
16
+ * to what the host can actually back with data, hiding the rail tool AND
17
+ * the toolbar control that opens it, and routing anything aimed at a
18
+ * withheld tool to the Appointments panel. A host with no business
19
+ * hours, holidays or closures must withhold the free-slot finder — it
20
+ * would otherwise report booked and shut-day times as free.
21
+ *
22
+ * The host owns the data and the domain state: it hands in a
23
+ * `CalendarData` read model (`calendar.data.ts`) and a `CalendarJourney`
24
+ * (`calendar.journey.ts`) — the demos from their fixtures and the
25
+ * fixture-backed journey hook, the platform island from
26
+ * `/internalApi/...`. The workspace owns what sits between the two: the
27
+ * cog's display settings, the privacy flag, the one polite region, the
28
+ * editor tool's mode, the placement / create modes, the deep-link
29
+ * effects and the tasks filter. It renders NO header or sidebar — the
30
+ * host page has its own — and expects a bounded block-size from its
31
+ * parent (it fills it; the surface scrolls inside, the rail stays put),
32
+ * exactly what `AppFrame`'s `<main>` gives a page.
33
+ *
34
+ * The confirmations stay kit `Dialog`s — they interrupt rather than
35
+ * dock: the move confirm, the delete confirm with its recurring scope
36
+ * and care-plan cleanup and the Create-bill confirm.
37
+ */
38
+ import type { CalendarView } from '../../components/calendar';
39
+ import { type ControlRoomFavoriteChange } from '../../components/control-room-rail';
1
40
  import { type CalendarAppointmentEditorLoader } from './calendar-editor-hydration';
2
41
  import { type CalendarAppointmentDetailsLoader } from './calendar-appointment-details';
3
42
  import { type CalendarData } from './calendar.data';
@@ -18,6 +57,46 @@ export interface CalendarOnlineBookings {
18
57
  createdAtById?: Readonly<Record<string, string>>;
19
58
  onRetry?: () => void;
20
59
  }
60
+ /** Where a tool panel was opened from. `system` is a dock the workspace
61
+ * made on its own (the resting panel, a return after a save, a
62
+ * toolbar or journey hand-off), not a pick on the rail. */
63
+ export type CalendarToolOpenSource = 'rail' | 'appointment_panel' | 'selection' | 'system';
64
+ /** Where the appointment behind a details panel was selected. `host` is
65
+ * a selection the journey made itself. */
66
+ export type CalendarDetailsOpenSource = 'calendar' | 'appointments_panel' | 'bookings_panel' | 'waiting_list' | 'deep_link' | 'host';
67
+ /**
68
+ * Usage callbacks for the host's analytics. The kit raises no event of
69
+ * its own and passes identifiers only, never patient data: the host owns
70
+ * the calls, the property allow-list and any once-per guard.
71
+ */
72
+ export interface CalendarWorkspaceAnalytics {
73
+ /** A tool panel opened. Not raised again while it stays open. */
74
+ onToolOpen?: (event: {
75
+ toolId: CalendarWorkspaceToolId;
76
+ source: CalendarToolOpenSource;
77
+ view: CalendarView;
78
+ }) => void;
79
+ /** An appointment's preview opened. Raised on EVERY opening: the
80
+ * once-per-appointment guard is the host's. */
81
+ onAppointmentPreviewOpen?: (event: {
82
+ eventId: string;
83
+ view: CalendarView;
84
+ privacy: boolean;
85
+ }) => void;
86
+ /** An appointment's details docked for a new selection. Not raised when
87
+ * details come back after an edit. */
88
+ onAppointmentDetailsOpen?: (event: {
89
+ eventId: string;
90
+ source: CalendarDetailsOpenSource;
91
+ view: CalendarView;
92
+ }) => void;
93
+ /** A rail preference was saved on this device. `resize` is raised only
94
+ * with `persistPanelWidthKey`, since without it nothing is saved. */
95
+ onToolPreferencesChange?: (event: {
96
+ action: ControlRoomFavoriteChange['action'] | 'resize';
97
+ toolId: string;
98
+ }) => void;
99
+ }
21
100
  export interface CalendarWorkspaceProps {
22
101
  /** Optional canonical read for every existing-appointment editor route.
23
102
  * The form waits for this response; failures/refusals expose no editable
@@ -131,6 +210,15 @@ export interface CalendarWorkspaceProps {
131
210
  * it cannot show never marks the cog. */
132
211
  backlogFilters?: Readonly<Record<BacklogGap, boolean>>;
133
212
  onBacklogFiltersChange?: (filters: Readonly<Record<BacklogGap, boolean>>) => void;
213
+ /** Device key the rail saves pinned tools and their order under. Omit
214
+ * it and the rail keeps its generic default, `ui.controlRoom.favorites`. */
215
+ persistFavoritesKey?: string;
216
+ /** Device key the rail saves the panel width under. Omit it and width
217
+ * is not saved, as before. On-device only; nothing reaches a server. */
218
+ persistPanelWidthKey?: string;
219
+ /** Usage callbacks for the host's analytics. Omit it and nothing is
220
+ * reported. */
221
+ analytics?: CalendarWorkspaceAnalytics;
134
222
  }
135
223
  /**
136
224
  * The cog's settings as the workspace opens with them: the remembered
@@ -179,6 +179,8 @@ export interface CalendarJourney {
179
179
  handleEditNote: (patientId: string, noteId: string, content: string) => void | Promise<void>;
180
180
  handleDeleteNote: (patientId: string, noteId: string) => void | Promise<void>;
181
181
  handleToggleNotePin: (patientId: string, noteId: string) => void | Promise<void>;
182
+ /** Flag or unflag a note. Omit it and the flag control is not offered. */
183
+ handleToggleNoteFlag?: (patientId: string, noteId: string) => void | Promise<void>;
182
184
  /** Read a patient's notes: the latest few, or every note. */
183
185
  handleLoadNotes?: (patientId: string, scope: 'preview' | 'all') => void;
184
186
  /**
@@ -73,6 +73,8 @@ export interface PatientNotesSeam {
73
73
  onEditNote: (noteId: string, content: string) => void | Promise<void>;
74
74
  onDeleteNote: (noteId: string) => void | Promise<void>;
75
75
  onTogglePin: (noteId: string) => void | Promise<void>;
76
+ /** Flag or unflag a note. Omitted → no flag control. */
77
+ onToggleFlag?: (noteId: string) => void | Promise<void>;
76
78
  /** The practice's own drafting endpoint. Omitted → no AI affordance. */
77
79
  onRequestAiDraft?: NotesPanelProps['onRequestAiDraft'];
78
80
  /** The host's live transcription. Omitted → no microphone. */
@@ -1,8 +1,9 @@
1
+ import { type CalendarView } from '../../components/calendar';
1
2
  import { type CalendarPreferenceAdapter } from './calendar.preferences';
2
3
  import { type CalendarRow, type RailFocus, type EditorPrefill, type HistoryInput, type AvailabilityContext, type CalendarFreeSlot } from './calendar.model';
3
4
  import { type WorkspaceDisplaySettings, type CreateModeRequest, type PlacementRequest, type SaveNotice, type CalendarWorkspaceToolId } from './calendar-workspace.model';
4
5
  import type { CalendarOccurrenceMove } from './calendar.journey';
5
- export declare function CalendarSurface({ rows, setRows, onFocus, locale, onComposeNew, onComposeTask, onOpenWaitingList, onAddWaitingEntry, onOpenOnlineBookings, onlineBookingsCount, waitingBadgeCount, onVisibleRangeChange, selectedEventId, gotoRequest, onBookSlot, onBookSlotFromFinder, display, setDisplay, onHistory, readOnly, reviewOnlyEventIds, detailsOnEveryClick, placement, onPlacementEnd, createMode, onCreateModeEnd, focusScroll, saveNotice, privacy, onPrivacyChange, availability, availabilityContext, availableTools, schedulerLicenseKey, id, preferences, onMoveOccurrence, }: {
6
+ export declare function CalendarSurface({ rows, setRows, onFocus, locale, onComposeNew, onComposeTask, onOpenWaitingList, onAddWaitingEntry, onOpenOnlineBookings, onlineBookingsCount, waitingBadgeCount, onVisibleRangeChange, selectedEventId, gotoRequest, onBookSlot, onBookSlotFromFinder, display, setDisplay, onHistory, readOnly, reviewOnlyEventIds, detailsOnEveryClick, placement, onPlacementEnd, createMode, onCreateModeEnd, focusScroll, saveNotice, privacy, onPrivacyChange, availability, availabilityContext, availableTools, schedulerLicenseKey, id, preferences, onMoveOccurrence, onViewChange, onPeekOpen, }: {
6
7
  rows: CalendarRow[];
7
8
  setRows: React.Dispatch<React.SetStateAction<CalendarRow[]>>;
8
9
  onFocus: (focus: RailFocus) => void;
@@ -96,5 +97,9 @@ export declare function CalendarSurface({ rows, setRows, onFocus, locale, onComp
96
97
  /** The host's series move (S-C8). With it, a recurring parent's move
97
98
  * always confirms, asks the scope and hides the notify boxes. */
98
99
  onMoveOccurrence?: (move: CalendarOccurrenceMove) => Promise<void>;
100
+ /** The grid's view, on mount and on every change. Usage reporting only. */
101
+ onViewChange?: (view: CalendarView) => void;
102
+ /** An appointment's preview opened. Usage reporting only. */
103
+ onPeekOpen?: (eventId: string) => void;
99
104
  }): import("react/jsx-runtime").JSX.Element;
100
105
  //# sourceMappingURL=calendar.surface.d.ts.map
@@ -1,4 +1,4 @@
1
- export { CalendarWorkspace, initialWorkspaceDisplay, WORKSPACE_TOOL, type CalendarWorkspaceProps, type CalendarOnlineBookings, type CalendarWorkspaceToolId, } from './calendar-workspace';
1
+ export { CalendarWorkspace, initialWorkspaceDisplay, WORKSPACE_TOOL, type CalendarWorkspaceProps, type CalendarOnlineBookings, type CalendarWorkspaceToolId, type CalendarWorkspaceAnalytics, type CalendarToolOpenSource, type CalendarDetailsOpenSource, } from './calendar-workspace';
2
2
  export { CalendarDataProvider, useCalendarData, type CalendarData, type DayLoadState, } from './calendar.data';
3
3
  export type { CalendarJourney, CalendarOccurrenceMove, PatientNotesLoad, } from './calendar.journey';
4
4
  export type { CalendarAppointmentEditorSnapshot, CalendarAppointmentEditorLoader, CalendarEditorSeries, } from './calendar-editor-hydration';
@@ -1,4 +1,4 @@
1
- import { C as s, a as r, b as E, c as P, D as S, d as o, S as C, V as t, W as d, e as A, i, m as n, r as D, u as W, f as _, g as c } from "../../_chunks/calendar-workspace-DDnQmiIL.js";
1
+ import { C as s, a as r, b as E, c as P, D as S, d as o, S as C, V as t, W as d, e as A, i, m as n, r as D, u as W, f as _, g as c } from "../../_chunks/calendar-workspace-BmscntRR.js";
2
2
  export {
3
3
  s as CALENDAR_PREFERENCE_KEYS,
4
4
  r as CalendarDataProvider,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfadocs/ui-kit",
3
- "version": "1.47.0",
3
+ "version": "1.47.1",
4
4
  "type": "module",
5
5
  "description": "AlfaDocs shared design system — tokens, components, patterns, and translations for platform, booking, and alfascribe.",
6
6
  "license": "BUSL-1.1",