@agent-native/toolkit 0.10.1 → 0.10.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/chat-history.css +2 -2
  2. package/dist/composer/PromptComposer.d.ts +0 -1
  3. package/dist/composer/PromptComposer.d.ts.map +1 -1
  4. package/dist/composer/PromptComposer.js +1 -27
  5. package/dist/composer/PromptComposer.js.map +1 -1
  6. package/dist/composer/PromptComposer.spec.js +1 -8
  7. package/dist/composer/PromptComposer.spec.js.map +1 -1
  8. package/dist/composer/RealtimeVoiceMode.d.ts.map +1 -1
  9. package/dist/composer/RealtimeVoiceMode.js +5 -2
  10. package/dist/composer/RealtimeVoiceMode.js.map +1 -1
  11. package/dist/composer/RealtimeVoiceMode.spec.js +9 -0
  12. package/dist/composer/RealtimeVoiceMode.spec.js.map +1 -1
  13. package/dist/design-system/design-system.spec.js +47 -2
  14. package/dist/design-system/design-system.spec.js.map +1 -1
  15. package/dist/editor/SharedRichEditor.d.ts +3 -1
  16. package/dist/editor/SharedRichEditor.d.ts.map +1 -1
  17. package/dist/editor/SharedRichEditor.js +17 -3
  18. package/dist/editor/SharedRichEditor.js.map +1 -1
  19. package/dist/editor/SharedRichEditor.spec.d.ts +2 -0
  20. package/dist/editor/SharedRichEditor.spec.d.ts.map +1 -0
  21. package/dist/editor/SharedRichEditor.spec.js +63 -0
  22. package/dist/editor/SharedRichEditor.spec.js.map +1 -0
  23. package/dist/editor/SlashCommandMenu.d.ts +10 -0
  24. package/dist/editor/SlashCommandMenu.d.ts.map +1 -1
  25. package/dist/editor/SlashCommandMenu.js +54 -2
  26. package/dist/editor/SlashCommandMenu.js.map +1 -1
  27. package/dist/editor/SlashCommandMenu.spec.js +48 -1
  28. package/dist/editor/SlashCommandMenu.spec.js.map +1 -1
  29. package/dist/editor/index.d.ts +1 -1
  30. package/dist/editor/index.d.ts.map +1 -1
  31. package/dist/editor/index.js +1 -1
  32. package/dist/editor/index.js.map +1 -1
  33. package/dist/editor.css +75 -0
  34. package/dist/styles.css +183 -36
  35. package/dist/ui/button.d.ts.map +1 -1
  36. package/dist/ui/button.js +2 -2
  37. package/dist/ui/button.js.map +1 -1
  38. package/package.json +1 -1
  39. package/src/chat-history.css +2 -2
  40. package/src/composer/PromptComposer.spec.ts +1 -12
  41. package/src/composer/PromptComposer.tsx +0 -31
  42. package/src/composer/RealtimeVoiceMode.spec.tsx +14 -0
  43. package/src/composer/RealtimeVoiceMode.tsx +7 -2
  44. package/src/design-system/design-system.spec.tsx +99 -1
  45. package/src/editor/SharedRichEditor.spec.tsx +82 -0
  46. package/src/editor/SharedRichEditor.tsx +23 -2
  47. package/src/editor/SlashCommandMenu.spec.ts +57 -0
  48. package/src/editor/SlashCommandMenu.tsx +68 -2
  49. package/src/editor/index.ts +1 -0
  50. package/src/editor.css +75 -0
  51. package/src/styles.css +183 -36
  52. package/src/ui/button.tsx +3 -2
package/dist/styles.css CHANGED
@@ -20,66 +20,213 @@
20
20
  */
21
21
  @source "./**/*.{js,ts,tsx}";
22
22
 
