@alexkroman1/aai-ui 3.1.0 → 4.0.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/audio.d.ts +0 -33
- package/dist/audio.js +2 -20
- package/dist/{chat-view-C1oJxsWz.js → chat-view-CW-tZCMm.js} +1 -4
- package/dist/components/chat-view.js +1 -1
- package/dist/components/console-shell.d.ts +0 -9
- package/dist/components/markdown.d.ts +21 -0
- package/dist/components/message-list.d.ts +0 -8
- package/dist/components/message-list.js +3 -230
- package/dist/components/url-chips.d.ts +0 -15
- package/dist/context.d.ts +1 -1
- package/dist/default-client/assets/audio-DQseUQnN.js +1 -0
- package/dist/default-client/assets/{capture-processor-BLPsqnGl.js → capture-processor-DKFNcEhw.js} +1 -1
- package/dist/default-client/assets/index-CRfdZPH1.css +2 -0
- package/dist/default-client/assets/index-CkZ6t_eJ.js +417 -0
- package/dist/default-client/assets/{playback-processor-B_T_1KQP.js → playback-processor-HeyncQUX.js} +1 -1
- package/dist/default-client/index.html +2 -2
- package/dist/{define-client-Cyf1jqAl.js → define-client-DqRs1XPd.js} +2 -2
- package/dist/define-client.d.ts +1 -1
- package/dist/define-client.js +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +6 -7
- package/dist/message-list-q2lTiFhF.js +381 -0
- package/dist/{session-core-BM3WHeoY.js → session-core-CkZ8LyEA.js} +30 -24
- package/dist/session-core-audio-setup.d.ts +3 -6
- package/dist/session-core-types.d.ts +0 -9
- package/dist/session-core.d.ts +0 -1
- package/dist/session-core.js +1 -1
- package/dist/types.d.ts +1 -1
- package/dist/types.js +2 -2
- package/package.json +4 -2
- package/dist/default-client/assets/audio-BGHiiDY_.js +0 -1
- package/dist/default-client/assets/index-DXf7-M0Q.js +0 -244
- package/dist/default-client/assets/index-Dv-Q5VRL.css +0 -2
package/dist/audio.d.ts
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Clamp-and-convert Float32 samples to PCM16. The one main-thread home of the
|
|
3
|
-
* asymmetric-rounding convention (negative × 0x8000, positive × 0x7fff) —
|
|
4
|
-
* the capture worklet's `accumulate` embeds the same math, which cannot
|
|
5
|
-
* import it (worklet source is a string).
|
|
6
|
-
*
|
|
7
|
-
* @public
|
|
8
|
-
*/
|
|
9
|
-
export declare function floatToPcm16(samples: Float32Array): Int16Array;
|
|
10
1
|
/**
|
|
11
2
|
* How much of one turn's playback was covered by concealment rather than
|
|
12
3
|
* received audio — the playback worklet's underrun report, in the shape
|
|
@@ -78,21 +69,6 @@ export type VoiceIO = AsyncDisposable & {
|
|
|
78
69
|
/** Release all audio resources (microphone, AudioContext, worklets). */
|
|
79
70
|
close(): Promise<void>;
|
|
80
71
|
};
|
|
81
|
-
/**
|
|
82
|
-
* Throw unless the browser honored a requested context sample rate. The
|
|
83
|
-
* requested rates are never advisory: captured audio is tagged with the
|
|
84
|
-
* requested rate on the wire, so a context running at some other rate ships
|
|
85
|
-
* audio that only sounds like speech to the wrong decoder. Every capture
|
|
86
|
-
* path must call this after context creation.
|
|
87
|
-
*/
|
|
88
|
-
export declare function assertGranted(granted: number, requested: number, side: string): void;
|
|
89
|
-
/**
|
|
90
|
-
* Release a microphone that was (or later gets) granted while another init
|
|
91
|
-
* step failed; if `getUserMedia` itself rejected, this is a no-op. Without
|
|
92
|
-
* it, a mic granted after a failed init keeps the browser's recording
|
|
93
|
-
* indicator lit with no way to turn it off.
|
|
94
|
-
*/
|
|
95
|
-
export declare function releaseStreamOnFailure(streamPromise: Promise<MediaStream>): void;
|
|
96
72
|
/** Handle to one capture worklet node (`worklets/capture-processor.ts`). */
|
|
97
73
|
export type CaptureNode = {
|
|
98
74
|
node: AudioWorkletNode;
|
|
@@ -105,15 +81,6 @@ export type CaptureNode = {
|
|
|
105
81
|
*/
|
|
106
82
|
stop(): Promise<void>;
|
|
107
83
|
};
|
|
108
|
-
/**
|
|
109
|
-
* Wire one capture worklet node: node construction, the chunk/silent/stopped
|
|
110
|
-
* port protocol, and the stop→ack handshake — one spelling for both the
|
|
111
|
-
* WebSocket mic and the push-to-talk recorder. No `processorOptions`: the
|
|
112
|
-
* worklet reads the context rate from its global scope (callers assert the
|
|
113
|
-
* granted rate first) and owns its own batching default — re-spelling
|
|
114
|
-
* defaults caller-side is drift.
|
|
115
|
-
*/
|
|
116
|
-
export declare function createCaptureNode(ctx: AudioContext, onChunk: (pcm16: ArrayBuffer) => void, onSilent?: () => void): CaptureNode;
|
|
117
84
|
/**
|
|
118
85
|
* Create a {@link VoiceIO} instance that captures microphone audio and
|
|
119
86
|
* plays back TTS audio using the Web Audio API.
|
package/dist/audio.js
CHANGED
|
@@ -1,23 +1,6 @@
|
|
|
1
1
|
import { CAPTURE_STOP_ACK_TIMEOUT_MS, PLAYBACK_DONE_MAX_WAIT_MS, PLAYBACK_DONE_POLL_MS, VOICE_CAPTURE_CONSTRAINTS } from "./types.js";
|
|
2
2
|
//#region audio.ts
|
|
3
3
|
/**
|
|
4
|
-
* Clamp-and-convert Float32 samples to PCM16. The one main-thread home of the
|
|
5
|
-
* asymmetric-rounding convention (negative × 0x8000, positive × 0x7fff) —
|
|
6
|
-
* the capture worklet's `accumulate` embeds the same math, which cannot
|
|
7
|
-
* import it (worklet source is a string).
|
|
8
|
-
*
|
|
9
|
-
* @public
|
|
10
|
-
*/
|
|
11
|
-
function floatToPcm16(samples) {
|
|
12
|
-
const pcm = new Int16Array(samples.length);
|
|
13
|
-
let i = 0;
|
|
14
|
-
for (const sample of samples) {
|
|
15
|
-
const s = Math.max(-1, Math.min(1, sample));
|
|
16
|
-
pcm[i++] = s < 0 ? s * 32768 : s * 32767;
|
|
17
|
-
}
|
|
18
|
-
return pcm;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
4
|
* Throw unless the browser honored a requested context sample rate. The
|
|
22
5
|
* requested rates are never advisory: captured audio is tagged with the
|
|
23
6
|
* requested rate on the wire, so a context running at some other rate ships
|
|
@@ -41,8 +24,7 @@ function releaseStreamOnFailure(streamPromise) {
|
|
|
41
24
|
}
|
|
42
25
|
/**
|
|
43
26
|
* Wire one capture worklet node: node construction, the chunk/silent/stopped
|
|
44
|
-
* port protocol, and the stop→ack handshake
|
|
45
|
-
* WebSocket mic and the push-to-talk recorder. No `processorOptions`: the
|
|
27
|
+
* port protocol, and the stop→ack handshake. No `processorOptions`: the
|
|
46
28
|
* worklet reads the context rate from its global scope (callers assert the
|
|
47
29
|
* granted rate first) and owns its own batching default — re-spelling
|
|
48
30
|
* defaults caller-side is drift.
|
|
@@ -217,4 +199,4 @@ async function createVoiceIO(opts) {
|
|
|
217
199
|
return io;
|
|
218
200
|
}
|
|
219
201
|
//#endregion
|
|
220
|
-
export {
|
|
202
|
+
export { createVoiceIO };
|
|
@@ -3,7 +3,7 @@ import { r as TEXT_FAINT, t as ERROR_COLOR } from "./_colors-DYX7XRTr.js";
|
|
|
3
3
|
import { t as AaiLogo } from "./aai-logo-B8lDmsut.js";
|
|
4
4
|
import { t as Eyebrow } from "./eyebrow-C6ZFuiz6.js";
|
|
5
5
|
import { t as Controls } from "./controls-DV368uhb.js";
|
|
6
|
-
import { MessageList } from "./
|
|
6
|
+
import { t as MessageList } from "./message-list-q2lTiFhF.js";
|
|
7
7
|
import clsx from "clsx";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
9
|
//#region components/console-shell.tsx
|
|
@@ -29,9 +29,6 @@ function stateColor(state, primary) {
|
|
|
29
29
|
* (logo + live-status eyebrow), an optional error banner, the main content
|
|
30
30
|
* on a raised white card, and a footer row beneath it.
|
|
31
31
|
*
|
|
32
|
-
* Extracted so the two default surfaces stay visually identical by
|
|
33
|
-
* construction — they used to be hand-copied down to the same `boxShadow`
|
|
34
|
-
* literal, and drifted.
|
|
35
32
|
*
|
|
36
33
|
* @internal
|
|
37
34
|
*/
|
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
import type { ReactNode } from "react";
|
|
2
2
|
import type { AgentState } from "../types.ts";
|
|
3
|
-
/**
|
|
4
|
-
* Indicator dot color per state, on the light refresh palette.
|
|
5
|
-
*
|
|
6
|
-
* @internal
|
|
7
|
-
*/
|
|
8
|
-
export declare function stateColor(state: AgentState, primary: string): string;
|
|
9
3
|
/**
|
|
10
4
|
* The design-system "console" chrome for the chat shell:
|
|
11
5
|
* a 760px column on the cream page with a header
|
|
12
6
|
* (logo + live-status eyebrow), an optional error banner, the main content
|
|
13
7
|
* on a raised white card, and a footer row beneath it.
|
|
14
8
|
*
|
|
15
|
-
* Extracted so the two default surfaces stay visually identical by
|
|
16
|
-
* construction — they used to be hand-copied down to the same `boxShadow`
|
|
17
|
-
* literal, and drifted.
|
|
18
9
|
*
|
|
19
10
|
* @internal
|
|
20
11
|
*/
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** @jsxImportSource react */
|
|
2
|
+
import { type ReactNode } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Agent prose, rendered as Markdown.
|
|
5
|
+
*
|
|
6
|
+
* Pipeline and S2S models write emphasis, lists, `code`, and links; before
|
|
7
|
+
* this they arrived as literal asterisks and backticks. Styling is
|
|
8
|
+
* per-element (theme colors via inline styles, spacing via Tailwind) so it
|
|
9
|
+
* stays on the default client's type scale and follows custom themes.
|
|
10
|
+
* GFM is on for tables and strikethrough. react-markdown does not render
|
|
11
|
+
* raw HTML unless rehype-raw is added — keep it that way, this text comes
|
|
12
|
+
* from a model.
|
|
13
|
+
*
|
|
14
|
+
* Memoized alongside `MessageBubble`: message content is referentially
|
|
15
|
+
* stable across snapshots, so only the streaming row re-parses.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
19
|
+
export declare const Markdown: import("react").MemoExoticComponent<({ text }: {
|
|
20
|
+
text: string;
|
|
21
|
+
}) => ReactNode>;
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
import { type ReactNode } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* Animated three-dot "thinking" indicator. Shared with the sync-transport
|
|
4
|
-
* chat shell so both defaults render the same wait state.
|
|
5
|
-
*
|
|
6
|
-
* @internal
|
|
7
|
-
*/
|
|
8
|
-
export declare function ThinkingDots(): ReactNode;
|
|
9
1
|
/**
|
|
10
2
|
* Scrollable list of all chat messages, tool-call blocks, live transcript,
|
|
11
3
|
* streaming agent utterance, and a thinking indicator.
|
|
@@ -1,230 +1,3 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
import clsx from "clsx";
|
|
5
|
-
import { memo, useCallback, useEffect, useMemo, useRef } from "react";
|
|
6
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
7
|
-
//#region components/message-list.tsx
|
|
8
|
-
/** @jsxImportSource react */
|
|
9
|
-
const DOT_STYLES = [
|
|
10
|
-
0,
|
|
11
|
-
.16,
|
|
12
|
-
.32
|
|
13
|
-
].map((delay) => ({
|
|
14
|
-
animation: "aai-bounce 1.4s infinite ease-in-out both",
|
|
15
|
-
animationDelay: `${delay}s`
|
|
16
|
-
}));
|
|
17
|
-
/**
|
|
18
|
-
* Animated three-dot "thinking" indicator. Shared with the sync-transport
|
|
19
|
-
* chat shell so both defaults render the same wait state.
|
|
20
|
-
*
|
|
21
|
-
* @internal
|
|
22
|
-
*/
|
|
23
|
-
function ThinkingDots() {
|
|
24
|
-
return /* @__PURE__ */ jsx("div", {
|
|
25
|
-
className: "flex items-center gap-2 text-sm font-medium min-h-5",
|
|
26
|
-
style: { color: TEXT_MUTED },
|
|
27
|
-
children: DOT_STYLES.map((style, i) => /* @__PURE__ */ jsx("div", {
|
|
28
|
-
className: "w-1.5 h-1.5 rounded-full",
|
|
29
|
-
style: {
|
|
30
|
-
...style,
|
|
31
|
-
background: TEXT_MUTED
|
|
32
|
-
}
|
|
33
|
-
}, i))
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
/**
|
|
37
|
-
* Right-aligned user bubble — a primary-tinted card (the design system's
|
|
38
|
-
* indigo-50 fill with an indigo-100 edge, derived from the theme primary so
|
|
39
|
-
* custom themes stay coherent). Shared by finalized messages and the live
|
|
40
|
-
* transcript.
|
|
41
|
-
*/
|
|
42
|
-
function UserBubble({ theme, color, children }) {
|
|
43
|
-
return /* @__PURE__ */ jsx("div", {
|
|
44
|
-
className: "flex flex-col w-full items-end",
|
|
45
|
-
children: /* @__PURE__ */ jsx("div", {
|
|
46
|
-
className: "max-w-[min(78%,64ch)] border px-3.5 py-2.5 rounded-md whitespace-pre-wrap wrap-break-word text-[15px] font-normal leading-[22px]",
|
|
47
|
-
style: {
|
|
48
|
-
background: primaryTint(theme.primary, theme.surface, 7),
|
|
49
|
-
borderColor: primaryTint(theme.primary, theme.surface, 16),
|
|
50
|
-
color
|
|
51
|
-
},
|
|
52
|
-
children
|
|
53
|
-
})
|
|
54
|
-
});
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Renders a single chat message: labeled agent prose, or a user bubble.
|
|
58
|
-
*
|
|
59
|
-
* Memoized so appending one message re-renders one row, not the whole capped
|
|
60
|
-
* list: message objects and the theme are referentially stable across
|
|
61
|
-
* snapshots, and rows are keyed on stable ids (`ChatMessage.id`) that survive
|
|
62
|
-
* the sliding 200-message window.
|
|
63
|
-
*/
|
|
64
|
-
const MessageBubble = memo(function MessageBubble({ message, theme }) {
|
|
65
|
-
if (message.role === "user") return /* @__PURE__ */ jsx(UserBubble, {
|
|
66
|
-
theme,
|
|
67
|
-
color: theme.text,
|
|
68
|
-
children: message.content
|
|
69
|
-
});
|
|
70
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
71
|
-
className: "flex flex-col gap-1 max-w-[82%]",
|
|
72
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
73
|
-
className: "text-[10px] font-medium tracking-[1.2px] uppercase leading-none",
|
|
74
|
-
style: { color: TEXT_FAINT },
|
|
75
|
-
children: "Agent"
|
|
76
|
-
}), /* @__PURE__ */ jsx("div", {
|
|
77
|
-
className: "whitespace-pre-wrap wrap-break-word text-[15px] font-normal leading-[23px]",
|
|
78
|
-
style: { color: theme.text },
|
|
79
|
-
children: message.content
|
|
80
|
-
})]
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
/**
|
|
84
|
-
* How close to the bottom (px) the container must be for auto-scroll to stay
|
|
85
|
-
* engaged. Generous enough that an in-flight smooth scroll doesn't unpin.
|
|
86
|
-
*/
|
|
87
|
-
const NEAR_BOTTOM_PX = 96;
|
|
88
|
-
/**
|
|
89
|
-
* Smooth-scroll to the anchor whenever the content version advances — but
|
|
90
|
-
* only while the container is pinned near the bottom. A user who scrolled up
|
|
91
|
-
* to read history isn't yanked back down by streaming updates; scrolling back
|
|
92
|
-
* to the bottom re-engages the auto-scroll.
|
|
93
|
-
*
|
|
94
|
-
* The scroll runs inside `requestAnimationFrame` and is deduped per frame:
|
|
95
|
-
* several snapshot updates in one frame (transcript + message + tool call)
|
|
96
|
-
* trigger a single scroll after layout instead of one forced layout each.
|
|
97
|
-
*
|
|
98
|
-
* While a partial transcript is streaming, updates arrive faster than a
|
|
99
|
-
* smooth scroll finishes — each restart leaves the animation perpetually
|
|
100
|
-
* mid-flight — so `streaming` switches to an instant jump; committed-content
|
|
101
|
-
* updates keep the smooth animation.
|
|
102
|
-
*/
|
|
103
|
-
function useAutoScroll(contentVersion, streaming) {
|
|
104
|
-
const anchorRef = useRef(null);
|
|
105
|
-
const pinnedRef = useRef(true);
|
|
106
|
-
const scheduledRef = useRef(false);
|
|
107
|
-
const streamingRef = useRef(streaming);
|
|
108
|
-
streamingRef.current = streaming;
|
|
109
|
-
const onScroll = useCallback((event) => {
|
|
110
|
-
const el = event.currentTarget;
|
|
111
|
-
pinnedRef.current = el.scrollTop + el.clientHeight >= el.scrollHeight - NEAR_BOTTOM_PX;
|
|
112
|
-
}, []);
|
|
113
|
-
useEffect(() => {
|
|
114
|
-
if (contentVersion === 0 || scheduledRef.current || !pinnedRef.current) return;
|
|
115
|
-
scheduledRef.current = true;
|
|
116
|
-
requestAnimationFrame(() => {
|
|
117
|
-
scheduledRef.current = false;
|
|
118
|
-
if (!pinnedRef.current) return;
|
|
119
|
-
anchorRef.current?.scrollIntoView({
|
|
120
|
-
behavior: streamingRef.current ? "instant" : "smooth",
|
|
121
|
-
block: "end"
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
}, [contentVersion]);
|
|
125
|
-
return {
|
|
126
|
-
anchorRef,
|
|
127
|
-
onScroll
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Interleave messages and tool calls into render items, ordered by insertion
|
|
132
|
-
* time. Each tool call renders immediately after its anchor message
|
|
133
|
-
* (`afterMessageId`); tool calls whose anchor slid out of the retained window
|
|
134
|
-
* (or that were inserted before any message existed) render first.
|
|
135
|
-
*/
|
|
136
|
-
function interleave(messages, toolCalls, renderMessage, renderToolCall) {
|
|
137
|
-
const items = [];
|
|
138
|
-
let tci = 0;
|
|
139
|
-
const pushToolCallsThrough = (maxAfterId) => {
|
|
140
|
-
let tc = toolCalls[tci];
|
|
141
|
-
while (tc && tc.afterMessageId <= maxAfterId) {
|
|
142
|
-
items.push(renderToolCall(tc));
|
|
143
|
-
tci++;
|
|
144
|
-
tc = toolCalls[tci];
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
const firstMessage = messages[0];
|
|
148
|
-
if (firstMessage) pushToolCallsThrough(firstMessage.id - 1);
|
|
149
|
-
for (const msg of messages) {
|
|
150
|
-
items.push(renderMessage(msg));
|
|
151
|
-
pushToolCallsThrough(msg.id);
|
|
152
|
-
}
|
|
153
|
-
pushToolCallsThrough(Number.POSITIVE_INFINITY);
|
|
154
|
-
return items;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Scrollable list of all chat messages, tool-call blocks, live transcript,
|
|
158
|
-
* streaming agent utterance, and a thinking indicator.
|
|
159
|
-
*
|
|
160
|
-
* Messages and tool calls are interleaved in the correct order. The list
|
|
161
|
-
* auto-scrolls to the latest content.
|
|
162
|
-
*
|
|
163
|
-
* Must be rendered inside a {@link SessionProvider}.
|
|
164
|
-
*
|
|
165
|
-
* @example
|
|
166
|
-
* ```tsx
|
|
167
|
-
* <MessageList className="flex-1" />
|
|
168
|
-
* ```
|
|
169
|
-
*
|
|
170
|
-
* @param className - Additional CSS class names applied to the scroll container.
|
|
171
|
-
*
|
|
172
|
-
* @public
|
|
173
|
-
*/
|
|
174
|
-
const MessageList = memo(function MessageList({ className }) {
|
|
175
|
-
const state = useSessionSelector((s) => s.state);
|
|
176
|
-
const messages = useSessionSelector((s) => s.messages);
|
|
177
|
-
const toolCalls = useSessionSelector((s) => s.toolCalls);
|
|
178
|
-
const userTranscript = useSessionSelector((s) => s.userTranscript);
|
|
179
|
-
const agentTranscript = useSessionSelector((s) => s.agentTranscript);
|
|
180
|
-
const contentVersion = useSessionSelector((s) => s.contentVersion);
|
|
181
|
-
const theme = useTheme();
|
|
182
|
-
const showThinking = useMemo(() => {
|
|
183
|
-
if (state !== "thinking") return false;
|
|
184
|
-
const last = toolCalls.at(-1);
|
|
185
|
-
if (last?.status === "pending") return false;
|
|
186
|
-
const lastMsg = messages.at(-1);
|
|
187
|
-
return !lastMsg || lastMsg.role === "user" || Boolean(last);
|
|
188
|
-
}, [
|
|
189
|
-
state,
|
|
190
|
-
toolCalls,
|
|
191
|
-
messages
|
|
192
|
-
]);
|
|
193
|
-
const { anchorRef, onScroll } = useAutoScroll(contentVersion, userTranscript !== null);
|
|
194
|
-
const items = useMemo(() => interleave(messages, toolCalls, (msg) => /* @__PURE__ */ jsx(MessageBubble, {
|
|
195
|
-
message: msg,
|
|
196
|
-
theme
|
|
197
|
-
}, msg.id), (tc) => /* @__PURE__ */ jsx(ToolCallBlock, { toolCall: tc }, tc.callId)), [
|
|
198
|
-
messages,
|
|
199
|
-
toolCalls,
|
|
200
|
-
theme
|
|
201
|
-
]);
|
|
202
|
-
return /* @__PURE__ */ jsx("div", {
|
|
203
|
-
role: "log",
|
|
204
|
-
className: clsx("flex-1 overflow-y-auto [scrollbar-width:none]", className),
|
|
205
|
-
style: { background: theme.surface },
|
|
206
|
-
onScroll,
|
|
207
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
208
|
-
className: "flex flex-col gap-4 p-7",
|
|
209
|
-
children: [
|
|
210
|
-
items,
|
|
211
|
-
agentTranscript && /* @__PURE__ */ jsx(MessageBubble, {
|
|
212
|
-
message: {
|
|
213
|
-
role: "assistant",
|
|
214
|
-
content: agentTranscript
|
|
215
|
-
},
|
|
216
|
-
theme
|
|
217
|
-
}),
|
|
218
|
-
userTranscript !== null && /* @__PURE__ */ jsx(UserBubble, {
|
|
219
|
-
theme,
|
|
220
|
-
color: "#6F6A60",
|
|
221
|
-
children: userTranscript ? userTranscript : /* @__PURE__ */ jsx(ThinkingDots, {})
|
|
222
|
-
}),
|
|
223
|
-
showThinking && /* @__PURE__ */ jsx(ThinkingDots, {}),
|
|
224
|
-
/* @__PURE__ */ jsx("div", { ref: anchorRef })
|
|
225
|
-
]
|
|
226
|
-
})
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
//#endregion
|
|
230
|
-
export { MessageList, ThinkingDots };
|
|
1
|
+
import "../context.js";
|
|
2
|
+
import { t as MessageList } from "../message-list-q2lTiFhF.js";
|
|
3
|
+
export { MessageList };
|
|
@@ -1,18 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* A compact labeled chip showing a URL. Click to copy.
|
|
3
|
-
*
|
|
4
|
-
* The label is what makes a pair of these readable — on its own a bare URL
|
|
5
|
-
* leaves you guessing whether it's the page or the socket.
|
|
6
|
-
*
|
|
7
|
-
* @internal
|
|
8
|
-
*/
|
|
9
|
-
export declare function UrlChip({ label, url, hint, testId, className, }: {
|
|
10
|
-
label: string;
|
|
11
|
-
url: string;
|
|
12
|
-
hint: string;
|
|
13
|
-
testId: string;
|
|
14
|
-
className?: string | undefined;
|
|
15
|
-
}): import("react").JSX.Element;
|
|
16
1
|
/**
|
|
17
2
|
* The session's shareable UI URL.
|
|
18
3
|
*
|
package/dist/context.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
|
-
import type { SessionCore, SessionSnapshot } from "./session-core.ts";
|
|
2
|
+
import type { SessionCore, SessionSnapshot } from "./session-core-types.ts";
|
|
3
3
|
import type { ClientTheme } from "./types.ts";
|
|
4
4
|
export declare function SessionProvider({ value, children }: {
|
|
5
5
|
value: SessionCore;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,o as t,t as n}from"./index-CkZ6t_eJ.js";function r(e,t,n){if(e!==t)throw Error(`Browser refused the ${n} sample rate: asked for ${t} Hz, got ${e} Hz`)}function i(e){e.then(e=>{for(let t of e.getTracks())t.stop()}).catch(()=>{})}function a(e,t,n){let r=new AudioWorkletNode(e,`capture-processor`,{channelCount:1,channelCountMode:`explicit`}),i=null;return r.port.onmessage=e=>{let r=e.data;r.event===`chunk`&&r.buffer?t(r.buffer):r.event===`silent`?n?.():r.event===`stopped`&&(i?.(),i=null)},{node:r,start(){r.port.postMessage({event:`start`})},stop(){return new Promise(e=>{let t=setTimeout(e,250);i=()=>{clearTimeout(t),e()},r.port.postMessage({event:`stop`})})}}}async function o(o){let{sttSampleRate:s,ttsSampleRate:c,captureWorkletSrc:l,playbackWorkletSrc:u,onMicData:d,onError:f,onPlaybackStats:p,onMicSilent:m}=o,h=new AudioContext({sampleRate:c,latencyHint:`playback`}),g=s===c,_=g?h:new AudioContext({sampleRate:s,latencyHint:`interactive`});async function v(){let e=g?[h]:[h,_];await Promise.all(e.map(e=>e.close().catch(e=>{console.warn(`AudioContext close failed:`,e)})))}let y=navigator.mediaDevices.getUserMedia({audio:{deviceId:{ideal:`default`},...n}}),b;try{[b]=await Promise.all([y,h.resume(),_.resume(),_.audioWorklet.addModule(l),h.audioWorklet.addModule(u)]),r(_.sampleRate,s,`capture`),r(h.sampleRate,c,`playback`)}catch(e){throw i(y),await v(),e}let x=_.createMediaStreamSource(b),S=a(_,d,m);x.connect(S.node),S.node.onprocessorerror=()=>{let e=Error(`Audio capture worklet crashed`);console.error(`[aai-ui]`,e.message),f?.(e)},S.start();let C=null,w=null,T=new AbortController;function E(){if(C)return C;let e=new AudioWorkletNode(h,`playback-processor`);return e.connect(h.destination),e.port.onmessage=e=>{if(e.data.event===`stop`){let t=e.data.stats;if(t&&t.concealedSamples>0&&p?.(t),e.data.reason===`interrupt`)return;w?.(),w=null}},e.onprocessorerror=()=>{let e=Error(`Audio playback worklet crashed`);console.error(`[aai-ui]`,e.message),w?.(),w=null,f?.(e)},C=e,e}let D={enqueue(e){T.signal.aborted||e.byteLength!==0&&E().port.postMessage({event:`write`,buffer:new Uint8Array(e)},[e])},done(){return!C||(C.port.postMessage({event:`done`}),h.state!==`running`)?Promise.resolve():new Promise(n=>{w?.();let r=()=>{clearInterval(i),clearTimeout(a),w===r&&(w=null),n()},i=setInterval(()=>{h.state!==`running`&&r()},t),a=setTimeout(r,e);w=r})},flush(){C&&(w?.(),w=null,C.port.postMessage({event:`interrupt`}))},async close(){if(!T.signal.aborted){T.abort(),await S.stop(),x.disconnect(),S.node.disconnect(),C&&C.disconnect();for(let e of b.getTracks())e.stop();await v()}},async[Symbol.asyncDispose](){await D.close()}};return D}export{o as createVoiceIO};
|
package/dist/default-client/assets/{capture-processor-BLPsqnGl.js → capture-processor-DKFNcEhw.js}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{n as e,r as t}from"./index-
|
|
1
|
+
import{n as e,r as t}from"./index-CkZ6t_eJ.js";import{t as n}from"./_module-url-BX0RuRU2.js";var r=n(`
|
|
2
2
|
class CaptureProcessor extends AudioWorkletProcessor {
|
|
3
3
|
constructor(options) {
|
|
4
4
|
super();
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-wide:.025em;--radius-sm:.25rem;--radius-md:.375rem;--radius-lg:.5rem;--radius-xl:.75rem;--ease-in-out:cubic-bezier(.4, 0, .2, 1);--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono);--font-aai:"Monument Grotesk", "ABC Monument Grotesk", ui-sans-serif, system-ui, -apple-system, sans-serif;--font-aai-serif:"Source Serif 4", "Source Serif Pro", Charter, "Iowan Old Style", Georgia, serif;--font-aai-mono:"JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;--radius-aai:4px}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}html,body{margin:0;padding:0}}@layer components;@layer utilities{.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.static{position:static}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-auto{margin-inline:auto}.my-0\.5{margin-block:calc(var(--spacing) * .5)}.my-1\.5{margin-block:calc(var(--spacing) * 1.5)}.my-2\.5{margin-block:calc(var(--spacing) * 2.5)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.ml-auto{margin-left:auto}.box-border{box-sizing:border-box}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.h-1\.5{height:calc(var(--spacing) * 1.5)}.h-4{height:calc(var(--spacing) * 4)}.h-9{height:calc(var(--spacing) * 9)}.h-11{height:calc(var(--spacing) * 11)}.h-\[7px\]{height:7px}.h-screen{height:100vh}.max-h-64{max-height:calc(var(--spacing) * 64)}.min-h-0{min-height:0}.min-h-5{min-height:calc(var(--spacing) * 5)}.w-1\.5{width:calc(var(--spacing) * 1.5)}.w-4{width:calc(var(--spacing) * 4)}.w-\[7px\]{width:7px}.w-fit{width:fit-content}.w-full{width:100%}.max-w-75{max-width:calc(var(--spacing) * 75)}.max-w-105{max-width:calc(var(--spacing) * 105)}.max-w-190{max-width:calc(var(--spacing) * 190)}.max-w-\[60\%\]{max-width:60%}.max-w-\[82\%\]{max-width:82%}.max-w-\[min\(78\%\,64ch\)\]{max-width:min(78%,64ch)}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.rotate-90{rotate:90deg}.cursor-pointer{cursor:pointer}.\[scrollbar-width\:none\]{scrollbar-width:none}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.items-center{align-items:center}.items-end{align-items:flex-end}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.rounded-aai{border-radius:var(--radius-aai)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.rounded-sm{border-radius:var(--radius-sm)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-none{--tw-border-style:none;border-style:none}.bg-transparent{background-color:#0000}.p-2\.5{padding:calc(var(--spacing) * 2.5)}.p-7{padding:calc(var(--spacing) * 7)}.px-1{padding-inline:var(--spacing)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-5{padding-inline:calc(var(--spacing) * 5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.px-7{padding-inline:calc(var(--spacing) * 7)}.px-10{padding-inline:calc(var(--spacing) * 10)}.py-0\.5{padding-block:calc(var(--spacing) * .5)}.py-1{padding-block:var(--spacing)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-8{padding-block:calc(var(--spacing) * 8)}.py-12{padding-block:calc(var(--spacing) * 12)}.pl-3{padding-left:calc(var(--spacing) * 3)}.pl-5{padding-left:calc(var(--spacing) * 5)}.text-center{text-align:center}.text-left{text-align:left}.font-aai{font-family:var(--font-aai)}.font-aai-mono{font-family:var(--font-aai-mono)}.font-aai-serif{font-family:var(--font-aai-serif)}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[12\.5px\]{font-size:12.5px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[16px\]{font-size:16px}.text-\[17px\]{font-size:17px}.text-\[22px\]{font-size:22px}.text-\[32px\]{font-size:32px}.leading-4{--tw-leading:calc(var(--spacing) * 4);line-height:calc(var(--spacing) * 4)}.leading-\[1\.2\]{--tw-leading:1.2;line-height:1.2}.leading-\[1\.15\]{--tw-leading:1.15;line-height:1.15}.leading-\[22px\]{--tw-leading:22px;line-height:22px}.leading-\[23px\]{--tw-leading:23px;line-height:23px}.leading-\[130\%\]{--tw-leading:130%;line-height:130%}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-\[-0\.2px\]{--tw-tracking:-.2px;letter-spacing:-.2px}.tracking-\[1\.2px\]{--tw-tracking:1.2px;letter-spacing:1.2px}.tracking-\[1\.4px\]{--tw-tracking:1.4px;letter-spacing:1.4px}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.wrap-break-word{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.uppercase{text-transform:uppercase}.underline{text-decoration-line:underline}.underline-offset-2{text-underline-offset:2px}.ring{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-transform{transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.first\:mt-0:first-child{margin-top:0}.last\:mb-0:last-child{margin-bottom:0}.disabled\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\:opacity-50:disabled{opacity:.5}@media (width>=40rem){.sm\:px-16{padding-inline:calc(var(--spacing) * 16)}.sm\:py-14{padding-block:calc(var(--spacing) * 14)}}}@keyframes aai-pulse{0%,to{opacity:1;transform:scale(1)}50%{opacity:.45;transform:scale(.82)}}@keyframes aai-bounce{0%,80%,to{opacity:.3;transform:scale(.8)}40%{opacity:1;transform:scale(1)}}@keyframes aai-shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.tool-shimmer{-webkit-text-fill-color:transparent;background:linear-gradient(90deg,currentColor 25%,#0000 50%,currentColor 75%) 0 0/200% 100%;-webkit-background-clip:text;background-clip:text;animation:2s infinite aai-shimmer}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}
|