@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.
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * `AssistantProvider` — the React binding of `Mihe` (doc 08).
4
+ *
5
+ * Everything the assistant does — the session, the screen publishing, the
6
+ * commands, the cards, voice — lives in `@mihe-dev/js`. This file only holds one
7
+ * `Mihe` for the tree and reads its state with `useSyncExternalStore`, so
8
+ * the React SDK and the JavaScript one cannot behave differently.
9
+ */
10
+ import { createContext, useContext, useEffect, useMemo, useState, useSyncExternalStore, } from "react";
11
+ import { Mihe, } from "@mihe-dev/js";
12
+ export { SDK_VERSION, ASSISTANT_PANEL_ID } from "@mihe-dev/js";
13
+ const AssistantContext = createContext(null);
14
+ export function AssistantProvider({ url, publicKey, getUserToken, navigate, openModal, onActionComplete, debug = false, children, }) {
15
+ // One for the life of the tree. Constructing it has no effects; the
16
+ // session opens in the effect below, so StrictMode's double mount opens
17
+ // and closes it rather than leaking one.
18
+ const [mihe] = useState(() => new Mihe({ url, publicKey, getUserToken, debug }));
19
+ // Callbacks are read at call time, so a caller passing inline arrow
20
+ // functions — which almost everyone does — does not rebuild the session on
21
+ // every render. None of these reconnects.
22
+ mihe.update({ getUserToken, navigate, openModal, onActionComplete });
23
+ // The session outlives renders; only a genuine identity change rebuilds it.
24
+ useEffect(() => {
25
+ mihe.update({ url, publicKey, debug });
26
+ mihe.connect();
27
+ return () => mihe.disconnect();
28
+ }, [mihe, url, publicKey, debug]);
29
+ const state = useSyncExternalStore(mihe.subscribe, mihe.getState, mihe.getState);
30
+ const value = useMemo(() => ({
31
+ ...state,
32
+ store: mihe.store,
33
+ send: mihe.send,
34
+ respondToProposal: mihe.respondToProposal,
35
+ open: mihe.open,
36
+ close: mihe.close,
37
+ toggle: mihe.toggle,
38
+ }), [mihe, state]);
39
+ return _jsx(AssistantContext.Provider, { value: value, children: children });
40
+ }
41
+ export function useAssistant() {
42
+ const value = useContext(AssistantContext);
43
+ if (!value) {
44
+ throw new Error("useAssistant must be used inside <AssistantProvider>. Wrap your app in it.");
45
+ }
46
+ return value;
47
+ }
48
+ /** Non-throwing variant, for hooks that should no-op outside the provider. */
49
+ export function useOptionalAssistant() {
50
+ return useContext(AssistantContext);
51
+ }
52
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../../react/src/provider.tsx"],"names":[],"mappings":";AAAA;;;;;;;GAOG;AAEH,OAAO,EACL,aAAa,EACb,UAAU,EACV,SAAS,EACT,OAAO,EACP,QAAQ,EACR,oBAAoB,GAErB,MAAM,OAAO,CAAC;AAEf,OAAO,EACL,IAAI,GAIL,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAY/D,MAAM,gBAAgB,GAAG,aAAa,CAA+B,IAAI,CAAC,CAAC;AAM3E,MAAM,UAAU,iBAAiB,CAAC,EAChC,GAAG,EACH,SAAS,EACT,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,gBAAgB,EAChB,KAAK,GAAG,KAAK,EACb,QAAQ,GACe;IACvB,oEAAoE;IACpE,wEAAwE;IACxE,yCAAyC;IACzC,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC;IAEjF,oEAAoE;IACpE,2EAA2E;IAC3E,0CAA0C;IAC1C,IAAI,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,CAAC,CAAC;IAErE,4EAA4E;IAC5E,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACjC,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IAElC,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAEjF,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC;QACL,GAAG,KAAK;QACR,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,iBAAiB,EAAE,IAAI,CAAC,iBAAiB;QACzC,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,EACF,CAAC,IAAI,EAAE,KAAK,CAAC,CACd,CAAC;IAEF,OAAO,KAAC,gBAAgB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAA6B,CAAC;AACzF,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,4EAA4E,CAC7E,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,oBAAoB;IAClC,OAAO,UAAU,CAAC,gBAAgB,CAAC,CAAC;AACtC,CAAC"}
@@ -0,0 +1,105 @@
1
+ /**
2
+ * The chat UI, in two pieces so host apps can take as much or as little as
3
+ * they want:
4
+ *
5
+ * - `AssistantWidget` — a floating launcher and panel. Drop it in, done.
6
+ * - `AssistantPanel` — just the conversation, unpositioned. Put it in a
7
+ * sidebar, a drawer, a modal, a settings tab.
8
+ * - Neither, and `useAssistant()` instead — every piece of state the panel
9
+ * renders is on that hook, so a fully custom UI needs nothing from here.
10
+ *
11
+ * Opening and closing lives in the provider rather than in the widget, so a
12
+ * button, a command palette, a keyboard shortcut, or a plain div in the host
13
+ * app can drive it. See `useAssistantTrigger`.
14
+ *
15
+ * Styled with inline styles rather than a stylesheet: this mounts inside
16
+ * someone else's app, and a stylesheet would either leak into their page or
17
+ * be overridden by it. Inline styles are the one approach that cannot do
18
+ * either.
19
+ *
20
+ * The confirmation card is the part to read carefully. It renders `label`,
21
+ * `description`, and `input` from the proposal payload, which the runtime
22
+ * copies from its registry — never from the assistant's prose. Text smuggled
23
+ * into a product name or a document therefore cannot change what a user is
24
+ * shown they are about to approve.
25
+ */
26
+ import { type CSSProperties, type ReactNode } from "react";
27
+ import { type OrbCorner, type OrbVoiceMode } from "./orb.js";
28
+ import { ASSISTANT_PANEL_ID } from "./provider.js";
29
+ export { ASSISTANT_PANEL_ID };
30
+ export { formatValue, humanizeKey } from "./card.js";
31
+ export interface AssistantPanelProps {
32
+ /**
33
+ * Header title, and the launcher's accessible name.
34
+ *
35
+ * Left out, it is the assistant's name from the app's settings — the same
36
+ * one the model introduces itself by — so the header and its own words
37
+ * cannot disagree, and renaming it is a setting rather than a deploy of this
38
+ * app. Pass it to override that; `"Assistant"` is the fallback before the
39
+ * handshake answers.
40
+ */
41
+ title?: string;
42
+ /** Placeholder for the input. */
43
+ placeholder?: string;
44
+ /**
45
+ * Show the header's close button. Off by default for the standalone panel,
46
+ * since a panel embedded in a sidebar usually has nothing to close.
47
+ */
48
+ showClose?: boolean;
49
+ /** Merged over the panel's own styles, for sizing and positioning. */
50
+ style?: CSSProperties;
51
+ /**
52
+ * Show the microphone and hands-free buttons beside the input, when voice
53
+ * is on for the app. True by default. The orb turns them off: in that form
54
+ * voice lives in the orb, and two ways into it would be one too many.
55
+ */
56
+ showVoice?: boolean;
57
+ }
58
+ export interface AssistantWidgetProps extends AssistantPanelProps {
59
+ /**
60
+ * Render the floating launcher button. Turn it off when the host app has
61
+ * its own trigger, so the user does not get two.
62
+ */
63
+ showLauncher?: boolean;
64
+ /** Open on first mount. */
65
+ defaultOpen?: boolean;
66
+ /**
67
+ * What the launcher button shows, drawn inside its 52px circle.
68
+ *
69
+ * Left out, it is the icon uploaded in the dashboard (the app's settings),
70
+ * so changing it needs no deploy of this app; with none uploaded, it is the
71
+ * Mihe mark. Pass it to override both.
72
+ */
73
+ launcherIcon?: ReactNode;
74
+ /**
75
+ * `"orb"`, the default: a circle that opens a menu of chat and voice, and
76
+ * shows voice in itself so the page stays visible (amendment 61).
77
+ * `"classic"`: a launcher that opens the panel, with voice inside it.
78
+ */
79
+ form?: "orb" | "classic";
80
+ /** Orb only. Let the user drag it to either side; it remembers where. */
81
+ draggable?: boolean;
82
+ /** Orb only. Where it sits until dragged. */
83
+ corner?: OrbCorner;
84
+ /**
85
+ * Orb only. Which voice modes its menu offers, when voice is on for the
86
+ * app. With none, or voice off, tapping the orb opens chat directly.
87
+ *
88
+ * Narrows the app's setting and never widens it: a mode the app has not
89
+ * allowed is refused by the runtime, so offering it would be a button that
90
+ * fails.
91
+ */
92
+ voiceModes?: OrbVoiceMode[];
93
+ }
94
+ /**
95
+ * The batteries-included option: the orb by default, or the classic launcher
96
+ * and floating panel.
97
+ */
98
+ export declare function AssistantWidget({ showLauncher, defaultOpen, title, launcherIcon, form: formProp, draggable: draggableProp, corner: cornerProp, voiceModes: voiceModesProp, ...panelProps }: AssistantWidgetProps): import("react").JSX.Element | null;
99
+ /**
100
+ * The conversation on its own: transcript, confirmation cards, composer.
101
+ *
102
+ * Unpositioned, so it fills whatever the host app puts it in.
103
+ */
104
+ export declare function AssistantPanel({ title, placeholder, showClose, style, showVoice, }: AssistantPanelProps): import("react").JSX.Element;
105
+ //# sourceMappingURL=widget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.d.ts","sourceRoot":"","sources":["../../../react/src/widget.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAA+B,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAMxF,OAAO,EAAO,KAAK,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAoC,MAAM,YAAY,CAAC;AAGlF,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAElD,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;OAGG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sEAAsE;IACtE,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,2BAA2B;IAC3B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IAMzB;;;;OAIG;IACH,IAAI,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACzB,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,YAAY,EAAE,CAAC;CAC7B;AAuBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,YAAmB,EACnB,WAAmB,EACnB,KAAK,EACL,YAAY,EACZ,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,UAAU,EAClB,UAAU,EAAE,cAAc,EAC1B,GAAG,UAAU,EACd,EAAE,oBAAoB,sCAoEtB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,WAA+C,EAC/C,SAAiB,EACjB,KAAK,EACL,SAAgB,GACjB,EAAE,mBAAmB,+BA6KrB"}
package/dist/widget.js ADDED
@@ -0,0 +1,414 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * The chat UI, in two pieces so host apps can take as much or as little as
4
+ * they want:
5
+ *
6
+ * - `AssistantWidget` — a floating launcher and panel. Drop it in, done.
7
+ * - `AssistantPanel` — just the conversation, unpositioned. Put it in a
8
+ * sidebar, a drawer, a modal, a settings tab.
9
+ * - Neither, and `useAssistant()` instead — every piece of state the panel
10
+ * renders is on that hook, so a fully custom UI needs nothing from here.
11
+ *
12
+ * Opening and closing lives in the provider rather than in the widget, so a
13
+ * button, a command palette, a keyboard shortcut, or a plain div in the host
14
+ * app can drive it. See `useAssistantTrigger`.
15
+ *
16
+ * Styled with inline styles rather than a stylesheet: this mounts inside
17
+ * someone else's app, and a stylesheet would either leak into their page or
18
+ * be overridden by it. Inline styles are the one approach that cannot do
19
+ * either.
20
+ *
21
+ * The confirmation card is the part to read carefully. It renders `label`,
22
+ * `description`, and `input` from the proposal payload, which the runtime
23
+ * copies from its registry — never from the assistant's prose. Text smuggled
24
+ * into a product name or a document therefore cannot change what a user is
25
+ * shown they are about to approve.
26
+ */
27
+ import { useEffect, useRef, useState } from "react";
28
+ import { ConfirmationCard } from "./card.js";
29
+ import { LAUNCHER_BG, LAUNCHER_INK, LauncherIcon } from "./launcher-icon.js";
30
+ import { Orb } from "./orb.js";
31
+ import { ASSISTANT_PANEL_ID, useAssistant } from "./provider.js";
32
+ export { ASSISTANT_PANEL_ID };
33
+ // Still importable from here, where they lived before `card.tsx`.
34
+ export { formatValue, humanizeKey } from "./card.js";
35
+ const DEFAULT_VOICE_MODES = ["hands-free", "hold"];
36
+ /**
37
+ * A prop where one was passed, the app's setting where one arrived, the
38
+ * SDK's default otherwise. Voice modes intersect instead of overriding.
39
+ */
40
+ function resolveWidget(props, settings) {
41
+ const allowed = settings?.voiceModes ?? DEFAULT_VOICE_MODES;
42
+ return {
43
+ form: props.form ?? settings?.form ?? "orb",
44
+ draggable: props.draggable ?? settings?.draggable ?? false,
45
+ corner: props.corner ?? settings?.corner ?? "bottom-right",
46
+ voiceModes: props.voiceModes
47
+ ? props.voiceModes.filter((mode) => allowed.includes(mode))
48
+ : allowed,
49
+ };
50
+ }
51
+ /**
52
+ * The batteries-included option: the orb by default, or the classic launcher
53
+ * and floating panel.
54
+ */
55
+ export function AssistantWidget({ showLauncher = true, defaultOpen = false, title, launcherIcon, form: formProp, draggable: draggableProp, corner: cornerProp, voiceModes: voiceModesProp, ...panelProps }) {
56
+ const { isOpen, open, assistantName, launcherIconUrl, widgetSettings } = useAssistant();
57
+ const { form, draggable, corner, voiceModes } = resolveWidget({
58
+ form: formProp,
59
+ draggable: draggableProp,
60
+ corner: cornerProp,
61
+ voiceModes: voiceModesProp,
62
+ }, widgetSettings);
63
+ const heading = title ?? assistantName ?? "Assistant";
64
+ // `defaultOpen` is honoured once, on mount. After that the provider owns
65
+ // the state, so a host trigger and this prop cannot fight over it.
66
+ const applied = useRef(false);
67
+ useEffect(() => {
68
+ if (applied.current)
69
+ return;
70
+ applied.current = true;
71
+ if (defaultOpen)
72
+ open();
73
+ }, [defaultOpen, open]);
74
+ if (form === "orb") {
75
+ return (_jsx(Orb, { heading: heading, launcherIcon: launcherIcon, draggable: draggable, corner: corner, voiceModes: voiceModes, showOrb: showLauncher, renderPanel: (position) => (_jsx(AssistantPanel, { title: heading, showClose: true, ...panelProps, showVoice: false, style: { ...position, ...panelProps.style } })) }));
76
+ }
77
+ if (!isOpen) {
78
+ if (!showLauncher)
79
+ return null;
80
+ return (_jsx("button", { type: "button", onClick: open, "aria-label": `Open ${heading}`, "aria-controls": ASSISTANT_PANEL_ID, "aria-expanded": false, style: styles.launcher, children: launcherIcon ?? _jsx(LauncherIcon, { url: launcherIconUrl }) }));
81
+ }
82
+ return (_jsx(AssistantPanel, { title: heading, showClose: true, ...panelProps, style: { ...styles.floating, ...panelProps.style } }));
83
+ }
84
+ /**
85
+ * The conversation on its own: transcript, confirmation cards, composer.
86
+ *
87
+ * Unpositioned, so it fills whatever the host app puts it in.
88
+ */
89
+ export function AssistantPanel({ title, placeholder = "Ask me anything about this app…", showClose = false, style, showVoice = true, }) {
90
+ const { messages, proposals, busy, connection, lastError, send, respondToProposal, close, voice, assistantName, widgetSettings, } = useAssistant();
91
+ // The modes the app allows. Offering one it does not would be a button the
92
+ // runtime refuses.
93
+ const voiceModes = widgetSettings?.voiceModes ?? DEFAULT_VOICE_MODES;
94
+ // Explicit prop, then the app's own setting, then a name that is at least
95
+ // not blank. The panel resolves it again rather than trusting the widget to,
96
+ // because it is exported on its own for host apps that place it themselves.
97
+ const heading = title ?? assistantName ?? "Assistant";
98
+ const [draft, setDraft] = useState("");
99
+ const scrollRef = useRef(null);
100
+ useEffect(() => {
101
+ scrollRef.current?.scrollTo({
102
+ top: scrollRef.current.scrollHeight,
103
+ behavior: "smooth",
104
+ });
105
+ }, [messages, proposals]);
106
+ const submit = () => {
107
+ send(draft);
108
+ setDraft("");
109
+ };
110
+ return (_jsxs("section", { id: ASSISTANT_PANEL_ID, style: { ...styles.panel, ...style }, "aria-label": heading, children: [_jsxs("header", { style: styles.header, children: [_jsxs("div", { style: styles.headerTitle, children: [_jsx("span", { "aria-hidden": "true", style: {
111
+ ...styles.statusDot,
112
+ background: connection === "open" ? "#22c55e" : "#f59e0b",
113
+ } }), heading] }), showClose && (_jsx("button", { type: "button", onClick: close, "aria-label": "Close assistant", style: styles.iconButton, children: "\u2715" }))] }), _jsxs("div", { ref: scrollRef, style: styles.transcript, children: [messages.length === 0 && (_jsx("p", { style: styles.empty, children: "Ask where something is, what a screen does, or for help getting something done." })), messages.map((message) => (_jsxs("div", { style: message.role === "user" ? styles.userBubble : styles.assistantBubble, children: [message.text, message.streaming && message.text === "" && (_jsx("span", { style: styles.thinking, children: "thinking\u2026" })), message.sources && message.sources.length > 0 && (_jsx("div", { style: styles.sources, children: message.sources.map((source) => (_jsx("span", { style: styles.source, children: source.url ? (_jsx("a", { href: source.url, target: "_blank", rel: "noreferrer noopener", style: styles.sourceLink, children: source.title })) : (source.title) }, source.sourceId + source.title))) }))] }, message.id))), proposals.map((proposal) => (_jsx(ConfirmationCard, { proposal: proposal, onRespond: respondToProposal }, proposal.proposalId))), voice.state === "connecting" && (
114
+ // Setting up a voice session takes a moment — the socket, the
115
+ // microphone permission, and the provider accepting its
116
+ // configuration — and the microphone stays shut until it finishes
117
+ // (amendment 32). Without a word here the user talks into a session
118
+ // that is not listening yet and concludes it is broken.
119
+ _jsx("div", { style: styles.voiceNotice, children: "Setting up the microphone\u2026" })), voice.notice && (_jsx("div", { style: styles.voiceNotice, children: voice.notice })), lastError && _jsx("div", { style: styles.error, children: lastError }), connection !== "open" && (_jsx("div", { style: styles.notice, children: connection === "closed"
120
+ ? "Disconnected."
121
+ : "Connecting…" }))] }), _jsxs("form", { style: styles.composer, onSubmit: (event) => {
122
+ event.preventDefault();
123
+ submit();
124
+ }, children: [showVoice && voice.available && voiceModes.length > 0 && (_jsx(VoiceControl, { voice: voice, disabled: connection !== "open", allowHold: voiceModes.includes("hold"), allowHandsFree: voiceModes.includes("hands-free") })), _jsx("input", { value: draft, onChange: (event) => setDraft(event.target.value), placeholder: placeholder, "aria-label": "Message", style: styles.input, disabled: connection !== "open" }), _jsx("button", { type: "submit", disabled: busy || !draft.trim() || connection !== "open", style: styles.send, children: "Send" })] })] }));
125
+ }
126
+ const PULSE_KEYFRAMES = `
127
+ @keyframes mihe-pulse {
128
+ 0%, 100% { transform: scale(1); opacity: 1; }
129
+ 50% { transform: scale(0.6); opacity: 0.45; }
130
+ }
131
+ @media (prefers-reduced-motion: reduce) {
132
+ .mihe-pulse { animation: none !important; }
133
+ }
134
+ `;
135
+ /**
136
+ * The microphone, in whichever of its two modes is running.
137
+ *
138
+ * Idle, it offers both: tap to hold-and-talk, or switch to hands-free. Once a
139
+ * session is live the two behave differently enough to be different controls —
140
+ * one is held, the other is a state you are in — so only the running one is
141
+ * shown, with a way out.
142
+ */
143
+ function VoiceControl({ voice, disabled, allowHold, allowHandsFree, }) {
144
+ // Connecting is excluded deliberately. A hands-free session that is still
145
+ // being set up used to render the pulsing live button, which says "the
146
+ // microphone is open" — the one thing that is not yet true, and the reason
147
+ // someone talks into a session that cannot hear them.
148
+ const live = voice.state !== "idle" && voice.state !== "error" && voice.state !== "connecting";
149
+ if (live && voice.handsFree) {
150
+ return (_jsxs(_Fragment, { children: [_jsx("style", { children: PULSE_KEYFRAMES }), _jsx("button", { type: "button", "aria-label": "Stop hands-free voice", "aria-pressed": true, disabled: disabled, onClick: voice.stop, style: { ...styles.mic, ...styles.micLive }, title: voice.state === "speaking"
151
+ ? "Speaking — just talk to interrupt"
152
+ : "Listening — say anything", children: _jsx("span", { className: "mihe-pulse", style: {
153
+ ...styles.pulse,
154
+ // Speaking and listening both pulse, at different rates, because
155
+ // the one thing a hands-free user cannot tell from a static icon
156
+ // is whether the microphone is actually open.
157
+ animationDuration: voice.state === "speaking" ? "0.8s" : "2s",
158
+ } }) })] }));
159
+ }
160
+ if (live) {
161
+ return (_jsx(PushToTalk, { state: voice.state, onStart: () => voice.start(), onPress: voice.press, onRelease: voice.release, disabled: disabled }));
162
+ }
163
+ return (_jsxs(_Fragment, { children: [allowHold && (_jsx(PushToTalk, { state: voice.state, onStart: () => voice.start(), onPress: voice.press, onRelease: voice.release, disabled: disabled })), allowHandsFree && (_jsx("button", { type: "button", "aria-label": "Start hands-free voice", disabled: disabled, onClick: () => voice.start({ handsFree: true }), style: styles.handsFree, title: "Hands-free \u2014 talk without holding anything", children: "\u221E" }))] }));
164
+ }
165
+ /**
166
+ * The push-to-talk button.
167
+ *
168
+ * Hold to speak, release to send — the same gesture on a mouse, a touchscreen,
169
+ * and a keyboard. Three details are doing real work:
170
+ *
171
+ * - **`onPointerDown` rather than `onClick`**, because the press has to begin
172
+ * the utterance and the release has to end it. It is also the user gesture
173
+ * iOS Safari requires before any audio can start, which is why the first
174
+ * press opens the session rather than an effect doing it on mount.
175
+ * - **`setPointerCapture`**, so a finger that slides off the button while
176
+ * speaking still ends the utterance on release. Without it the pointer-up
177
+ * lands on whatever is underneath and the microphone stays open.
178
+ * - **Space and Enter**, held rather than tapped, so the button is usable
179
+ * without a pointer at all. `repeat` is ignored, because a held key fires
180
+ * `keydown` continuously.
181
+ */
182
+ function PushToTalk({ state, onStart, onPress, onRelease, disabled, }) {
183
+ const connecting = state === "connecting";
184
+ // Connecting is not idle and not ready: the session exists but the
185
+ // microphone is shut until the provider accepts its configuration. Treating
186
+ // it as live meant the button looked armed and swallowed presses.
187
+ const live = state !== "idle" && state !== "error" && !connecting;
188
+ const recording = state === "recording";
189
+ const begin = (event) => {
190
+ if (connecting)
191
+ return;
192
+ if (!live) {
193
+ onStart();
194
+ return;
195
+ }
196
+ if (event.pointerId !== undefined) {
197
+ event.currentTarget.setPointerCapture?.(event.pointerId);
198
+ }
199
+ onPress();
200
+ };
201
+ return (_jsx("button", { type: "button", "aria-label": connecting
202
+ ? "Setting up the microphone"
203
+ : !live
204
+ ? "Start voice"
205
+ : recording
206
+ ? "Release to send"
207
+ : "Hold to speak", "aria-busy": connecting, "aria-pressed": recording, disabled: disabled || connecting, style: {
208
+ ...styles.mic,
209
+ ...(recording ? styles.micRecording : null),
210
+ ...(live && !recording ? styles.micLive : null),
211
+ }, onPointerDown: begin, onPointerUp: () => live && onRelease(), onPointerCancel: () => live && onRelease(), onKeyDown: (event) => {
212
+ if (event.repeat)
213
+ return;
214
+ if (event.key === " " || event.key === "Enter") {
215
+ event.preventDefault();
216
+ begin(event);
217
+ }
218
+ }, onKeyUp: (event) => {
219
+ if (live && (event.key === " " || event.key === "Enter")) {
220
+ event.preventDefault();
221
+ onRelease();
222
+ }
223
+ }, title: state === "thinking"
224
+ ? "Thinking…"
225
+ : state === "speaking"
226
+ ? "Speaking — press to interrupt"
227
+ : undefined, children: state === "thinking" ? "…" : "\u{1F399}" }));
228
+ }
229
+ const FONT = "system-ui, -apple-system, 'Segoe UI', sans-serif";
230
+ const styles = {
231
+ launcher: {
232
+ position: "fixed",
233
+ right: 20,
234
+ bottom: 20,
235
+ width: 52,
236
+ height: 52,
237
+ borderRadius: "50%",
238
+ border: "none",
239
+ padding: 0,
240
+ display: "grid",
241
+ placeItems: "center",
242
+ overflow: "hidden",
243
+ background: LAUNCHER_BG,
244
+ color: LAUNCHER_INK,
245
+ cursor: "pointer",
246
+ boxShadow: "0 8px 24px rgba(15,23,42,0.25)",
247
+ zIndex: 2147482000,
248
+ },
249
+ // Unpositioned: fills its container. `floating` adds the corner placement.
250
+ panel: {
251
+ display: "flex",
252
+ width: "100%",
253
+ height: "100%",
254
+ flexDirection: "column",
255
+ background: "#fff",
256
+ color: "#0f172a",
257
+ borderRadius: 14,
258
+ border: "1px solid #e2e8f0",
259
+ boxShadow: "0 20px 50px rgba(15,23,42,0.22)",
260
+ font: `14px/1.5 ${FONT}`,
261
+ overflow: "hidden",
262
+ },
263
+ floating: {
264
+ position: "fixed",
265
+ right: 20,
266
+ bottom: 20,
267
+ width: "min(380px, calc(100vw - 40px))",
268
+ height: "min(560px, calc(100vh - 40px))",
269
+ zIndex: 2147482000,
270
+ },
271
+ header: {
272
+ display: "flex",
273
+ alignItems: "center",
274
+ justifyContent: "space-between",
275
+ padding: "12px 14px",
276
+ borderBottom: "1px solid #e2e8f0",
277
+ fontWeight: 600,
278
+ },
279
+ headerTitle: { display: "flex", alignItems: "center", gap: 8 },
280
+ statusDot: { width: 8, height: 8, borderRadius: "50%", display: "inline-block" },
281
+ iconButton: {
282
+ border: "none",
283
+ background: "transparent",
284
+ cursor: "pointer",
285
+ fontSize: 14,
286
+ color: "#64748b",
287
+ },
288
+ transcript: {
289
+ flex: 1,
290
+ overflowY: "auto",
291
+ padding: 14,
292
+ display: "flex",
293
+ flexDirection: "column",
294
+ gap: 10,
295
+ },
296
+ empty: { color: "#64748b", margin: 0 },
297
+ userBubble: {
298
+ alignSelf: "flex-end",
299
+ maxWidth: "85%",
300
+ background: "#4f7cff",
301
+ color: "#fff",
302
+ padding: "8px 12px",
303
+ borderRadius: "12px 12px 2px 12px",
304
+ whiteSpace: "pre-wrap",
305
+ },
306
+ assistantBubble: {
307
+ alignSelf: "flex-start",
308
+ maxWidth: "85%",
309
+ background: "#f1f5f9",
310
+ padding: "8px 12px",
311
+ borderRadius: "12px 12px 12px 2px",
312
+ whiteSpace: "pre-wrap",
313
+ },
314
+ thinking: { color: "#64748b", fontStyle: "italic" },
315
+ sources: {
316
+ display: "flex",
317
+ flexWrap: "wrap",
318
+ gap: 6,
319
+ marginTop: 8,
320
+ paddingTop: 8,
321
+ borderTop: "1px solid #e2e8f0",
322
+ },
323
+ source: {
324
+ fontSize: 11,
325
+ color: "#475569",
326
+ background: "#f1f5f9",
327
+ padding: "2px 8px",
328
+ borderRadius: 999,
329
+ },
330
+ sourceLink: { color: "inherit", textDecoration: "none" },
331
+ error: {
332
+ background: "#fef2f2",
333
+ color: "#991b1b",
334
+ padding: "8px 10px",
335
+ borderRadius: 8,
336
+ fontSize: 13,
337
+ },
338
+ notice: { color: "#64748b", fontSize: 13, textAlign: "center" },
339
+ // The shape of the error box, deliberately, in the weight of a remark. A
340
+ // voice session ending on time is the ordinary case and the user has lost
341
+ // nothing, so it must not be red — but it is about their session rather than
342
+ // about the connection, so it is not the grey centred line either.
343
+ voiceNotice: {
344
+ background: "#f1f5f9",
345
+ color: "#475569",
346
+ padding: "8px 10px",
347
+ borderRadius: 8,
348
+ fontSize: 13,
349
+ },
350
+ composer: {
351
+ display: "flex",
352
+ gap: 8,
353
+ padding: 12,
354
+ borderTop: "1px solid #e2e8f0",
355
+ },
356
+ input: {
357
+ flex: 1,
358
+ padding: "9px 12px",
359
+ borderRadius: 8,
360
+ border: "1px solid #cbd5e1",
361
+ font: `14px ${FONT}`,
362
+ outline: "none",
363
+ },
364
+ mic: {
365
+ width: 38,
366
+ borderRadius: 8,
367
+ border: "1px solid #cbd5e1",
368
+ background: "#fff",
369
+ cursor: "pointer",
370
+ fontSize: 16,
371
+ // Otherwise a long press on a phone selects the emoji and pops up the
372
+ // copy menu instead of recording.
373
+ userSelect: "none",
374
+ touchAction: "none",
375
+ },
376
+ micLive: {
377
+ borderColor: "#4f7cff",
378
+ },
379
+ micRecording: {
380
+ borderColor: "#dc2626",
381
+ background: "#fef2f2",
382
+ },
383
+ handsFree: {
384
+ width: 30,
385
+ borderRadius: 8,
386
+ border: "1px solid #cbd5e1",
387
+ background: "#fff",
388
+ color: "#475569",
389
+ cursor: "pointer",
390
+ fontSize: 15,
391
+ userSelect: "none",
392
+ },
393
+ pulse: {
394
+ display: "block",
395
+ width: 12,
396
+ height: 12,
397
+ margin: "0 auto",
398
+ borderRadius: "50%",
399
+ background: "#4f7cff",
400
+ animationName: "mihe-pulse",
401
+ animationIterationCount: "infinite",
402
+ animationTimingFunction: "ease-in-out",
403
+ },
404
+ send: {
405
+ padding: "9px 16px",
406
+ borderRadius: 8,
407
+ border: "none",
408
+ background: "#4f7cff",
409
+ color: "#fff",
410
+ cursor: "pointer",
411
+ font: `600 13px ${FONT}`,
412
+ },
413
+ };
414
+ //# sourceMappingURL=widget.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widget.js","sourceRoot":"","sources":["../../../react/src/widget.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@mihe-dev/react",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0",
4
+ "description": "Embed an app-aware AI assistant in your React app.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./package.json": "./package.json"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "README.md",
21
+ "LICENSE"
22
+ ],
23
+ "sideEffects": false,
24
+ "homepage": "https://mihe.dev/docs",
25
+ "keywords": [
26
+ "ai",
27
+ "assistant",
28
+ "copilot",
29
+ "agent",
30
+ "react",
31
+ "voice",
32
+ "mihe"
33
+ ],
34
+ "peerDependencies": {
35
+ "react": ">=18"
36
+ },
37
+ "dependencies": {
38
+ "@mihe-dev/js": "0.1.0",
39
+ "@mihe-dev/protocol": "0.1.0"
40
+ },
41
+ "publishConfig": {
42
+ "access": "public"
43
+ }
44
+ }