23
+ @property --agent-realtime-voice-angle {
24
+ syntax: "<angle>";
25
+ inherits: true;
26
+ initial-value: 0deg;
27
+ }
28
+
23
29
  .agent-realtime-voice-glow {
24
- --agent-realtime-voice-edge-opacity: 0.52;
25
- --agent-realtime-voice-halo-opacity: 0.28;
30
+ --agent-realtime-voice-angle: 0deg;
31
+ --agent-realtime-voice-proximity: 72;
32
+ --agent-realtime-voice-edge-sensitivity: 30;
33
+ --agent-realtime-voice-color-sensitivity: 50;
34
+ --agent-realtime-voice-cone-spread: 25;
35
+ --agent-realtime-voice-fill-opacity: 0.5;
36
+ --agent-realtime-voice-card-bg: hsl(var(--background));
37
+ --agent-realtime-voice-glow-color: 40 80% 80%;
38
+ --agent-realtime-voice-glow-padding: 18px;
39
+ --agent-realtime-voice-gradient-one: radial-gradient(
40
+ at 80% 55%,
41
+ #c084fc 0,
42
+ transparent 50%
43
+ );
44
+ --agent-realtime-voice-gradient-two: radial-gradient(
45
+ at 69% 34%,
46
+ #f472b6 0,
47
+ transparent 50%
48
+ );
49
+ --agent-realtime-voice-gradient-three: radial-gradient(
50
+ at 8% 6%,
51
+ #38bdf8 0,
52
+ transparent 50%
53
+ );
54
+ --agent-realtime-voice-gradient-four: radial-gradient(
55
+ at 41% 38%,
56
+ #c084fc 0,
57
+ transparent 50%
58
+ );
59
+ --agent-realtime-voice-gradient-five: radial-gradient(
60
+ at 86% 85%,
61
+ #f472b6 0,
62
+ transparent 50%
63
+ );
64
+ --agent-realtime-voice-gradient-six: radial-gradient(
65
+ at 82% 18%,
66
+ #38bdf8 0,
67
+ transparent 50%
68
+ );
69
+ --agent-realtime-voice-gradient-seven: radial-gradient(
70
+ at 51% 4%,
71
+ #f472b6 0,
72
+ transparent 50%
73
+ );
26
74
  position: absolute;
27
75
  z-index: 0;
28
- inset: -4px;
76
+ inset: -1px;
29
77
  border-radius: inherit;
78
+ isolation: isolate;
30
79
  pointer-events: none;
31
- transform: rotate(0turn);
32
- will-change: transform;
80
+ transform: translate3d(0, 0, 0.01px);
33
81
  }
34
82
 
35
83
  .agent-realtime-voice-working {
36
- --agent-realtime-voice-edge-opacity: 0.92;
37
- --agent-realtime-voice-halo-opacity: 0.58;
84
+ --agent-realtime-voice-proximity: 96;
38
85
  }
39
86
 
40
87
  .agent-realtime-voice-glow::before,
