@mihe-dev/react 0.0.0-stage → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/hooks.js ADDED
@@ -0,0 +1,302 @@
1
+ /**
2
+ * The three registration hooks (spec §8.3–8.5).
3
+ *
4
+ * All three are declarative: a screen or component is registered while it is
5
+ * mounted and gone when it unmounts, so the assistant's picture of the app can
6
+ * never describe something the user is no longer looking at.
7
+ */
8
+ import { useCallback, useEffect, useMemo, useRef } from "react";
9
+ import { COMPONENT_ATTRIBUTE, chartDeclaration, chartSignature, tableDeclaration, tableSignature, tabsDeclaration, tabsSignature, } from "@mihe-dev/js";
10
+ import { ASSISTANT_PANEL_ID, useOptionalAssistant } from "./provider.js";
11
+ /**
12
+ * Declare the screen the user is on.
13
+ *
14
+ * Call once per page or view. `visibleData` is what makes answers concrete —
15
+ * "you have 7 low-stock products" rather than "check your stock levels" — so
16
+ * include the summary values already on screen, and only those.
17
+ */
18
+ export function useAssistantScreen(screen) {
19
+ const assistant = useOptionalAssistant();
20
+ // Compared by value so a caller passing an inline object literal — the
21
+ // normal thing to do — does not republish on every render.
22
+ const serialized = JSON.stringify(screen);
23
+ useEffect(() => {
24
+ if (!assistant)
25
+ return;
26
+ const declaration = JSON.parse(serialized);
27
+ assistant.store.setScreen(declaration);
28
+ return () => assistant.store.clearScreen(declaration.screenId);
29
+ }, [assistant, serialized]);
30
+ }
31
+ /**
32
+ * Declare a component the assistant can talk about or point at, and get back
33
+ * the props that make it findable.
34
+ *
35
+ * ```tsx
36
+ * const props = useAssistantComponent("products.addButton", {
37
+ * type: "button",
38
+ * label: "Add Product",
39
+ * description: "Opens the form to create a new product",
40
+ * });
41
+ * return <button {...props}>Add Product</button>;
42
+ * ```
43
+ *
44
+ * The returned props must be spread onto a real DOM element. Without them the
45
+ * component is described to the assistant but cannot be highlighted, which
46
+ * produces the confusing case of an assistant confidently pointing at nothing.
47
+ */
48
+ export function useAssistantComponent(componentKey, meta) {
49
+ const assistant = useOptionalAssistant();
50
+ const serialized = JSON.stringify(meta);
51
+ useEffect(() => {
52
+ if (!assistant)
53
+ return;
54
+ assistant.store.registerComponent(componentKey, JSON.parse(serialized));
55
+ return () => assistant.store.unregisterComponent(componentKey);
56
+ }, [assistant, componentKey, serialized]);
57
+ return useMemo(() => ({ [COMPONENT_ATTRIBUTE]: componentKey }), [componentKey]);
58
+ }
59
+ /**
60
+ * Register a handler for an action the assistant may run in the browser.
61
+ *
62
+ * The action itself — its risk tier, permissions, and whether it needs
63
+ * confirmation — is configured in the dashboard, not here. This only supplies
64
+ * the code that runs once the runtime has decided it may.
65
+ *
66
+ * Whatever the handler returns becomes the tool result the model sees, so
67
+ * return something descriptive: `{ shown: 7 }` tells it more than `undefined`.
68
+ * Throwing is fine and reports honestly — the assistant will tell the user it
69
+ * failed rather than claiming success.
70
+ */
71
+ export function useAssistantAction(action) {
72
+ const assistant = useOptionalAssistant();
73
+ // The handler is read through a ref so a caller can close over fresh state
74
+ // without re-registering on every render.
75
+ const handlerRef = useRef(action.handler);
76
+ handlerRef.current = action.handler;
77
+ useEffect(() => {
78
+ if (!assistant)
79
+ return;
80
+ assistant.store.registerAction({
81
+ name: action.name,
82
+ handler: (input) => handlerRef.current(input),
83
+ });
84
+ return () => assistant.store.unregisterAction(action.name);
85
+ }, [assistant, action.name]);
86
+ }
87
+ /**
88
+ * Let the assistant see which tab is open and switch to another.
89
+ *
90
+ * ```tsx
91
+ * const [tab, setTab] = useState("sales");
92
+ * useAssistantTabs({
93
+ * id: "reports.tabs",
94
+ * label: "Report",
95
+ * tabs: [{ value: "sales", label: "Sales" }, { value: "stock", label: "Stock" }],
96
+ * value: tab,
97
+ * onChange: setTab,
98
+ * });
99
+ * ```
100
+ *
101
+ * Tabs are built a dozen ways — a UI library's component, a route segment, a
102
+ * query parameter, plain state — so the SDK never touches them. It reports
103
+ * what you declare and calls your `onChange`, and the runtime only ever asks
104
+ * for a value you listed (amendment 67).
105
+ *
106
+ * Pass the tab that is really showing as `value`. The assistant is told it,
107
+ * and a switch is not reported done until `value` matches what was asked.
108
+ */
109
+ export function useAssistantTabs(tabs) {
110
+ const assistant = useOptionalAssistant();
111
+ // Read through a ref for `useAssistantAction`'s reason: a caller closing
112
+ // over fresh state must not re-register on every render.
113
+ const latest = useRef(tabs);
114
+ latest.current = tabs;
115
+ const signature = tabsSignature(tabs);
116
+ useEffect(() => {
117
+ if (!assistant)
118
+ return;
119
+ assistant.store.registerControl(tabs.id, tabsDeclaration(() => latest.current));
120
+ }, [assistant, tabs.id, signature]);
121
+ // Unregistered only when the id or the assistant goes, not on every change
122
+ // of tab: a cleanup between two registrations would publish a screen with
123
+ // no tabs in between, and a voice session would rebuild its tools for it.
124
+ useEffect(() => {
125
+ if (!assistant)
126
+ return;
127
+ return () => assistant.store.unregisterControl(tabs.id);
128
+ }, [assistant, tabs.id]);
129
+ }
130
+ /**
131
+ * Let the assistant read a table on the screen.
132
+ *
133
+ * ```tsx
134
+ * useAssistantTable({
135
+ * id: "orders.table",
136
+ * label: "Orders",
137
+ * columns: [
138
+ * { key: "orderNumber", label: "Order" },
139
+ * { key: "total", label: "Total" },
140
+ * ],
141
+ * rows: orders,
142
+ * rowId: (order) => order.id,
143
+ * rowIdName: "orderId",
144
+ * total,
145
+ * });
146
+ * ```
147
+ *
148
+ * The rows are not sent with the screen. The model is told the table and its
149
+ * columns, and reads rows with `read_table` when a question needs them, so a
150
+ * table costs a line per answer rather than its contents (amendment 67).
151
+ * Only the declared columns ever leave the browser, and cell text is treated
152
+ * as data, never instructions.
153
+ */
154
+ export function useAssistantTable(table) {
155
+ const assistant = useOptionalAssistant();
156
+ // The rows and functions are read at the moment of a read, so a table that
157
+ // re-renders every second does not re-register every second.
158
+ const latest = useRef(table);
159
+ latest.current = table;
160
+ const signature = tableSignature(table);
161
+ useEffect(() => {
162
+ if (!assistant)
163
+ return;
164
+ assistant.store.registerTable(table.id, tableDeclaration(() => latest.current));
165
+ }, [assistant, table.id, signature]);
166
+ // Unregistered only when the table goes, for `useAssistantTabs`' reason.
167
+ useEffect(() => {
168
+ if (!assistant)
169
+ return;
170
+ return () => assistant.store.unregisterTable(table.id);
171
+ }, [assistant, table.id]);
172
+ }
173
+ /**
174
+ * Add the figures a component shows to the screen's `visibleData`, under
175
+ * `key`.
176
+ *
177
+ * For values that live below the page that calls `useAssistantScreen`: the
178
+ * stat cards inside a tab, a summary panel. They are dropped when the
179
+ * component unmounts or the screen changes, and held back while the screen
180
+ * says it is loading, as `visibleData` is.
181
+ *
182
+ * ```tsx
183
+ * useAssistantValues("stockSummary", { currentStockValue, periodInflow });
184
+ * ```
185
+ */
186
+ export function useAssistantValues(key, values) {
187
+ const assistant = useOptionalAssistant();
188
+ const serialized = JSON.stringify(values);
189
+ useEffect(() => {
190
+ if (!assistant)
191
+ return;
192
+ assistant.store.setValues(key, JSON.parse(serialized));
193
+ }, [assistant, key, serialized]);
194
+ useEffect(() => {
195
+ if (!assistant)
196
+ return;
197
+ return () => assistant.store.clearValues(key);
198
+ }, [assistant, key]);
199
+ }
200
+ /**
201
+ * Let the assistant explain a chart.
202
+ *
203
+ * ```tsx
204
+ * useAssistantChart({
205
+ * id: "stock.trend",
206
+ * title: "Stock trend",
207
+ * data: series,
208
+ * x: { key: "bucket", label: "Month", format: (v) => monthLabel(String(v)) },
209
+ * series: [
210
+ * { key: "inflowValue", name: "Stock in", unit: "NGN" },
211
+ * { key: "outflowValue", name: "Stock out", unit: "NGN" },
212
+ * ],
213
+ * });
214
+ * ```
215
+ *
216
+ * Each series is summarised here, in the browser, and the summary is what
217
+ * the model gets with the screen: start, end, high, low, total and the
218
+ * largest steps. That answers most questions about a trend in a few dozen
219
+ * tokens a series. The points are read with `read_chart` when an exact value
220
+ * is wanted (amendment 67). A picture of the chart is never sent.
221
+ */
222
+ export function useAssistantChart(chart) {
223
+ const assistant = useOptionalAssistant();
224
+ const latest = useRef(chart);
225
+ latest.current = chart;
226
+ const signature = chartSignature(chart);
227
+ useEffect(() => {
228
+ if (!assistant)
229
+ return;
230
+ assistant.store.registerChart(chart.id, chartDeclaration(() => latest.current));
231
+ }, [assistant, chart.id, signature]);
232
+ useEffect(() => {
233
+ if (!assistant)
234
+ return;
235
+ return () => assistant.store.unregisterChart(chart.id);
236
+ }, [assistant, chart.id]);
237
+ }
238
+ /**
239
+ * Make anything open the assistant — a nav button, a menu item, a card, a
240
+ * plain div.
241
+ *
242
+ * ```tsx
243
+ * const trigger = useAssistantTrigger();
244
+ * return <div {...trigger}>Ask the assistant</div>;
245
+ * ```
246
+ *
247
+ * The `role`, `tabIndex`, and `onKeyDown` are why this is a hook rather than
248
+ * advice to call `toggle()` yourself: a `div` with only an `onClick` is
249
+ * invisible to keyboards and screen readers, and that is the most common way
250
+ * a custom trigger ships broken. On a real `<button>` they are harmless.
251
+ *
252
+ * **Returns `null` when there is no assistant**, so the caller can render
253
+ * nothing rather than a control that does not work. Triggers live in shared
254
+ * chrome — a command palette, a nav item, a help link — which is exactly the
255
+ * code that renders whether or not a host app has configured the assistant.
256
+ * Throwing there would make the whole surface conditional on something it has
257
+ * no reason to know about.
258
+ */
259
+ export function useAssistantTrigger() {
260
+ const assistant = useOptionalAssistant();
261
+ const isOpen = assistant?.isOpen ?? false;
262
+ const toggle = assistant?.toggle;
263
+ return useMemo(() => (!toggle ? null : {
264
+ onClick: toggle,
265
+ onKeyDown: (event) => {
266
+ // Space and Enter are what a native button responds to.
267
+ if (event.key === "Enter" || event.key === " ") {
268
+ event.preventDefault();
269
+ toggle();
270
+ }
271
+ },
272
+ role: "button",
273
+ tabIndex: 0,
274
+ "aria-expanded": isOpen,
275
+ "aria-controls": ASSISTANT_PANEL_ID,
276
+ "aria-haspopup": "dialog",
277
+ }), [isOpen, toggle]);
278
+ }
279
+ /**
280
+ * A one-tap "ask this" trigger, for suggestion chips and contextual help
281
+ * links.
282
+ *
283
+ * ```tsx
284
+ * <button onClick={useAssistantPrompt("How do I add a product?")}>
285
+ * How do I add a product?
286
+ * </button>
287
+ * ```
288
+ *
289
+ * Sending opens the assistant, so the reply is visible without the host app
290
+ * having to coordinate two calls.
291
+ *
292
+ * `null` when there is no assistant, for the same reason as
293
+ * [`useAssistantTrigger`]: a chip that silently does nothing is worse than one
294
+ * that was never rendered.
295
+ */
296
+ export function useAssistantPrompt(text) {
297
+ const assistant = useOptionalAssistant();
298
+ const send = assistant?.send;
299
+ const ask = useCallback(() => send?.(text), [send, text]);
300
+ return send ? ask : null;
301
+ }
302
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../../react/src/hooks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * @mihe-dev/react — an app-aware AI assistant for React apps.
3
+ *
4
+ * Three things to wire up:
5
+ *
6
+ * 1. Wrap your app in `<AssistantProvider>` and render `<AssistantWidget />`.
7
+ * 2. Call `useAssistantScreen` on each page so the assistant knows where the
8
+ * user is.
9
+ * 3. Call `useAssistantComponent` on the elements it should be able to point
10
+ * at, and `useAssistantAction` for anything it should be able to run.
11
+ *
12
+ * The assistant reasons; your app executes. It can only navigate to screens
13
+ * you registered, point at components you declared, and run actions you
14
+ * handled — there is no path by which it drives your UI directly.
15
+ */
16
+ export { AssistantProvider, useAssistant, SDK_VERSION, ASSISTANT_PANEL_ID, } from "./provider.js";
17
+ export type { AssistantContextValue, AssistantProviderProps, ChatMessage, VoiceControls, } from "./provider.js";
18
+ export { VoiceSession, voiceUrl } from "@mihe-dev/js";
19
+ export type { VoiceEvent, VoiceState, VoiceSessionOptions } from "@mihe-dev/js";
20
+ export { MicrophoneCapture, SpeakerQueue, toPcm16, fromPcm16 } from "@mihe-dev/js";
21
+ export { AssistantWidget, AssistantPanel } from "./widget.js";
22
+ export { MiheMark } from "./mark.js";
23
+ export type { AssistantWidgetProps, AssistantPanelProps } from "./widget.js";
24
+ export type { OrbCorner, OrbVoiceMode } from "./orb.js";
25
+ export { useAssistantScreen, useAssistantComponent, useAssistantAction, useAssistantTabs, useAssistantTable, useAssistantChart, useAssistantValues, useAssistantTrigger, useAssistantPrompt, } from "./hooks.js";
26
+ export type { AssistantChart, AssistantQueryParam, AssistantTable, AssistantTableColumn, AssistantTableQuery, AssistantTabs, AssistantTriggerProps, } from "./hooks.js";
27
+ export { AssistantStore } from "@mihe-dev/js";
28
+ export type { ActionHandler, ComponentDeclaration, ScreenDeclaration, ChartDeclaration, TableDeclaration, TableRow, ViewControlDeclaration, } from "@mihe-dev/js";
29
+ export { AssistantClient } from "@mihe-dev/js";
30
+ export type { ClientEvent, ClientOptions, ConnectionState, ProposalPayload, } from "@mihe-dev/js";
31
+ export { executeCommand } from "@mihe-dev/js";
32
+ export { formatContextReport } from "@mihe-dev/js";
33
+ export type { ContextReport } from "@mihe-dev/js";
34
+ export type { CommandContext, CommandResult } from "@mihe-dev/js";
35
+ export { HighlightEngine, COMPONENT_ATTRIBUTE } from "@mihe-dev/js";
36
+ export { PROTOCOL_VERSION, VOICE_SAMPLE_RATE } from "@mihe-dev/protocol";
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../react/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,WAAW,EACX,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACtD,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEhF,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEnF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAClC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAC1E,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,qBAAqB,GACtB,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,YAAY,EACV,aAAa,EACb,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,EACR,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,YAAY,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,eAAe,GAChB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,29 @@
1
+ "use client";
2
+ /**
3
+ * @mihe-dev/react — an app-aware AI assistant for React apps.
4
+ *
5
+ * Three things to wire up:
6
+ *
7
+ * 1. Wrap your app in `<AssistantProvider>` and render `<AssistantWidget />`.
8
+ * 2. Call `useAssistantScreen` on each page so the assistant knows where the
9
+ * user is.
10
+ * 3. Call `useAssistantComponent` on the elements it should be able to point
11
+ * at, and `useAssistantAction` for anything it should be able to run.
12
+ *
13
+ * The assistant reasons; your app executes. It can only navigate to screens
14
+ * you registered, point at components you declared, and run actions you
15
+ * handled — there is no path by which it drives your UI directly.
16
+ */
17
+ export { AssistantProvider, useAssistant, SDK_VERSION, ASSISTANT_PANEL_ID, } from "./provider.js";
18
+ export { VoiceSession, voiceUrl } from "@mihe-dev/js";
19
+ export { MicrophoneCapture, SpeakerQueue, toPcm16, fromPcm16 } from "@mihe-dev/js";
20
+ export { AssistantWidget, AssistantPanel } from "./widget.js";
21
+ export { MiheMark } from "./mark.js";
22
+ export { useAssistantScreen, useAssistantComponent, useAssistantAction, useAssistantTabs, useAssistantTable, useAssistantChart, useAssistantValues, useAssistantTrigger, useAssistantPrompt, } from "./hooks.js";
23
+ export { AssistantStore } from "@mihe-dev/js";
24
+ export { AssistantClient } from "@mihe-dev/js";
25
+ export { executeCommand } from "@mihe-dev/js";
26
+ export { formatContextReport } from "@mihe-dev/js";
27
+ export { HighlightEngine, COMPONENT_ATTRIBUTE } from "@mihe-dev/js";
28
+ export { PROTOCOL_VERSION, VOICE_SAMPLE_RATE } from "@mihe-dev/protocol";
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../react/src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,WAAW,EACX,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEnF,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC3D,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIlC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAWjB,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAW9C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAQ/C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAInD,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * What the launcher and the orb show: the customer's uploaded icon, or the
3
+ * Mihe mark on the brand's warm ink.
4
+ */
5
+ export declare const LAUNCHER_BG = "#221f1b";
6
+ export declare const LAUNCHER_INK = "#eae7e4";
7
+ export declare const LAUNCHER_VOICE = "#5ac8cd";
8
+ /**
9
+ * The uploaded icon, or the Mihe mark.
10
+ *
11
+ * The uploaded image fills the circle, so what the dashboard's preview shows
12
+ * is what a user sees. If it cannot load (a host page whose
13
+ * Content-Security-Policy does not allow the storage's domain, say), the
14
+ * launcher falls back to the mark instead of becoming an empty circle.
15
+ */
16
+ export declare function LauncherIcon({ url }: {
17
+ url: string | null;
18
+ }): import("react").JSX.Element;
19
+ //# sourceMappingURL=launcher-icon.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher-icon.d.ts","sourceRoot":"","sources":["../../../react/src/launcher-icon.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,eAAO,MAAM,WAAW,YAAY,CAAC;AACrC,eAAO,MAAM,YAAY,YAAY,CAAC;AACtC,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,+BAe3D"}
@@ -0,0 +1,36 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * What the launcher and the orb show: the customer's uploaded icon, or the
4
+ * Mihe mark on the brand's warm ink.
5
+ */
6
+ import { useState } from "react";
7
+ import { MiheMark } from "./mark.js";
8
+ // The default launcher is the brand: warm ink, a light figure, verdigris arcs
9
+ // (the dashboard's dark-mode values, docs/README.md amendment 57).
10
+ export const LAUNCHER_BG = "#221f1b";
11
+ export const LAUNCHER_INK = "#eae7e4";
12
+ export const LAUNCHER_VOICE = "#5ac8cd";
13
+ /**
14
+ * The uploaded icon, or the Mihe mark.
15
+ *
16
+ * The uploaded image fills the circle, so what the dashboard's preview shows
17
+ * is what a user sees. If it cannot load (a host page whose
18
+ * Content-Security-Policy does not allow the storage's domain, say), the
19
+ * launcher falls back to the mark instead of becoming an empty circle.
20
+ */
21
+ export function LauncherIcon({ url }) {
22
+ const [failed, setFailed] = useState(null);
23
+ if (url && failed !== url) {
24
+ return (_jsx("img", { src: url, alt: "", draggable: false, onError: () => setFailed(url), style: styles.launcherImage }));
25
+ }
26
+ return _jsx(MiheMark, { size: 34, body: LAUNCHER_INK, voice: LAUNCHER_VOICE });
27
+ }
28
+ const styles = {
29
+ launcherImage: {
30
+ width: "100%",
31
+ height: "100%",
32
+ objectFit: "cover",
33
+ display: "block",
34
+ },
35
+ };
36
+ //# sourceMappingURL=launcher-icon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launcher-icon.js","sourceRoot":"","sources":["../../../react/src/launcher-icon.tsx"],"names":[],"mappings":";AAAA;;;GAGG;AAEH,OAAO,EAAE,QAAQ,EAAsB,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAElC,8EAA8E;AAC9E,mEAAmE;AACnE,MAAM,CAAC,MAAM,WAAW,GAAG,SAAS,CAAC;AACrC,MAAM,CAAC,MAAM,YAAY,GAAG,SAAS,CAAC;AACtC,MAAM,CAAC,MAAM,cAAc,GAAG,SAAS,CAAC;AAExC;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,GAAG,EAA0B;IAC1D,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE1D,IAAI,GAAG,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;QAC1B,OAAO,CACL,cACE,GAAG,EAAE,GAAG,EACR,GAAG,EAAC,EAAE,EACN,SAAS,EAAE,KAAK,EAChB,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAC7B,KAAK,EAAE,MAAM,CAAC,aAAa,GAC3B,CACH,CAAC;IACJ,CAAC;IACD,OAAO,KAAC,QAAQ,IAAC,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,cAAc,GAAI,CAAC;AAC3E,CAAC;AAED,MAAM,MAAM,GAAG;IACb,aAAa,EAAE;QACb,KAAK,EAAE,MAAM;QACb,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,OAAO;KACjB;CACsC,CAAC"}
package/dist/mark.d.ts ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * The Mihe mark, the widget's default launcher icon (amendment 58).
3
+ *
4
+ * An oracle in an open ring, with one pair of arcs for its voice. Drawn inline
5
+ * rather than loaded, so the default launcher needs no request and no
6
+ * permission from the host page's Content-Security-Policy.
7
+ *
8
+ * The master files live in the brand folder; this is a copy, like the
9
+ * dashboard's `components/logo.tsx`.
10
+ */
11
+ export declare function MiheMark({ size, body, voice, }: {
12
+ size: number;
13
+ /** The figure and the ring. */
14
+ body: string;
15
+ /** The two arcs, the only part of the mark in colour. */
16
+ voice: string;
17
+ }): import("react").JSX.Element;
18
+ //# sourceMappingURL=mark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mark.d.ts","sourceRoot":"","sources":["../../../react/src/mark.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wBAAgB,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,KAAK,GACN,EAAE;IACD,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;CACf,+BAcA"}
package/dist/mark.js ADDED
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The Mihe mark, the widget's default launcher icon (amendment 58).
4
+ *
5
+ * An oracle in an open ring, with one pair of arcs for its voice. Drawn inline
6
+ * rather than loaded, so the default launcher needs no request and no
7
+ * permission from the host page's Content-Security-Policy.
8
+ *
9
+ * The master files live in the brand folder; this is a copy, like the
10
+ * dashboard's `components/logo.tsx`.
11
+ */
12
+ export function MiheMark({ size, body, voice, }) {
13
+ return (_jsxs("svg", { viewBox: "0 0 1760 1760", width: size, height: size, "aria-hidden": "true", focusable: "false", style: { display: "block" }, children: [_jsx("path", { fill: body, fillRule: "evenodd", transform: "translate(0.000000,1760.000000) scale(0.100000,-0.100000)", d: "M8165 16868 c-450 -31 -1057 -131 -1495 -248 -76 -20 -156 -42 -180 -50 -14 -5 -50 -15 -80 -24 -146 -41 -273 -82 -360 -117 -25 -9 -74 -27 -110 -39 -36 -12 -74 -25 -85 -30 -11 -4 -40 -15 -65 -25 -25 -10 -54 -21 -65 -26 -11 -4 -85 -35 -165 -67 -218 -90 -530 -238 -715 -340 -38 -21 -106 -58 -150 -82 -44 -24 -108 -61 -143 -82 -34 -21 -65 -38 -68 -38 -2 0 -17 -8 -32 -19 -15 -10 -52 -34 -82 -53 -1161 -733 -2106 -1735 -2771 -2935 -74 -134 -219 -425 -219 -440 0 -4 -10 -24 -23 -43 -13 -19 -34 -60 -46 -90 -13 -30 -35 -80 -48 -110 -49 -112 -56 -127 -91 -220 -16 -41 -32 -84 -37 -95 -45 -114 -195 -563 -238 -715 -26 -88 -58 -212 -67 -255 -5 -22 -16 -69 -25 -105 -19 -78 -66 -317 -89 -455 -140 -836 -144 -1701 -11 -2525 9 -52 20 -122 25 -155 9 -53 17 -97 51 -262 16 -78 80 -337 105 -423 74 -256 219 -700 264 -810 26 -63 55 -135 79 -192 6 -13 24 -54 40 -91 17 -38 31 -70 31 -72 0 -3 105 -221 203 -425 39 -79 80 -154 128 -233 16 -26 29 -50 29 -52 0 -3 37 -65 82 -138 45 -72 88 -143 95 -157 64 -113 285 -440 339 -500 12 -14 43 -56 70 -95 42 -63 164 -220 221 -285 12 -14 36 -43 55 -66 250 -310 644 -706 1038 -1045 68 -59 396 -310 514 -395 88 -63 522 -341 596 -382 19 -10 80 -45 135 -77 120 -69 571 -298 670 -339 39 -16 107 -47 153 -68 46 -21 87 -38 93 -38 5 0 17 -4 27 -10 25 -13 78 -35 157 -63 39 -14 120 -43 180 -65 222 -82 417 -145 565 -183 41 -10 91 -23 110 -29 134 -37 514 -119 645 -139 836 -130 1685 -150 2385 -57 63 8 151 20 195 26 44 6 100 15 125 20 25 5 88 17 140 25 286 49 729 160 1015 256 198 67 349 119 370 129 11 6 72 30 135 54 63 24 142 56 175 71 103 46 118 52 183 79 53 22 224 108 572 287 750 385 1586 1059 2290 1844 219 244 499 612 666 873 32 52 91 144 131 205 91 141 268 456 366 652 87 172 167 341 167 350 0 4 6 21 14 38 56 124 212 529 241 627 9 30 21 64 26 75 4 11 16 45 25 75 9 30 25 82 36 115 54 166 146 535 178 710 82 461 106 640 137 1030 20 252 23 814 5 1015 -6 74 -17 191 -23 260 -12 141 -34 328 -49 410 -5 30 -16 100 -25 155 -9 55 -26 145 -37 200 -11 55 -24 118 -28 140 -4 22 -16 72 -25 110 -9 39 -20 86 -24 105 -203 889 -617 1816 -1181 2640 -141 205 -236 333 -350 470 -52 63 -113 138 -135 165 -203 255 -745 786 -1035 1016 -58 45 -138 109 -179 142 -228 181 -749 524 -1006 662 -49 26 -115 62 -145 78 -71 38 -346 176 -430 215 -138 64 -201 92 -206 92 -3 0 -35 14 -71 30 -35 17 -70 30 -77 30 -6 0 -16 4 -21 8 -9 8 -216 87 -387 148 -38 13 -98 35 -135 49 -38 13 -102 34 -143 45 -41 12 -97 28 -125 36 -180 53 -464 125 -610 154 -165 33 -214 43 -240 47 -16 2 -66 10 -110 18 -328 56 -573 84 -755 88 l-125 2 0 -515 0 -515 190 -21 c105 -12 242 -29 305 -39 63 -10 138 -21 165 -26 123 -18 192 -30 225 -39 19 -5 62 -14 95 -20 233 -44 615 -154 905 -260 47 -17 105 -38 130 -47 25 -8 59 -21 75 -28 17 -7 93 -39 170 -71 418 -173 867 -425 1345 -757 747 -518 1525 -1379 1970 -2182 18 -33 41 -73 50 -90 64 -116 84 -152 123 -231 25 -49 57 -118 72 -154 15 -36 36 -85 47 -110 42 -93 56 -127 78 -180 12 -30 26 -64 31 -75 61 -146 144 -376 194 -540 15 -49 31 -101 36 -115 9 -26 46 -175 74 -295 8 -38 20 -86 25 -105 15 -58 45 -214 80 -425 24 -141 62 -499 79 -745 34 -482 -17 -1111 -134 -1655 -14 -66 -30 -140 -35 -165 -8 -38 -22 -93 -65 -260 -28 -107 -86 -292 -127 -405 -59 -164 -118 -318 -128 -337 -6 -10 -10 -22 -10 -27 0 -6 -18 -49 -40 -96 -22 -47 -40 -88 -40 -90 0 -27 -247 -518 -314 -624 -14 -22 -26 -43 -26 -45 0 -37 -381 -596 -565 -829 -225 -283 -622 -706 -875 -929 -155 -137 -228 -198 -237 -198 -9 0 -127 185 -183 285 -12 22 -28 47 -35 55 -7 8 -32 49 -55 90 -24 41 -76 125 -115 185 -40 61 -123 195 -186 298 -63 103 -126 207 -141 230 -15 23 -31 49 -35 57 -3 8 -16 29 -27 45 -12 17 -26 39 -33 50 -7 11 -33 54 -59 95 -67 106 -620 996 -1072 1725 -58 94 -129 206 -158 251 -29 45 -65 103 -80 130 -15 27 -55 92 -89 144 -88 134 -280 445 -400 645 -56 94 -163 269 -239 389 -75 121 -135 224 -134 228 2 5 35 54 73 109 403 577 447 641 713 1032 134 197 262 399 262 413 0 8 -36 85 -79 172 -44 86 -142 285 -219 442 -77 157 -244 497 -372 755 -128 259 -297 601 -375 760 -78 160 -220 448 -315 640 -95 193 -264 535 -376 760 -400 810 -543 1101 -566 1155 -14 30 -33 74 -43 98 -17 39 -55 61 -55 31 0 -6 -35 -83 -79 -172 -43 -89 -106 -218 -139 -287 -68 -142 -323 -661 -607 -1235 -106 -214 -271 -550 -368 -745 -225 -457 -457 -927 -747 -1515 -363 -735 -420 -852 -420 -862 0 -10 166 -267 241 -373 21 -30 95 -138 164 -240 68 -102 160 -237 204 -300 80 -115 147 -212 296 -430 43 -63 93 -135 112 -159 42 -56 42 -57 -11 -134 -24 -35 -58 -90 -76 -122 -29 -52 -66 -114 -107 -180 -7 -11 -20 -33 -29 -50 -9 -16 -45 -73 -79 -125 -34 -52 -74 -117 -89 -145 -16 -27 -34 -57 -42 -66 -8 -8 -14 -19 -14 -23 0 -4 -10 -22 -23 -39 -12 -18 -28 -41 -34 -52 -7 -11 -33 -54 -59 -95 -26 -41 -58 -95 -72 -120 -13 -25 -35 -58 -47 -75 -21 -29 -238 -378 -619 -995 -96 -157 -210 -339 -252 -405 -104 -164 -269 -429 -343 -550 -33 -55 -92 -149 -131 -210 -38 -60 -78 -126 -90 -145 -11 -19 -25 -42 -30 -50 -5 -8 -44 -71 -86 -140 -42 -69 -104 -168 -138 -220 -34 -53 -66 -104 -73 -115 -6 -11 -76 -123 -155 -249 -79 -126 -145 -234 -147 -240 -2 -6 -21 -36 -41 -66 -76 -112 -170 -260 -170 -267 0 -5 -14 -24 -30 -43 -29 -35 -29 -35 -82 16 -29 28 -91 84 -138 124 -567 490 -1171 1224 -1508 1832 -47 85 -232 451 -274 543 -20 44 -53 115 -72 158 -20 42 -36 80 -36 83 0 3 -6 20 -14 37 -20 47 -40 99 -85 222 -79 217 -90 252 -140 420 -49 167 -85 311 -141 558 -120 534 -163 1390 -99 1962 41 369 37 343 84 595 48 260 75 373 159 683 39 143 224 654 286 792 110 242 174 371 314 630 563 1039 1532 2008 2644 2642 68 38 455 233 532 267 131 58 397 168 465 192 108 39 384 130 445 148 30 8 87 25 125 36 316 96 789 185 1190 225 94 9 176 20 183 24 12 5 16 287 12 1022 0 13 -27 15 -135 7z m660 -4508 c4 -16 11 -32 16 -35 5 -4 9 -12 9 -20 0 -8 19 -53 41 -102 71 -151 106 -226 129 -278 12 -27 39 -86 60 -130 21 -44 52 -111 70 -150 17 -38 44 -97 60 -130 15 -33 35 -76 43 -95 8 -19 31 -69 50 -110 62 -134 89 -194 107 -240 10 -25 46 -103 80 -175 90 -190 106 -224 133 -285 49 -108 70 -156 97 -215 15 -33 37 -82 50 -110 12 -27 40 -87 61 -133 40 -83 40 -83 6 -140 -19 -31 -50 -86 -69 -122 -65 -120 -91 -165 -140 -242 -26 -43 -48 -80 -48 -83 0 -2 -17 -33 -38 -67 -21 -35 -41 -70 -45 -78 -4 -8 -11 -22 -17 -30 -34 -54 -110 -181 -110 -185 0 -3 -11 -23 -25 -45 -14 -22 -46 -80 -72 -128 -25 -48 -54 -98 -63 -112 -41 -58 -150 -263 -150 -280 0 -10 15 -47 33 -82 62 -117 120 -223 128 -234 5 -6 48 -87 95 -180 47 -93 90 -173 94 -179 4 -5 27 -46 50 -90 23 -44 67 -127 98 -185 30 -58 59 -110 63 -116 11 -14 72 -130 111 -209 37 -77 56 -114 103 -200 142 -264 186 -348 323 -615 63 -124 128 -250 145 -280 33 -59 82 -154 250 -480 58 -113 129 -250 157 -305 96 -182 151 -288 268 -515 63 -124 135 -263 160 -310 24 -47 118 -229 207 -405 170 -333 225 -440 277 -534 17 -31 112 -216 211 -411 99 -195 188 -372 199 -393 11 -22 18 -40 16 -42 -10 -11 -431 -215 -443 -215 -2 0 -36 -15 -77 -34 -40 -18 -109 -48 -153 -66 -44 -18 -93 -38 -110 -45 -16 -7 -75 -29 -130 -50 -55 -20 -116 -43 -135 -50 -39 -14 -282 -90 -345 -107 -22 -6 -60 -16 -85 -24 -61 -17 -216 -55 -265 -64 -22 -4 -85 -17 -140 -28 -165 -33 -277 -52 -513 -87 -183 -27 -182 -27 -182 78 0 34 -4 98 -10 142 -5 44 -14 141 -20 215 -24 285 -30 360 -45 530 -9 96 -20 229 -25 295 -5 66 -17 206 -25 310 -9 105 -20 249 -25 320 -5 72 -12 148 -15 170 -3 22 -10 105 -15 185 -5 80 -17 228 -25 330 -9 102 -20 237 -24 300 -5 63 -19 225 -30 360 -11 135 -27 335 -36 445 -30 392 -37 461 -50 510 -8 28 -26 97 -41 155 -14 58 -37 146 -50 195 -41 154 -55 209 -64 245 -9 33 -23 89 -55 205 -7 28 -25 100 -40 160 -24 98 -49 196 -61 233 -8 27 -28 5 -40 -44 -6 -27 -24 -94 -38 -149 -15 -55 -43 -161 -62 -235 -20 -74 -49 -187 -65 -250 -17 -63 -39 -151 -50 -195 -23 -92 -39 -157 -69 -270 -30 -113 -36 -170 -75 -720 -8 -110 -21 -276 -30 -370 -8 -93 -19 -226 -25 -295 -5 -69 -12 -143 -15 -165 -3 -22 -10 -105 -16 -185 -24 -330 -41 -552 -59 -745 -22 -237 -31 -345 -40 -460 -5 -66 -16 -201 -25 -300 -8 -99 -19 -234 -25 -300 -15 -193 -40 -482 -50 -590 -5 -55 -9 -106 -10 -112 0 -18 -71 -17 -184 2 -50 9 -122 20 -161 26 -108 16 -241 39 -345 61 -52 11 -113 24 -135 28 -52 11 -235 56 -300 75 -27 7 -75 20 -106 29 -62 17 -397 127 -444 146 -16 7 -39 16 -50 21 -11 5 -56 22 -100 39 -214 82 -663 292 -724 339 -23 18 -23 18 62 182 46 90 130 252 185 359 55 107 121 236 147 285 26 50 100 194 165 320 64 127 146 286 182 355 36 69 100 193 143 275 43 83 106 204 140 270 34 66 109 210 165 320 108 211 202 391 280 540 26 50 70 133 97 185 28 52 112 217 188 365 76 149 141 275 145 280 4 6 54 100 110 210 57 110 123 238 148 285 25 47 63 119 85 160 22 41 71 133 110 205 39 71 107 202 152 290 45 88 91 177 103 197 12 21 37 66 55 100 19 35 51 95 72 133 238 435 243 447 218 497 -34 66 -100 186 -137 247 -19 31 -43 72 -53 91 -65 116 -87 155 -142 248 -34 57 -61 106 -61 108 0 2 -10 21 -23 42 -13 20 -44 75 -69 122 -25 47 -73 132 -107 188 -33 57 -61 106 -61 108 0 2 -29 52 -65 110 -68 111 -74 132 -51 180 26 52 103 218 126 269 13 28 41 88 62 135 22 47 54 114 70 150 48 104 78 169 124 267 24 51 44 98 44 103 0 6 4 18 10 28 13 22 90 192 90 198 0 2 23 52 51 112 54 112 81 171 205 440 19 41 34 76 34 78 0 3 15 37 34 77 18 40 43 95 56 122 12 28 43 93 67 145 25 52 49 105 54 117 12 32 36 28 44 -7z" }), _jsx("path", { fill: voice, fillRule: "evenodd", transform: "translate(0.000000,1760.000000) scale(0.100000,-0.100000)", d: "M4399 12732 c-37 -42 -101 -117 -143 -166 -123 -145 -496 -679 -496 -712 0 -2 -18 -34 -41 -71 -100 -164 -271 -530 -369 -793 -17 -47 -36 -96 -42 -110 -35 -86 -134 -426 -172 -595 -50 -218 -49 -218 -81 -445 -85 -598 -74 -1269 30 -1820 8 -47 20 -107 24 -135 11 -60 68 -292 87 -355 8 -25 21 -67 29 -95 23 -79 72 -227 85 -260 7 -16 16 -39 20 -50 34 -90 73 -186 108 -265 11 -25 30 -70 43 -100 45 -106 197 -400 256 -493 14 -22 36 -60 50 -85 97 -175 409 -612 437 -612 6 0 85 66 176 147 91 80 199 176 240 212 41 36 100 89 130 117 30 29 73 67 95 86 123 107 120 82 23 209 -209 275 -459 726 -589 1064 -112 292 -165 474 -219 750 -19 96 -26 136 -50 287 -70 444 -45 1047 65 1543 9 39 20 88 24 110 149 680 553 1448 1043 1980 15 17 28 33 28 36 0 11 -703 699 -714 699 -6 0 -41 -35 -77 -78z M12835 12532 c-154 -152 -313 -307 -354 -344 -84 -76 -85 -63 16 -174 227 -250 460 -601 637 -959 70 -144 93 -192 130 -280 10 -22 21 -49 26 -60 5 -11 16 -42 25 -70 10 -27 21 -59 26 -70 23 -55 77 -234 112 -370 45 -175 56 -227 78 -345 24 -127 27 -151 58 -425 26 -231 28 -544 6 -780 -17 -180 -30 -267 -85 -570 -9 -47 -39 -165 -89 -350 -23 -83 -54 -178 -76 -230 -7 -16 -19 -48 -28 -70 -144 -374 -335 -726 -576 -1060 -56 -77 -100 -145 -99 -151 2 -5 68 -68 148 -140 80 -71 172 -154 205 -185 138 -128 375 -329 388 -329 23 0 437 582 437 614 0 3 16 30 35 60 62 98 305 576 305 601 0 3 14 35 31 72 54 117 135 338 174 478 124 434 155 590 214 1065 67 536 5 1382 -141 1930 -11 41 -24 89 -28 105 -24 91 -128 414 -175 543 -34 95 -127 306 -196 447 -145 295 -273 511 -475 795 -154 217 -416 530 -443 530 -3 0 -132 -125 -286 -278z" })] }));
14
+ }
15
+ //# sourceMappingURL=mark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mark.js","sourceRoot":"","sources":["../../../react/src/mark.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;AAEH,MAAM,UAAU,QAAQ,CAAC,EACvB,IAAI,EACJ,IAAI,EACJ,KAAK,GAON;IACC,OAAO,CACL,eACE,OAAO,EAAC,eAAe,EACvB,KAAK,EAAE,IAAI,EACX,MAAM,EAAE,IAAI,iBACA,MAAM,EAClB,SAAS,EAAC,OAAO,EACjB,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,aAE3B,eAAM,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAC,SAAS,EAAC,SAAS,EAAC,2DAA2D,EAAC,CAAC,EAAC,m2RAAm2R,GAAG,EACn9R,eAAM,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAC,SAAS,EAAC,SAAS,EAAC,2DAA2D,EAAC,CAAC,EAAC,0iDAA0iD,GAAG,IACvpD,CACP,CAAC;AACJ,CAAC"}
package/dist/orb.d.ts ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The orb: the widget as a circle, and voice shown in the circle itself
3
+ * (amendment 61).
4
+ *
5
+ * Tapping it opens a small menu, chat and whichever voice modes the app
6
+ * allows, or goes straight to chat when chat is the only one. Chat opens the
7
+ * panel. Voice stays in the orb, which is the point of it: with the panel out
8
+ * of the way, the user watches their own page being navigated, highlighted and
9
+ * changed, instead of reading about it in a transcript.
10
+ *
11
+ * Two things the orb must still show, because collapsing the panel is not a
12
+ * licence to hide them:
13
+ *
14
+ * - **The confirmation card**, anchored to the orb, rendered from the proposal
15
+ * payload exactly as the panel renders it. High-risk actions need that tap
16
+ * in every mode.
17
+ * - **Refusals and errors**, in a bubble above it.
18
+ *
19
+ * Live captions are not shown. Streamed transcript text never kept pace with
20
+ * the voice, and a caption that lags what you hear reads as broken. Finished
21
+ * lines still land in the conversation, and `voice.caption` is still exposed
22
+ * for a host that wants to draw its own.
23
+ *
24
+ * Tap, hold and drag share one element, so a press is read like this:
25
+ *
26
+ * | Mode | Tap | Hold | Drag past 8px |
27
+ * |--------------|--------------------------|--------------------------|--------------------------|
28
+ * | Idle | menu, or chat | nothing | moves it, if draggable |
29
+ * | Menu open | closes it | nothing | nothing |
30
+ * | Hands-free | ends the session | nothing | moves it, if draggable |
31
+ * | Push-to-talk | nothing | records, release sends | discards, then moves it |
32
+ *
33
+ * Push-to-talk records from the moment the finger goes down, so the first word
34
+ * is not lost. On a draggable orb the first 150ms are held on the device
35
+ * rather than sent: still, they are sent and recording carries on; moved, they
36
+ * are dropped and never leave the browser.
37
+ */
38
+ import { type CSSProperties, type ReactNode } from "react";
39
+ import type { VoiceMode, WidgetCorner } from "@mihe-dev/protocol";
40
+ /** The voice modes an app can offer. The protocol's type, under the SDK's name. */
41
+ export type OrbVoiceMode = VoiceMode;
42
+ /** Which corner the orb sits in until someone drags it. */
43
+ export type OrbCorner = WidgetCorner;
44
+ export interface OrbProps {
45
+ heading: string;
46
+ launcherIcon?: ReactNode;
47
+ draggable: boolean;
48
+ corner: OrbCorner;
49
+ voiceModes: OrbVoiceMode[];
50
+ /** Hide the orb itself, for a host app with its own trigger. */
51
+ showOrb: boolean;
52
+ /** The panel, positioned by the orb on whichever side it sits. */
53
+ renderPanel: (style: CSSProperties) => ReactNode;
54
+ }
55
+ export declare function Orb({ heading, launcherIcon, draggable, corner, voiceModes, showOrb, renderPanel, }: OrbProps): import("react").JSX.Element | null;
56
+ //# sourceMappingURL=orb.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orb.d.ts","sourceRoot":"","sources":["../../../react/src/orb.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAEH,OAAO,EAKL,KAAK,aAAa,EAGlB,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAMlE,mFAAmF;AACnF,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC;AAErC,2DAA2D;AAC3D,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC;AAErC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,EAAE,YAAY,EAAE,CAAC;IAC3B,gEAAgE;IAChE,OAAO,EAAE,OAAO,CAAC;IACjB,kEAAkE;IAClE,WAAW,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,SAAS,CAAC;CAClD;AAmFD,wBAAgB,GAAG,CAAC,EAClB,OAAO,EACP,YAAY,EACZ,SAAS,EACT,MAAM,EACN,UAAU,EACV,OAAO,EACP,WAAW,GACZ,EAAE,QAAQ,sCAkeV"}