@stealthscale/component-messaging 0.1.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1055 @@
1
+ import { t as __exportAll } from "../../rolldown-runtime-D7D4PA-g.js";
2
+ import { n as recipe } from "../../recipes-D1oVFnRU.js";
3
+ import { C as Toolbar, D as Context, E as Input, T as Root$1, a as Item, c as Status$1, d as Footer, f as Content, h as Actions, l as Root, m as Avatar$1, p as Bubble, r as Root$2, u as Header, w as Submit } from "../../shared-B0H4dgkB.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ import { useId, useState } from "react";
7
+ import { Button, ButtonPropsProvider, IconButton } from "@stealthscale/component-actions";
8
+ import { flushSync } from "react-dom";
9
+ import { Portal } from "@stealthscale/component-primitives";
10
+ import { Popover } from "@stealthscale/component-disclosure";
11
+ import { Room, scenesOf, specimen, useWords } from "@stealthscale/specimen";
12
+ import { ArrowUpIcon, CheckCheckIcon, CheckIcon, CircleAlertIcon, ClockIcon, CopyIcon, PencilIcon, RefreshCwIcon, RotateCcwIcon, SparklesIcon, ThumbsDownIcon, ThumbsUpIcon, Trash2Icon } from "lucide-react";
13
+ import { Avatar } from "@stealthscale/component-media";
14
+ import { Span, Strong } from "@stealthscale/component-typography";
15
+ import { Stack } from "@stealthscale/component-layout";
16
+ import { Markdown } from "@stealthscale/component-content";
17
+ import { Timestamp } from "@stealthscale/component-data";
18
+ //#region src/message/examples/answer.example.tsx
19
+ var answer_example_exports = /* @__PURE__ */ __exportAll({
20
+ Answer: () => Answer,
21
+ source: () => source$5
22
+ });
23
+ const ACTIONS = [
24
+ ["copy", CopyIcon],
25
+ ["regenerate", RefreshCwIcon],
26
+ ["good", ThumbsUpIcon],
27
+ ["bad", ThumbsDownIcon]
28
+ ];
29
+ function Answer() {
30
+ const $ = c(17);
31
+ const { t } = useWords("message");
32
+ let t0;
33
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
34
+ t0 = /* @__PURE__ */ jsx(Avatar$1, { children: /* @__PURE__ */ jsx(Avatar.Root, {
35
+ "aria-hidden": true,
36
+ size: "sm",
37
+ children: /* @__PURE__ */ jsx(Avatar.Fallback, { children: /* @__PURE__ */ jsx(SparklesIcon, {}) })
38
+ }) });
39
+ $[0] = t0;
40
+ } else t0 = $[0];
41
+ let t1;
42
+ if ($[1] !== t) {
43
+ t1 = t("assistant");
44
+ $[1] = t;
45
+ $[2] = t1;
46
+ } else t1 = $[2];
47
+ let t2;
48
+ if ($[3] !== t1) {
49
+ t2 = /* @__PURE__ */ jsx(Header, { children: /* @__PURE__ */ jsx(Strong, { children: t1 }) });
50
+ $[3] = t1;
51
+ $[4] = t2;
52
+ } else t2 = $[4];
53
+ let t3;
54
+ if ($[5] !== t) {
55
+ t3 = t("summary");
56
+ $[5] = t;
57
+ $[6] = t3;
58
+ } else t3 = $[6];
59
+ let t4;
60
+ if ($[7] !== t3) {
61
+ t4 = /* @__PURE__ */ jsx(Bubble, { children: /* @__PURE__ */ jsx(Markdown, {
62
+ headingLevel: 3,
63
+ source: t3
64
+ }) });
65
+ $[7] = t3;
66
+ $[8] = t4;
67
+ } else t4 = $[8];
68
+ let t5;
69
+ if ($[9] !== t) {
70
+ t5 = ACTIONS.map((t6) => {
71
+ const [action, Glyph] = t6;
72
+ return /* @__PURE__ */ jsx(IconButton, {
73
+ "aria-label": t(action),
74
+ size: "xs",
75
+ variant: "ghost",
76
+ children: /* @__PURE__ */ jsx(Glyph, { size: "1em" })
77
+ }, action);
78
+ });
79
+ $[9] = t;
80
+ $[10] = t5;
81
+ } else t5 = $[10];
82
+ let t6;
83
+ if ($[11] !== t5) {
84
+ t6 = /* @__PURE__ */ jsx(Footer, { children: /* @__PURE__ */ jsx(Actions, { children: t5 }) });
85
+ $[11] = t5;
86
+ $[12] = t6;
87
+ } else t6 = $[12];
88
+ let t7;
89
+ if ($[13] !== t2 || $[14] !== t4 || $[15] !== t6) {
90
+ t7 = /* @__PURE__ */ jsxs(Root, {
91
+ look: "plain",
92
+ reveal: "always",
93
+ children: [t0, /* @__PURE__ */ jsxs(Content, { children: [
94
+ t2,
95
+ t4,
96
+ t6
97
+ ] })]
98
+ });
99
+ $[13] = t2;
100
+ $[14] = t4;
101
+ $[15] = t6;
102
+ $[16] = t7;
103
+ } else t7 = $[16];
104
+ return t7;
105
+ }
106
+ const source$5 = "import { type ReactElement } from \"react\";\n\nimport { CopyIcon, RefreshCwIcon, SparklesIcon, ThumbsDownIcon, ThumbsUpIcon } from \"lucide-react\";\n\nimport { IconButton } from \"@stealthscale/component-actions\";\nimport { Markdown } from \"@stealthscale/component-content\";\nimport { Avatar } from \"@stealthscale/component-media\";\nimport { Strong } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Message } from \"@stealthscale/component-messaging\";\n\nconst ACTIONS = [\n [\"copy\", CopyIcon],\n [\"regenerate\", RefreshCwIcon],\n [\"good\", ThumbsUpIcon],\n [\"bad\", ThumbsDownIcon],\n] as const;\n\nexport function Answer(): ReactElement {\n const { t } = useWords(\"message\");\n\n return (\n <Message.Root look=\"plain\" reveal=\"always\">\n <Message.Avatar>\n <Avatar.Root aria-hidden size=\"sm\">\n <Avatar.Fallback>\n <SparklesIcon />\n </Avatar.Fallback>\n </Avatar.Root>\n </Message.Avatar>\n <Message.Content>\n <Message.Header>\n <Strong>{t(\"assistant\")}</Strong>\n </Message.Header>\n <Message.Bubble>\n <Markdown headingLevel={3} source={t(\"summary\")} />\n </Message.Bubble>\n <Message.Footer>\n <Message.Actions>\n {ACTIONS.map(([action, Glyph]) => (\n <IconButton aria-label={t(action)} key={action} size=\"xs\" variant=\"ghost\">\n <Glyph size=\"1em\" />\n </IconButton>\n ))}\n </Message.Actions>\n </Message.Footer>\n </Message.Content>\n </Message.Root>\n );\n}\n";
107
+ //#endregion
108
+ //#region src/message/examples/delivery.example.tsx
109
+ var delivery_example_exports = /* @__PURE__ */ __exportAll({
110
+ Delivery: () => Delivery,
111
+ source: () => source$4
112
+ });
113
+ const TIME$2 = {
114
+ timeStyle: "short",
115
+ timeZone: "UTC"
116
+ };
117
+ const SENT = [
118
+ [
119
+ "read",
120
+ CheckCheckIcon,
121
+ "09:14"
122
+ ],
123
+ [
124
+ "delivered",
125
+ CheckCheckIcon,
126
+ "09:20"
127
+ ],
128
+ [
129
+ "sent",
130
+ CheckIcon,
131
+ "09:21"
132
+ ],
133
+ [
134
+ "sending",
135
+ ClockIcon,
136
+ "09:22"
137
+ ]
138
+ ];
139
+ function Delivery() {
140
+ const $ = c(4);
141
+ const { t } = useWords("message");
142
+ let t0;
143
+ if ($[0] !== t) {
144
+ t0 = SENT.map((t1) => {
145
+ const [status, Glyph, at] = t1;
146
+ return /* @__PURE__ */ jsx(Root, {
147
+ align: "end",
148
+ "aria-label": t("you"),
149
+ look: "solid",
150
+ palette: "primary",
151
+ children: /* @__PURE__ */ jsxs(Content, { children: [/* @__PURE__ */ jsx(Bubble, { children: t(`${status}Text`) }), /* @__PURE__ */ jsxs(Footer, { children: [/* @__PURE__ */ jsx(Timestamp, {
152
+ options: TIME$2,
153
+ value: `2026-09-30T${at}:00Z`
154
+ }), /* @__PURE__ */ jsxs(Status$1, {
155
+ status,
156
+ children: [/* @__PURE__ */ jsx(Glyph, { "aria-hidden": true }), t(status)]
157
+ })] })] })
158
+ }, status);
159
+ });
160
+ $[0] = t;
161
+ $[1] = t0;
162
+ } else t0 = $[1];
163
+ let t1;
164
+ if ($[2] !== t0) {
165
+ t1 = /* @__PURE__ */ jsx(Stack, {
166
+ gap: "md",
167
+ children: t0
168
+ });
169
+ $[2] = t0;
170
+ $[3] = t1;
171
+ } else t1 = $[3];
172
+ return t1;
173
+ }
174
+ const source$4 = "import { type ReactElement } from \"react\";\n\nimport { CheckCheckIcon, CheckIcon, ClockIcon } from \"lucide-react\";\n\nimport { Timestamp } from \"@stealthscale/component-data\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Message } from \"@stealthscale/component-messaging\";\n\nconst TIME: Intl.DateTimeFormatOptions = { timeStyle: \"short\", timeZone: \"UTC\" };\n\nconst SENT = [\n [\"read\", CheckCheckIcon, \"09:14\"],\n [\"delivered\", CheckCheckIcon, \"09:20\"],\n [\"sent\", CheckIcon, \"09:21\"],\n [\"sending\", ClockIcon, \"09:22\"],\n] as const;\n\nexport function Delivery(): ReactElement {\n const { t } = useWords(\"message\");\n\n return (\n <Stack gap=\"md\">\n {SENT.map(([status, Glyph, at]) => (\n <Message.Root align=\"end\" aria-label={t(\"you\")} key={status} look=\"solid\" palette=\"primary\">\n <Message.Content>\n <Message.Bubble>{t(`${status}Text`)}</Message.Bubble>\n <Message.Footer>\n <Timestamp options={TIME} value={`2026-09-30T${at}:00Z`} />\n <Message.Status status={status}>\n <Glyph aria-hidden />\n {t(status)}\n </Message.Status>\n </Message.Footer>\n </Message.Content>\n </Message.Root>\n ))}\n </Stack>\n );\n}\n";
175
+ //#endregion
176
+ //#region src/message/examples/exchange.example.tsx
177
+ var exchange_example_exports = /* @__PURE__ */ __exportAll({
178
+ Exchange: () => Exchange,
179
+ source: () => source$3
180
+ });
181
+ const TIME$1 = {
182
+ timeStyle: "short",
183
+ timeZone: "UTC"
184
+ };
185
+ function Exchange() {
186
+ const $ = c(48);
187
+ const { t } = useWords("message");
188
+ let t0;
189
+ if ($[0] !== t) {
190
+ t0 = t("ada");
191
+ $[0] = t;
192
+ $[1] = t0;
193
+ } else t0 = $[1];
194
+ let t1;
195
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
196
+ t1 = /* @__PURE__ */ jsx(Avatar.Fallback, {});
197
+ $[2] = t1;
198
+ } else t1 = $[2];
199
+ let t2;
200
+ if ($[3] !== t0) {
201
+ t2 = /* @__PURE__ */ jsx(Avatar$1, { children: /* @__PURE__ */ jsx(Avatar.Root, {
202
+ "aria-hidden": true,
203
+ name: t0,
204
+ size: "sm",
205
+ children: t1
206
+ }) });
207
+ $[3] = t0;
208
+ $[4] = t2;
209
+ } else t2 = $[4];
210
+ let t3;
211
+ if ($[5] !== t) {
212
+ t3 = t("ada");
213
+ $[5] = t;
214
+ $[6] = t3;
215
+ } else t3 = $[6];
216
+ let t4;
217
+ if ($[7] !== t3) {
218
+ t4 = /* @__PURE__ */ jsx(Strong, { children: t3 });
219
+ $[7] = t3;
220
+ $[8] = t4;
221
+ } else t4 = $[8];
222
+ let t5;
223
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
224
+ t5 = /* @__PURE__ */ jsx(Timestamp, {
225
+ options: TIME$1,
226
+ value: "2026-09-30T09:12:00Z"
227
+ });
228
+ $[9] = t5;
229
+ } else t5 = $[9];
230
+ let t6;
231
+ if ($[10] !== t4) {
232
+ t6 = /* @__PURE__ */ jsxs(Header, { children: [t4, t5] });
233
+ $[10] = t4;
234
+ $[11] = t6;
235
+ } else t6 = $[11];
236
+ let t7;
237
+ if ($[12] !== t) {
238
+ t7 = t("invoice");
239
+ $[12] = t;
240
+ $[13] = t7;
241
+ } else t7 = $[13];
242
+ let t8;
243
+ if ($[14] !== t7) {
244
+ t8 = /* @__PURE__ */ jsx(Bubble, { children: t7 });
245
+ $[14] = t7;
246
+ $[15] = t8;
247
+ } else t8 = $[15];
248
+ let t9;
249
+ if ($[16] !== t) {
250
+ t9 = t("approve");
251
+ $[16] = t;
252
+ $[17] = t9;
253
+ } else t9 = $[17];
254
+ let t10;
255
+ if ($[18] !== t9) {
256
+ t10 = /* @__PURE__ */ jsx(Bubble, { children: t9 });
257
+ $[18] = t9;
258
+ $[19] = t10;
259
+ } else t10 = $[19];
260
+ let t11;
261
+ if ($[20] !== t10 || $[21] !== t6 || $[22] !== t8) {
262
+ t11 = /* @__PURE__ */ jsxs(Content, { children: [
263
+ t6,
264
+ t8,
265
+ t10
266
+ ] });
267
+ $[20] = t10;
268
+ $[21] = t6;
269
+ $[22] = t8;
270
+ $[23] = t11;
271
+ } else t11 = $[23];
272
+ let t12;
273
+ if ($[24] !== t11 || $[25] !== t2) {
274
+ t12 = /* @__PURE__ */ jsxs(Root, { children: [t2, t11] });
275
+ $[24] = t11;
276
+ $[25] = t2;
277
+ $[26] = t12;
278
+ } else t12 = $[26];
279
+ let t13;
280
+ if ($[27] !== t) {
281
+ t13 = t("you");
282
+ $[27] = t;
283
+ $[28] = t13;
284
+ } else t13 = $[28];
285
+ let t14;
286
+ if ($[29] !== t) {
287
+ t14 = t("approved");
288
+ $[29] = t;
289
+ $[30] = t14;
290
+ } else t14 = $[30];
291
+ let t15;
292
+ if ($[31] !== t14) {
293
+ t15 = /* @__PURE__ */ jsx(Bubble, { children: t14 });
294
+ $[31] = t14;
295
+ $[32] = t15;
296
+ } else t15 = $[32];
297
+ let t16;
298
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
299
+ t16 = /* @__PURE__ */ jsx(Timestamp, {
300
+ options: TIME$1,
301
+ value: "2026-09-30T09:14:00Z"
302
+ });
303
+ $[33] = t16;
304
+ } else t16 = $[33];
305
+ let t17;
306
+ if ($[34] === Symbol.for("react.memo_cache_sentinel")) {
307
+ t17 = /* @__PURE__ */ jsx(CheckCheckIcon, { "aria-hidden": true });
308
+ $[34] = t17;
309
+ } else t17 = $[34];
310
+ let t18;
311
+ if ($[35] !== t) {
312
+ t18 = t("read");
313
+ $[35] = t;
314
+ $[36] = t18;
315
+ } else t18 = $[36];
316
+ let t19;
317
+ if ($[37] !== t18) {
318
+ t19 = /* @__PURE__ */ jsxs(Footer, { children: [t16, /* @__PURE__ */ jsxs(Status$1, {
319
+ status: "read",
320
+ children: [t17, t18]
321
+ })] });
322
+ $[37] = t18;
323
+ $[38] = t19;
324
+ } else t19 = $[38];
325
+ let t20;
326
+ if ($[39] !== t15 || $[40] !== t19) {
327
+ t20 = /* @__PURE__ */ jsxs(Content, { children: [t15, t19] });
328
+ $[39] = t15;
329
+ $[40] = t19;
330
+ $[41] = t20;
331
+ } else t20 = $[41];
332
+ let t21;
333
+ if ($[42] !== t13 || $[43] !== t20) {
334
+ t21 = /* @__PURE__ */ jsx(Root, {
335
+ align: "end",
336
+ "aria-label": t13,
337
+ look: "solid",
338
+ palette: "primary",
339
+ children: t20
340
+ });
341
+ $[42] = t13;
342
+ $[43] = t20;
343
+ $[44] = t21;
344
+ } else t21 = $[44];
345
+ let t22;
346
+ if ($[45] !== t12 || $[46] !== t21) {
347
+ t22 = /* @__PURE__ */ jsxs(Stack, {
348
+ gap: "lg",
349
+ children: [t12, t21]
350
+ });
351
+ $[45] = t12;
352
+ $[46] = t21;
353
+ $[47] = t22;
354
+ } else t22 = $[47];
355
+ return t22;
356
+ }
357
+ const source$3 = "import { type ReactElement } from \"react\";\n\nimport { CheckCheckIcon } from \"lucide-react\";\n\nimport { Timestamp } from \"@stealthscale/component-data\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { Avatar } from \"@stealthscale/component-media\";\nimport { Strong } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Message } from \"@stealthscale/component-messaging\";\n\nconst TIME: Intl.DateTimeFormatOptions = { timeStyle: \"short\", timeZone: \"UTC\" };\n\nexport function Exchange(): ReactElement {\n const { t } = useWords(\"message\");\n\n return (\n <Stack gap=\"lg\">\n <Message.Root>\n <Message.Avatar>\n <Avatar.Root aria-hidden name={t(\"ada\")} size=\"sm\">\n <Avatar.Fallback />\n </Avatar.Root>\n </Message.Avatar>\n <Message.Content>\n <Message.Header>\n <Strong>{t(\"ada\")}</Strong>\n <Timestamp options={TIME} value=\"2026-09-30T09:12:00Z\" />\n </Message.Header>\n <Message.Bubble>{t(\"invoice\")}</Message.Bubble>\n <Message.Bubble>{t(\"approve\")}</Message.Bubble>\n </Message.Content>\n </Message.Root>\n <Message.Root align=\"end\" aria-label={t(\"you\")} look=\"solid\" palette=\"primary\">\n <Message.Content>\n <Message.Bubble>{t(\"approved\")}</Message.Bubble>\n <Message.Footer>\n <Timestamp options={TIME} value=\"2026-09-30T09:14:00Z\" />\n <Message.Status status=\"read\">\n <CheckCheckIcon aria-hidden />\n {t(\"read\")}\n </Message.Status>\n </Message.Footer>\n </Message.Content>\n </Message.Root>\n </Stack>\n );\n}\n";
358
+ //#endregion
359
+ //#region src/message/examples/failed.example.tsx
360
+ var failed_example_exports = /* @__PURE__ */ __exportAll({
361
+ Failed: () => Failed,
362
+ source: () => source$2
363
+ });
364
+ function Failed() {
365
+ const $ = c(25);
366
+ const { t } = useWords("message");
367
+ let t0;
368
+ if ($[0] !== t) {
369
+ t0 = t("you");
370
+ $[0] = t;
371
+ $[1] = t0;
372
+ } else t0 = $[1];
373
+ let t1;
374
+ if ($[2] !== t) {
375
+ t1 = t("failedText");
376
+ $[2] = t;
377
+ $[3] = t1;
378
+ } else t1 = $[3];
379
+ let t2;
380
+ if ($[4] !== t1) {
381
+ t2 = /* @__PURE__ */ jsx(Bubble, {
382
+ failed: true,
383
+ children: t1
384
+ });
385
+ $[4] = t1;
386
+ $[5] = t2;
387
+ } else t2 = $[5];
388
+ let t3;
389
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
390
+ t3 = /* @__PURE__ */ jsx(CircleAlertIcon, { "aria-hidden": true });
391
+ $[6] = t3;
392
+ } else t3 = $[6];
393
+ let t4;
394
+ if ($[7] !== t) {
395
+ t4 = t("failed");
396
+ $[7] = t;
397
+ $[8] = t4;
398
+ } else t4 = $[8];
399
+ let t5;
400
+ if ($[9] !== t4) {
401
+ t5 = /* @__PURE__ */ jsxs(Status$1, {
402
+ status: "failed",
403
+ children: [t3, t4]
404
+ });
405
+ $[9] = t4;
406
+ $[10] = t5;
407
+ } else t5 = $[10];
408
+ let t6;
409
+ if ($[11] === Symbol.for("react.memo_cache_sentinel")) {
410
+ t6 = /* @__PURE__ */ jsx(RotateCcwIcon, { size: "1em" });
411
+ $[11] = t6;
412
+ } else t6 = $[11];
413
+ let t7;
414
+ if ($[12] !== t) {
415
+ t7 = t("retry");
416
+ $[12] = t;
417
+ $[13] = t7;
418
+ } else t7 = $[13];
419
+ let t8;
420
+ if ($[14] !== t7) {
421
+ t8 = /* @__PURE__ */ jsx(Actions, { children: /* @__PURE__ */ jsxs(Button, {
422
+ size: "xs",
423
+ variant: "ghost",
424
+ children: [t6, t7]
425
+ }) });
426
+ $[14] = t7;
427
+ $[15] = t8;
428
+ } else t8 = $[15];
429
+ let t9;
430
+ if ($[16] !== t5 || $[17] !== t8) {
431
+ t9 = /* @__PURE__ */ jsxs(Footer, { children: [t5, t8] });
432
+ $[16] = t5;
433
+ $[17] = t8;
434
+ $[18] = t9;
435
+ } else t9 = $[18];
436
+ let t10;
437
+ if ($[19] !== t2 || $[20] !== t9) {
438
+ t10 = /* @__PURE__ */ jsxs(Content, { children: [t2, t9] });
439
+ $[19] = t2;
440
+ $[20] = t9;
441
+ $[21] = t10;
442
+ } else t10 = $[21];
443
+ let t11;
444
+ if ($[22] !== t0 || $[23] !== t10) {
445
+ t11 = /* @__PURE__ */ jsx(Root, {
446
+ align: "end",
447
+ "aria-label": t0,
448
+ look: "solid",
449
+ palette: "primary",
450
+ reveal: "always",
451
+ children: t10
452
+ });
453
+ $[22] = t0;
454
+ $[23] = t10;
455
+ $[24] = t11;
456
+ } else t11 = $[24];
457
+ return t11;
458
+ }
459
+ const source$2 = "import { type ReactElement } from \"react\";\n\nimport { CircleAlertIcon, RotateCcwIcon } from \"lucide-react\";\n\nimport { Button } from \"@stealthscale/component-actions\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Message } from \"@stealthscale/component-messaging\";\n\nexport function Failed(): ReactElement {\n const { t } = useWords(\"message\");\n\n return (\n <Message.Root align=\"end\" aria-label={t(\"you\")} look=\"solid\" palette=\"primary\" reveal=\"always\">\n <Message.Content>\n <Message.Bubble failed>{t(\"failedText\")}</Message.Bubble>\n <Message.Footer>\n <Message.Status status=\"failed\">\n <CircleAlertIcon aria-hidden />\n {t(\"failed\")}\n </Message.Status>\n <Message.Actions>\n <Button size=\"xs\" variant=\"ghost\">\n <RotateCcwIcon size=\"1em\" />\n {t(\"retry\")}\n </Button>\n </Message.Actions>\n </Message.Footer>\n </Message.Content>\n </Message.Root>\n );\n}\n";
460
+ //#endregion
461
+ //#region src/message/examples/thread.example.tsx
462
+ var thread_example_exports = /* @__PURE__ */ __exportAll({
463
+ Thread: () => Thread,
464
+ source: () => source$1
465
+ });
466
+ const NOW = Date.parse("2026-09-30T10:00:00Z");
467
+ const OPENING = [
468
+ {
469
+ author: "ada",
470
+ id: "c1",
471
+ key: "move",
472
+ likes: 2,
473
+ minutes: 130
474
+ },
475
+ {
476
+ author: "bram",
477
+ id: "c2",
478
+ key: "works",
479
+ likes: 1,
480
+ minutes: 95
481
+ },
482
+ {
483
+ author: "me",
484
+ id: "c3",
485
+ key: "tell",
486
+ likes: 0,
487
+ minutes: 40
488
+ }
489
+ ];
490
+ function revised(comment, typed) {
491
+ return {
492
+ author: comment.author,
493
+ edited: true,
494
+ id: comment.id,
495
+ likes: comment.likes,
496
+ minutes: comment.minutes,
497
+ typed
498
+ };
499
+ }
500
+ function toggled(liked, id) {
501
+ return new Set(liked.has(id) ? [...liked].filter((one) => one !== id) : [...liked, id]);
502
+ }
503
+ function editorOf(comment, text, scope) {
504
+ return /* @__PURE__ */ jsxs(Root$1, {
505
+ defaultValue: text,
506
+ onCancelContext: () => {
507
+ scope.onSave(comment.id);
508
+ },
509
+ onSubmit: (typed) => {
510
+ scope.onSave(comment.id, typed);
511
+ },
512
+ size: "sm",
513
+ children: [
514
+ /* @__PURE__ */ jsxs(Context, { children: [/* @__PURE__ */ jsx(PencilIcon, { "aria-hidden": true }), /* @__PURE__ */ jsx(Span, { children: scope.t("editing") })] }),
515
+ /* @__PURE__ */ jsx(Input, {
516
+ id: `${scope.base}-editor`,
517
+ label: scope.t("editLabel")
518
+ }),
519
+ /* @__PURE__ */ jsxs(Toolbar, { children: [/* @__PURE__ */ jsx(Button, {
520
+ onClick: () => {
521
+ scope.onSave(comment.id);
522
+ },
523
+ size: "xs",
524
+ variant: "ghost",
525
+ children: scope.t("cancel")
526
+ }), /* @__PURE__ */ jsx(Submit, {
527
+ label: scope.t("save"),
528
+ children: /* @__PURE__ */ jsx(CheckIcon, { size: "1em" })
529
+ })] })
530
+ ]
531
+ });
532
+ }
533
+ function deletion(comment, scope) {
534
+ return /* @__PURE__ */ jsxs(Popover.Root, {
535
+ initialFocusEl: () => document.querySelector(`[id="${scope.base}-keep"]`),
536
+ onOpenChange: (details) => {
537
+ scope.onConfirm(details.open ? comment.id : void 0);
538
+ },
539
+ open: scope.confirming === comment.id,
540
+ children: [/* @__PURE__ */ jsx(ButtonPropsProvider, {
541
+ value: {
542
+ size: "xs",
543
+ variant: "ghost"
544
+ },
545
+ children: /* @__PURE__ */ jsxs(Popover.Trigger, {
546
+ as: Button,
547
+ children: [/* @__PURE__ */ jsx(Trash2Icon, { size: "1em" }), scope.t("delete")]
548
+ })
549
+ }), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, { children: /* @__PURE__ */ jsxs(Popover.Content, { children: [
550
+ /* @__PURE__ */ jsx(Popover.Title, {
551
+ as: "h3",
552
+ children: scope.t("deleteTitle")
553
+ }),
554
+ /* @__PURE__ */ jsx(Popover.Description, { children: scope.t("deleteNote") }),
555
+ /* @__PURE__ */ jsxs(Stack, {
556
+ direction: "row",
557
+ gap: "sm",
558
+ children: [/* @__PURE__ */ jsx(Button, {
559
+ onClick: () => {
560
+ scope.onRemove(comment.id);
561
+ },
562
+ palette: "error",
563
+ size: "sm",
564
+ children: scope.t("delete")
565
+ }), /* @__PURE__ */ jsx(Button, {
566
+ id: `${scope.base}-keep`,
567
+ onClick: () => {
568
+ scope.onConfirm();
569
+ },
570
+ size: "sm",
571
+ variant: "outline",
572
+ children: scope.t("cancel")
573
+ })]
574
+ })
575
+ ] }) }) })]
576
+ });
577
+ }
578
+ function footerOf(comment, scope) {
579
+ const mine = scope.liked.has(comment.id);
580
+ const count = comment.likes + (mine ? 1 : 0);
581
+ return /* @__PURE__ */ jsxs(Footer, { children: [/* @__PURE__ */ jsx(Root$2, {
582
+ label: scope.t("reactions"),
583
+ children: /* @__PURE__ */ jsx(Item, {
584
+ label: scope.t(mine ? "likedMine" : "liked", { count }),
585
+ onClick: () => {
586
+ scope.onLike(comment.id);
587
+ },
588
+ pressed: mine,
589
+ ...count > 0 ? { count } : {},
590
+ children: "👍"
591
+ })
592
+ }), comment.author === "me" ? /* @__PURE__ */ jsxs(Actions, { children: [/* @__PURE__ */ jsxs(Button, {
593
+ id: `${scope.base}-edit-${comment.id}`,
594
+ onClick: () => {
595
+ scope.onEdit(comment.id);
596
+ },
597
+ size: "xs",
598
+ variant: "ghost",
599
+ children: [/* @__PURE__ */ jsx(PencilIcon, { size: "1em" }), scope.t("edit")]
600
+ }), deletion(comment, scope)] }) : null] });
601
+ }
602
+ function commentOf(comment, scope) {
603
+ const name = scope.t(comment.author === "me" ? "you" : comment.author);
604
+ const text = comment.key === void 0 ? comment.typed ?? "" : scope.t(comment.key);
605
+ return /* @__PURE__ */ jsxs(Root, {
606
+ look: "plain",
607
+ reveal: "always",
608
+ children: [/* @__PURE__ */ jsx(Avatar$1, { children: /* @__PURE__ */ jsx(Avatar.Root, {
609
+ "aria-hidden": true,
610
+ name,
611
+ size: "sm",
612
+ children: /* @__PURE__ */ jsx(Avatar.Fallback, {})
613
+ }) }), /* @__PURE__ */ jsxs(Content, { children: [
614
+ /* @__PURE__ */ jsxs(Header, { children: [
615
+ /* @__PURE__ */ jsx(Strong, { children: name }),
616
+ /* @__PURE__ */ jsx(Timestamp, {
617
+ now: NOW,
618
+ reads: "relative",
619
+ value: NOW - comment.minutes * 6e4
620
+ }),
621
+ comment.edited ? /* @__PURE__ */ jsx(Span, { children: scope.t("edited") }) : null
622
+ ] }),
623
+ scope.editing === comment.id ? editorOf(comment, text, scope) : /* @__PURE__ */ jsx(Bubble, { children: text }),
624
+ scope.editing === comment.id ? null : footerOf(comment, scope)
625
+ ] })]
626
+ }, comment.id);
627
+ }
628
+ function Thread() {
629
+ const $ = c(42);
630
+ const { t } = useWords("message");
631
+ const base = useId();
632
+ let t0;
633
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
634
+ t0 = OPENING.map(_temp);
635
+ $[0] = t0;
636
+ } else t0 = $[0];
637
+ const [comments, setComments] = useState(t0);
638
+ let t1;
639
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
640
+ t1 = /* @__PURE__ */ new Set(["c1"]);
641
+ $[1] = t1;
642
+ } else t1 = $[1];
643
+ const [liked, setLiked] = useState(t1);
644
+ const [editing, setEditing] = useState();
645
+ const [confirming, setConfirming] = useState();
646
+ let t2;
647
+ if ($[2] !== base) {
648
+ t2 = (id_0) => {
649
+ flushSync(() => {
650
+ setEditing(id_0);
651
+ });
652
+ document.querySelector(`[id="${base}-editor"]`)?.focus();
653
+ };
654
+ $[2] = base;
655
+ $[3] = t2;
656
+ } else t2 = $[3];
657
+ let t3;
658
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
659
+ t3 = (id_1) => {
660
+ setLiked((was) => toggled(was, id_1));
661
+ };
662
+ $[4] = t3;
663
+ } else t3 = $[4];
664
+ let t4;
665
+ let t5;
666
+ if ($[5] !== base) {
667
+ t4 = (id_2) => {
668
+ flushSync(() => {
669
+ setComments((was_0) => was_0.filter((one) => one.id !== id_2));
670
+ });
671
+ document.querySelector(`[id="${base}-reply"]`)?.focus();
672
+ };
673
+ t5 = (id_3, text) => {
674
+ flushSync(() => {
675
+ if (text !== void 0) setComments((was_1) => was_1.map((one_0) => one_0.id === id_3 ? revised(one_0, text) : one_0));
676
+ setEditing(void 0);
677
+ });
678
+ document.querySelector(`[id="${base}-edit-${id_3}"]`)?.focus();
679
+ };
680
+ $[5] = base;
681
+ $[6] = t4;
682
+ $[7] = t5;
683
+ } else {
684
+ t4 = $[6];
685
+ t5 = $[7];
686
+ }
687
+ let T0;
688
+ let t6;
689
+ let t7;
690
+ if ($[8] !== base || $[9] !== comments || $[10] !== confirming || $[11] !== editing || $[12] !== liked || $[13] !== t || $[14] !== t2 || $[15] !== t4 || $[16] !== t5) {
691
+ const scope = {
692
+ base,
693
+ confirming,
694
+ editing,
695
+ liked,
696
+ onConfirm: setConfirming,
697
+ onEdit: t2,
698
+ onLike: t3,
699
+ onRemove: t4,
700
+ onSave: t5,
701
+ t
702
+ };
703
+ T0 = Stack;
704
+ t6 = "lg";
705
+ t7 = comments.map((comment) => commentOf(comment, scope));
706
+ $[8] = base;
707
+ $[9] = comments;
708
+ $[10] = confirming;
709
+ $[11] = editing;
710
+ $[12] = liked;
711
+ $[13] = t;
712
+ $[14] = t2;
713
+ $[15] = t4;
714
+ $[16] = t5;
715
+ $[17] = T0;
716
+ $[18] = t6;
717
+ $[19] = t7;
718
+ } else {
719
+ T0 = $[17];
720
+ t6 = $[18];
721
+ t7 = $[19];
722
+ }
723
+ let t8;
724
+ if ($[20] === Symbol.for("react.memo_cache_sentinel")) {
725
+ t8 = (typed) => {
726
+ setComments((was_2) => [...was_2, {
727
+ author: "me",
728
+ edited: false,
729
+ id: `c${String(Date.now())}`,
730
+ likes: 0,
731
+ minutes: 0,
732
+ typed
733
+ }]);
734
+ };
735
+ $[20] = t8;
736
+ } else t8 = $[20];
737
+ const t9 = `${base}-reply`;
738
+ let t10;
739
+ if ($[21] !== t) {
740
+ t10 = t("replyLabel");
741
+ $[21] = t;
742
+ $[22] = t10;
743
+ } else t10 = $[22];
744
+ let t11;
745
+ if ($[23] !== t) {
746
+ t11 = t("replyPlaceholder");
747
+ $[23] = t;
748
+ $[24] = t11;
749
+ } else t11 = $[24];
750
+ let t12;
751
+ if ($[25] !== t10 || $[26] !== t11 || $[27] !== t9) {
752
+ t12 = /* @__PURE__ */ jsx(Input, {
753
+ id: t9,
754
+ label: t10,
755
+ placeholder: t11
756
+ });
757
+ $[25] = t10;
758
+ $[26] = t11;
759
+ $[27] = t9;
760
+ $[28] = t12;
761
+ } else t12 = $[28];
762
+ let t13;
763
+ if ($[29] !== t) {
764
+ t13 = t("send");
765
+ $[29] = t;
766
+ $[30] = t13;
767
+ } else t13 = $[30];
768
+ let t14;
769
+ if ($[31] === Symbol.for("react.memo_cache_sentinel")) {
770
+ t14 = /* @__PURE__ */ jsx(ArrowUpIcon, { size: "1em" });
771
+ $[31] = t14;
772
+ } else t14 = $[31];
773
+ let t15;
774
+ if ($[32] !== t13) {
775
+ t15 = /* @__PURE__ */ jsx(Toolbar, { children: /* @__PURE__ */ jsx(Submit, {
776
+ label: t13,
777
+ children: t14
778
+ }) });
779
+ $[32] = t13;
780
+ $[33] = t15;
781
+ } else t15 = $[33];
782
+ let t16;
783
+ if ($[34] !== t12 || $[35] !== t15) {
784
+ t16 = /* @__PURE__ */ jsxs(Root$1, {
785
+ onSubmit: t8,
786
+ children: [t12, t15]
787
+ });
788
+ $[34] = t12;
789
+ $[35] = t15;
790
+ $[36] = t16;
791
+ } else t16 = $[36];
792
+ let t17;
793
+ if ($[37] !== T0 || $[38] !== t16 || $[39] !== t6 || $[40] !== t7) {
794
+ t17 = /* @__PURE__ */ jsxs(T0, {
795
+ gap: t6,
796
+ children: [t7, t16]
797
+ });
798
+ $[37] = T0;
799
+ $[38] = t16;
800
+ $[39] = t6;
801
+ $[40] = t7;
802
+ $[41] = t17;
803
+ } else t17 = $[41];
804
+ return t17;
805
+ }
806
+ function _temp(t0) {
807
+ const { author, id, key, likes, minutes } = t0;
808
+ return {
809
+ author,
810
+ edited: false,
811
+ id,
812
+ key,
813
+ likes,
814
+ minutes
815
+ };
816
+ }
817
+ const source$1 = "import { type ReactElement, useId, useState } from \"react\";\nimport { flushSync } from \"react-dom\";\n\nimport { ArrowUpIcon, CheckIcon, PencilIcon, Trash2Icon } from \"lucide-react\";\n\nimport { Button, ButtonPropsProvider } from \"@stealthscale/component-actions\";\nimport { Timestamp } from \"@stealthscale/component-data\";\nimport { Popover } from \"@stealthscale/component-disclosure\";\nimport { Stack } from \"@stealthscale/component-layout\";\nimport { Avatar } from \"@stealthscale/component-media\";\nimport { Portal } from \"@stealthscale/component-primitives\";\nimport { Span, Strong } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Composer, Message, Reactions } from \"@stealthscale/component-messaging\";\n\nconst NOW = Date.parse(\"2026-09-30T10:00:00Z\");\n\nconst OPENING = [\n { author: \"ada\", id: \"c1\", key: \"move\", likes: 2, minutes: 130 },\n { author: \"bram\", id: \"c2\", key: \"works\", likes: 1, minutes: 95 },\n { author: \"me\", id: \"c3\", key: \"tell\", likes: 0, minutes: 40 },\n] as const;\n\ntype Said = (typeof OPENING)[number][\"key\"];\n\ninterface Comment {\n readonly author: (typeof OPENING)[number][\"author\"];\n readonly edited: boolean;\n readonly id: string;\n readonly key?: Said;\n readonly likes: number;\n readonly minutes: number;\n readonly typed?: string;\n}\n\ninterface Scope {\n readonly base: string;\n readonly confirming: string | undefined;\n readonly editing: string | undefined;\n readonly liked: ReadonlySet<string>;\n readonly onConfirm: (id?: string) => void;\n readonly onEdit: (id: string) => void;\n readonly onLike: (id: string) => void;\n readonly onRemove: (id: string) => void;\n readonly onSave: (id: string, text?: string) => void;\n readonly t: ReturnType<typeof useWords>[\"t\"];\n}\n\nfunction revised(comment: Comment, typed: string): Comment {\n return {\n author: comment.author,\n edited: true,\n id: comment.id,\n likes: comment.likes,\n minutes: comment.minutes,\n typed,\n };\n}\n\nfunction toggled(liked: ReadonlySet<string>, id: string): ReadonlySet<string> {\n return new Set(liked.has(id) ? [...liked].filter((one) => one !== id) : [...liked, id]);\n}\n\nfunction editorOf(comment: Comment, text: string, scope: Scope): ReactElement {\n return (\n <Composer.Root\n defaultValue={text}\n onCancelContext={() => {\n scope.onSave(comment.id);\n }}\n onSubmit={(typed) => {\n scope.onSave(comment.id, typed);\n }}\n size=\"sm\"\n >\n <Composer.Context>\n <PencilIcon aria-hidden />\n <Span>{scope.t(\"editing\")}</Span>\n </Composer.Context>\n <Composer.Input id={`${scope.base}-editor`} label={scope.t(\"editLabel\")} />\n <Composer.Toolbar>\n <Button\n onClick={() => {\n scope.onSave(comment.id);\n }}\n size=\"xs\"\n variant=\"ghost\"\n >\n {scope.t(\"cancel\")}\n </Button>\n <Composer.Submit label={scope.t(\"save\")}>\n <CheckIcon size=\"1em\" />\n </Composer.Submit>\n </Composer.Toolbar>\n </Composer.Root>\n );\n}\n\nfunction deletion(comment: Comment, scope: Scope): ReactElement {\n return (\n <Popover.Root\n initialFocusEl={() => document.querySelector(`[id=\"${scope.base}-keep\"]`)}\n onOpenChange={(details) => {\n scope.onConfirm(details.open ? comment.id : undefined);\n }}\n open={scope.confirming === comment.id}\n >\n <ButtonPropsProvider value={{ size: \"xs\", variant: \"ghost\" }}>\n <Popover.Trigger as={Button}>\n <Trash2Icon size=\"1em\" />\n {scope.t(\"delete\")}\n </Popover.Trigger>\n </ButtonPropsProvider>\n <Portal>\n <Popover.Positioner>\n <Popover.Content>\n <Popover.Title as=\"h3\">{scope.t(\"deleteTitle\")}</Popover.Title>\n <Popover.Description>{scope.t(\"deleteNote\")}</Popover.Description>\n <Stack direction=\"row\" gap=\"sm\">\n <Button\n onClick={() => {\n scope.onRemove(comment.id);\n }}\n palette=\"error\"\n size=\"sm\"\n >\n {scope.t(\"delete\")}\n </Button>\n <Button\n id={`${scope.base}-keep`}\n onClick={() => {\n scope.onConfirm();\n }}\n size=\"sm\"\n variant=\"outline\"\n >\n {scope.t(\"cancel\")}\n </Button>\n </Stack>\n </Popover.Content>\n </Popover.Positioner>\n </Portal>\n </Popover.Root>\n );\n}\n\nfunction footerOf(comment: Comment, scope: Scope): ReactElement {\n const mine = scope.liked.has(comment.id);\n const count = comment.likes + (mine ? 1 : 0);\n\n return (\n <Message.Footer>\n <Reactions.Root label={scope.t(\"reactions\")}>\n <Reactions.Item\n label={scope.t(mine ? \"likedMine\" : \"liked\", { count })}\n onClick={() => {\n scope.onLike(comment.id);\n }}\n pressed={mine}\n {...(count > 0 ? { count } : {})}\n >\n 👍\n </Reactions.Item>\n </Reactions.Root>\n {comment.author === \"me\" ? (\n <Message.Actions>\n <Button\n id={`${scope.base}-edit-${comment.id}`}\n onClick={() => {\n scope.onEdit(comment.id);\n }}\n size=\"xs\"\n variant=\"ghost\"\n >\n <PencilIcon size=\"1em\" />\n {scope.t(\"edit\")}\n </Button>\n {deletion(comment, scope)}\n </Message.Actions>\n ) : null}\n </Message.Footer>\n );\n}\n\nfunction commentOf(comment: Comment, scope: Scope): ReactElement {\n const name = scope.t(comment.author === \"me\" ? \"you\" : comment.author);\n const text = comment.key === undefined ? (comment.typed ?? \"\") : scope.t(comment.key);\n\n return (\n <Message.Root key={comment.id} look=\"plain\" reveal=\"always\">\n <Message.Avatar>\n <Avatar.Root aria-hidden name={name} size=\"sm\">\n <Avatar.Fallback />\n </Avatar.Root>\n </Message.Avatar>\n <Message.Content>\n <Message.Header>\n <Strong>{name}</Strong>\n <Timestamp now={NOW} reads=\"relative\" value={NOW - comment.minutes * 60_000} />\n {comment.edited ? <Span>{scope.t(\"edited\")}</Span> : null}\n </Message.Header>\n {scope.editing === comment.id ? (\n editorOf(comment, text, scope)\n ) : (\n <Message.Bubble>{text}</Message.Bubble>\n )}\n {scope.editing === comment.id ? null : footerOf(comment, scope)}\n </Message.Content>\n </Message.Root>\n );\n}\n\nexport function Thread(): ReactElement {\n const { t } = useWords(\"message\");\n const base = useId();\n const [comments, setComments] = useState<readonly Comment[]>(\n OPENING.map(({ author, id, key, likes, minutes }) => ({\n author,\n edited: false,\n id,\n key,\n likes,\n minutes,\n })),\n );\n const [liked, setLiked] = useState<ReadonlySet<string>>(new Set([\"c1\"]));\n const [editing, setEditing] = useState<string>();\n const [confirming, setConfirming] = useState<string>();\n const scope: Scope = {\n base,\n confirming,\n editing,\n liked,\n onConfirm: setConfirming,\n onEdit: (id) => {\n flushSync(() => {\n setEditing(id);\n });\n document.querySelector<HTMLElement>(`[id=\"${base}-editor\"]`)?.focus();\n },\n onLike: (id) => {\n setLiked((was) => toggled(was, id));\n },\n onRemove: (id) => {\n flushSync(() => {\n setComments((was) => was.filter((one) => one.id !== id));\n });\n document.querySelector<HTMLElement>(`[id=\"${base}-reply\"]`)?.focus();\n },\n onSave: (id, text) => {\n flushSync(() => {\n if (text !== undefined) {\n setComments((was) => was.map((one) => (one.id === id ? revised(one, text) : one)));\n }\n setEditing(undefined);\n });\n document.querySelector<HTMLElement>(`[id=\"${base}-edit-${id}\"]`)?.focus();\n },\n t,\n };\n\n return (\n <Stack gap=\"lg\">\n {comments.map((comment) => commentOf(comment, scope))}\n <Composer.Root\n onSubmit={(typed) => {\n setComments((was) => [\n ...was,\n {\n author: \"me\",\n edited: false,\n id: `c${String(Date.now())}`,\n likes: 0,\n minutes: 0,\n typed,\n },\n ]);\n }}\n >\n <Composer.Input\n id={`${base}-reply`}\n label={t(\"replyLabel\")}\n placeholder={t(\"replyPlaceholder\")}\n />\n <Composer.Toolbar>\n <Composer.Submit label={t(\"send\")}>\n <ArrowUpIcon size=\"1em\" />\n </Composer.Submit>\n </Composer.Toolbar>\n </Composer.Root>\n </Stack>\n );\n}\n";
818
+ //#endregion
819
+ //#region src/message/examples/turn.example.tsx
820
+ var turn_example_exports = /* @__PURE__ */ __exportAll({
821
+ Turn: () => Turn,
822
+ source: () => source
823
+ });
824
+ const TIME = {
825
+ timeStyle: "short",
826
+ timeZone: "UTC"
827
+ };
828
+ function Turn(props) {
829
+ const $ = c(34);
830
+ const { t } = useWords("message");
831
+ let t0;
832
+ if ($[0] !== t) {
833
+ t0 = t("ada");
834
+ $[0] = t;
835
+ $[1] = t0;
836
+ } else t0 = $[1];
837
+ let t1;
838
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
839
+ t1 = /* @__PURE__ */ jsx(Avatar.Fallback, {});
840
+ $[2] = t1;
841
+ } else t1 = $[2];
842
+ let t2;
843
+ if ($[3] !== t0) {
844
+ t2 = /* @__PURE__ */ jsx(Avatar$1, { children: /* @__PURE__ */ jsx(Avatar.Root, {
845
+ "aria-hidden": true,
846
+ name: t0,
847
+ size: "sm",
848
+ children: t1
849
+ }) });
850
+ $[3] = t0;
851
+ $[4] = t2;
852
+ } else t2 = $[4];
853
+ let t3;
854
+ if ($[5] !== t) {
855
+ t3 = t("ada");
856
+ $[5] = t;
857
+ $[6] = t3;
858
+ } else t3 = $[6];
859
+ let t4;
860
+ if ($[7] !== t3) {
861
+ t4 = /* @__PURE__ */ jsx(Strong, { children: t3 });
862
+ $[7] = t3;
863
+ $[8] = t4;
864
+ } else t4 = $[8];
865
+ let t5;
866
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
867
+ t5 = /* @__PURE__ */ jsx(Timestamp, {
868
+ options: TIME,
869
+ value: "2026-09-30T09:12:00Z"
870
+ });
871
+ $[9] = t5;
872
+ } else t5 = $[9];
873
+ let t6;
874
+ if ($[10] !== t4) {
875
+ t6 = /* @__PURE__ */ jsxs(Header, { children: [t4, t5] });
876
+ $[10] = t4;
877
+ $[11] = t6;
878
+ } else t6 = $[11];
879
+ let t7;
880
+ if ($[12] !== t) {
881
+ t7 = t("invoice");
882
+ $[12] = t;
883
+ $[13] = t7;
884
+ } else t7 = $[13];
885
+ let t8;
886
+ if ($[14] !== t7) {
887
+ t8 = /* @__PURE__ */ jsx(Bubble, { children: t7 });
888
+ $[14] = t7;
889
+ $[15] = t8;
890
+ } else t8 = $[15];
891
+ let t9;
892
+ if ($[16] !== t) {
893
+ t9 = t("approve");
894
+ $[16] = t;
895
+ $[17] = t9;
896
+ } else t9 = $[17];
897
+ let t10;
898
+ if ($[18] !== t9) {
899
+ t10 = /* @__PURE__ */ jsx(Bubble, { children: t9 });
900
+ $[18] = t9;
901
+ $[19] = t10;
902
+ } else t10 = $[19];
903
+ let t11;
904
+ if ($[20] !== t) {
905
+ t11 = t("copy");
906
+ $[20] = t;
907
+ $[21] = t11;
908
+ } else t11 = $[21];
909
+ let t12;
910
+ if ($[22] === Symbol.for("react.memo_cache_sentinel")) {
911
+ t12 = /* @__PURE__ */ jsx(CopyIcon, { size: "1em" });
912
+ $[22] = t12;
913
+ } else t12 = $[22];
914
+ let t13;
915
+ if ($[23] !== t11) {
916
+ t13 = /* @__PURE__ */ jsx(Footer, { children: /* @__PURE__ */ jsx(Actions, { children: /* @__PURE__ */ jsx(IconButton, {
917
+ "aria-label": t11,
918
+ size: "xs",
919
+ variant: "ghost",
920
+ children: t12
921
+ }) }) });
922
+ $[23] = t11;
923
+ $[24] = t13;
924
+ } else t13 = $[24];
925
+ let t14;
926
+ if ($[25] !== t10 || $[26] !== t13 || $[27] !== t6 || $[28] !== t8) {
927
+ t14 = /* @__PURE__ */ jsxs(Content, { children: [
928
+ t6,
929
+ t8,
930
+ t10,
931
+ t13
932
+ ] });
933
+ $[25] = t10;
934
+ $[26] = t13;
935
+ $[27] = t6;
936
+ $[28] = t8;
937
+ $[29] = t14;
938
+ } else t14 = $[29];
939
+ let t15;
940
+ if ($[30] !== props || $[31] !== t14 || $[32] !== t2) {
941
+ t15 = /* @__PURE__ */ jsxs(Root, {
942
+ ...props,
943
+ children: [t2, t14]
944
+ });
945
+ $[30] = props;
946
+ $[31] = t14;
947
+ $[32] = t2;
948
+ $[33] = t15;
949
+ } else t15 = $[33];
950
+ return t15;
951
+ }
952
+ const source = "import { type ReactElement } from \"react\";\n\nimport { CopyIcon } from \"lucide-react\";\n\nimport { IconButton } from \"@stealthscale/component-actions\";\nimport { Timestamp } from \"@stealthscale/component-data\";\nimport { Avatar } from \"@stealthscale/component-media\";\nimport { Strong } from \"@stealthscale/component-typography\";\nimport { useWords } from \"@stealthscale/specimen\";\n\nimport { Message } from \"@stealthscale/component-messaging\";\n\nconst TIME: Intl.DateTimeFormatOptions = { timeStyle: \"short\", timeZone: \"UTC\" };\n\nexport function Turn(props: Message.RootProps): ReactElement {\n const { t } = useWords(\"message\");\n\n return (\n <Message.Root {...props}>\n <Message.Avatar>\n <Avatar.Root aria-hidden name={t(\"ada\")} size=\"sm\">\n <Avatar.Fallback />\n </Avatar.Root>\n </Message.Avatar>\n <Message.Content>\n <Message.Header>\n <Strong>{t(\"ada\")}</Strong>\n <Timestamp options={TIME} value=\"2026-09-30T09:12:00Z\" />\n </Message.Header>\n <Message.Bubble>{t(\"invoice\")}</Message.Bubble>\n <Message.Bubble>{t(\"approve\")}</Message.Bubble>\n <Message.Footer>\n <Message.Actions>\n <IconButton aria-label={t(\"copy\")} size=\"xs\" variant=\"ghost\">\n <CopyIcon size=\"1em\" />\n </IconButton>\n </Message.Actions>\n </Message.Footer>\n </Message.Content>\n </Message.Root>\n );\n}\n";
953
+ //#endregion
954
+ //#region src/message/message.specimen.tsx
955
+ /**
956
+ * Catalogue page for the message.
957
+ *
958
+ * @remarks
959
+ * The first scene renders a short exchange: another person's turn at the start of the line and
960
+ * the reader's own at the end. `scenesOf` generates the look, palette, size, align and reveal
961
+ * scenes from one turn of two messages, each in a room at the `sm` measure, the width of a phone.
962
+ * Hand-written scenes render the delivery states, a message that did not send, an answer in the
963
+ * plain look, and a comment thread. The words are keys under `message` in
964
+ * `locales/en/specimen/message.json`.
965
+ */
966
+ /**
967
+ * Hand-written scene for another person's turn and the reader's reply.
968
+ */
969
+ const exchanged = {
970
+ about: "message.exchange.about",
971
+ draw: () => /* @__PURE__ */ jsx(Room, {
972
+ size: "sm",
973
+ children: /* @__PURE__ */ jsx(Exchange, {})
974
+ }),
975
+ example: exchange_example_exports,
976
+ title: "message.exchange.title"
977
+ };
978
+ /**
979
+ * Hand-written scene for the reader's messages in each delivery state.
980
+ */
981
+ const delivered = {
982
+ about: "message.delivery.about",
983
+ draw: () => /* @__PURE__ */ jsx(Room, {
984
+ size: "sm",
985
+ children: /* @__PURE__ */ jsx(Delivery, {})
986
+ }),
987
+ example: delivery_example_exports,
988
+ title: "message.delivery.title"
989
+ };
990
+ /**
991
+ * Hand-written scene for a message that did not send, with a retry.
992
+ */
993
+ const unsent = {
994
+ about: "message.failure.about",
995
+ draw: () => /* @__PURE__ */ jsx(Room, {
996
+ size: "sm",
997
+ children: /* @__PURE__ */ jsx(Failed, {})
998
+ }),
999
+ example: failed_example_exports,
1000
+ title: "message.failure.title"
1001
+ };
1002
+ /**
1003
+ * Hand-written scene for an answer that reads as a document.
1004
+ */
1005
+ const answered = {
1006
+ about: "message.answer.about",
1007
+ draw: () => /* @__PURE__ */ jsx(Room, {
1008
+ size: "md",
1009
+ children: /* @__PURE__ */ jsx(Answer, {})
1010
+ }),
1011
+ example: answer_example_exports,
1012
+ title: "message.answer.title"
1013
+ };
1014
+ /**
1015
+ * Hand-written scene for a thread of comments the reader edits, deletes and answers.
1016
+ */
1017
+ const threaded = {
1018
+ about: "message.thread.about",
1019
+ draw: () => /* @__PURE__ */ jsx(Room, {
1020
+ size: "md",
1021
+ children: /* @__PURE__ */ jsx(Thread, {})
1022
+ }),
1023
+ example: thread_example_exports,
1024
+ title: "message.thread.title"
1025
+ };
1026
+ var message_specimen_default = specimen({
1027
+ about: "message.about",
1028
+ id: "components/messaging/message",
1029
+ imports: "import { Message } from \"@stealthscale/component-messaging\";",
1030
+ scenes: [
1031
+ exchanged,
1032
+ ...scenesOf(recipe, {
1033
+ draw: (props) => /* @__PURE__ */ jsx(Room, {
1034
+ size: "sm",
1035
+ children: /* @__PURE__ */ jsx(Turn, { ...props })
1036
+ }),
1037
+ example: turn_example_exports,
1038
+ namespace: "message",
1039
+ order: [
1040
+ "look",
1041
+ "palette",
1042
+ "size",
1043
+ "align",
1044
+ "reveal"
1045
+ ]
1046
+ }),
1047
+ delivered,
1048
+ unsent,
1049
+ answered,
1050
+ threaded
1051
+ ],
1052
+ title: "message.title"
1053
+ });
1054
+ //#endregion
1055
+ export { answered, message_specimen_default as default, delivered, exchanged, threaded, unsent };