@signalcore/ui 1.0.0-beta.0 → 1.0.0-beta.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.
Files changed (114) hide show
  1. package/README.md +8 -1
  2. package/dist/AgentAbout.js +7 -4
  3. package/dist/AgentAbout.js.map +1 -1
  4. package/dist/AgentChat.js +10 -2
  5. package/dist/AgentChat.js.map +1 -1
  6. package/dist/AgentTasks.js +2 -1
  7. package/dist/AgentTasks.js.map +1 -1
  8. package/dist/VoiceCall.js +1 -1
  9. package/dist/VoiceCall.js.map +1 -1
  10. package/dist/about.d.ts +34 -144
  11. package/dist/about.js +6 -8
  12. package/dist/about.js.map +1 -1
  13. package/dist/automation/cron.d.ts +1 -1
  14. package/dist/automation/cron.js.map +1 -1
  15. package/dist/automation/marks.js +7 -3
  16. package/dist/automation/marks.js.map +1 -1
  17. package/dist/automation/messages.d.ts +2 -0
  18. package/dist/automation/messages.js +2 -0
  19. package/dist/automation/messages.js.map +1 -1
  20. package/dist/automation/types.d.ts +25 -128
  21. package/dist/automation/types.js +36 -0
  22. package/dist/automation/types.js.map +1 -0
  23. package/dist/automation/when.d.ts +1 -1
  24. package/dist/automation/when.js +5 -1
  25. package/dist/automation/when.js.map +1 -1
  26. package/dist/blocks.d.ts +23 -1
  27. package/dist/browser.js +2 -2
  28. package/dist/browser.js.map +1 -1
  29. package/dist/call.d.ts +1 -1
  30. package/dist/call.js.map +1 -1
  31. package/dist/contract.d.ts +262 -0
  32. package/dist/credentials.js.map +1 -1
  33. package/dist/dev.js +1 -1
  34. package/dist/dev.js.map +1 -1
  35. package/dist/es.js +9 -1
  36. package/dist/es.js.map +1 -1
  37. package/dist/index.d.ts +3 -3
  38. package/dist/index.js +2 -1
  39. package/dist/kit/AudioPlayer.js +1 -1
  40. package/dist/kit/AudioPlayer.js.map +1 -1
  41. package/dist/kit/Choices.js +1 -1
  42. package/dist/kit/Choices.js.map +1 -1
  43. package/dist/kit/FileField.js +1 -1
  44. package/dist/kit/FileField.js.map +1 -1
  45. package/dist/kit/Popover.js.map +1 -1
  46. package/dist/kit/Tile.d.ts +1 -1
  47. package/dist/kit/Tile.js +1 -1
  48. package/dist/kit/Tile.js.map +1 -1
  49. package/dist/kit/messages.d.ts +13 -0
  50. package/dist/kit/messages.js +7 -1
  51. package/dist/kit/messages.js.map +1 -1
  52. package/dist/kit/uploads.d.ts +2 -1
  53. package/dist/kit/uploads.js +1 -1
  54. package/dist/kit/uploads.js.map +1 -1
  55. package/dist/kit/waveform.js.map +1 -1
  56. package/dist/markdown.js.map +1 -1
  57. package/dist/marks.js +2 -3
  58. package/dist/marks.js.map +1 -1
  59. package/dist/surface/Markdown.js +1 -1
  60. package/dist/surface/Markdown.js.map +1 -1
  61. package/dist/surface/Surface.js +43 -4
  62. package/dist/surface/Surface.js.map +1 -1
  63. package/dist/surface/scope.d.ts +1 -1
  64. package/dist/surface/scope.js.map +1 -1
  65. package/dist/surface/values.js +1 -1
  66. package/dist/surface/values.js.map +1 -1
  67. package/dist/tint.d.ts +1 -1
  68. package/dist/tint.js +1 -1
  69. package/dist/tint.js.map +1 -1
  70. package/dist/types.d.ts +7 -0
  71. package/dist/types.js.map +1 -1
  72. package/dist/usePolled.js +1 -1
  73. package/dist/usePolled.js.map +1 -1
  74. package/dist/voice/webgl.js +1 -1
  75. package/dist/voice/webgl.js.map +1 -1
  76. package/dist/widget.js +14 -14
  77. package/package.json +1 -1
  78. package/src/AgentAbout.tsx +10 -3
  79. package/src/AgentChat.tsx +20 -3
  80. package/src/AgentTasks.tsx +2 -2
  81. package/src/VoiceCall.tsx +1 -1
  82. package/src/about.ts +42 -144
  83. package/src/automation/cron.ts +1 -1
  84. package/src/automation/marks.tsx +6 -2
  85. package/src/automation/messages.ts +4 -0
  86. package/src/automation/types.ts +58 -118
  87. package/src/automation/when.ts +3 -1
  88. package/src/blocks.ts +25 -0
  89. package/src/browser.ts +4 -4
  90. package/src/call.ts +1 -1
  91. package/src/contract.ts +1720 -0
  92. package/src/credentials.ts +2 -2
  93. package/src/dev.ts +1 -1
  94. package/src/es.ts +8 -0
  95. package/src/index.ts +2 -0
  96. package/src/kit/AudioPlayer.tsx +1 -1
  97. package/src/kit/Choices.tsx +1 -1
  98. package/src/kit/FileField.tsx +1 -1
  99. package/src/kit/Popover.tsx +1 -1
  100. package/src/kit/Tile.tsx +1 -1
  101. package/src/kit/messages.ts +20 -0
  102. package/src/kit/uploads.ts +2 -2
  103. package/src/kit/waveform.ts +1 -1
  104. package/src/markdown.ts +1 -1
  105. package/src/marks.tsx +3 -123
  106. package/src/styles.css +24 -0
  107. package/src/surface/Markdown.tsx +1 -1
  108. package/src/surface/Surface.tsx +53 -4
  109. package/src/surface/scope.ts +3 -1
  110. package/src/surface/values.ts +5 -5
  111. package/src/tint.ts +1 -1
  112. package/src/types.ts +8 -0
  113. package/src/usePolled.ts +2 -2
  114. package/src/voice/webgl.ts +1 -1