41
88
  .agent-realtime-voice-glow::after {
42
89
  position: absolute;
43
90
  inset: 0;
91
+ z-index: 0;
44
92
  border-radius: inherit;
45
93
  pointer-events: none;
46
94
  content: "";
47
- background: conic-gradient(
48
- from -18deg,
49
- transparent 0deg 228deg,
50
- oklch(0.65 0.2 294 / 0.18) 244deg,
51
- oklch(0.7 0.2 265 / 0.7) 274deg,
52
- oklch(0.79 0.16 235 / 0.96) 306deg,
53
- oklch(0.96 0.035 210) 326deg,
54
- oklch(0.88 0.11 202 / 0.72) 340deg,
55
- transparent 360deg
56
- );
57
- opacity: var(--agent-realtime-voice-edge-opacity);
58
- padding: 1.5px;
59
- -webkit-mask:
60
- linear-gradient(#000 0 0) content-box,
61
- linear-gradient(#000 0 0);
62
- mask:
63
- linear-gradient(#000 0 0) content-box,
64
- linear-gradient(#000 0 0);
65
- -webkit-mask-composite: xor;
66
- mask-composite: exclude;
67
- transition: opacity 220ms ease-out;
95
+ transition: opacity 250ms ease-out;
68
96
  }
69
97
 
70
98
  .agent-realtime-voice-glow::before {
71
- inset: -1px;
72
- opacity: var(--agent-realtime-voice-halo-opacity);
73
- padding: 2px;
74
- filter: blur(1px) drop-shadow(0 0 2px oklch(0.9 0.07 215 / 0.95))
75
- drop-shadow(0 0 6px oklch(0.78 0.15 236 / 0.82))
76
- drop-shadow(0 0 14px oklch(0.67 0.2 258 / 0.48))
77
- drop-shadow(0 0 28px oklch(0.62 0.18 276 / 0.26));
99
+ border: 1px solid transparent;
100
+ background:
101
+ linear-gradient(
102
+ var(--agent-realtime-voice-card-bg),
103
+ var(--agent-realtime-voice-card-bg)
104
+ )
105
+ padding-box,
106
+ linear-gradient(transparent 0 100%) border-box,
107
+ var(--agent-realtime-voice-gradient-one) border-box,
108
+ var(--agent-realtime-voice-gradient-two) border-box,
109
+ var(--agent-realtime-voice-gradient-three) border-box,
110
+ var(--agent-realtime-voice-gradient-four) border-box,
111
+ var(--agent-realtime-voice-gradient-five) border-box,
112
+ var(--agent-realtime-voice-gradient-six) border-box,
113
+ var(--agent-realtime-voice-gradient-seven) border-box,
114
+ linear-gradient(#c084fc 0 100%) border-box;
115
+ opacity: calc(
116
+ (
117
+ var(--agent-realtime-voice-proximity) -
118
+ var(--agent-realtime-voice-color-sensitivity)
119
+ ) /
120
+ (100 - var(--agent-realtime-voice-color-sensitivity))
121
+ );
122
+ mask-image: conic-gradient(
123
+ from var(--agent-realtime-voice-angle) at center,
124
+ #000 calc(var(--agent-realtime-voice-cone-spread) * 1%),
125
+ rgb(0 0 0 / 75%) calc((var(--agent-realtime-voice-cone-spread) + 4) * 1%),
126
+ rgb(0 0 0 / 45%) calc((var(--agent-realtime-voice-cone-spread) + 8) * 1%),
127
+ rgb(0 0 0 / 18%) calc((var(--agent-realtime-voice-cone-spread) + 12) * 1%),
128
+ transparent calc((var(--agent-realtime-voice-cone-spread) + 15) * 1%),
129
+ transparent calc((100 - var(--agent-realtime-voice-cone-spread) - 15) * 1%),
130
+ rgb(0 0 0 / 18%)
131
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 12) * 1%),
132
+ rgb(0 0 0 / 45%)
133
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 8) * 1%),
134
+ rgb(0 0 0 / 75%)
135
+ calc((100 - var(--agent-realtime-voice-cone-spread) - 4) * 1%),
136
+ #000 calc((100 - var(--agent-realtime-voice-cone-spread)) * 1%)
137
+ );
138
+ }
139
+
140
+ .agent-realtime-voice-glow::after {
141
+ border: 1px solid transparent;
142
+ background:
143
+ var(--agent-realtime-voice-gradient-one) padding-box,
144
+ var(--agent-realtime-voice-gradient-two) padding-box,
145
+ var(--agent-realtime-voice-gradient-three) padding-box,
146
+ var(--agent-realtime-voice-gradient-four) padding-box,
147
+ var(--agent-realtime-voice-gradient-five) padding-box,
148
+ var(--agent-realtime-voice-gradient-six) padding-box,
149
+ var(--agent-realtime-voice-gradient-seven) padding-box,
150
+ linear-gradient(#c084fc 0 100%) padding-box;
151
+ mask-image:
152
+ linear-gradient(to bottom, #000, #000),
153
+ radial-gradient(ellipse at 50% 50%, #000 40%, transparent 65%),
154
+ radial-gradient(ellipse at 66% 66%, #000 5%, transparent 40%),
155
+ radial-gradient(ellipse at 33% 33%, #000 5%, transparent 40%),
156
+ radial-gradient(ellipse at 66% 33%, #000 5%, transparent 40%),
157
+ radial-gradient(ellipse at 33% 66%, #000 5%, transparent 40%),
158
+ conic-gradient(
159
+ from var(--agent-realtime-voice-angle) at center,
160
+ transparent 5%,
161
+ #000 15%,
162
+ #000 85%,
163
+ transparent 95%
164
+ );
165
+ mask-composite: subtract, add, add, add, add, add;
166
+ opacity: calc(
167
+ var(--agent-realtime-voice-fill-opacity) *
168
+ (
169
+ var(--agent-realtime-voice-proximity) -
170
+ var(--agent-realtime-voice-color-sensitivity)
171
+ ) /
172
+ (100 - var(--agent-realtime-voice-color-sensitivity))
173
+ );
174
+ mix-blend-mode: soft-light;
175
+ }
176
+
177
+ .agent-realtime-voice-edge-light {
178
+ position: absolute;
179
+ z-index: 1;
180
+ inset: calc(var(--agent-realtime-voice-glow-padding) * -1);
181
+ border-radius: inherit;
182
+ pointer-events: none;
183
+ opacity: calc(
184
+ (
185
+ var(--agent-realtime-voice-proximity) -
186
+ var(--agent-realtime-voice-edge-sensitivity)
187
+ ) /
188
+ (100 - var(--agent-realtime-voice-edge-sensitivity))
189
+ );
190
+ mask-image: conic-gradient(
191
+ from var(--agent-realtime-voice-angle) at center,
192
+ #000 2.5%,
193
+ rgb(0 0 0 / 85%) 4%,
194
+ rgb(0 0 0 / 55%) 7%,
195
+ rgb(0 0 0 / 25%) 11%,
196
+ transparent 15%,
197
+ transparent 85%,
198
+ rgb(0 0 0 / 25%) 89%,
199
+ rgb(0 0 0 / 55%) 93%,
200
+ rgb(0 0 0 / 85%) 96%,
201
+ #000 97.5%
202
+ );
78
203
  mix-blend-mode: plus-lighter;
204
+ transition: opacity 250ms ease-out;
205
+ }
206
+
207
+ .agent-realtime-voice-edge-light::before {
208
+ position: absolute;
209
+ inset: var(--agent-realtime-voice-glow-padding);
210
+ border-radius: inherit;
211
+ content: "";
212
+ box-shadow:
213
+ inset 0 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 100%),
214
+ inset 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 60%),
215
+ inset 0 0 3px hsl(var(--agent-realtime-voice-glow-color) / 50%),
216
+ inset 0 0 6px hsl(var(--agent-realtime-voice-glow-color) / 40%),
217
+ inset 0 0 15px hsl(var(--agent-realtime-voice-glow-color) / 30%),
218
+ inset 0 0 25px 2px hsl(var(--agent-realtime-voice-glow-color) / 20%),
219
+ inset 0 0 50px 2px hsl(var(--agent-realtime-voice-glow-color) / 10%),
220
+ 0 0 1px hsl(var(--agent-realtime-voice-glow-color) / 60%),
221
+ 0 0 3px hsl(var(--agent-realtime-voice-glow-color) / 50%),
222
+ 0 0 6px hsl(var(--agent-realtime-voice-glow-color) / 40%),
223
+ 0 0 15px hsl(var(--agent-realtime-voice-glow-color) / 30%),
224
+ 0 0 25px 2px hsl(var(--agent-realtime-voice-glow-color) / 20%),
225
+ 0 0 50px 2px hsl(var(--agent-realtime-voice-glow-color) / 10%);
79
226
  }
80
227
 
81
228
  @media (prefers-reduced-motion: reduce) {
82
229
  .agent-realtime-voice-glow {
83
- transform: rotate(35deg);
230
+ --agent-realtime-voice-angle: 35deg;
84
231
  }
85
232
  }
@@ -1 +1 @@
1
- {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/ui/button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AAInC,QAAA,MAAM,cAAc;;;8EA2BnB,CAAC;AAEF,MAAM,WAAW,WACf,SACE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAC7C,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,QAAA,MAAM,UAAU,uFAsBf,CAAC;AAKF,QAAA,MAAM,MAAM,uFAgFX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../src/ui/button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAO/B,OAAO,KAAK,EACV,oBAAoB,EACpB,kBAAkB,EACnB,MAAM,2BAA2B,CAAC;AAInC,QAAA,MAAM,cAAc;;;8EA2BnB,CAAC;AAEF,MAAM,WAAW,WACf,SACE,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAC7C,YAAY,CAAC,OAAO,cAAc,CAAC;IACrC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,iFAAiF;IACjF,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC;AAED,QAAA,MAAM,UAAU,uFAsBf,CAAC;AAKF,QAAA,MAAM,MAAM,uFAiFX,CAAC;AAGF,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC"}
package/dist/ui/button.js CHANGED
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Slot } from "@radix-ui/react-slot";
3
3
  import { cva } from "class-variance-authority";
4
4
  import * as React from "react";
5
- import { LegacyButtonRenderContext, useDesignSystemComponent, } from "../design-system/context.js";
5
+ import { LegacyButtonRenderContext, useDesignSystem, } from "../design-system/context.js";
6
6
  import { DesignSystemErrorBoundary } from "../design-system/error-boundary.js";
7
7
  import { useToolkitComponent } from "../provider.js";
8
8
  import { cn } from "../utils.js";
@@ -35,7 +35,7 @@ const ButtonBase = React.forwardRef(({ className, variant, size, asChild = false
35
35
  ButtonBase.displayName = "ButtonBase";
36
36
  const ButtonOverrideRenderContext = React.createContext(false);
37
37
  const Button = React.forwardRef(({ variant, size, asChild = false, intent, emphasis, ...props }, ref) => {
38
- const DesignSystemActionButton = useDesignSystemComponent("ActionButton");
38
+ const DesignSystemActionButton = useDesignSystem()?.components?.ActionButton;
39
39
  const Override = useToolkitComponent("Button");
40
40
  const isRenderingOverride = React.useContext(ButtonOverrideRenderContext);
41
41
  const isRenderingLegacyButton = React.useContext(LegacyButtonRenderContext);
@@ -1 +1 @@
1
- {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/ui/button.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"button.js","sourceRoot":"","sources":["../../src/ui/button.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/toolkit",
3
- "version": "0.10.1",
3
+ "version": "0.10.4",
4
4
  "description": "Reusable app-building UI and helpers for Agent-Native apps.",
5
5
  "homepage": "https://github.com/BuilderIO/agent-native#readme",
6
6
  "bugs": {
@@ -211,7 +211,7 @@
211
211
  white-space: nowrap;
212
212
  font-size: 12px;
213
213
  font-weight: 500;
214
- color: hsl(var(--foreground));
214
+ color: hsl(var(--muted-foreground));
215
215
  }
216
216
 
217
217
  .an-chat-history-row--active .an-chat-history-row__title {
@@ -227,7 +227,7 @@
227
227
  .an-chat-history--rail
228
228
  .an-chat-history-row--pinned:not(.an-chat-history-row--active)
229
229
  .an-chat-history-row__title {
230
- color: hsl(var(--foreground));
230
+ color: hsl(var(--muted-foreground));
231
231
  }
232
232
 
233
233
  .an-chat-history-row__timestamp {
@@ -2,18 +2,7 @@
2
2
 
3
3
  import { describe, expect, it } from "vitest";
4
4
 
5
- import {
6
- buildPromptComposerSubmission,
7
- canSubmitWithAgentEngineState,
8
- } from "./PromptComposer.js";
9
-
10
- describe("canSubmitWithAgentEngineState", () => {
11
- it("allows configured engines and blocks unresolved states", () => {
12
- expect(canSubmitWithAgentEngineState("configured")).toBe(true);
13
- expect(canSubmitWithAgentEngineState("missing")).toBe(false);
14
- expect(canSubmitWithAgentEngineState("unavailable")).toBe(false);
15
- });
16
- });
5
+ import { buildPromptComposerSubmission } from "./PromptComposer.js";
17
6
 
18
7
  describe("buildPromptComposerSubmission", () => {
19
8
  it("passes images through files only — never inlines base64 into prompt text", async () => {
@@ -59,11 +59,6 @@ import type {
59
59
  } from "./types.js";
60
60
 
61
61
  const MAX_INLINE_TEXT_FILE_CHARS = 60_000;
62
- const SUBMIT_ENGINE_STATUS_TIMEOUT_MS = 1000;
63
-
64
- export function canSubmitWithAgentEngineState(state: string): boolean {
65
- return state === "configured";
66
- }
67
62
 
68
63
  /**
69
64
  * Files the user attached via the "+" button in PromptComposer. The host owns
@@ -536,31 +531,6 @@ function PromptComposerInner({
536
531
  window.dispatchEvent(new Event("agent-engine:configured-changed"));
537
532
  }
538
533
  }, []);
539
- const ensureAgentEngineReadyForSubmit = useCallback(async () => {
540
- if (!resolvedModelStatusChecksEnabled) return true;
541
- const state =
542
- agentEngineConfigured.state === "missing"
543
- ? "missing"
544
- : await modelsAdapter.fetchAgentEngineConfiguredState!(
545
- resolvedModelStatusChecksEnabled,
546
- {
547
- timeoutMs: SUBMIT_ENGINE_STATUS_TIMEOUT_MS,
548
- },
549
- );
550
- if (state === "missing") {
551
- bounceMissingKeySetup();
552
- return false;
553
- }
554
- if (typeof window !== "undefined") {
555
- window.dispatchEvent(new Event("agent-engine:configured-changed"));
556
- }
557
- return canSubmitWithAgentEngineState(state);
558
- }, [
559
- agentEngineConfigured.state,
560
- bounceMissingKeySetup,
561
- modelsAdapter,
562
- resolvedModelStatusChecksEnabled,
563
- ]);
564
534
  const retryAgentEngineStatus = useCallback(() => {
565
535
  if (typeof window !== "undefined") {
566
536
  window.dispatchEvent(new Event("agent-engine:configured-changed"));
@@ -657,7 +627,6 @@ function PromptComposerInner({
657
627
  initialText={initialText}
658
628
  initialTextKey={initialTextKey}
659
629
  onSubmit={handleSubmit}
660
- onBeforeSubmit={ensureAgentEngineReadyForSubmit}
661
630
  clearOnSubmit={!preserveDraftOnSubmit}
662
631
  plusMenuMode={
663
632
  plusMenuMode ?? (attachmentsEnabled ? "upload-only" : "hidden")
@@ -807,6 +807,9 @@ describe("RealtimeVoiceMode", () => {
807
807
  expect(
808
808
  document.querySelector(".agent-realtime-voice-glow"),
809
809
  ).not.toBeNull();
810
+ expect(
811
+ document.querySelector(".agent-realtime-voice-edge-light"),
812
+ ).not.toBeNull();
810
813
  expect(
811
814
  document.querySelector(".agent-realtime-voice-working"),
812
815
  ).toBeNull();
@@ -843,6 +846,17 @@ describe("RealtimeVoiceMode", () => {
843
846
  const glow = document.querySelector('[data-realtime-voice-glow="true"]');
844
847
 
845
848
  expect(animate).toHaveBeenCalledTimes(1);
849
+ expect(animate).toHaveBeenCalledWith(
850
+ [
851
+ { "--agent-realtime-voice-angle": "0deg" },
852
+ { "--agent-realtime-voice-angle": "360deg" },
853
+ ],
854
+ {
855
+ duration: 12_000,
856
+ easing: "linear",
857
+ iterations: Number.POSITIVE_INFINITY,
858
+ },
859
+ );
846
860
  expect(updateGlowPlaybackRate).toHaveBeenLastCalledWith(1);
847
861
 
848
862
  render(
@@ -775,7 +775,10 @@ export function RealtimeVoiceModeDock({
775
775
  }
776
776
 
777
777
  const animation = glowRef.current.animate(
778
- [{ transform: "rotate(0turn)" }, { transform: "rotate(1turn)" }],
778
+ [
779
+ { "--agent-realtime-voice-angle": "0deg" },
780
+ { "--agent-realtime-voice-angle": "360deg" },
781
+ ] as Keyframe[],
779
782
  {
780
783
  duration: 12_000,
781
784
  easing: "linear",
@@ -989,7 +992,9 @@ export function RealtimeVoiceModeDock({
989
992
  "agent-realtime-voice-glow",
990
993
  workingGlowActive && "agent-realtime-voice-working",
991
994
  )}
992
- />
995
+ >
996
+ <span className="agent-realtime-voice-edge-light" />
997
+ </span>
993
998
  ) : null}
994
999
  <span className="relative z-10 flex items-center justify-center">
995
1000
  {state === "connecting" ? (
@@ -1,11 +1,17 @@
1
1
  // @vitest-environment happy-dom
2
2
 
3
- import { act, type ComponentProps } from "react";
3
+ import { act, forwardRef, type ComponentProps } from "react";
4
4
  import { createRoot, type Root } from "react-dom/client";
5
5
  import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
6
 
7
7
  import { ToolkitProvider } from "../provider.js";
8
8
  import { Button } from "../ui/button.js";
9
+ import {
10
+ DropdownMenu,
11
+ DropdownMenuContent,
12
+ DropdownMenuItem,
13
+ DropdownMenuTrigger,
14
+ } from "../ui/dropdown-menu.js";
9
15
  import { ActionButton } from "./components.js";
10
16
  import { defaultDesignSystemComponents } from "./default-adapter.js";
11
17
  import { defineDesignSystem } from "./definition.js";
@@ -157,6 +163,98 @@ describe("design-system contract", () => {
157
163
  );
158
164
  });
159
165
 
166
+ it.each(["pointer", "Enter", "Space", "ArrowDown"])(
167
+ "preserves Radix menu trigger behavior through a legacy Button override with %s activation",
168
+ async (activation) => {
169
+ const onOpenChange = vi.fn();
170
+ let buttonRef: HTMLButtonElement | null = null;
171
+ const LegacyButton = forwardRef<
172
+ HTMLButtonElement,
173
+ ComponentProps<typeof Button>
174
+ >(
175
+ (
176
+ {
177
+ asChild: _asChild,
178
+ emphasis: _emphasis,
179
+ intent: _intent,
180
+ size: _size,
181
+ variant: _variant,
182
+ ...props
183
+ },
184
+ ref,
185
+ ) => <button {...props} ref={ref} data-adapter="legacy" />,
186
+ );
187
+
188
+ await act(async () => {
189
+ root.render(
190
+ <ToolkitProvider
191
+ components={{ Button: LegacyButton }}
192
+ designSystem={{}}
193
+ >
194
+ <DropdownMenu onOpenChange={onOpenChange}>
195
+ <DropdownMenuTrigger asChild>
196
+ <Button
197
+ ref={(node) => {
198
+ buttonRef = node;
199
+ }}
200
+ >
201
+ Open menu
202
+ </Button>
203
+ </DropdownMenuTrigger>
204
+ <DropdownMenuContent>
205
+ <DropdownMenuItem>First item</DropdownMenuItem>
206
+ </DropdownMenuContent>
207
+ </DropdownMenu>
208
+ </ToolkitProvider>,
209
+ );
210
+ });
211
+
212
+ const trigger = container.querySelector<HTMLButtonElement>("button");
213
+ expect(trigger).not.toBeNull();
214
+ expect(buttonRef).toBe(trigger);
215
+ expect(trigger?.getAttribute("aria-haspopup")).toBe("menu");
216
+ expect(trigger?.getAttribute("aria-expanded")).toBe("false");
217
+ expect(trigger?.dataset.state).toBe("closed");
218
+
219
+ await act(async () => {
220
+ trigger?.focus();
221
+ if (activation === "pointer") {
222
+ trigger?.dispatchEvent(
223
+ new PointerEvent("pointerdown", {
224
+ bubbles: true,
225
+ button: 0,
226
+ pointerType: "mouse",
227
+ }),
228
+ );
229
+ } else {
230
+ const key = activation === "Space" ? " " : activation;
231
+ trigger?.dispatchEvent(
232
+ new KeyboardEvent("keydown", { bubbles: true, key }),
233
+ );
234
+ }
235
+ await Promise.resolve();
236
+ });
237
+
238
+ expect(onOpenChange).toHaveBeenCalledTimes(1);
239
+ expect(onOpenChange).toHaveBeenLastCalledWith(true);
240
+ expect(trigger?.getAttribute("aria-expanded")).toBe("true");
241
+ expect(trigger?.dataset.state).toBe("open");
242
+ expect(document.querySelector("[role=menu]")).not.toBeNull();
243
+
244
+ await act(async () => {
245
+ document.activeElement?.dispatchEvent(
246
+ new KeyboardEvent("keydown", { bubbles: true, key: "Escape" }),
247
+ );
248
+ await Promise.resolve();
249
+ });
250
+
251
+ expect(onOpenChange).toHaveBeenCalledTimes(2);
252
+ expect(onOpenChange).toHaveBeenLastCalledWith(false);
253
+ expect(trigger?.getAttribute("aria-expanded")).toBe("false");
254
+ expect(trigger?.dataset.state).toBe("closed");
255
+ },
256
+ );
257
+
160
258
  it("isolates a broken customer component and renders the default control", () => {
161
259
  vi.spyOn(console, "error").mockImplementation(() => {});
162
260
  const BrokenActionButton = () => {
@@ -0,0 +1,82 @@
1
+ // @vitest-environment happy-dom
2
+
3
+ import { act } from "react";
4
+ import { createRoot, type Root } from "react-dom/client";
5
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
6
+
7
+ import { SharedRichEditor } from "./SharedRichEditor.js";
8
+
9
+ describe("SharedRichEditor block controls", () => {
10
+ let container: HTMLDivElement;
11
+ let root: Root;
12
+
13
+ beforeEach(() => {
14
+ vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
15
+ container = document.createElement("div");
16
+ document.body.appendChild(container);
17
+ root = createRoot(container);
18
+ });
19
+
20
+ afterEach(() => {
21
+ act(() => root.unmount());
22
+ container.remove();
23
+ vi.restoreAllMocks();
24
+ vi.unstubAllGlobals();
25
+ });
26
+
27
+ it("mounts the shared Notion-style block grip by default", async () => {
28
+ await act(async () => {
29
+ root.render(
30
+ <SharedRichEditor
31
+ value="<p>First</p><p>Second</p>"
32
+ onChange={() => undefined}
33
+ />,
34
+ );
35
+ await new Promise((resolve) => setTimeout(resolve, 10));
36
+ });
37
+
38
+ const prose = container.querySelector<HTMLElement>(".an-rich-md-prose");
39
+ const firstBlock = prose?.firstElementChild;
40
+ for (const [element, rect] of [
41
+ [prose, { left: 0, top: 0, right: 640, bottom: 100 }],
42
+ [firstBlock, { left: 0, top: 0, right: 640, bottom: 24 }],
43
+ ] as const) {
44
+ if (!element) continue;
45
+ Object.defineProperty(element, "getBoundingClientRect", {
46
+ configurable: true,
47
+ value: () => ({
48
+ ...rect,
49
+ x: rect.left,
50
+ y: rect.top,
51
+ width: rect.right - rect.left,
52
+ height: rect.bottom - rect.top,
53
+ toJSON: () => ({}),
54
+ }),
55
+ });
56
+ }
57
+ document.dispatchEvent(
58
+ new MouseEvent("mousemove", {
59
+ bubbles: true,
60
+ clientX: 8,
61
+ clientY: 8,
62
+ }),
63
+ );
64
+ expect(container.querySelector(".an-rich-md-wrapper")).not.toBeNull();
65
+ expect(container.querySelector(".drag-handle")).not.toBeNull();
66
+ });
67
+
68
+ it("allows hosts to opt out when they own block controls", async () => {
69
+ await act(async () => {
70
+ root.render(
71
+ <SharedRichEditor
72
+ value="First"
73
+ onChange={() => undefined}
74
+ dragHandle={false}
75
+ />,
76
+ );
77
+ await new Promise((resolve) => setTimeout(resolve, 10));
78
+ });
79
+
80
+ expect(container.querySelector(".drag-handle")).toBeNull();
81
+ });
82
+ });