@agent-native/toolkit 0.211.0 → 0.212.0-nightly-20261021010049
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/agent-native.eject.json +1 -0
- package/dist/app/i18n/catalogs/ar-SA.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ar-SA.js +23 -0
- package/dist/app/i18n/catalogs/ar-SA.js.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/de-DE.js +23 -0
- package/dist/app/i18n/catalogs/de-DE.js.map +1 -1
- package/dist/app/i18n/catalogs/en-US.d.ts +23 -0
- package/dist/app/i18n/catalogs/en-US.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/en-US.js +23 -0
- package/dist/app/i18n/catalogs/en-US.js.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/es-ES.js +23 -0
- package/dist/app/i18n/catalogs/es-ES.js.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/fr-FR.js +23 -0
- package/dist/app/i18n/catalogs/fr-FR.js.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/hi-IN.js +23 -0
- package/dist/app/i18n/catalogs/hi-IN.js.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ja-JP.js +23 -0
- package/dist/app/i18n/catalogs/ja-JP.js.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/ko-KR.js +23 -0
- package/dist/app/i18n/catalogs/ko-KR.js.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/pt-BR.js +23 -0
- package/dist/app/i18n/catalogs/pt-BR.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-CN.js +23 -0
- package/dist/app/i18n/catalogs/zh-CN.js.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.d.ts.map +1 -1
- package/dist/app/i18n/catalogs/zh-TW.js +23 -0
- package/dist/app/i18n/catalogs/zh-TW.js.map +1 -1
- package/dist/app/sharing/OwnershipFilter.d.ts +8 -0
- package/dist/app/sharing/OwnershipFilter.d.ts.map +1 -0
- package/dist/app/sharing/OwnershipFilter.js +20 -0
- package/dist/app/sharing/OwnershipFilter.js.map +1 -0
- package/dist/app/sharing/ShareButton.d.ts +43 -1
- package/dist/app/sharing/ShareButton.d.ts.map +1 -1
- package/dist/app/sharing/ShareButton.js +102 -63
- package/dist/app/sharing/ShareButton.js.map +1 -1
- package/dist/app/sharing/ShareDialog.d.ts +3 -1
- package/dist/app/sharing/ShareDialog.d.ts.map +1 -1
- package/dist/app/sharing/ShareDialog.js +18 -12
- package/dist/app/sharing/ShareDialog.js.map +1 -1
- package/dist/app/sharing/ShareVisibilityConfirmDialog.d.ts +20 -0
- package/dist/app/sharing/ShareVisibilityConfirmDialog.d.ts.map +1 -0
- package/dist/app/sharing/ShareVisibilityConfirmDialog.js +57 -0
- package/dist/app/sharing/ShareVisibilityConfirmDialog.js.map +1 -0
- package/dist/app/sharing/VisibilityBadge.d.ts +8 -1
- package/dist/app/sharing/VisibilityBadge.d.ts.map +1 -1
- package/dist/app/sharing/VisibilityBadge.js +16 -1
- package/dist/app/sharing/VisibilityBadge.js.map +1 -1
- package/dist/app/sharing/index.d.ts +2 -0
- package/dist/app/sharing/index.d.ts.map +1 -1
- package/dist/app/sharing/index.js +2 -0
- package/dist/app/sharing/index.js.map +1 -1
- package/dist/chat-history/ChatHistoryList.d.ts +19 -0
- package/dist/chat-history/ChatHistoryList.d.ts.map +1 -1
- package/dist/chat-history/ChatHistoryList.js +19 -7
- package/dist/chat-history/ChatHistoryList.js.map +1 -1
- package/dist/chat-history/ChatHistoryRail.d.ts +55 -8
- package/dist/chat-history/ChatHistoryRail.d.ts.map +1 -1
- package/dist/chat-history/ChatHistoryRail.js +33 -7
- package/dist/chat-history/ChatHistoryRail.js.map +1 -1
- package/dist/chat-history/index.d.ts +3 -3
- package/dist/chat-history/index.d.ts.map +1 -1
- package/dist/chat-history/index.js +1 -1
- package/dist/chat-history/index.js.map +1 -1
- package/dist/chat-history/useChatHistoryRailController.d.ts +44 -0
- package/dist/chat-history/useChatHistoryRailController.d.ts.map +1 -1
- package/dist/chat-history/useChatHistoryRailController.js +46 -0
- package/dist/chat-history/useChatHistoryRailController.js.map +1 -1
- package/dist/chat-history.css +29 -0
- package/dist/composer/TiptapComposer.d.ts +7 -0
- package/dist/composer/TiptapComposer.d.ts.map +1 -1
- package/dist/composer/TiptapComposer.js +15 -2
- package/dist/composer/TiptapComposer.js.map +1 -1
- package/dist/sharing/OwnershipFilter.d.ts +21 -0
- package/dist/sharing/OwnershipFilter.d.ts.map +1 -0
- package/dist/sharing/OwnershipFilter.js +30 -0
- package/dist/sharing/OwnershipFilter.js.map +1 -0
- package/dist/sharing/VisibilityBadge.d.ts +12 -2
- package/dist/sharing/VisibilityBadge.d.ts.map +1 -1
- package/dist/sharing/VisibilityBadge.js +13 -4
- package/dist/sharing/VisibilityBadge.js.map +1 -1
- package/dist/sharing/index.d.ts +2 -1
- package/dist/sharing/index.d.ts.map +1 -1
- package/dist/sharing/index.js +2 -1
- package/dist/sharing/index.js.map +1 -1
- package/dist/ui/alert-dialog.d.ts +2 -0
- package/dist/ui/alert-dialog.d.ts.map +1 -1
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/alert-dialog.js.map +1 -1
- package/dist/ui/tooltip.d.ts +6 -1
- package/dist/ui/tooltip.d.ts.map +1 -1
- package/dist/ui/tooltip.js +13 -1
- package/dist/ui/tooltip.js.map +1 -1
- package/package.json +4 -4
- package/src/app/i18n/catalogs/ar-SA.ts +26 -0
- package/src/app/i18n/catalogs/de-DE.ts +25 -0
- package/src/app/i18n/catalogs/en-US.ts +25 -0
- package/src/app/i18n/catalogs/es-ES.ts +25 -0
- package/src/app/i18n/catalogs/fr-FR.ts +25 -0
- package/src/app/i18n/catalogs/hi-IN.ts +25 -0
- package/src/app/i18n/catalogs/ja-JP.ts +25 -0
- package/src/app/i18n/catalogs/ko-KR.ts +25 -0
- package/src/app/i18n/catalogs/pt-BR.ts +25 -0
- package/src/app/i18n/catalogs/zh-CN.ts +25 -0
- package/src/app/i18n/catalogs/zh-TW.ts +25 -0
- package/src/app/sharing/OwnershipFilter.tsx +35 -0
- package/src/app/sharing/ShareButton.tsx +384 -259
- package/src/app/sharing/ShareDialog.spec.tsx +50 -0
- package/src/app/sharing/ShareDialog.tsx +51 -15
- package/src/app/sharing/ShareVisibilityConfirmDialog.spec.tsx +138 -0
- package/src/app/sharing/ShareVisibilityConfirmDialog.tsx +124 -0
- package/src/app/sharing/ShareVisibilityKeyboard.spec.tsx +244 -0
- package/src/app/sharing/VisibilityBadge.spec.tsx +65 -0
- package/src/app/sharing/VisibilityBadge.tsx +31 -3
- package/src/app/sharing/index.ts +2 -0
- package/src/app/sharing/share-visibility-mutation-lifecycle.spec.tsx +1107 -0
- package/src/app/sharing/useShareButtonController.spec.tsx +226 -37
- package/src/app/sharing/useShareDialogController.spec.tsx +357 -9
- package/src/chat-history/ChatHistoryList.spec.tsx +157 -0
- package/src/chat-history/ChatHistoryList.tsx +104 -10
- package/src/chat-history/ChatHistoryRail.spec.tsx +50 -1
- package/src/chat-history/ChatHistoryRail.tsx +177 -26
- package/src/chat-history/ChatHistoryRailSections.spec.tsx +410 -0
- package/src/chat-history/index.ts +8 -0
- package/src/chat-history/useChatHistoryRailController.ts +94 -0
- package/src/chat-history/useChatHistoryRailSectionsController.spec.tsx +133 -0
- package/src/chat-history.css +29 -0
- package/src/composer/TiptapComposer.spec.ts +19 -0
- package/src/composer/TiptapComposer.tsx +26 -5
- package/src/sharing/OwnershipFilter.spec.tsx +108 -0
- package/src/sharing/OwnershipFilter.tsx +103 -0
- package/src/sharing/VisibilityBadge.spec.ts +53 -35
- package/src/sharing/VisibilityBadge.tsx +23 -3
- package/src/sharing/index.ts +11 -0
- package/src/ui/alert-dialog.tsx +7 -2
- package/src/ui/tooltip.tsx +22 -1
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import type { ShareButtonController } from "@agent-native/core/client/sharing/useShareButtonController";
|
|
4
|
+
import {
|
|
5
|
+
useShareVisibilityTransition,
|
|
6
|
+
type ShareVisibilityTransition,
|
|
7
|
+
} from "@agent-native/core/client/sharing/useShareVisibilityTransition";
|
|
8
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
9
|
+
import React, { act, useState } from "react";
|
|
10
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
11
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
12
|
+
|
|
13
|
+
import { ShareGeneralAccessRow } from "./ShareButton.js";
|
|
14
|
+
|
|
15
|
+
type Visibility = "private" | "org" | "public";
|
|
16
|
+
|
|
17
|
+
// The real picker (Radix Select) and the real confirmation (AlertDialog) over
|
|
18
|
+
// the real transition; only the save is replaced by a spy.
|
|
19
|
+
describe("organization confirmation from the keyboard", () => {
|
|
20
|
+
let container: HTMLDivElement;
|
|
21
|
+
let root: Root;
|
|
22
|
+
let queryClient: QueryClient;
|
|
23
|
+
let transition: ShareVisibilityTransition;
|
|
24
|
+
let saved: ReturnType<
|
|
25
|
+
typeof vi.fn<(next: Visibility) => void | Promise<void>>
|
|
26
|
+
>;
|
|
27
|
+
|
|
28
|
+
function Harness() {
|
|
29
|
+
const [visibility, setVisibility] = useState<Visibility>("private");
|
|
30
|
+
transition = useShareVisibilityTransition({
|
|
31
|
+
resourceType: "document",
|
|
32
|
+
resourceId: "doc-1",
|
|
33
|
+
current: visibility,
|
|
34
|
+
orgId: null,
|
|
35
|
+
canManage: true,
|
|
36
|
+
active: true,
|
|
37
|
+
apply: async (next) => {
|
|
38
|
+
await saved(next);
|
|
39
|
+
setVisibility(next);
|
|
40
|
+
},
|
|
41
|
+
onDirectError: () => undefined,
|
|
42
|
+
});
|
|
43
|
+
const controller = {
|
|
44
|
+
visibility,
|
|
45
|
+
canManage: true,
|
|
46
|
+
policy: { allowPublic: true },
|
|
47
|
+
handleVisibility: (next: Visibility) => void transition.request(next),
|
|
48
|
+
visibilityTransition: transition,
|
|
49
|
+
} as unknown as ShareButtonController;
|
|
50
|
+
return <ShareGeneralAccessRow controller={controller} />;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
beforeEach(async () => {
|
|
54
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
55
|
+
vi.stubGlobal(
|
|
56
|
+
"fetch",
|
|
57
|
+
vi.fn().mockResolvedValue({ ok: true, json: async () => ({}) }),
|
|
58
|
+
);
|
|
59
|
+
saved = vi.fn();
|
|
60
|
+
queryClient = new QueryClient({
|
|
61
|
+
defaultOptions: { queries: { retry: false } },
|
|
62
|
+
});
|
|
63
|
+
container = document.createElement("div");
|
|
64
|
+
document.body.appendChild(container);
|
|
65
|
+
root = createRoot(container);
|
|
66
|
+
await act(async () => {
|
|
67
|
+
root.render(
|
|
68
|
+
<QueryClientProvider client={queryClient}>
|
|
69
|
+
<Harness />
|
|
70
|
+
</QueryClientProvider>,
|
|
71
|
+
);
|
|
72
|
+
await Promise.resolve();
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
afterEach(() => {
|
|
77
|
+
act(() => root.unmount());
|
|
78
|
+
queryClient.clear();
|
|
79
|
+
container.remove();
|
|
80
|
+
vi.unstubAllGlobals();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const trigger = () =>
|
|
84
|
+
container.querySelector<HTMLButtonElement>(
|
|
85
|
+
'[aria-label="General access"]',
|
|
86
|
+
)!;
|
|
87
|
+
const alertDialog = () =>
|
|
88
|
+
document.body.querySelector<HTMLElement>('[role="alertdialog"]');
|
|
89
|
+
const alertButton = (label: string) =>
|
|
90
|
+
Array.from(
|
|
91
|
+
alertDialog()?.querySelectorAll<HTMLButtonElement>("button") ?? [],
|
|
92
|
+
).find((button) => button.textContent?.trim() === label)!;
|
|
93
|
+
const option = (label: string) =>
|
|
94
|
+
Array.from(
|
|
95
|
+
document.body.querySelectorAll<HTMLElement>('[role="option"]'),
|
|
96
|
+
).find((candidate) => candidate.textContent?.includes(label))!;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* One keystroke the way a browser delivers it: keydown, then (for keys that
|
|
100
|
+
* were not prevented) a keypress on whatever is focused by then, whose
|
|
101
|
+
* default action presses a focused button, then keyup where focus is now.
|
|
102
|
+
*/
|
|
103
|
+
function press(key: string, target: Element) {
|
|
104
|
+
const code = key === " " ? "Space" : key;
|
|
105
|
+
const down = new KeyboardEvent("keydown", {
|
|
106
|
+
key,
|
|
107
|
+
code,
|
|
108
|
+
bubbles: true,
|
|
109
|
+
cancelable: true,
|
|
110
|
+
});
|
|
111
|
+
act(() => {
|
|
112
|
+
target.dispatchEvent(down);
|
|
113
|
+
});
|
|
114
|
+
const afterDown = document.activeElement ?? document.body;
|
|
115
|
+
if (!down.defaultPrevented && key === "Enter") {
|
|
116
|
+
const keypress = new KeyboardEvent("keypress", {
|
|
117
|
+
key,
|
|
118
|
+
code,
|
|
119
|
+
bubbles: true,
|
|
120
|
+
cancelable: true,
|
|
121
|
+
});
|
|
122
|
+
act(() => {
|
|
123
|
+
afterDown.dispatchEvent(keypress);
|
|
124
|
+
});
|
|
125
|
+
if (
|
|
126
|
+
!keypress.defaultPrevented &&
|
|
127
|
+
afterDown instanceof HTMLButtonElement
|
|
128
|
+
) {
|
|
129
|
+
act(() => afterDown.click());
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const up = new KeyboardEvent("keyup", {
|
|
133
|
+
key,
|
|
134
|
+
code,
|
|
135
|
+
bubbles: true,
|
|
136
|
+
cancelable: true,
|
|
137
|
+
});
|
|
138
|
+
act(() => {
|
|
139
|
+
(document.activeElement ?? document.body).dispatchEvent(up);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async function chooseOrganizationWith(key: "Enter" | " ") {
|
|
144
|
+
trigger().focus();
|
|
145
|
+
press("ArrowDown", trigger());
|
|
146
|
+
const content = document.body.querySelector('[role="listbox"]')!;
|
|
147
|
+
expect(content).not.toBeNull();
|
|
148
|
+
const organization = option("Organization");
|
|
149
|
+
(document.activeElement as HTMLElement | null)?.blur?.();
|
|
150
|
+
organization.focus();
|
|
151
|
+
press(key, organization);
|
|
152
|
+
await act(async () => {
|
|
153
|
+
await Promise.resolve();
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
it("disables the existing picker for a physical direct save and enables it after settlement", async () => {
|
|
158
|
+
let finish!: () => void;
|
|
159
|
+
saved.mockImplementationOnce(
|
|
160
|
+
() =>
|
|
161
|
+
new Promise<void>((resolve) => {
|
|
162
|
+
finish = resolve;
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
let applying!: Promise<void>;
|
|
166
|
+
act(() => {
|
|
167
|
+
applying = transition.request("public");
|
|
168
|
+
});
|
|
169
|
+
expect(trigger().disabled).toBe(true);
|
|
170
|
+
expect(transition.submitting).toBe(true);
|
|
171
|
+
await act(async () => {
|
|
172
|
+
finish();
|
|
173
|
+
await applying;
|
|
174
|
+
});
|
|
175
|
+
expect(trigger().disabled).toBe(false);
|
|
176
|
+
expect(transition.submitting).toBe(false);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("keeps Enter on the picker: Enter on Organization holds the change and opens the confirmation with Cancel focused", async () => {
|
|
180
|
+
await chooseOrganizationWith("Enter");
|
|
181
|
+
|
|
182
|
+
expect(saved).not.toHaveBeenCalled();
|
|
183
|
+
expect(transition.pending).toEqual({ from: "private", to: "org" });
|
|
184
|
+
expect(alertDialog()).not.toBeNull();
|
|
185
|
+
expect(document.activeElement).toBe(alertButton("Cancel"));
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("keeps Space working the same way", async () => {
|
|
189
|
+
await chooseOrganizationWith(" ");
|
|
190
|
+
|
|
191
|
+
expect(saved).not.toHaveBeenCalled();
|
|
192
|
+
expect(transition.pending).toEqual({ from: "private", to: "org" });
|
|
193
|
+
expect(alertDialog()).not.toBeNull();
|
|
194
|
+
expect(document.activeElement).toBe(alertButton("Cancel"));
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("cancels only on a deliberate press of Cancel", async () => {
|
|
198
|
+
await chooseOrganizationWith("Enter");
|
|
199
|
+
|
|
200
|
+
press("Enter", alertButton("Cancel"));
|
|
201
|
+
|
|
202
|
+
expect(saved).not.toHaveBeenCalled();
|
|
203
|
+
expect(transition.pending).toBeNull();
|
|
204
|
+
expect(alertDialog()).toBeNull();
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
it("saves only on a deliberate press of the confirm button", async () => {
|
|
208
|
+
await chooseOrganizationWith("Enter");
|
|
209
|
+
expect(saved).not.toHaveBeenCalled();
|
|
210
|
+
|
|
211
|
+
const dialogBefore = alertDialog();
|
|
212
|
+
const cancel = alertButton("Cancel");
|
|
213
|
+
press("Tab", cancel);
|
|
214
|
+
// The browser's default action for Tab: the next control in the dialog.
|
|
215
|
+
const confirm = alertButton("Share with organization");
|
|
216
|
+
act(() => confirm.focus());
|
|
217
|
+
expect(alertDialog()).toBe(dialogBefore);
|
|
218
|
+
expect(document.activeElement).toBe(confirm);
|
|
219
|
+
expect(saved).not.toHaveBeenCalled();
|
|
220
|
+
|
|
221
|
+
press("Enter", confirm);
|
|
222
|
+
await act(async () => {
|
|
223
|
+
await Promise.resolve();
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(saved).toHaveBeenCalledOnce();
|
|
227
|
+
expect(saved).toHaveBeenCalledWith("org");
|
|
228
|
+
expect(transition.pending).toBeNull();
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("closes on Escape without saving and hands focus back to the picker", async () => {
|
|
232
|
+
await chooseOrganizationWith("Enter");
|
|
233
|
+
|
|
234
|
+
press("Escape", alertButton("Cancel"));
|
|
235
|
+
await act(async () => {
|
|
236
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
expect(saved).not.toHaveBeenCalled();
|
|
240
|
+
expect(transition.pending).toBeNull();
|
|
241
|
+
expect(alertDialog()).toBeNull();
|
|
242
|
+
expect(document.activeElement).toBe(trigger());
|
|
243
|
+
});
|
|
244
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { AgentNativeI18nProvider } from "@agent-native/core/client/i18n";
|
|
4
|
+
import { act } from "react";
|
|
5
|
+
import { createRoot, type Root } from "react-dom/client";
|
|
6
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
7
|
+
|
|
8
|
+
import { createToolkitI18nCatalog } from "../i18n.js";
|
|
9
|
+
import { OwnershipFilter } from "./OwnershipFilter.js";
|
|
10
|
+
import { VisibilityBadge } from "./VisibilityBadge.js";
|
|
11
|
+
|
|
12
|
+
const catalog = createToolkitI18nCatalog({ messages: {} });
|
|
13
|
+
|
|
14
|
+
describe("localized sharing wrappers", () => {
|
|
15
|
+
let container: HTMLDivElement;
|
|
16
|
+
let root: Root;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
vi.stubGlobal("IS_REACT_ACT_ENVIRONMENT", true);
|
|
20
|
+
// The i18n provider reads the saved language over HTTP; keep it offline.
|
|
21
|
+
vi.stubGlobal(
|
|
22
|
+
"fetch",
|
|
23
|
+
vi.fn(async () => new Response("{}", { status: 200 })),
|
|
24
|
+
);
|
|
25
|
+
container = document.createElement("div");
|
|
26
|
+
document.body.appendChild(container);
|
|
27
|
+
root = createRoot(container);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
act(() => root.unmount());
|
|
32
|
+
container.remove();
|
|
33
|
+
vi.unstubAllGlobals();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
function render(node: React.ReactNode) {
|
|
37
|
+
act(() =>
|
|
38
|
+
root.render(
|
|
39
|
+
<AgentNativeI18nProvider catalog={catalog}>
|
|
40
|
+
{node}
|
|
41
|
+
</AgentNativeI18nProvider>,
|
|
42
|
+
),
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
it("names every visibility through Core copy, with Organization spelled out", () => {
|
|
47
|
+
const texts = (["private", "org", "public"] as const).map((visibility) => {
|
|
48
|
+
render(<VisibilityBadge visibility={visibility} />);
|
|
49
|
+
return container.querySelector("span")?.textContent;
|
|
50
|
+
});
|
|
51
|
+
expect(texts).toEqual(["Private", "Organization", "Public"]);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("lets a caller override a single label", () => {
|
|
55
|
+
render(<VisibilityBadge visibility="org" labels={{ org: "Team" }} />);
|
|
56
|
+
expect(container.querySelector("span")?.textContent).toBe("Team");
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("labels the ownership filter through Core copy", () => {
|
|
60
|
+
render(<OwnershipFilter value="shared" onChange={() => {}} />);
|
|
61
|
+
expect(container.querySelector("button")?.getAttribute("aria-label")).toBe(
|
|
62
|
+
"Shared with me",
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { useT } from "@agent-native/core/client/i18n";
|
|
2
|
+
import {
|
|
3
|
+
VisibilityBadge as ToolkitVisibilityBadge,
|
|
4
|
+
type VisibilityBadgeLabels,
|
|
5
|
+
type VisibilityBadgeProps as ToolkitVisibilityBadgeProps,
|
|
4
6
|
} from "@agent-native/toolkit/sharing";
|
|
7
|
+
|
|
8
|
+
export type { VisibilityBadgeLabels };
|
|
9
|
+
|
|
10
|
+
export type VisibilityBadgeProps = Omit<
|
|
11
|
+
ToolkitVisibilityBadgeProps,
|
|
12
|
+
"labels"
|
|
13
|
+
> & {
|
|
14
|
+
labels?: Partial<VisibilityBadgeLabels>;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function useVisibilityBadgeLabels(): VisibilityBadgeLabels {
|
|
18
|
+
const t = useT();
|
|
19
|
+
return {
|
|
20
|
+
private: t("agentChat.share.private", { defaultValue: "Private" }),
|
|
21
|
+
org: t("agentChat.share.organization", { defaultValue: "Organization" }),
|
|
22
|
+
public: t("agentChat.share.public", { defaultValue: "Public" }),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Always passes catalog labels, so the pure English fallback never shows. */
|
|
27
|
+
export function VisibilityBadge({ labels, ...props }: VisibilityBadgeProps) {
|
|
28
|
+
const defaults = useVisibilityBadgeLabels();
|
|
29
|
+
return (
|
|
30
|
+
<ToolkitVisibilityBadge {...props} labels={{ ...defaults, ...labels }} />
|
|
31
|
+
);
|
|
32
|
+
}
|
package/src/app/sharing/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from "./AccessRequestApprovalPage.js";
|
|
2
2
|
export * from "./AgentShareSection.js";
|
|
3
3
|
export * from "./McpInstallActions.js";
|
|
4
|
+
export * from "./OwnershipFilter.js";
|
|
4
5
|
export * from "./ResourceAccessScreen.js";
|
|
5
6
|
export * from "./ShareButton.js";
|
|
6
7
|
export * from "./ShareDialog.js";
|
|
8
|
+
export * from "./ShareVisibilityConfirmDialog.js";
|
|
7
9
|
export * from "./VisibilityBadge.js";
|