@@ -0,0 +1,262 @@
1
+ //#region src/contract.d.ts
2
+ /** What the agent says about itself. */
3
+ export interface About {
4
+ summary: string;
5
+ does: Array<Does>;
6
+ asks: Array<string>;
7
+ icon?: "sparkle" | "calendar" | "headset" | "message" | "phone" | "mail" | "cart" | "card" | "chart" | "megaphone" | "wrench" | "briefcase" | "heart" | "user" | "search" | "file" | "globe" | "code" | "map" | null;
8
+ }
9
+ /** Qué puede: the agent's own words (None until written) and the facts they rest on. */
10
+ export interface AboutOut {
11
+ about: About | null;
12
+ about_at: string | null;
13
+ facts: Facts;
14
+ }
15
+ /** One action as an agent has it: where it comes from, whether it is on and asks first. */
16
+ export interface ActionRowOut {
17
+ name: string;
18
+ description: string;
19
+ destructive: boolean;
20
+ input_schema?: Record<string, unknown>;
21
+ source: "default" | "library" | "own";
22
+ on: boolean;
23
+ needs_approval: boolean;
24
+ }
25
+ export interface AutomationDetailOut {
26
+ id: string;
27
+ agent_id: string;
28
+ name: string;
29
+ title: string;
30
+ summary: string;
31
+ trigger: TriggerView;
32
+ on: boolean;
33
+ next_run_at: string | null;
34
+ steps: Array<Step>;
35
+ board: Board | null;
36
+ state: "active" | "paused" | "failing";
37
+ last_run: RunOut | null;
38
+ runs: Array<RunOut>;
39
+ }
40
+ export interface AutomationOut {
41
+ id: string;
42
+ agent_id: string;
43
+ name: string;
44
+ title: string;
45
+ summary: string;
46
+ trigger: TriggerView;
47
+ on: boolean;
48
+ next_run_at: string | null;
49
+ steps: Array<Step>;
50
+ board: Board | null;
51
+ state: "active" | "paused" | "failing";
52
+ last_run: RunOut | null;
53
+ }
54
+ /** What the automation moves: its table's rows counted by the value of one field. */
55
+ export interface Board {
56
+ table: string;
57
+ title: string;
58
+ field: string;
59
+ counts: Array<Count>;
60
+ }
61
+ export interface Count {
62
+ value: string;
63
+ count: number;
64
+ }
65
+ /** One automation, as the owner reads it. */
66
+ export interface Does {
67
+ automation: string;
68
+ text: string;
69
+ when: string;
70
+ }
71
+ export interface FactAsk {
72
+ agent_id: string;
73
+ name: string;
74
+ }
75
+ /** An automation; one on an app's event also with its app's provider, name and mark, which the others leave out, as they always have. */
76
+ export interface FactAutomation {
77
+ id: string;
78
+ name: string;
79
+ kind: "schedule" | "webhook" | "event" | "platform";
80
+ title: string;
81
+ summary: string;
82
+ schedule: string | null;
83
+ timezone: string | null;
84
+ app: string | null;
85
+ event: string | null;
86
+ config: Record<string, unknown>;
87
+ url: string | null;
88
+ say: string;
89
+ on: boolean;
90
+ last_run_at: string | null;
91
+ next_run_at: string | null;
92
+ provider?: string | null;
93
+ app_title?: string | null;
94
+ icon?: string | null;
95
+ }
96
+ export interface FactChannel {
97
+ kind: "whatsapp" | "instagram" | "sms" | "phone" | "web";
98
+ name: string;
99
+ status: string;
100
+ }
101
+ /** An app it was given: the app's name and mark, and its tools, with their names for people (`titles`) and as the model calls them (`called`: `gmail__Gmail_SendEmail`), each by the tool's own. */
102
+ export interface FactConnection {
103
+ name: string;
104
+ provider: "composio" | "arcade";
105
+ toolkit: string;
106
+ title: string;
107
+ status: string;
108
+ actions: Array<string>;
109
+ titles: Record<string, string>;
110
+ called: Record<string, string>;
111
+ icon: string | null;
112
+ }
113
+ export interface FactDevice {
114
+ kind: "extension" | "installer";
115
+ name: string;
116
+ status: string;
117
+ }
118
+ export interface FactFile {
119
+ path: string;
120
+ size: number;
121
+ searchable: boolean;
122
+ shared: boolean;
123
+ }
124
+ export interface FactKey {
125
+ name: string;
126
+ hosts: Array<string>;
127
+ shared: boolean;
128
+ }
129
+ export interface FactTable {
130
+ table: string;
131
+ can: Array<string>;
132
+ title: string | null;
133
+ }
134
+ /** What the agent has, as the app draws it. Every list is here from day one; the ones whose phase hasn't come are empty, and their shape is fixed so the renderer never changes. */
135
+ export interface Facts {
136
+ actions: Array<ActionRowOut>;
137
+ automations: Array<FactAutomation>;
138
+ connections: Array<FactConnection>;
139
+ channels: Array<FactChannel>;
140
+ files: Array<FactFile>;
141
+ memories: Array<MemoryOut>;
142
+ vault: Array<FactKey>;
143
+ data: Array<FactTable>;
144
+ asks: Array<FactAsk>;
145
+ devices: Array<FactDevice>;
146
+ }
147
+ export interface MemoryOut {
148
+ id: string;
149
+ agent_id: string;
150
+ contact_id?: string | null;
151
+ text: string;
152
+ created_at: string;
153
+ }
154
+ export interface RunDetailOut {
155
+ id: string;
156
+ agent_id: string;
157
+ automation: string;
158
+ title: string;
159
+ by: "schedule" | "webhook" | "event" | "platform" | "agent" | "test";
160
+ conversation_id: string | null;
161
+ status: "running" | "waiting" | "done" | "failed" | "skipped";
162
+ summary: string | null;
163
+ error: string | null;
164
+ dry: boolean;
165
+ started_at: string;
166
+ ended_at: string | null;
167
+ tokens_in: number;
168
+ tokens_out: number;
169
+ opened: Array<string>;
170
+ decision?: RunsDecisionOut | null;
171
+ steps: Array<RunStepOut>;
172
+ }
173
+ export interface RunOut {
174
+ id: string;
175
+ agent_id: string;
176
+ automation: string;
177
+ title: string;
178
+ by: "schedule" | "webhook" | "event" | "platform" | "agent" | "test";
179
+ conversation_id: string | null;
180
+ status: "running" | "waiting" | "done" | "failed" | "skipped";
181
+ summary: string | null;
182
+ error: string | null;
183
+ dry: boolean;
184
+ started_at: string;
185
+ ended_at: string | null;
186
+ tokens_in: number;
187
+ tokens_out: number;
188
+ opened: Array<string>;
189
+ decision?: RunsDecisionOut | null;
190
+ }
191
+ export interface RunStepOut {
192
+ seq: number;
193
+ step: string | null;
194
+ call: string;
195
+ input: unknown;
196
+ output: unknown;
197
+ error: string | null;
198
+ ms: number;
199
+ at: string;
200
+ would: boolean;
201
+ }
202
+ /** What a handler decided of a message (`sc.answer`, `sc.hold`, `sc.ignore`). */
203
+ export interface RunsDecisionOut {
204
+ kind: "answer" | "hold" | "ignore";
205
+ reason: string;
206
+ }
207
+ export interface Step {
208
+ name: string;
209
+ uses: Array<Use>;
210
+ }
211
+ /** A contact's subscription: an instance of a definition (`automation`: the business's automation for contacts, by name; None for an instruction), what it gives it (`inputs`: an instruction's words are `inputs.instruction`), when (`schedule`, a cron line in `timezone`, or once at `next_run_at`), whether it is on, its contact, the conversation it runs about and its newest runs. It read as an automation before: those fields stay, deprecated. */
212
+ export interface TaskOut {
213
+ id: string;
214
+ agent_id: string;
215
+ automation: string | null;
216
+ title: string;
217
+ inputs: Record<string, unknown>;
218
+ schedule: string | null;
219
+ timezone: string | null;
220
+ on: boolean;
221
+ next_run_at: string | null;
222
+ last_run_at: string | null;
223
+ contact_id: string;
224
+ conversation_id: string | null;
225
+ runs: Array<RunOut>;
226
+ created_at: string;
227
+ /** @deprecated Kept for the clients that read it. */
228
+ name: string;
229
+ /** @deprecated Kept for the clients that read it. */
230
+ summary: string;
231
+ /** @deprecated Kept for the clients that read it. */
232
+ trigger: TriggerView;
233
+ /** @deprecated Kept for the clients that read it. */
234
+ steps: Array<Step>;
235
+ /** @deprecated Kept for the clients that read it. */
236
+ board: Board | null;
237
+ /** @deprecated Kept for the clients that read it. */
238
+ state: "active" | "paused" | "failing";
239
+ /** @deprecated Kept for the clients that read it. */
240
+ last_run: RunOut | null;
241
+ }
242
+ export interface TriggerView {
243
+ kind: "schedule" | "webhook" | "event" | "platform";
244
+ schedule: string | null;
245
+ timezone: string | null;
246
+ url: string | null;
247
+ app: string | null;
248
+ app_title: string | null;
249
+ event: string | null;
250
+ event_title: string | null;
251
+ icon: string | null;
252
+ decides?: boolean;
253
+ channels?: Array<string>;
254
+ }
255
+ export interface Use {
256
+ kind: "app" | "ai" | "agent" | "notify" | "send" | "data" | "http";
257
+ app: string | null;
258
+ title: string | null;
259
+ icon: string | null;
260
+ }
261
+ //#endregion
262
+ //# sourceMappingURL=contract.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"credentials.js","names":[],"sources":["../src/credentials.ts"],"sourcesContent":["/**\n * Who a client calls as, one way at a time (v3/README.md, Credentials): the owner's session cookie\n * in our own app; a person's token, given as it is or asked of the host's backend (and asked again\n * once it expires); or an anonymous visitor of a site, by the site's publishable key and the id\n * the page keeps for them.\n */\n\ntype Way = \"credentials\" | \"token\" | \"getToken\" | \"publishableKey\" | \"visitorId\";\n\n/** One way of signing in, with none of the others beside it. */\ntype Alone<T> = T & { [K in Exclude<Way, keyof T>]?: never };\n\nexport type Credentials =\n /** Our app, on the API's own origin (`/api`): the session cookie the browser holds. */\n | Alone<{ credentials: \"cookie\" }>\n /** A person's token the host's backend minted (`POST /v1/tokens`), used as it is. */\n | Alone<{ token: string }>\n /**\n * A person's token asked of the host's backend: when first needed, and once more each time the\n * API refuses the one kept (it lasts an hour).\n */\n | Alone<{ getToken: () => Promise<string> }>\n /**\n * An anonymous visitor (the widget): the site's publishable key, and who they are, an id the\n * page keeps; one is made and kept in `localStorage` when none is given.\n */\n | Alone<{ publishableKey: string; visitorId?: string | undefined }>;\n\n/** What one request carries to say who calls, and how to have it anew once it is refused. */\nexport interface Signed {\n headers: Readonly<Record<string, string>>;\n /** Lets go of a token the API refused, for the next request to ask for another; null: none. */\n renew: (() => void) | null;\n}\n\n/**\n * Who a page speaks for: the business (the owner, in our own app) or a person it serves (a token's\n * person, a publishable key's visitor). The API lets each answer different things: a yes the\n * business decides is the business's alone.\n */\nexport type Speaker = \"business\" | \"person\";\n\n/** How every request and socket of a client says who calls. */\nexport interface Signer {\n who: Speaker;\n /** What `fetch` sends of the browser's own: the cookie on the page's origin, or nothing. */\n credentials: RequestCredentials;\n sign: () => Promise<Signed>;\n /**\n * What a socket carries in its address instead (a browser's socket takes no header); `fresh`\n * asks for a new token first, for a socket that could not open with the last one.\n */\n query: (fresh: boolean) => Promise<Readonly<Record<string, string>>>;\n}\n\n/** Where the page keeps its visitor's id, for every SignalCore widget on the site. */\nexport const VISITOR_KEY = \"signalcore.visitor\";\n\n/** What the API takes as a visitor's id: 16 to 128 letters, digits, `_` and `-`. */\nconst VISITOR = /^[A-Za-z0-9_-]{16,128}$/;\n\n/** A new visitor's id: 32 hex characters of the browser's own randomness (any page has it). */\nfunction newVisitor(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * The visitor this page speaks for: the one kept in `localStorage`, else a new one kept there for\n * their next visit; where the page can't keep anything (a private window, storage blocked), a new\n * one for this page alone.\n */\nexport function keptVisitor(): string {\n try {\n const kept = localStorage.getItem(VISITOR_KEY);\n if (kept !== null && VISITOR.test(kept)) return kept;\n const made = newVisitor();\n localStorage.setItem(VISITOR_KEY, made);\n return made;\n } catch {\n return newVisitor();\n }\n}\n\n/** A credential that never changes: the same headers and the same query, nothing to renew. */\nconst fixed = (\n who: Speaker,\n credentials: RequestCredentials,\n headers: Record<string, string>,\n query: Record<string, string>,\n): Signer => ({\n who,\n credentials,\n sign: () => Promise.resolve({ headers, renew: null }),\n query: () => Promise.resolve(query),\n});\n\n/**\n * A token asked of the host's backend: when first needed, then kept. A refusal lets it go, once\n * however many requests were refused with it, so the next request asks for another; one that\n * could not be had is asked for again next time.\n */\nfunction fetched(getToken: () => Promise<string>): Signer {\n let current: Promise<string> | null = null;\n const latest = (): Promise<string> => {\n if (current !== null) return current;\n const asked = Promise.resolve().then(getToken);\n current = asked;\n asked.catch(() => {\n if (current === asked) current = null;\n });\n return asked;\n };\n return {\n who: \"person\",\n credentials: \"omit\",\n sign: async () => {\n const used = latest();\n const token = await used;\n return {\n headers: { Authorization: `Bearer ${token}` },\n renew: () => {\n if (current === used) current = null;\n },\n };\n },\n query: async (fresh) => {\n if (fresh) current = null;\n return { token: await latest() };\n },\n };\n}\n\n/**\n * How a client signs in with what it was given. The API's public prefix reads the header (the\n * socket, its query) and never a cookie, so only our own app sends the browser's.\n */\nexport function signerOf(given: Credentials): Signer {\n if (given.credentials === \"cookie\") return fixed(\"business\", \"same-origin\", {}, {});\n if (typeof given.token === \"string\") {\n const { token } = given;\n return fixed(\"person\", \"omit\", { Authorization: `Bearer ${token}` }, { token });\n }\n if (typeof given.getToken === \"function\") return fetched(given.getToken);\n if (typeof given.publishableKey === \"string\") {\n const key = given.publishableKey;\n const visitor = given.visitorId ?? keptVisitor();\n return fixed(\n \"person\",\n \"omit\",\n { Authorization: `Bearer ${key}`, \"SignalCore-Visitor\": visitor },\n { token: key, visitor },\n );\n }\n throw new TypeError(\n 'createClient takes one way to sign in: credentials: \"cookie\", token, getToken or publishableKey',\n );\n}\n"],"mappings":";;AAwDA,MAAa,cAAc;;AAG3B,MAAM,UAAU;;AAGhB,SAAS,aAAqB;CAC5B,MAAM,QAAQ,OAAO,gCAAgB,IAAI,WAAW,EAAE,CAAC;CACvD,OAAO,MAAM,KAAK,QAAQ,SAAS,KAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AAChF;;;;;;AAOA,SAAgB,cAAsB;CACpC,IAAI;EACF,MAAM,OAAO,aAAa,QAAQ,WAAW;EAC7C,IAAI,SAAS,QAAQ,QAAQ,KAAK,IAAI,GAAG,OAAO;EAChD,MAAM,OAAO,WAAW;EACxB,aAAa,QAAQ,aAAa,IAAI;EACtC,OAAO;CACT,QAAQ;EACN,OAAO,WAAW;CACpB;AACF;;AAGA,MAAM,SACJ,KACA,aACA,SACA,WACY;CACZ;CACA;CACA,YAAY,QAAQ,QAAQ;EAAE;EAAS,OAAO;CAAK,CAAC;CACpD,aAAa,QAAQ,QAAQ,KAAK;AACpC;;;;;;AAOA,SAAS,QAAQ,UAAyC;CACxD,IAAI,UAAkC;CACtC,MAAM,eAAgC;EACpC,IAAI,YAAY,MAAM,OAAO;EAC7B,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC,KAAK,QAAQ;EAC7C,UAAU;EACV,MAAM,YAAY;GAChB,IAAI,YAAY,OAAO,UAAU;EACnC,CAAC;EACD,OAAO;CACT;CACA,OAAO;EACL,KAAK;EACL,aAAa;EACb,MAAM,YAAY;GAChB,MAAM,OAAO,OAAO;GAEpB,OAAO;IACL,SAAS,EAAE,eAAe,UAAU,MAFlB,OAE0B;IAC5C,aAAa;KACX,IAAI,YAAY,MAAM,UAAU;IAClC;GACF;EACF;EACA,OAAO,OAAO,UAAU;GACtB,IAAI,OAAO,UAAU;GACrB,OAAO,EAAE,OAAO,MAAM,OAAO,EAAE;EACjC;CACF;AACF;;;;;AAMA,SAAgB,SAAS,OAA4B;CACnD,IAAI,MAAM,gBAAgB,UAAU,OAAO,MAAM,YAAY,eAAe,CAAC,GAAG,CAAC,CAAC;CAClF,IAAI,OAAO,MAAM,UAAU,UAAU;EACnC,MAAM,EAAE,UAAU;EAClB,OAAO,MAAM,UAAU,QAAQ,EAAE,eAAe,UAAU,QAAQ,GAAG,EAAE,MAAM,CAAC;CAChF;CACA,IAAI,OAAO,MAAM,aAAa,YAAY,OAAO,QAAQ,MAAM,QAAQ;CACvE,IAAI,OAAO,MAAM,mBAAmB,UAAU;EAC5C,MAAM,MAAM,MAAM;EAClB,MAAM,UAAU,MAAM,aAAa,YAAY;EAC/C,OAAO,MACL,UACA,QACA;GAAE,eAAe,UAAU;GAAO,sBAAsB;EAAQ,GAChE;GAAE,OAAO;GAAK;EAAQ,CACxB;CACF;CACA,MAAM,IAAI,UACR,mGACF;AACF"}
1
+ {"version":3,"file":"credentials.js","names":[],"sources":["../src/credentials.ts"],"sourcesContent":["/**\n * Who a client calls as, one way at a time (v3/README.md, Credentials): the owner's session cookie\n * in our own app; a person's token, given as it is or asked of the host's backend (and asked again\n * once it expires); or an anonymous visitor of a site, by the site's publishable key and the id\n * the page keeps for them.\n */\n\ntype Way = \"credentials\" | \"token\" | \"getToken\" | \"publishableKey\" | \"visitorId\";\n\n/** One way of signing in, with none of the others beside it. */\ntype Alone<T> = T & { [K in Exclude<Way, keyof T>]?: never };\n\nexport type Credentials =\n /** Our app, on the API's own origin (`/api`): the session cookie the browser holds. */\n | Alone<{ credentials: \"cookie\" }>\n /** A person's token the host's backend minted (`POST /v1/tokens`), used as it is. */\n | Alone<{ token: string }>\n /**\n * A person's token asked of the host's backend: when first needed, and once more each time the\n * API refuses the one kept (it lasts an hour).\n */\n | Alone<{ getToken: () => Promise<string> }>\n /**\n * An anonymous visitor (the widget): the site's publishable key, and who they are, an id the\n * page keeps; one is made and kept in `localStorage` when none is given.\n */\n | Alone<{ publishableKey: string; visitorId?: string | undefined }>;\n\n/** What one request carries to say who calls, and how to have it anew once it is refused. */\ninterface Signed {\n headers: Readonly<Record<string, string>>;\n /** Lets go of a token the API refused, for the next request to ask for another; null: none. */\n renew: (() => void) | null;\n}\n\n/**\n * Who a page speaks for: the business (the owner, in our own app) or a person it serves (a token's\n * person, a publishable key's visitor). The API lets each answer different things: a yes the\n * business decides is the business's alone.\n */\nexport type Speaker = \"business\" | \"person\";\n\n/** How every request and socket of a client says who calls. */\ninterface Signer {\n who: Speaker;\n /** What `fetch` sends of the browser's own: the cookie on the page's origin, or nothing. */\n credentials: RequestCredentials;\n sign: () => Promise<Signed>;\n /**\n * What a socket carries in its address instead (a browser's socket takes no header); `fresh`\n * asks for a new token first, for a socket that could not open with the last one.\n */\n query: (fresh: boolean) => Promise<Readonly<Record<string, string>>>;\n}\n\n/** Where the page keeps its visitor's id, for every SignalCore widget on the site. */\nexport const VISITOR_KEY = \"signalcore.visitor\";\n\n/** What the API takes as a visitor's id: 16 to 128 letters, digits, `_` and `-`. */\nconst VISITOR = /^[A-Za-z0-9_-]{16,128}$/;\n\n/** A new visitor's id: 32 hex characters of the browser's own randomness (any page has it). */\nfunction newVisitor(): string {\n const bytes = crypto.getRandomValues(new Uint8Array(16));\n return Array.from(bytes, (byte) => byte.toString(16).padStart(2, \"0\")).join(\"\");\n}\n\n/**\n * The visitor this page speaks for: the one kept in `localStorage`, else a new one kept there for\n * their next visit; where the page can't keep anything (a private window, storage blocked), a new\n * one for this page alone.\n */\nexport function keptVisitor(): string {\n try {\n const kept = localStorage.getItem(VISITOR_KEY);\n if (kept !== null && VISITOR.test(kept)) return kept;\n const made = newVisitor();\n localStorage.setItem(VISITOR_KEY, made);\n return made;\n } catch {\n return newVisitor();\n }\n}\n\n/** A credential that never changes: the same headers and the same query, nothing to renew. */\nconst fixed = (\n who: Speaker,\n credentials: RequestCredentials,\n headers: Record<string, string>,\n query: Record<string, string>,\n): Signer => ({\n who,\n credentials,\n sign: () => Promise.resolve({ headers, renew: null }),\n query: () => Promise.resolve(query),\n});\n\n/**\n * A token asked of the host's backend: when first needed, then kept. A refusal lets it go, once\n * however many requests were refused with it, so the next request asks for another; one that\n * could not be had is asked for again next time.\n */\nfunction fetched(getToken: () => Promise<string>): Signer {\n let current: Promise<string> | null = null;\n const latest = (): Promise<string> => {\n if (current !== null) return current;\n const asked = Promise.resolve().then(getToken);\n current = asked;\n asked.catch(() => {\n if (current === asked) current = null;\n });\n return asked;\n };\n return {\n who: \"person\",\n credentials: \"omit\",\n sign: async () => {\n const used = latest();\n const token = await used;\n return {\n headers: { Authorization: `Bearer ${token}` },\n renew: () => {\n if (current === used) current = null;\n },\n };\n },\n query: async (fresh) => {\n if (fresh) current = null;\n return { token: await latest() };\n },\n };\n}\n\n/**\n * How a client signs in with what it was given. The API's public prefix reads the header (the\n * socket, its query) and never a cookie, so only our own app sends the browser's.\n */\nexport function signerOf(given: Credentials): Signer {\n if (given.credentials === \"cookie\") return fixed(\"business\", \"same-origin\", {}, {});\n if (typeof given.token === \"string\") {\n const { token } = given;\n return fixed(\"person\", \"omit\", { Authorization: `Bearer ${token}` }, { token });\n }\n if (typeof given.getToken === \"function\") return fetched(given.getToken);\n if (typeof given.publishableKey === \"string\") {\n const key = given.publishableKey;\n const visitor = given.visitorId ?? keptVisitor();\n return fixed(\n \"person\",\n \"omit\",\n { Authorization: `Bearer ${key}`, \"SignalCore-Visitor\": visitor },\n { token: key, visitor },\n );\n }\n throw new TypeError(\n 'createClient takes one way to sign in: credentials: \"cookie\", token, getToken or publishableKey',\n );\n}\n"],"mappings":";;AAwDA,MAAa,cAAc;;AAG3B,MAAM,UAAU;;AAGhB,SAAS,aAAqB;CAC5B,MAAM,QAAQ,OAAO,gCAAgB,IAAI,WAAW,EAAE,CAAC;CACvD,OAAO,MAAM,KAAK,QAAQ,SAAS,KAAK,SAAS,EAAE,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE;AAChF;;;;;;AAOA,SAAgB,cAAsB;CACpC,IAAI;EACF,MAAM,OAAO,aAAa,QAAQ,WAAW;EAC7C,IAAI,SAAS,QAAQ,QAAQ,KAAK,IAAI,GAAG,OAAO;EAChD,MAAM,OAAO,WAAW;EACxB,aAAa,QAAQ,aAAa,IAAI;EACtC,OAAO;CACT,QAAQ;EACN,OAAO,WAAW;CACpB;AACF;;AAGA,MAAM,SACJ,KACA,aACA,SACA,WACY;CACZ;CACA;CACA,YAAY,QAAQ,QAAQ;EAAE;EAAS,OAAO;CAAK,CAAC;CACpD,aAAa,QAAQ,QAAQ,KAAK;AACpC;;;;;;AAOA,SAAS,QAAQ,UAAyC;CACxD,IAAI,UAAkC;CACtC,MAAM,eAAgC;EACpC,IAAI,YAAY,MAAM,OAAO;EAC7B,MAAM,QAAQ,QAAQ,QAAQ,CAAC,CAAC,KAAK,QAAQ;EAC7C,UAAU;EACV,MAAM,YAAY;GAChB,IAAI,YAAY,OAAO,UAAU;EACnC,CAAC;EACD,OAAO;CACT;CACA,OAAO;EACL,KAAK;EACL,aAAa;EACb,MAAM,YAAY;GAChB,MAAM,OAAO,OAAO;GAEpB,OAAO;IACL,SAAS,EAAE,eAAe,UAAU,MAFlB,OAE0B;IAC5C,aAAa;KACX,IAAI,YAAY,MAAM,UAAU;IAClC;GACF;EACF;EACA,OAAO,OAAO,UAAU;GACtB,IAAI,OAAO,UAAU;GACrB,OAAO,EAAE,OAAO,MAAM,OAAO,EAAE;EACjC;CACF;AACF;;;;;AAMA,SAAgB,SAAS,OAA4B;CACnD,IAAI,MAAM,gBAAgB,UAAU,OAAO,MAAM,YAAY,eAAe,CAAC,GAAG,CAAC,CAAC;CAClF,IAAI,OAAO,MAAM,UAAU,UAAU;EACnC,MAAM,EAAE,UAAU;EAClB,OAAO,MAAM,UAAU,QAAQ,EAAE,eAAe,UAAU,QAAQ,GAAG,EAAE,MAAM,CAAC;CAChF;CACA,IAAI,OAAO,MAAM,aAAa,YAAY,OAAO,QAAQ,MAAM,QAAQ;CACvE,IAAI,OAAO,MAAM,mBAAmB,UAAU;EAC5C,MAAM,MAAM,MAAM;EAClB,MAAM,UAAU,MAAM,aAAa,YAAY;EAC/C,OAAO,MACL,UACA,QACA;GAAE,eAAe,UAAU;GAAO,sBAAsB;EAAQ,GAChE;GAAE,OAAO;GAAK;EAAQ,CACxB;CACF;CACA,MAAM,IAAI,UACR,mGACF;AACF"}
package/dist/dev.js CHANGED
@@ -12,6 +12,6 @@ function note(...said) {
12
12
  if (DEV) console.debug("[signalcore]", ...said);
13
13
  }
14
14
  //#endregion
15
- export { DEV, note };
15
+ export { note };
16
16
 
17
17
  //# sourceMappingURL=dev.js.map
package/dist/dev.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"dev.js","names":[],"sources":["../src/dev.ts"],"sourcesContent":["/**\n * Whether the page runs a development build, as React tells it: a host's bundler writes in\n * `process.env.NODE_ENV`; a page without one has no `process`, and counts as production.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\nfunction development(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n\nexport const DEV = development();\n\n/** A note for the developer of the page, in development only: what the package let pass, and why. */\nexport function note(...said: unknown[]): void {\n if (DEV) console.debug(\"[signalcore]\", ...said);\n}\n"],"mappings":";AAMA,SAAS,cAAuB;CAC9B,IAAI;EACF,OAAA,QAAA,IAAA,aAAgC;CAClC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAa,MAAM,YAAY;;AAG/B,SAAgB,KAAK,GAAG,MAAuB;CAC7C,IAAI,KAAK,QAAQ,MAAM,gBAAgB,GAAG,IAAI;AAChD"}
1
+ {"version":3,"file":"dev.js","names":[],"sources":["../src/dev.ts"],"sourcesContent":["/**\n * Whether the page runs a development build, as React tells it: a host's bundler writes in\n * `process.env.NODE_ENV`; a page without one has no `process`, and counts as production.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\nfunction development(): boolean {\n try {\n return process.env.NODE_ENV !== \"production\";\n } catch {\n return false;\n }\n}\n\nconst DEV = development();\n\n/** A note for the developer of the page, in development only: what the package let pass, and why. */\nexport function note(...said: unknown[]): void {\n if (DEV) console.debug(\"[signalcore]\", ...said);\n}\n"],"mappings":";AAMA,SAAS,cAAuB;CAC9B,IAAI;EACF,OAAA,QAAA,IAAA,aAAgC;CAClC,QAAQ;EACN,OAAO;CACT;AACF;AAEA,MAAM,MAAM,YAAY;;AAGxB,SAAgB,KAAK,GAAG,MAAuB;CAC7C,IAAI,KAAK,QAAQ,MAAM,gBAAgB,GAAG,IAAI;AAChD"}
package/dist/es.js CHANGED
@@ -41,6 +41,7 @@ const AUTOMATION_MESSAGES_ES = {
41
41
  on: (often, when) => `${often}, ${when.charAt(0).toLowerCase()}${when.slice(1)}`,
42
42
  custom: "Con un horario propio",
43
43
  webhook: "Cuando otro sistema la llama",
44
+ platform: "Cuando llega un mensaje",
44
45
  event: (app, event) => event ? `Cuando pasa «${event}» en ${app ?? "una app"}` : `Cuando pasa algo en ${app ?? "una app"}`,
45
46
  next: (day, time) => [
46
47
  "próxima",
@@ -78,6 +79,7 @@ const AUTOMATION_MESSAGES_ES = {
78
79
  schedule: "horario",
79
80
  webhook: "webhook",
80
81
  event: app ? `evento de ${app}` : "evento",
82
+ platform: "un mensaje",
81
83
  agent: "se lo pidieron en el chat",
82
84
  test: "prueba"
83
85
  })[by],
@@ -179,7 +181,13 @@ const KIT_MESSAGES_ES = {
179
181
  play: "Reproducir",
180
182
  pause: "Pausar",
181
183
  position: "Posición",
182
- automation: AUTOMATION_MESSAGES_ES
184
+ automation: AUTOMATION_MESSAGES_ES,
185
+ connect: {
186
+ authorize: (app) => `Autorizar en ${app}`,
187
+ connected: "Conectada",
188
+ failed: "No se ha podido conectar",
189
+ preparing: "Preparando la conexión"
190
+ }
183
191
  };
184
192
  const BROWSER_MESSAGES_ES = {
185
193
  agent: (name) => `Lo controla ${name}`,
package/dist/es.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"es.js","names":[],"sources":["../src/es.ts"],"sourcesContent":["/**\n * The package's words in Spanish, for the people an agent serves: the chat, the browser it drives,\n * the kit's controls (with an automation's and its runs'), a call and the agent's space. English\n * is every component's default; a host in Spanish passes these as `messages`, the calendar's\n * language as `locale` (`import { es } from \"@signalcore/ui/locale\"`).\n */\nimport type { ChatMessages } from \"./AgentChat\";\nimport type { SpaceMessages } from \"./AgentSpace\";\nimport type { TaskMessages } from \"./AgentTasks\";\nimport type { AutomationMessages, DayRef } from \"./automation/messages\";\nimport type { BrowserMessages } from \"./BrowserView\";\nimport type { KitMessages } from \"./kit/messages\";\nimport type { VoiceCallMessages } from \"./VoiceCall\";\n\n/** The article before a time: \"la 1:00\", \"las 8:00\". */\nconst at = (time: string): string => `a ${time.startsWith(\"1:\") ? \"la\" : \"las\"} ${time}`;\n\nconst list = (items: readonly string[]): string => new Intl.ListFormat(\"es\").format(items);\n\n/** A weekday as the plural says it: \"los lunes\", \"los sábados\". */\nconst days = (name: string): string => (name.endsWith(\"s\") ? name : `${name}s`);\n\nconst capital = (text: string): string => text.charAt(0).toUpperCase() + text.slice(1);\n\n/** A day said after \"próxima\": \"hoy\", \"mañana\", \"el lunes\", \"el 3 nov\". */\nfunction nextDay(day: DayRef): string {\n switch (day.kind) {\n case \"today\":\n return \"hoy\";\n case \"tomorrow\":\n return \"mañana\";\n case \"yesterday\":\n return \"\";\n default:\n return `el ${day.name}`;\n }\n}\n\n/** A message sent on a channel, by the channel's kind: \"un WhatsApp\", \"un SMS\". */\nconst SENT: Readonly<Record<string, string>> = {\n whatsapp: \"un WhatsApp\",\n instagram: \"un mensaje de Instagram\",\n sms: \"un SMS\",\n};\n\n/** What an automation's tool call did, by what the tool's name says, done or (a test) not. */\nconst TOOL = {\n search: [(app: string) => `Buscó en ${app}`, (app: string) => `Buscó en ${app}`],\n send: [(app: string) => `Envió por ${app}`, (app: string) => `Habría enviado por ${app}`],\n create: [(app: string) => `Creó en ${app}`, (app: string) => `Habría creado en ${app}`],\n update: [(app: string) => `Cambió en ${app}`, (app: string) => `Habría cambiado en ${app}`],\n remove: [(app: string) => `Borró en ${app}`, (app: string) => `Habría borrado en ${app}`],\n use: [(app: string) => `Usó ${app}`, (app: string) => `Habría usado ${app}`],\n} as const;\n\nexport const AUTOMATION_MESSAGES_ES: AutomationMessages = {\n daily: \"Cada día\",\n weekdays: \"Cada día laborable\",\n weekends: \"Los fines de semana\",\n weekly: (names) =>\n names.length === 1 ? `Cada ${names[0] ?? \"\"}` : `Los ${list(names.map(days))}`,\n monthly: (numbers) =>\n numbers.length === 1\n ? `El día ${numbers[0] ?? \"\"} de cada mes`\n : `Los días ${list(numbers.map(String))} de cada mes`,\n at: (times) => list(times.map(at)),\n every: (count, unit) =>\n unit === \"minute\"\n ? count === 1\n ? \"Cada minuto\"\n : `Cada ${count} minutos`\n : count === 1\n ? \"Cada hora\"\n : `Cada ${count} horas`,\n between: (from, to) => `de ${from} a ${to}`,\n on: (often, when) => `${often}, ${when.charAt(0).toLowerCase()}${when.slice(1)}`,\n custom: \"Con un horario propio\",\n webhook: \"Cuando otro sistema la llama\",\n event: (app, event) =>\n event\n ? `Cuando pasa «${event}» en ${app ?? \"una app\"}`\n : `Cuando pasa algo en ${app ?? \"una app\"}`,\n next: (day, time) =>\n [\"próxima\", nextDay(day), time === null ? \"\" : at(time)].filter(Boolean).join(\" \"),\n states: { active: \"Activa\", paused: \"En pausa\", failing: \"Falló la última\" },\n switchLabel: \"Activa\",\n steps: \"Pasos\",\n runs: \"Ejecuciones\",\n noRuns: \"Aún no se ha ejecutado.\",\n uses: {\n ai: \"IA\",\n agent: \"Agente\",\n notify: \"Aviso\",\n send: \"Mensaje\",\n data: \"Tabla\",\n http: \"Web\",\n },\n more: (count) => `+${count}`,\n gone: \"Esta automatización ya no existe.\",\n moment: (day, time) => {\n switch (day.kind) {\n case \"today\":\n return `Hoy ${time}`;\n case \"yesterday\":\n return `Ayer ${time}`;\n case \"tomorrow\":\n return `Mañana ${time}`;\n default:\n return `${capital(day.name)} ${time}`;\n }\n },\n by: (by, app) =>\n ({\n schedule: \"horario\",\n webhook: \"webhook\",\n event: app ? `evento de ${app}` : \"evento\",\n agent: \"se lo pidieron en el chat\",\n test: \"prueba\",\n })[by],\n statuses: {\n running: \"En curso\",\n waiting: \"Esperando\",\n done: \"Hecha\",\n failed: \"Falló\",\n skipped: \"Omitida\",\n },\n dry: (summary) => `Prueba: ${summary}`,\n took: (ms) => {\n if (ms < 1000) return \"menos de 1 s\";\n const seconds = Math.round(ms / 1000);\n return seconds < 60 ? `${seconds} s` : `${Math.floor(seconds / 60)} min ${seconds % 60} s`;\n },\n opened: \"Conversaciones que abrió\",\n conversation: (index) => `Conversación ${index}`,\n askedIn: \"La conversación donde se lo pidieron\",\n noCalls: \"No llegó a hacer nada.\",\n outside: \"Fuera de los pasos\",\n times: (count) => `×${count}`,\n calls: {\n tool: (verb, app, would) => TOOL[verb][would ? 1 : 0](app),\n ai: \"Usó la IA\",\n notify: (would) => (would ? \"Habría avisado en la bandeja\" : \"Avisó en la bandeja\"),\n send: (channel, to, would) => {\n const sent = `${SENT[channel ?? \"\"] ?? \"un mensaje\"} a ${to || \"un contacto\"}`;\n return would ? `Habría enviado ${sent}` : `Envió ${sent}`;\n },\n start: (would) => (would ? \"Habría abierto una conversación\" : \"Abrió una conversación\"),\n find: (table) => `Consultó ${table}`,\n add: (table, would) =>\n would ? `Habría añadido una fila a ${table}` : `Añadió una fila a ${table}`,\n change: (table, would) =>\n would ? `Habría cambiado una fila de ${table}` : `Cambió una fila de ${table}`,\n http: (host, would) => (would ? `Habría llamado a ${host}` : `Llamó a ${host}`),\n files: \"Buscó en los archivos\",\n read: (file) => `Leyó ${file}`,\n wrote: (file, would) => (would ? `Habría guardado ${file}` : `Guardó ${file}`),\n listed: \"Miró sus archivos\",\n remember: (would) => (would ? \"Habría guardado un recuerdo\" : \"Guardó un recuerdo\"),\n recall: \"Buscó en lo aprendido\",\n },\n};\n\nconst FAMILIES: Readonly<Record<string, string>> = {\n image: \"imágenes\",\n video: \"vídeos\",\n audio: \"audios\",\n text: \"textos\",\n};\n\nexport const KIT_MESSAGES_ES: KitMessages = {\n required: \"Este campo es obligatorio\",\n chooseDate: \"Elige un día\",\n chooseTime: \"Elige una hora\",\n chooseMoment: \"Elige día y hora\",\n chooseOption: \"Elige una opción\",\n other: \"Otra respuesta\",\n otherPlaceholder: \"Escribe tu respuesta\",\n chooseRating: \"Elige una puntuación\",\n check: \"Marca la casilla para seguir\",\n invalidEmail: \"Correo no válido\",\n invalidPhone: \"Teléfono no válido\",\n invalidUrl: \"Dirección no válida\",\n invalidNumber: \"Escribe un número\",\n invalidTime: \"Escribe la hora así: 9:30\",\n atLeast: (min) => `Como mínimo ${min}`,\n atMost: (max) => `Como máximo ${max}`,\n unavailableDate: \"Ese día no está disponible\",\n unavailableTime: \"Esa hora no está disponible\",\n optional: \"Opcional\",\n pick: \"Elige…\",\n search: \"Buscar…\",\n noResults: \"Sin resultados\",\n show: \"Mostrar\",\n hide: \"Ocultar\",\n increase: \"Sumar\",\n decrease: \"Restar\",\n remove: (label) => `Quitar ${label}`,\n yes: \"Sí\",\n no: \"No\",\n rated: (value, max) => `${value} de ${max}`,\n stars: (count) => (count === 1 ? \"1 estrella\" : `${count} estrellas`),\n send: \"Enviar\",\n sent: \"Enviado\",\n chooseFile: \"Falta el archivo\",\n upload: (multiple) => (multiple ? \"Sube archivos\" : \"Sube un archivo\"),\n drop: \"Suelta aquí o elige\",\n limits: (kinds, size) => (kinds ? `${kinds}, hasta ${size}` : `Hasta ${size}`),\n anyOf: (family) => FAMILIES[family] ?? family,\n uploading: \"Subiendo\",\n tooBig: (size) => `Pasa de ${size}`,\n wrongType: \"Aquí no vale este tipo de archivo\",\n tooMany: (max) => `Como máximo ${max} archivos`,\n uploadFailed: \"No se ha podido subir\",\n retry: \"Reintentar\",\n stillUploading: \"Espera a que termine de subir\",\n fixFiles: \"Quita o reintenta los archivos con error\",\n open: (name) => `Abrir ${name}`,\n file: \"Archivo\",\n play: \"Reproducir\",\n pause: \"Pausar\",\n position: \"Posición\",\n automation: AUTOMATION_MESSAGES_ES,\n};\n\nexport const BROWSER_MESSAGES_ES: BrowserMessages = {\n agent: (name) => `Lo controla ${name}`,\n agentMine: (name) => `${name}, en tu Chrome`,\n person: \"Lo controlas tú\",\n take: \"Tomar el control\",\n giveBack: \"Devolver\",\n handedOver: (name) => `${name} te pasa el navegador`,\n done: \"Listo, sigue\",\n closed: \"El navegador se cerró mientras te esperaba.\",\n close: \"Cerrar el navegador\",\n expand: \"Ampliar\",\n shrink: \"Reducir\",\n blank: \"Página en blanco\",\n screen: (where) => `Navegador: ${where}`,\n};\n\nexport const CHAT_MESSAGES_ES: ChatMessages = {\n placeholder: (name) => `Escribe a ${name}…`,\n connecting: \"Conectando…\",\n awaiting: \"Responde arriba para seguir…\",\n thinking: (name) => `${name} está pensando`,\n typing: \"Escribiendo\",\n working: \"Trabajando\",\n writing: \"Escribiendo\",\n elapsed: (seconds) => `${seconds} s`,\n escape: \"esc para detener\",\n done: (seconds) =>\n `Listo en ${seconds < 60 ? `${seconds} s` : `${Math.floor(seconds / 60)} min ${seconds % 60} s`}`,\n empty: (name) => `Habla con ${name}`,\n intro: () => \"\",\n send: \"Enviar\",\n attach: \"Adjuntar archivos\",\n drop: \"Suelta para adjuntar\",\n dictate: \"Dictar\",\n dictateStop: \"Parar y escribirlo\",\n dictation: {\n listening: \"Escuchando…\",\n writing: \"Escribiéndolo…\",\n failed: \"No te he oído: permite el micrófono e inténtalo otra vez\",\n },\n stop: \"Detener\",\n log: \"Conversación\",\n steps: {\n show: \"Muestra\",\n ask_person: \"Pregunta\",\n search_files: \"Busca en archivos\",\n read_file: \"Lee un archivo\",\n keep_file: \"Guarda un archivo\",\n remember: \"Recuerda\",\n recall: \"Busca en lo aprendido\",\n escalate: \"Pasa a una persona\",\n notify: \"Avisa\",\n data_find: \"Consulta una tabla\",\n data_add: \"Añade una fila\",\n data_update: \"Cambia una fila\",\n browser_open: \"Abre una página\",\n browser_read: \"Lee la página\",\n browser_click: \"Hace clic\",\n browser_fill: \"Rellena un campo\",\n browser_scroll: \"Desplaza la página\",\n browser_back: \"Vuelve atrás\",\n browser_submit: \"Envía en la web\",\n browser_hand_over: \"Te pasa el navegador\",\n browser_attach: \"Sube un archivo a la web\",\n browser_download: \"Guarda un archivo de la web\",\n browser_screenshot: \"Hace una captura de la web\",\n browser_record: \"Graba la web en vídeo\",\n browser_fill_key: \"Escribe una clave en la web\",\n ask_builder: \"Se lo pide al builder\",\n send_message: \"Envía un mensaje\",\n voice_note: \"Manda una nota de voz\",\n ai: \"Usa la IA\",\n call: \"Llama\",\n },\n failed: \"falló\",\n approval: \"Necesita tu aprobación\",\n request: (name, action) => `${name} quiere hacer «${action}»`,\n inputs: {},\n allow: \"Aprobar\",\n decline: \"Rechazar\",\n confirming: \"Esperando la confirmación del negocio\",\n handedOff: \"Pasada a una persona\",\n handover: (holder, by, name) => {\n const automation = by.kind === \"automation\" ? ` por «${by.title}»` : \"\";\n switch (holder) {\n case \"agent\":\n if (by.kind === \"owner\") return `Devolviste la conversación a ${name}`;\n return `Se devolvió a ${name}${automation}`;\n case \"person\":\n if (by.kind === \"owner\") return `Pausaste a ${name}`;\n if (by.kind === \"agent\") return `${name} la pasó a una persona`;\n return `Pasó a una persona${automation}`;\n case \"nobody\":\n return `Ignorada${automation}`;\n }\n },\n skipped: \"No respondió\",\n cut: (heard) =>\n heard === \"\" ? \"Interrumpida antes de que se oyera nada\" : `Interrumpida tras «${heard}»`,\n write: \"Responde como el negocio…\",\n business: \"Tú\",\n voiceNote: \"Nota de voz\",\n delivery: {\n queued: \"Esperando para salir\",\n sent: \"Enviado\",\n delivered: \"Entregado\",\n read: \"Leído\",\n failed: \"No entregado\",\n },\n undelivered: (error) => (error ? `No entregado: ${error}` : \"No entregado\"),\n noTool: \"Esta página no puede hacer eso\",\n kit: KIT_MESSAGES_ES,\n browser: BROWSER_MESSAGES_ES,\n};\n\nexport const VOICE_CALL_MESSAGES_ES: VoiceCallMessages = {\n call: (name) => `Llamada con ${name}`,\n states: {\n connecting: \"Conectando…\",\n listening: \"Escuchando\",\n thinking: \"Pensando\",\n speaking: \"Hablando\",\n reconnecting: \"Reconectando…\",\n ended: \"Llamada terminada\",\n },\n calling: (name) => `Llamando a ${name}`,\n ended: {\n person: () => \"Has colgado\",\n agent: (name) => `${name} ha colgado`,\n limit: () => \"Se alcanzó la duración máxima\",\n dropped: () => \"Se cortó la llamada\",\n },\n problems: {\n denied: {\n title: () => \"Sin permiso para el micrófono\",\n help: \"Permite el micrófono a esta página (en el icono junto a la dirección) y vuelve a llamar.\",\n },\n nomic: {\n title: () => \"No hay ningún micrófono\",\n help: \"Conecta uno, o elige otro en los ajustes de sonido del sistema, y vuelve a llamar.\",\n },\n inuse: {\n title: () => \"El micrófono está ocupado\",\n help: \"Otra aplicación lo está usando. Ciérrala y vuelve a llamar.\",\n },\n unsupported: {\n title: () => \"Este navegador no puede llamar\",\n help: \"Abre la página por https en un Chrome, Edge, Safari o Firefox actual.\",\n },\n off: {\n title: () => \"Las llamadas no están activadas\",\n help: \"Este servicio aún no atiende llamadas. Escríbele mientras tanto.\",\n },\n builder: {\n title: (name) => `${name} no atiende llamadas`,\n help: \"Escríbele en el chat.\",\n },\n refused: {\n title: (name) => `${name} no puede atender la llamada`,\n help: \"Inténtalo de nuevo en un momento.\",\n },\n failed: {\n title: (name) => `No se ha podido llamar a ${name}`,\n help: \"Comprueba tu conexión y vuelve a intentarlo.\",\n },\n unanswered: {\n title: (name) => `${name} no contesta`,\n help: \"Ahora mismo no atiende llamadas. Inténtalo de nuevo en un momento.\",\n },\n },\n mute: \"Silenciar\",\n hangUp: \"Colgar\",\n keys: \"Espacio silencia y activa el micrófono\",\n muted: \"Tu micrófono está silenciado\",\n hear: (name) => `Oír a ${name}`,\n};\n\nexport const TASK_MESSAGES_ES: TaskMessages = {\n open: (count) =>\n count === 1 ? \"Tienes 1 tarea programada\" : `Tienes ${count} tareas programadas`,\n title: \"Tus tareas\",\n back: \"Volver a la conversación\",\n remove: \"Quitar\",\n empty: \"No hay nada programado. Pídele que te recuerde algo, o que te escriba más adelante.\",\n failed: \"No se ha podido cambiar. Inténtalo de nuevo.\",\n};\n\nexport const SPACE_MESSAGES_ES: SpaceMessages = {\n modes: { label: \"Modo\", text: \"Texto\", voice: \"Voz\" },\n again: \"Volver a llamar\",\n close: \"Cerrar\",\n agent: \"Agente\",\n opening: \"Abriendo la conversación…\",\n failed: \"No se ha podido abrir la conversación.\",\n retry: \"Reintentar\",\n chat: CHAT_MESSAGES_ES,\n voice: VOICE_CALL_MESSAGES_ES,\n tasks: TASK_MESSAGES_ES,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"es.js","names":[],"sources":["../src/es.ts"],"sourcesContent":["/**\n * The package's words in Spanish, for the people an agent serves: the chat, the browser it drives,\n * the kit's controls (with an automation's and its runs'), a call and the agent's space. English\n * is every component's default; a host in Spanish passes these as `messages`, the calendar's\n * language as `locale` (`import { es } from \"@signalcore/ui/locale\"`).\n */\nimport type { ChatMessages } from \"./AgentChat\";\nimport type { SpaceMessages } from \"./AgentSpace\";\nimport type { TaskMessages } from \"./AgentTasks\";\nimport type { AutomationMessages, DayRef } from \"./automation/messages\";\nimport type { BrowserMessages } from \"./BrowserView\";\nimport type { KitMessages } from \"./kit/messages\";\nimport type { VoiceCallMessages } from \"./VoiceCall\";\n\n/** The article before a time: \"la 1:00\", \"las 8:00\". */\nconst at = (time: string): string => `a ${time.startsWith(\"1:\") ? \"la\" : \"las\"} ${time}`;\n\nconst list = (items: readonly string[]): string => new Intl.ListFormat(\"es\").format(items);\n\n/** A weekday as the plural says it: \"los lunes\", \"los sábados\". */\nconst days = (name: string): string => (name.endsWith(\"s\") ? name : `${name}s`);\n\nconst capital = (text: string): string => text.charAt(0).toUpperCase() + text.slice(1);\n\n/** A day said after \"próxima\": \"hoy\", \"mañana\", \"el lunes\", \"el 3 nov\". */\nfunction nextDay(day: DayRef): string {\n switch (day.kind) {\n case \"today\":\n return \"hoy\";\n case \"tomorrow\":\n return \"mañana\";\n case \"yesterday\":\n return \"\";\n default:\n return `el ${day.name}`;\n }\n}\n\n/** A message sent on a channel, by the channel's kind: \"un WhatsApp\", \"un SMS\". */\nconst SENT: Readonly<Record<string, string>> = {\n whatsapp: \"un WhatsApp\",\n instagram: \"un mensaje de Instagram\",\n sms: \"un SMS\",\n};\n\n/** What an automation's tool call did, by what the tool's name says, done or (a test) not. */\nconst TOOL = {\n search: [(app: string) => `Buscó en ${app}`, (app: string) => `Buscó en ${app}`],\n send: [(app: string) => `Envió por ${app}`, (app: string) => `Habría enviado por ${app}`],\n create: [(app: string) => `Creó en ${app}`, (app: string) => `Habría creado en ${app}`],\n update: [(app: string) => `Cambió en ${app}`, (app: string) => `Habría cambiado en ${app}`],\n remove: [(app: string) => `Borró en ${app}`, (app: string) => `Habría borrado en ${app}`],\n use: [(app: string) => `Usó ${app}`, (app: string) => `Habría usado ${app}`],\n} as const;\n\nexport const AUTOMATION_MESSAGES_ES: AutomationMessages = {\n daily: \"Cada día\",\n weekdays: \"Cada día laborable\",\n weekends: \"Los fines de semana\",\n weekly: (names) =>\n names.length === 1 ? `Cada ${names[0] ?? \"\"}` : `Los ${list(names.map(days))}`,\n monthly: (numbers) =>\n numbers.length === 1\n ? `El día ${numbers[0] ?? \"\"} de cada mes`\n : `Los días ${list(numbers.map(String))} de cada mes`,\n at: (times) => list(times.map(at)),\n every: (count, unit) =>\n unit === \"minute\"\n ? count === 1\n ? \"Cada minuto\"\n : `Cada ${count} minutos`\n : count === 1\n ? \"Cada hora\"\n : `Cada ${count} horas`,\n between: (from, to) => `de ${from} a ${to}`,\n on: (often, when) => `${often}, ${when.charAt(0).toLowerCase()}${when.slice(1)}`,\n custom: \"Con un horario propio\",\n webhook: \"Cuando otro sistema la llama\",\n platform: \"Cuando llega un mensaje\",\n event: (app, event) =>\n event\n ? `Cuando pasa «${event}» en ${app ?? \"una app\"}`\n : `Cuando pasa algo en ${app ?? \"una app\"}`,\n next: (day, time) =>\n [\"próxima\", nextDay(day), time === null ? \"\" : at(time)].filter(Boolean).join(\" \"),\n states: { active: \"Activa\", paused: \"En pausa\", failing: \"Falló la última\" },\n switchLabel: \"Activa\",\n steps: \"Pasos\",\n runs: \"Ejecuciones\",\n noRuns: \"Aún no se ha ejecutado.\",\n uses: {\n ai: \"IA\",\n agent: \"Agente\",\n notify: \"Aviso\",\n send: \"Mensaje\",\n data: \"Tabla\",\n http: \"Web\",\n },\n more: (count) => `+${count}`,\n gone: \"Esta automatización ya no existe.\",\n moment: (day, time) => {\n switch (day.kind) {\n case \"today\":\n return `Hoy ${time}`;\n case \"yesterday\":\n return `Ayer ${time}`;\n case \"tomorrow\":\n return `Mañana ${time}`;\n default:\n return `${capital(day.name)} ${time}`;\n }\n },\n by: (by, app) =>\n ({\n schedule: \"horario\",\n webhook: \"webhook\",\n event: app ? `evento de ${app}` : \"evento\",\n platform: \"un mensaje\",\n agent: \"se lo pidieron en el chat\",\n test: \"prueba\",\n })[by],\n statuses: {\n running: \"En curso\",\n waiting: \"Esperando\",\n done: \"Hecha\",\n failed: \"Falló\",\n skipped: \"Omitida\",\n },\n dry: (summary) => `Prueba: ${summary}`,\n took: (ms) => {\n if (ms < 1000) return \"menos de 1 s\";\n const seconds = Math.round(ms / 1000);\n return seconds < 60 ? `${seconds} s` : `${Math.floor(seconds / 60)} min ${seconds % 60} s`;\n },\n opened: \"Conversaciones que abrió\",\n conversation: (index) => `Conversación ${index}`,\n askedIn: \"La conversación donde se lo pidieron\",\n noCalls: \"No llegó a hacer nada.\",\n outside: \"Fuera de los pasos\",\n times: (count) => `×${count}`,\n calls: {\n tool: (verb, app, would) => TOOL[verb][would ? 1 : 0](app),\n ai: \"Usó la IA\",\n notify: (would) => (would ? \"Habría avisado en la bandeja\" : \"Avisó en la bandeja\"),\n send: (channel, to, would) => {\n const sent = `${SENT[channel ?? \"\"] ?? \"un mensaje\"} a ${to || \"un contacto\"}`;\n return would ? `Habría enviado ${sent}` : `Envió ${sent}`;\n },\n start: (would) => (would ? \"Habría abierto una conversación\" : \"Abrió una conversación\"),\n find: (table) => `Consultó ${table}`,\n add: (table, would) =>\n would ? `Habría añadido una fila a ${table}` : `Añadió una fila a ${table}`,\n change: (table, would) =>\n would ? `Habría cambiado una fila de ${table}` : `Cambió una fila de ${table}`,\n http: (host, would) => (would ? `Habría llamado a ${host}` : `Llamó a ${host}`),\n files: \"Buscó en los archivos\",\n read: (file) => `Leyó ${file}`,\n wrote: (file, would) => (would ? `Habría guardado ${file}` : `Guardó ${file}`),\n listed: \"Miró sus archivos\",\n remember: (would) => (would ? \"Habría guardado un recuerdo\" : \"Guardó un recuerdo\"),\n recall: \"Buscó en lo aprendido\",\n },\n};\n\nconst FAMILIES: Readonly<Record<string, string>> = {\n image: \"imágenes\",\n video: \"vídeos\",\n audio: \"audios\",\n text: \"textos\",\n};\n\nexport const KIT_MESSAGES_ES: KitMessages = {\n required: \"Este campo es obligatorio\",\n chooseDate: \"Elige un día\",\n chooseTime: \"Elige una hora\",\n chooseMoment: \"Elige día y hora\",\n chooseOption: \"Elige una opción\",\n other: \"Otra respuesta\",\n otherPlaceholder: \"Escribe tu respuesta\",\n chooseRating: \"Elige una puntuación\",\n check: \"Marca la casilla para seguir\",\n invalidEmail: \"Correo no válido\",\n invalidPhone: \"Teléfono no válido\",\n invalidUrl: \"Dirección no válida\",\n invalidNumber: \"Escribe un número\",\n invalidTime: \"Escribe la hora así: 9:30\",\n atLeast: (min) => `Como mínimo ${min}`,\n atMost: (max) => `Como máximo ${max}`,\n unavailableDate: \"Ese día no está disponible\",\n unavailableTime: \"Esa hora no está disponible\",\n optional: \"Opcional\",\n pick: \"Elige…\",\n search: \"Buscar…\",\n noResults: \"Sin resultados\",\n show: \"Mostrar\",\n hide: \"Ocultar\",\n increase: \"Sumar\",\n decrease: \"Restar\",\n remove: (label) => `Quitar ${label}`,\n yes: \"Sí\",\n no: \"No\",\n rated: (value, max) => `${value} de ${max}`,\n stars: (count) => (count === 1 ? \"1 estrella\" : `${count} estrellas`),\n send: \"Enviar\",\n sent: \"Enviado\",\n chooseFile: \"Falta el archivo\",\n upload: (multiple) => (multiple ? \"Sube archivos\" : \"Sube un archivo\"),\n drop: \"Suelta aquí o elige\",\n limits: (kinds, size) => (kinds ? `${kinds}, hasta ${size}` : `Hasta ${size}`),\n anyOf: (family) => FAMILIES[family] ?? family,\n uploading: \"Subiendo\",\n tooBig: (size) => `Pasa de ${size}`,\n wrongType: \"Aquí no vale este tipo de archivo\",\n tooMany: (max) => `Como máximo ${max} archivos`,\n uploadFailed: \"No se ha podido subir\",\n retry: \"Reintentar\",\n stillUploading: \"Espera a que termine de subir\",\n fixFiles: \"Quita o reintenta los archivos con error\",\n open: (name) => `Abrir ${name}`,\n file: \"Archivo\",\n play: \"Reproducir\",\n pause: \"Pausar\",\n position: \"Posición\",\n automation: AUTOMATION_MESSAGES_ES,\n connect: {\n authorize: (app) => `Autorizar en ${app}`,\n connected: \"Conectada\",\n failed: \"No se ha podido conectar\",\n preparing: \"Preparando la conexión\",\n },\n};\n\nexport const BROWSER_MESSAGES_ES: BrowserMessages = {\n agent: (name) => `Lo controla ${name}`,\n agentMine: (name) => `${name}, en tu Chrome`,\n person: \"Lo controlas tú\",\n take: \"Tomar el control\",\n giveBack: \"Devolver\",\n handedOver: (name) => `${name} te pasa el navegador`,\n done: \"Listo, sigue\",\n closed: \"El navegador se cerró mientras te esperaba.\",\n close: \"Cerrar el navegador\",\n expand: \"Ampliar\",\n shrink: \"Reducir\",\n blank: \"Página en blanco\",\n screen: (where) => `Navegador: ${where}`,\n};\n\nexport const CHAT_MESSAGES_ES: ChatMessages = {\n placeholder: (name) => `Escribe a ${name}…`,\n connecting: \"Conectando…\",\n awaiting: \"Responde arriba para seguir…\",\n thinking: (name) => `${name} está pensando`,\n typing: \"Escribiendo\",\n working: \"Trabajando\",\n writing: \"Escribiendo\",\n elapsed: (seconds) => `${seconds} s`,\n escape: \"esc para detener\",\n done: (seconds) =>\n `Listo en ${seconds < 60 ? `${seconds} s` : `${Math.floor(seconds / 60)} min ${seconds % 60} s`}`,\n empty: (name) => `Habla con ${name}`,\n intro: () => \"\",\n send: \"Enviar\",\n attach: \"Adjuntar archivos\",\n drop: \"Suelta para adjuntar\",\n dictate: \"Dictar\",\n dictateStop: \"Parar y escribirlo\",\n dictation: {\n listening: \"Escuchando…\",\n writing: \"Escribiéndolo…\",\n failed: \"No te he oído: permite el micrófono e inténtalo otra vez\",\n },\n stop: \"Detener\",\n log: \"Conversación\",\n steps: {\n show: \"Muestra\",\n ask_person: \"Pregunta\",\n search_files: \"Busca en archivos\",\n read_file: \"Lee un archivo\",\n keep_file: \"Guarda un archivo\",\n remember: \"Recuerda\",\n recall: \"Busca en lo aprendido\",\n escalate: \"Pasa a una persona\",\n notify: \"Avisa\",\n data_find: \"Consulta una tabla\",\n data_add: \"Añade una fila\",\n data_update: \"Cambia una fila\",\n browser_open: \"Abre una página\",\n browser_read: \"Lee la página\",\n browser_click: \"Hace clic\",\n browser_fill: \"Rellena un campo\",\n browser_scroll: \"Desplaza la página\",\n browser_back: \"Vuelve atrás\",\n browser_submit: \"Envía en la web\",\n browser_hand_over: \"Te pasa el navegador\",\n browser_attach: \"Sube un archivo a la web\",\n browser_download: \"Guarda un archivo de la web\",\n browser_screenshot: \"Hace una captura de la web\",\n browser_record: \"Graba la web en vídeo\",\n browser_fill_key: \"Escribe una clave en la web\",\n ask_builder: \"Se lo pide al builder\",\n send_message: \"Envía un mensaje\",\n voice_note: \"Manda una nota de voz\",\n ai: \"Usa la IA\",\n call: \"Llama\",\n },\n failed: \"falló\",\n approval: \"Necesita tu aprobación\",\n request: (name, action) => `${name} quiere hacer «${action}»`,\n inputs: {},\n allow: \"Aprobar\",\n decline: \"Rechazar\",\n confirming: \"Esperando la confirmación del negocio\",\n handedOff: \"Pasada a una persona\",\n handover: (holder, by, name) => {\n const automation = by.kind === \"automation\" ? ` por «${by.title}»` : \"\";\n switch (holder) {\n case \"agent\":\n if (by.kind === \"owner\") return `Devolviste la conversación a ${name}`;\n return `Se devolvió a ${name}${automation}`;\n case \"person\":\n if (by.kind === \"owner\") return `Pausaste a ${name}`;\n if (by.kind === \"agent\") return `${name} la pasó a una persona`;\n return `Pasó a una persona${automation}`;\n case \"nobody\":\n return `Ignorada${automation}`;\n }\n },\n skipped: \"No respondió\",\n cut: (heard) =>\n heard === \"\" ? \"Interrumpida antes de que se oyera nada\" : `Interrumpida tras «${heard}»`,\n write: \"Responde como el negocio…\",\n business: \"Tú\",\n voiceNote: \"Nota de voz\",\n delivery: {\n queued: \"Esperando para salir\",\n sent: \"Enviado\",\n delivered: \"Entregado\",\n read: \"Leído\",\n failed: \"No entregado\",\n },\n undelivered: (error) => (error ? `No entregado: ${error}` : \"No entregado\"),\n noTool: \"Esta página no puede hacer eso\",\n kit: KIT_MESSAGES_ES,\n browser: BROWSER_MESSAGES_ES,\n};\n\nexport const VOICE_CALL_MESSAGES_ES: VoiceCallMessages = {\n call: (name) => `Llamada con ${name}`,\n states: {\n connecting: \"Conectando…\",\n listening: \"Escuchando\",\n thinking: \"Pensando\",\n speaking: \"Hablando\",\n reconnecting: \"Reconectando…\",\n ended: \"Llamada terminada\",\n },\n calling: (name) => `Llamando a ${name}`,\n ended: {\n person: () => \"Has colgado\",\n agent: (name) => `${name} ha colgado`,\n limit: () => \"Se alcanzó la duración máxima\",\n dropped: () => \"Se cortó la llamada\",\n },\n problems: {\n denied: {\n title: () => \"Sin permiso para el micrófono\",\n help: \"Permite el micrófono a esta página (en el icono junto a la dirección) y vuelve a llamar.\",\n },\n nomic: {\n title: () => \"No hay ningún micrófono\",\n help: \"Conecta uno, o elige otro en los ajustes de sonido del sistema, y vuelve a llamar.\",\n },\n inuse: {\n title: () => \"El micrófono está ocupado\",\n help: \"Otra aplicación lo está usando. Ciérrala y vuelve a llamar.\",\n },\n unsupported: {\n title: () => \"Este navegador no puede llamar\",\n help: \"Abre la página por https en un Chrome, Edge, Safari o Firefox actual.\",\n },\n off: {\n title: () => \"Las llamadas no están activadas\",\n help: \"Este servicio aún no atiende llamadas. Escríbele mientras tanto.\",\n },\n builder: {\n title: (name) => `${name} no atiende llamadas`,\n help: \"Escríbele en el chat.\",\n },\n refused: {\n title: (name) => `${name} no puede atender la llamada`,\n help: \"Inténtalo de nuevo en un momento.\",\n },\n failed: {\n title: (name) => `No se ha podido llamar a ${name}`,\n help: \"Comprueba tu conexión y vuelve a intentarlo.\",\n },\n unanswered: {\n title: (name) => `${name} no contesta`,\n help: \"Ahora mismo no atiende llamadas. Inténtalo de nuevo en un momento.\",\n },\n },\n mute: \"Silenciar\",\n hangUp: \"Colgar\",\n keys: \"Espacio silencia y activa el micrófono\",\n muted: \"Tu micrófono está silenciado\",\n hear: (name) => `Oír a ${name}`,\n};\n\nexport const TASK_MESSAGES_ES: TaskMessages = {\n open: (count) =>\n count === 1 ? \"Tienes 1 tarea programada\" : `Tienes ${count} tareas programadas`,\n title: \"Tus tareas\",\n back: \"Volver a la conversación\",\n remove: \"Quitar\",\n empty: \"No hay nada programado. Pídele que te recuerde algo, o que te escriba más adelante.\",\n failed: \"No se ha podido cambiar. Inténtalo de nuevo.\",\n};\n\nexport const SPACE_MESSAGES_ES: SpaceMessages = {\n modes: { label: \"Modo\", text: \"Texto\", voice: \"Voz\" },\n again: \"Volver a llamar\",\n close: \"Cerrar\",\n agent: \"Agente\",\n opening: \"Abriendo la conversación…\",\n failed: \"No se ha podido abrir la conversación.\",\n retry: \"Reintentar\",\n chat: CHAT_MESSAGES_ES,\n voice: VOICE_CALL_MESSAGES_ES,\n tasks: TASK_MESSAGES_ES,\n};\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { formatSize } from "./kit/numbers.js";
2
2
  import { About, AboutOut, AboutState, ActionFact, AskFact, AutomationFact, AutomationKind, ChannelFact, ChannelKind, ConnectionFact, DataFact, DeviceFact, DeviceKind, Does, Facts, FileFact, ICONS, Icon, MemoryFact, Provider, StatusTone, TOPICS, Told, Topic, VaultFact, aboutState, actionWords, appSteps, appTitle, automationsOf, countOf, generatedName, namesOf, toneOf, toolName, toolTitle } from "./about.js";
3
- import { Automation as Automation$1, AutomationState, AutomationView, Board, Run, RunBy, RunRecord, RunStatus, RunStep, Step, Task, Trigger, Use } from "./automation/types.js";
3
+ import { Automation as Automation$1, AutomationState, AutomationView, Board, Run, RunBy, RunRecord, RunStatus, RunStep, Step, Task, Trigger, Use, taskCard } from "./automation/types.js";
4
4
  import { Credentials, Speaker, VISITOR_KEY } from "./credentials.js";
5
5
  import { AutomationBlock, Block, ButtonBlock, CardBlock, ChartBlock, ChartPoint, ChoiceBlock, DividerBlock, Entry, FieldKind, FieldValue, FieldsBlock, FormBlock, FormField, ImageBlock, ListBlock, NoteBlock, Option, StackBlock, StatBlock, Surface as Surface$1, TableBlock, TextBlock, Tone } from "./blocks.js";
6
- import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, Conversation, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
6
+ import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, Conversation, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepApp, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
7
7
  import { ApiError, Client, ClientOptions, Files, UploadOptions, createClient } from "./client.js";
8
8
  import { AUTOMATION_MESSAGES, AutomationMessages, CallMessages, DayRef, Verb } from "./automation/messages.js";
9
9
  import { KIT_MESSAGES, KitLocale, KitMessages } from "./kit/messages.js";
@@ -60,4 +60,4 @@ import { DateTimeField, DateTimeFieldProps, TimeField, TimeFieldProps } from "./
60
60
  import { Surface, SurfaceProps } from "./surface/Surface.js";
61
61
  import { FaceRead, useAgentFace } from "./useAgentFace.js";
62
62
  import { Live, LiveHandlers, useLive } from "./useLive.js";
63
- export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, type Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
63
+ export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, type Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepApp, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ import { FileMark } from "./kit/FileMark.js";
24
24
  import { MarkStack } from "./kit/MarkStack.js";
25
25
  import { agentTint } from "./tint.js";
26
26
  import { ABOUT_HOME, ABOUT_MESSAGES, AgentAbout, aboutBack } from "./AgentAbout.js";
27
+ import { taskCard } from "./automation/types.js";
27
28
  import { AgentTasks, TASKS_POLL_MS, TASK_MESSAGES, useTasks } from "./AgentTasks.js";
28
29
  import { AgentCard } from "./AgentCard.js";
29
30
  import { BROWSER_MESSAGES, BrowserView } from "./BrowserView.js";
@@ -56,4 +57,4 @@ import { VOICE_CALL_MESSAGES, VoiceCall } from "./VoiceCall.js";
56
57
  import { FILE_MESSAGES, FileView } from "./FileView.js";
57
58
  import { Tile, Tiles } from "./kit/Tile.js";
58
59
  import { WIDGET_FONTS } from "./types.js";
59
- export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, AgentAbout, AgentCard, AgentChat, AgentSpace, AgentTasks, ApiError, AudioPlayer, Automation, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, BrowserView, Button, CHAT_MESSAGES, CHAT_MESSAGES_ES, Card, Checkbox, Chips, Choices, Combobox, DateField, DateTimeField, FILES_PER_MESSAGE, FILE_MESSAGES, Field, FileChip, FileChips, FileField, FileMark, FileView, ICONS, KIT_MESSAGES, KIT_MESSAGES_ES, KitProvider, List, MAX_MB, Mark, MarkStack, NO_TOOL, Note, NumberInput, ORB_STYLES, Orb, RangeField, RatingField, Row, RunView, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, Stat, Stats, Surface, Switch, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, Tag, TextArea, TextInput, Tile, Tiles, TimeField, UploadChips, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, VoiceCall, WIDGET_FONTS, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
60
+ export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, AgentAbout, AgentCard, AgentChat, AgentSpace, AgentTasks, ApiError, AudioPlayer, Automation, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, BrowserView, Button, CHAT_MESSAGES, CHAT_MESSAGES_ES, Card, Checkbox, Chips, Choices, Combobox, DateField, DateTimeField, FILES_PER_MESSAGE, FILE_MESSAGES, Field, FileChip, FileChips, FileField, FileMark, FileView, ICONS, KIT_MESSAGES, KIT_MESSAGES_ES, KitProvider, List, MAX_MB, Mark, MarkStack, NO_TOOL, Note, NumberInput, ORB_STYLES, Orb, RangeField, RatingField, Row, RunView, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, Stat, Stats, Surface, Switch, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, Tag, TextArea, TextInput, Tile, Tiles, TimeField, UploadChips, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, VoiceCall, WIDGET_FONTS, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
@@ -111,6 +111,6 @@ function clock(seconds) {
111
111
  return hours > 0 ? `${hours}:${String(minutes).padStart(2, "0")}:${rest}` : `${minutes}:${rest}`;
112
112
  }
113
113
  //#endregion
114
- export { AudioPlayer, clock };
114
+ export { AudioPlayer };
115
115
 
116
116
  //# sourceMappingURL=AudioPlayer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AudioPlayer.js","names":[],"sources":["../../src/kit/AudioPlayer.tsx"],"sourcesContent":["import { PauseIcon, PlayIcon } from \"@phosphor-icons/react\";\nimport { useRef, useState, type ReactEventHandler } from \"react\";\n\nimport { joined, useKit, useParts } from \"./context\";\nimport { useWaveform } from \"./waveform\";\n\nexport interface AudioPlayerProps {\n src: string | undefined;\n /** What it is, for screen readers: a voice note, a call's recording, a file's name. */\n label: string;\n onError?: ReactEventHandler<HTMLAudioElement> | undefined;\n /** In a bar, beside other tools: a smaller play, a shorter waveform. */\n compact?: boolean | undefined;\n className?: string | undefined;\n}\n\n/** How many bars the waveform draws, and how high an even one stands while it is read. */\nconst BARS = { full: 44, compact: 24 } as const;\nconst EVEN = 0.35;\n/** The quietest bar still shows: silence reads as a line, not as nothing. */\nconst LEAST = 0.12;\n\n/**\n * Audio, played the kit's way: a quiet round play and pause, the audio's own waveform (its bars\n * light up as it plays; dragging through it seeks), and its time (how long it is until it plays,\n * then how far it is). The browser's own element plays it, never shown; a length the file\n * doesn't tell yet is learnt as it plays.\n */\nexport function AudioPlayer({ src, label, onError, compact, className }: AudioPlayerProps) {\n const part = useParts();\n const { messages: words } = useKit();\n const audio = useRef<HTMLAudioElement>(null);\n const [playing, setPlaying] = useState(false);\n const [at, setAt] = useState(0);\n const [length, setLength] = useState<number | null>(null);\n const bars = compact ? BARS.compact : BARS.full;\n const wave = useWaveform(src, bars);\n const learn = () => {\n const seconds = audio.current?.duration;\n if (seconds !== undefined && Number.isFinite(seconds)) setLength(seconds);\n };\n // The element's length, else the decoded one (an Ogg tells it only once played through).\n const seconds = length ?? wave?.seconds ?? null;\n const played = seconds ? Math.min(1, at / seconds) : 0;\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={joined(\n part(\"sc-audio\", ...(compact ? ([\"sc-audio--compact\"] as const) : [])),\n className,\n )}\n >\n <audio\n ref={audio}\n src={src}\n preload=\"metadata\"\n onLoadedMetadata={learn}\n onDurationChange={learn}\n onPlay={() => {\n setPlaying(true);\n }}\n onPause={() => {\n setPlaying(false);\n }}\n onEnded={() => {\n setPlaying(false);\n setAt(0);\n }}\n onTimeUpdate={() => {\n learn();\n setAt(audio.current?.currentTime ?? 0);\n }}\n onError={onError}\n />\n <button\n type=\"button\"\n className={part(\"sc-audio__play\")}\n aria-label={playing ? words.pause : words.play}\n disabled={src === undefined}\n onClick={() => {\n const element = audio.current;\n if (element === null) return;\n if (element.paused) void element.play();\n else element.pause();\n }}\n >\n {playing ? <PauseIcon weight=\"fill\" /> : <PlayIcon weight=\"fill\" />}\n </button>\n <div className={part(\"sc-audio__wave\")}>\n {Array.from({ length: bars }, (_, index) => (\n <span\n key={index}\n aria-hidden\n data-played={index / bars < played ? \"\" : undefined}\n style={{ height: `${Math.max(LEAST, wave?.heights[index] ?? EVEN) * 100}%` }}\n />\n ))}\n <input\n type=\"range\"\n min={0}\n max={seconds ?? 0}\n step=\"any\"\n value={Math.min(at, seconds ?? 0)}\n disabled={seconds === null}\n aria-label={words.position}\n aria-valuetext={clock(at)}\n onChange={(event) => {\n const seconds = Number(event.target.value);\n if (audio.current !== null) audio.current.currentTime = seconds;\n setAt(seconds);\n }}\n />\n </div>\n <span className={part(\"sc-audio__time\")}>\n {clock(playing || at > 0 ? at : (seconds ?? 0))}\n </span>\n </div>\n );\n}\n\n/** Seconds as a player says them: 0:07, 1:42, 1:02:05. */\nexport function clock(seconds: number): string {\n const whole = Math.max(0, Math.floor(seconds));\n const hours = Math.floor(whole / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const rest = String(whole % 60).padStart(2, \"0\");\n return hours > 0 ? `${hours}:${String(minutes).padStart(2, \"0\")}:${rest}` : `${minutes}:${rest}`;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AudioPlayer.js","names":[],"sources":["../../src/kit/AudioPlayer.tsx"],"sourcesContent":["import { PauseIcon, PlayIcon } from \"@phosphor-icons/react\";\nimport { useRef, useState, type ReactEventHandler } from \"react\";\n\nimport { joined, useKit, useParts } from \"./context\";\nimport { useWaveform } from \"./waveform\";\n\nexport interface AudioPlayerProps {\n src: string | undefined;\n /** What it is, for screen readers: a voice note, a call's recording, a file's name. */\n label: string;\n onError?: ReactEventHandler<HTMLAudioElement> | undefined;\n /** In a bar, beside other tools: a smaller play, a shorter waveform. */\n compact?: boolean | undefined;\n className?: string | undefined;\n}\n\n/** How many bars the waveform draws, and how high an even one stands while it is read. */\nconst BARS = { full: 44, compact: 24 } as const;\nconst EVEN = 0.35;\n/** The quietest bar still shows: silence reads as a line, not as nothing. */\nconst LEAST = 0.12;\n\n/**\n * Audio, played the kit's way: a quiet round play and pause, the audio's own waveform (its bars\n * light up as it plays; dragging through it seeks), and its time (how long it is until it plays,\n * then how far it is). The browser's own element plays it, never shown; a length the file\n * doesn't tell yet is learnt as it plays.\n */\nexport function AudioPlayer({ src, label, onError, compact, className }: AudioPlayerProps) {\n const part = useParts();\n const { messages: words } = useKit();\n const audio = useRef<HTMLAudioElement>(null);\n const [playing, setPlaying] = useState(false);\n const [at, setAt] = useState(0);\n const [length, setLength] = useState<number | null>(null);\n const bars = compact ? BARS.compact : BARS.full;\n const wave = useWaveform(src, bars);\n const learn = () => {\n const seconds = audio.current?.duration;\n if (seconds !== undefined && Number.isFinite(seconds)) setLength(seconds);\n };\n // The element's length, else the decoded one (an Ogg tells it only once played through).\n const seconds = length ?? wave?.seconds ?? null;\n const played = seconds ? Math.min(1, at / seconds) : 0;\n return (\n <div\n role=\"group\"\n aria-label={label}\n className={joined(\n part(\"sc-audio\", ...(compact ? ([\"sc-audio--compact\"] as const) : [])),\n className,\n )}\n >\n <audio\n ref={audio}\n src={src}\n preload=\"metadata\"\n onLoadedMetadata={learn}\n onDurationChange={learn}\n onPlay={() => {\n setPlaying(true);\n }}\n onPause={() => {\n setPlaying(false);\n }}\n onEnded={() => {\n setPlaying(false);\n setAt(0);\n }}\n onTimeUpdate={() => {\n learn();\n setAt(audio.current?.currentTime ?? 0);\n }}\n onError={onError}\n />\n <button\n type=\"button\"\n className={part(\"sc-audio__play\")}\n aria-label={playing ? words.pause : words.play}\n disabled={src === undefined}\n onClick={() => {\n const element = audio.current;\n if (element === null) return;\n if (element.paused) void element.play();\n else element.pause();\n }}\n >\n {playing ? <PauseIcon weight=\"fill\" /> : <PlayIcon weight=\"fill\" />}\n </button>\n <div className={part(\"sc-audio__wave\")}>\n {Array.from({ length: bars }, (_, index) => (\n <span\n key={index}\n aria-hidden\n data-played={index / bars < played ? \"\" : undefined}\n style={{ height: `${Math.max(LEAST, wave?.heights[index] ?? EVEN) * 100}%` }}\n />\n ))}\n <input\n type=\"range\"\n min={0}\n max={seconds ?? 0}\n step=\"any\"\n value={Math.min(at, seconds ?? 0)}\n disabled={seconds === null}\n aria-label={words.position}\n aria-valuetext={clock(at)}\n onChange={(event) => {\n const seconds = Number(event.target.value);\n if (audio.current !== null) audio.current.currentTime = seconds;\n setAt(seconds);\n }}\n />\n </div>\n <span className={part(\"sc-audio__time\")}>\n {clock(playing || at > 0 ? at : (seconds ?? 0))}\n </span>\n </div>\n );\n}\n\n/** Seconds as a player says them: 0:07, 1:42, 1:02:05. */\nfunction clock(seconds: number): string {\n const whole = Math.max(0, Math.floor(seconds));\n const hours = Math.floor(whole / 3600);\n const minutes = Math.floor((whole % 3600) / 60);\n const rest = String(whole % 60).padStart(2, \"0\");\n return hours > 0 ? `${hours}:${String(minutes).padStart(2, \"0\")}:${rest}` : `${minutes}:${rest}`;\n}\n"],"mappings":"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"}
@@ -94,6 +94,6 @@ function Chips({ options, value, onChange, ...control }) {
94
94
  });
95
95
  }
96
96
  //#endregion
97
- export { Chips, Choices, segmented, useRadios };
97
+ export { Chips, Choices, useRadios };
98
98
 
99
99
  //# sourceMappingURL=Choices.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Choices.js","names":[],"sources":["../../src/kit/Choices.tsx"],"sourcesContent":["import { CheckIcon } from \"@phosphor-icons/react\";\nimport { useRef, type KeyboardEvent } from \"react\";\n\nimport { useParts } from \"./context\";\nimport { ariaOf, type ControlBase } from \"./Field\";\nimport { toggled, type Option } from \"./options\";\n\nconst MOVES: Readonly<Record<string, 1 | -1>> = {\n ArrowRight: 1,\n ArrowDown: 1,\n ArrowLeft: -1,\n ArrowUp: -1,\n};\n\n/**\n * A group of radios as native ones behave: one stop for Tab (the one checked, else the first),\n * the arrows move to the next or the previous one and check it, Home and End to the ends.\n */\nexport function useRadios(count: number, checked: number, check: (index: number) => void) {\n const items = useRef<(HTMLElement | null)[]>([]);\n return {\n ref: (index: number) => (element: HTMLElement | null) => {\n items.current[index] = element;\n },\n tabIndex: (index: number) => (index === Math.max(0, checked) ? 0 : -1),\n onKeyDown: (event: KeyboardEvent, index: number) => {\n const move = MOVES[event.key];\n const next =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? count - 1\n : move !== undefined\n ? (index + move + count) % count\n : null;\n if (next === null) return;\n event.preventDefault();\n items.current[next]?.focus();\n check(next);\n },\n };\n}\n\n/** Few short options with no hints sit side by side in one bar; any other few are cards. */\nexport function segmented(options: Option[]): boolean {\n const length = options.reduce((sum, option) => sum + option.label.length, 0);\n return options.length <= 4 && length <= 32 && options.every((option) => !option.hint);\n}\n\n/**\n * One of a few options, all in sight, as a group of radios: one bar of segments when they are\n * short, else a card each with its hint under its label and a dot that fills when picked.\n */\nexport function Choices({\n options,\n value,\n onChange,\n ...control\n}: ControlBase & {\n options: Option[];\n value: string | null;\n onChange: (id: string) => void;\n}) {\n const part = useParts();\n const checked = options.findIndex((option) => option.id === value);\n const radios = useRadios(options.length, checked, (index) => {\n const option = options[index];\n if (option) onChange(option.id);\n });\n const bar = segmented(options);\n return (\n <div role=\"radiogroup\" {...ariaOf(control)} className={part(bar ? \"sc-segments\" : \"sc-picks\")}>\n {options.map((option, index) => (\n <button\n key={option.id}\n ref={radios.ref(index)}\n type=\"button\"\n role=\"radio\"\n aria-checked={index === checked}\n tabIndex={radios.tabIndex(index)}\n disabled={control.disabled}\n onKeyDown={(event) => radios.onKeyDown(event, index)}\n onClick={() => onChange(option.id)}\n className={part(\"sc-pick\")}\n >\n {!bar && <i aria-hidden />}\n <span>\n {option.label}\n {option.hint !== undefined && <small>{option.hint}</small>}\n </span>\n </button>\n ))}\n </div>\n );\n}\n\n/** Several of a few options: a chip each, ticked on and off, a check on those picked. */\nexport function Chips({\n options,\n value,\n onChange,\n ...control\n}: ControlBase & {\n options: Option[];\n value: string[];\n onChange: (ids: string[]) => void;\n}) {\n const part = useParts();\n return (\n <div role=\"group\" {...ariaOf(control)} aria-required={undefined} className={part(\"sc-chips\")}>\n {options.map((option) => {\n const on = value.includes(option.id);\n return (\n <button\n key={option.id}\n type=\"button\"\n role=\"checkbox\"\n aria-checked={on}\n title={option.hint}\n disabled={control.disabled}\n onClick={() => onChange(toggled(options, value, option.id))}\n className={part(\"sc-chip\")}\n >\n {on && <CheckIcon aria-hidden weight=\"bold\" />}\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAOA,MAAM,QAA0C;CAC9C,YAAY;CACZ,WAAW;CACX,WAAW;CACX,SAAS;AACX;;;;;AAMA,SAAgB,UAAU,OAAe,SAAiB,OAAgC;CACxF,MAAM,QAAQ,OAA+B,CAAC,CAAC;CAC/C,OAAO;EACL,MAAM,WAAmB,YAAgC;GACvD,MAAM,QAAQ,SAAS;EACzB;EACA,WAAW,UAAmB,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI,IAAI;EACnE,YAAY,OAAsB,UAAkB;GAClD,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,OACJ,MAAM,QAAQ,SACV,IACA,MAAM,QAAQ,QACZ,QAAQ,IACR,SAAS,KAAA,KACN,QAAQ,OAAO,SAAS,QACzB;GACV,IAAI,SAAS,MAAM;GACnB,MAAM,eAAe;GACrB,MAAM,QAAQ,KAAK,EAAE,MAAM;GAC3B,MAAM,IAAI;EACZ;CACF;AACF;;AAGA,SAAgB,UAAU,SAA4B;CACpD,MAAM,SAAS,QAAQ,QAAQ,KAAK,WAAW,MAAM,OAAO,MAAM,QAAQ,CAAC;CAC3E,OAAO,QAAQ,UAAU,KAAK,UAAU,MAAM,QAAQ,OAAO,WAAW,CAAC,OAAO,IAAI;AACtF;;;;;AAMA,SAAgB,QAAQ,EACtB,SACA,OACA,UACA,GAAG,WAKF;CACD,MAAM,OAAO,SAAS;CACtB,MAAM,UAAU,QAAQ,WAAW,WAAW,OAAO,OAAO,KAAK;CACjE,MAAM,SAAS,UAAU,QAAQ,QAAQ,UAAU,UAAU;EAC3D,MAAM,SAAS,QAAQ;EACvB,IAAI,QAAQ,SAAS,OAAO,EAAE;CAChC,CAAC;CACD,MAAM,MAAM,UAAU,OAAO;CAC7B,OACE,oBAAC,OAAD;EAAK,MAAK;EAAa,GAAI,OAAO,OAAO;EAAG,WAAW,KAAK,MAAM,gBAAgB,UAAU;EACzF,UAAA,QAAQ,KAAK,QAAQ,UACpB,qBAAC,UAAD;GAEE,KAAK,OAAO,IAAI,KAAK;GACrB,MAAK;GACL,MAAK;GACL,gBAAc,UAAU;GACxB,UAAU,OAAO,SAAS,KAAK;GAC/B,UAAU,QAAQ;GAClB,YAAY,UAAU,OAAO,UAAU,OAAO,KAAK;GACnD,eAAe,SAAS,OAAO,EAAE;GACjC,WAAW,KAAK,SAAS;GAV3B,UAAA,CAYG,CAAC,OAAO,oBAAC,KAAD,EAAG,eAAA,KAAa,CAAA,GACzB,qBAAC,QAAD,EAAA,UAAA,CACG,OAAO,OACP,OAAO,SAAS,KAAA,KAAa,oBAAC,SAAD,EAAA,UAAQ,OAAO,KAAY,CAAA,CACrD,EAAA,CAAA,CACA;EAhBD,GAAA,OAAO,EAgBN,CACT;CACE,CAAA;AAET;;AAGA,SAAgB,MAAM,EACpB,SACA,OACA,UACA,GAAG,WAKF;CACD,MAAM,OAAO,SAAS;CACtB,OACE,oBAAC,OAAD;EAAK,MAAK;EAAQ,GAAI,OAAO,OAAO;EAAG,iBAAe,KAAA;EAAW,WAAW,KAAK,UAAU;EACxF,UAAA,QAAQ,KAAK,WAAW;GACvB,MAAM,KAAK,MAAM,SAAS,OAAO,EAAE;GACnC,OACE,qBAAC,UAAD;IAEE,MAAK;IACL,MAAK;IACL,gBAAc;IACd,OAAO,OAAO;IACd,UAAU,QAAQ;IAClB,eAAe,SAAS,QAAQ,SAAS,OAAO,OAAO,EAAE,CAAC;IAC1D,WAAW,KAAK,SAAS;IAR3B,UAAA,CAUG,MAAM,oBAAC,WAAD;KAAW,eAAA;KAAY,QAAO;IAAQ,CAAA,GAC5C,OAAO,KACF;GAXD,GAAA,OAAO,EAWN;EAEZ,CAAC;CACE,CAAA;AAET"}
1
+ {"version":3,"file":"Choices.js","names":[],"sources":["../../src/kit/Choices.tsx"],"sourcesContent":["import { CheckIcon } from \"@phosphor-icons/react\";\nimport { useRef, type KeyboardEvent } from \"react\";\n\nimport { useParts } from \"./context\";\nimport { ariaOf, type ControlBase } from \"./Field\";\nimport { toggled, type Option } from \"./options\";\n\nconst MOVES: Readonly<Record<string, 1 | -1>> = {\n ArrowRight: 1,\n ArrowDown: 1,\n ArrowLeft: -1,\n ArrowUp: -1,\n};\n\n/**\n * A group of radios as native ones behave: one stop for Tab (the one checked, else the first),\n * the arrows move to the next or the previous one and check it, Home and End to the ends.\n */\nexport function useRadios(count: number, checked: number, check: (index: number) => void) {\n const items = useRef<(HTMLElement | null)[]>([]);\n return {\n ref: (index: number) => (element: HTMLElement | null) => {\n items.current[index] = element;\n },\n tabIndex: (index: number) => (index === Math.max(0, checked) ? 0 : -1),\n onKeyDown: (event: KeyboardEvent, index: number) => {\n const move = MOVES[event.key];\n const next =\n event.key === \"Home\"\n ? 0\n : event.key === \"End\"\n ? count - 1\n : move !== undefined\n ? (index + move + count) % count\n : null;\n if (next === null) return;\n event.preventDefault();\n items.current[next]?.focus();\n check(next);\n },\n };\n}\n\n/** Few short options with no hints sit side by side in one bar; any other few are cards. */\nfunction segmented(options: Option[]): boolean {\n const length = options.reduce((sum, option) => sum + option.label.length, 0);\n return options.length <= 4 && length <= 32 && options.every((option) => !option.hint);\n}\n\n/**\n * One of a few options, all in sight, as a group of radios: one bar of segments when they are\n * short, else a card each with its hint under its label and a dot that fills when picked.\n */\nexport function Choices({\n options,\n value,\n onChange,\n ...control\n}: ControlBase & {\n options: Option[];\n value: string | null;\n onChange: (id: string) => void;\n}) {\n const part = useParts();\n const checked = options.findIndex((option) => option.id === value);\n const radios = useRadios(options.length, checked, (index) => {\n const option = options[index];\n if (option) onChange(option.id);\n });\n const bar = segmented(options);\n return (\n <div role=\"radiogroup\" {...ariaOf(control)} className={part(bar ? \"sc-segments\" : \"sc-picks\")}>\n {options.map((option, index) => (\n <button\n key={option.id}\n ref={radios.ref(index)}\n type=\"button\"\n role=\"radio\"\n aria-checked={index === checked}\n tabIndex={radios.tabIndex(index)}\n disabled={control.disabled}\n onKeyDown={(event) => radios.onKeyDown(event, index)}\n onClick={() => onChange(option.id)}\n className={part(\"sc-pick\")}\n >\n {!bar && <i aria-hidden />}\n <span>\n {option.label}\n {option.hint !== undefined && <small>{option.hint}</small>}\n </span>\n </button>\n ))}\n </div>\n );\n}\n\n/** Several of a few options: a chip each, ticked on and off, a check on those picked. */\nexport function Chips({\n options,\n value,\n onChange,\n ...control\n}: ControlBase & {\n options: Option[];\n value: string[];\n onChange: (ids: string[]) => void;\n}) {\n const part = useParts();\n return (\n <div role=\"group\" {...ariaOf(control)} aria-required={undefined} className={part(\"sc-chips\")}>\n {options.map((option) => {\n const on = value.includes(option.id);\n return (\n <button\n key={option.id}\n type=\"button\"\n role=\"checkbox\"\n aria-checked={on}\n title={option.hint}\n disabled={control.disabled}\n onClick={() => onChange(toggled(options, value, option.id))}\n className={part(\"sc-chip\")}\n >\n {on && <CheckIcon aria-hidden weight=\"bold\" />}\n {option.label}\n </button>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;AAOA,MAAM,QAA0C;CAC9C,YAAY;CACZ,WAAW;CACX,WAAW;CACX,SAAS;AACX;;;;;AAMA,SAAgB,UAAU,OAAe,SAAiB,OAAgC;CACxF,MAAM,QAAQ,OAA+B,CAAC,CAAC;CAC/C,OAAO;EACL,MAAM,WAAmB,YAAgC;GACvD,MAAM,QAAQ,SAAS;EACzB;EACA,WAAW,UAAmB,UAAU,KAAK,IAAI,GAAG,OAAO,IAAI,IAAI;EACnE,YAAY,OAAsB,UAAkB;GAClD,MAAM,OAAO,MAAM,MAAM;GACzB,MAAM,OACJ,MAAM,QAAQ,SACV,IACA,MAAM,QAAQ,QACZ,QAAQ,IACR,SAAS,KAAA,KACN,QAAQ,OAAO,SAAS,QACzB;GACV,IAAI,SAAS,MAAM;GACnB,MAAM,eAAe;GACrB,MAAM,QAAQ,KAAK,EAAE,MAAM;GAC3B,MAAM,IAAI;EACZ;CACF;AACF;;AAGA,SAAS,UAAU,SAA4B;CAC7C,MAAM,SAAS,QAAQ,QAAQ,KAAK,WAAW,MAAM,OAAO,MAAM,QAAQ,CAAC;CAC3E,OAAO,QAAQ,UAAU,KAAK,UAAU,MAAM,QAAQ,OAAO,WAAW,CAAC,OAAO,IAAI;AACtF;;;;;AAMA,SAAgB,QAAQ,EACtB,SACA,OACA,UACA,GAAG,WAKF;CACD,MAAM,OAAO,SAAS;CACtB,MAAM,UAAU,QAAQ,WAAW,WAAW,OAAO,OAAO,KAAK;CACjE,MAAM,SAAS,UAAU,QAAQ,QAAQ,UAAU,UAAU;EAC3D,MAAM,SAAS,QAAQ;EACvB,IAAI,QAAQ,SAAS,OAAO,EAAE;CAChC,CAAC;CACD,MAAM,MAAM,UAAU,OAAO;CAC7B,OACE,oBAAC,OAAD;EAAK,MAAK;EAAa,GAAI,OAAO,OAAO;EAAG,WAAW,KAAK,MAAM,gBAAgB,UAAU;EACzF,UAAA,QAAQ,KAAK,QAAQ,UACpB,qBAAC,UAAD;GAEE,KAAK,OAAO,IAAI,KAAK;GACrB,MAAK;GACL,MAAK;GACL,gBAAc,UAAU;GACxB,UAAU,OAAO,SAAS,KAAK;GAC/B,UAAU,QAAQ;GAClB,YAAY,UAAU,OAAO,UAAU,OAAO,KAAK;GACnD,eAAe,SAAS,OAAO,EAAE;GACjC,WAAW,KAAK,SAAS;GAV3B,UAAA,CAYG,CAAC,OAAO,oBAAC,KAAD,EAAG,eAAA,KAAa,CAAA,GACzB,qBAAC,QAAD,EAAA,UAAA,CACG,OAAO,OACP,OAAO,SAAS,KAAA,KAAa,oBAAC,SAAD,EAAA,UAAQ,OAAO,KAAY,CAAA,CACrD,EAAA,CAAA,CACA;EAhBD,GAAA,OAAO,EAgBN,CACT;CACE,CAAA;AAET;;AAGA,SAAgB,MAAM,EACpB,SACA,OACA,UACA,GAAG,WAKF;CACD,MAAM,OAAO,SAAS;CACtB,OACE,oBAAC,OAAD;EAAK,MAAK;EAAQ,GAAI,OAAO,OAAO;EAAG,iBAAe,KAAA;EAAW,WAAW,KAAK,UAAU;EACxF,UAAA,QAAQ,KAAK,WAAW;GACvB,MAAM,KAAK,MAAM,SAAS,OAAO,EAAE;GACnC,OACE,qBAAC,UAAD;IAEE,MAAK;IACL,MAAK;IACL,gBAAc;IACd,OAAO,OAAO;IACd,UAAU,QAAQ;IAClB,eAAe,SAAS,QAAQ,SAAS,OAAO,OAAO,EAAE,CAAC;IAC1D,WAAW,KAAK,SAAS;IAR3B,UAAA,CAUG,MAAM,oBAAC,WAAD;KAAW,eAAA;KAAY,QAAO;IAAQ,CAAA,GAC5C,OAAO,KACF;GAXD,GAAA,OAAO,EAWN;EAEZ,CAAC;CACE,CAAA;AAET"}
@@ -336,6 +336,6 @@ function FileField({ value, onChange, files, accept, multiple = false, maxMb, on
336
336
  });
337
337
  }
338
338
  //#endregion
339
- export { FileChip, FileChips, FileField, UploadChips, carriesFiles, uploaded, useUploads };
339
+ export { FileChip, FileChips, FileField, UploadChips, carriesFiles, useUploads };
340
340
 
341
341
  //# sourceMappingURL=FileField.js.map