@ai-matrx/alchemy 0.6.2 → 0.8.2
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/CHANGELOG.md +58 -0
- package/dist/actions.cjs +374 -0
- package/dist/actions.cjs.map +1 -0
- package/dist/actions.d.cts +773 -0
- package/dist/actions.d.ts +773 -0
- package/dist/actions.js +351 -0
- package/dist/actions.js.map +1 -0
- package/dist/checks.cjs +31 -2
- package/dist/checks.cjs.map +1 -1
- package/dist/checks.d.cts +24 -1
- package/dist/checks.d.ts +24 -1
- package/dist/checks.js +31 -2
- package/dist/checks.js.map +1 -1
- package/dist/core.cjs +1757 -2
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +595 -1
- package/dist/core.d.ts +595 -1
- package/dist/core.js +1749 -2
- package/dist/core.js.map +1 -1
- package/dist/declare.cjs +12 -10
- package/dist/declare.cjs.map +1 -1
- package/dist/declare.d.cts +18 -2
- package/dist/declare.d.ts +18 -2
- package/dist/declare.js +12 -10
- package/dist/declare.js.map +1 -1
- package/dist/index.cjs +1757 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +595 -1
- package/dist/index.d.ts +595 -1
- package/dist/index.js +1749 -2
- package/dist/index.js.map +1 -1
- package/dist/menu.cjs +436 -0
- package/dist/menu.cjs.map +1 -0
- package/dist/menu.d.cts +834 -0
- package/dist/menu.d.ts +834 -0
- package/dist/menu.js +413 -0
- package/dist/menu.js.map +1 -0
- package/dist/operate-document.cjs +163 -0
- package/dist/operate-document.cjs.map +1 -0
- package/dist/operate-document.d.cts +132 -0
- package/dist/operate-document.d.ts +132 -0
- package/dist/operate-document.js +130 -0
- package/dist/operate-document.js.map +1 -0
- package/dist/operate-rich-html.cjs +129 -0
- package/dist/operate-rich-html.cjs.map +1 -0
- package/dist/operate-rich-html.d.cts +136 -0
- package/dist/operate-rich-html.d.ts +136 -0
- package/dist/operate-rich-html.js +96 -0
- package/dist/operate-rich-html.js.map +1 -0
- package/dist/operate-server.cjs +157 -0
- package/dist/operate-server.cjs.map +1 -0
- package/dist/operate-server.d.cts +183 -0
- package/dist/operate-server.d.ts +183 -0
- package/dist/operate-server.js +134 -0
- package/dist/operate-server.js.map +1 -0
- package/dist/operate-xlsx.cjs +248 -0
- package/dist/operate-xlsx.cjs.map +1 -0
- package/dist/operate-xlsx.d.cts +129 -0
- package/dist/operate-xlsx.d.ts +129 -0
- package/dist/operate-xlsx.js +215 -0
- package/dist/operate-xlsx.js.map +1 -0
- package/dist/operate.cjs +1774 -0
- package/dist/operate.cjs.map +1 -0
- package/dist/operate.d.cts +595 -0
- package/dist/operate.d.ts +595 -0
- package/dist/operate.js +1750 -0
- package/dist/operate.js.map +1 -0
- package/dist/ports.cjs.map +1 -1
- package/dist/ports.d.cts +361 -3
- package/dist/ports.d.ts +361 -3
- package/dist/react-bar.cjs +686 -0
- package/dist/react-bar.cjs.map +1 -0
- package/dist/react-bar.d.cts +379 -0
- package/dist/react-bar.d.ts +379 -0
- package/dist/react-bar.js +665 -0
- package/dist/react-bar.js.map +1 -0
- package/dist/react-host.cjs +301 -0
- package/dist/react-host.cjs.map +1 -0
- package/dist/react-host.d.cts +820 -0
- package/dist/react-host.d.ts +820 -0
- package/dist/react-host.js +269 -0
- package/dist/react-host.js.map +1 -0
- package/dist/react-menu.cjs +735 -0
- package/dist/react-menu.cjs.map +1 -0
- package/dist/react-menu.d.cts +370 -0
- package/dist/react-menu.d.ts +370 -0
- package/dist/react-menu.js +722 -0
- package/dist/react-menu.js.map +1 -0
- package/dist/react-overflow.cjs +592 -0
- package/dist/react-overflow.cjs.map +1 -0
- package/dist/react-overflow.d.cts +817 -0
- package/dist/react-overflow.d.ts +817 -0
- package/dist/react-overflow.js +571 -0
- package/dist/react-overflow.js.map +1 -0
- package/dist/react-palette.cjs +489 -0
- package/dist/react-palette.cjs.map +1 -0
- package/dist/react-palette.d.cts +359 -0
- package/dist/react-palette.d.ts +359 -0
- package/dist/react-palette.js +457 -0
- package/dist/react-palette.js.map +1 -0
- package/dist/react-selection.cjs +617 -0
- package/dist/react-selection.cjs.map +1 -0
- package/dist/react-selection.d.cts +357 -0
- package/dist/react-selection.d.ts +357 -0
- package/dist/react-selection.js +596 -0
- package/dist/react-selection.js.map +1 -0
- package/dist/react-sheet.cjs +616 -0
- package/dist/react-sheet.cjs.map +1 -0
- package/dist/react-sheet.d.cts +361 -0
- package/dist/react-sheet.d.ts +361 -0
- package/dist/react-sheet.js +595 -0
- package/dist/react-sheet.js.map +1 -0
- package/package.json +148 -5
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/react/menu.tsx
|
|
4
|
+
import * as React4 from "react";
|
|
5
|
+
import {
|
|
6
|
+
DropdownMenu,
|
|
7
|
+
DropdownMenuContent,
|
|
8
|
+
DropdownMenuItem as DropdownMenuItem2,
|
|
9
|
+
DropdownMenuLabel as DropdownMenuLabel2,
|
|
10
|
+
DropdownMenuSeparator as DropdownMenuSeparator2,
|
|
11
|
+
DropdownMenuTrigger,
|
|
12
|
+
TooltipProvider
|
|
13
|
+
} from "@ai-matrx/design-system";
|
|
14
|
+
|
|
15
|
+
// src/menu/layouts.ts
|
|
16
|
+
var INLINE_SECTION_MAX = 3;
|
|
17
|
+
function sectionLabel(section) {
|
|
18
|
+
return section.label ?? null;
|
|
19
|
+
}
|
|
20
|
+
function isLeaf(node) {
|
|
21
|
+
return node.kind === "item" || node.kind === "checkbox" || node.kind === "link";
|
|
22
|
+
}
|
|
23
|
+
function fold(section) {
|
|
24
|
+
return {
|
|
25
|
+
kind: "submenu",
|
|
26
|
+
id: `${section.id}:fold`,
|
|
27
|
+
label: section.label,
|
|
28
|
+
...section.icon !== void 0 ? { icon: section.icon } : {},
|
|
29
|
+
children: section.nodes
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function rowCount(nodes) {
|
|
33
|
+
return nodes.filter((n) => n.kind !== "separator" && n.kind !== "label").length;
|
|
34
|
+
}
|
|
35
|
+
function stripOf(model) {
|
|
36
|
+
const clipboard = model.sections.find((s) => s.group === "clipboard" && !s.primary);
|
|
37
|
+
return clipboard ? clipboard.nodes.filter(isLeaf) : [];
|
|
38
|
+
}
|
|
39
|
+
function clipboardRest(model) {
|
|
40
|
+
const clipboard = model.sections.find((s) => s.group === "clipboard" && !s.primary);
|
|
41
|
+
return clipboard ? clipboard.nodes.filter((n) => !isLeaf(n) && n.kind === "submenu") : [];
|
|
42
|
+
}
|
|
43
|
+
function classic(model) {
|
|
44
|
+
return { strip: [], sections: model.sections, filterable: false };
|
|
45
|
+
}
|
|
46
|
+
function tiered(model, filterable) {
|
|
47
|
+
const strip = stripOf(model);
|
|
48
|
+
const hierarchical = model.sections.some((s) => s.primary);
|
|
49
|
+
const sections = [];
|
|
50
|
+
const rest = clipboardRest(model);
|
|
51
|
+
for (const s of model.sections) {
|
|
52
|
+
if (s.group === "clipboard" && !s.primary) {
|
|
53
|
+
if (rest.length) sections.push({ ...s, nodes: rest });
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (s.primary) {
|
|
57
|
+
sections.push(s);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (!s.label || s.group === "surface-info" || rowCount(s.nodes) <= INLINE_SECTION_MAX) {
|
|
61
|
+
if (hierarchical) sections.push(s);
|
|
62
|
+
else {
|
|
63
|
+
const { label: _label, ...unlabelled } = s;
|
|
64
|
+
sections.push(unlabelled);
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
sections.push({ id: s.id, group: s.group, nodes: [fold({ ...s, label: s.label })] });
|
|
69
|
+
}
|
|
70
|
+
return { strip, sections, filterable };
|
|
71
|
+
}
|
|
72
|
+
function context(model, arrangement) {
|
|
73
|
+
if (arrangement === "classic") return classic(model);
|
|
74
|
+
return tiered(model, arrangement === "command");
|
|
75
|
+
}
|
|
76
|
+
function palette(model) {
|
|
77
|
+
const leaves = [];
|
|
78
|
+
const walk = (nodes, trail) => {
|
|
79
|
+
for (const n of nodes) {
|
|
80
|
+
if (isLeaf(n)) leaves.push({ node: n, breadcrumb: trail });
|
|
81
|
+
else if (n.kind === "submenu") {
|
|
82
|
+
if (n.lazy) leaves.push({ node: n, breadcrumb: trail });
|
|
83
|
+
else walk(n.children, [...trail, n.label]);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
for (const s of model.sections) walk(s.nodes, s.label ? [s.label] : []);
|
|
88
|
+
return { leaves };
|
|
89
|
+
}
|
|
90
|
+
function filterPalette(arranged, query) {
|
|
91
|
+
const words = query.toLowerCase().split(/\s+/).filter(Boolean);
|
|
92
|
+
if (!words.length) return arranged;
|
|
93
|
+
return {
|
|
94
|
+
leaves: arranged.leaves.filter((l) => {
|
|
95
|
+
const hay = `${l.node.label} ${l.breadcrumb.join(" ")}`.toLowerCase();
|
|
96
|
+
return words.every((w) => hay.includes(w));
|
|
97
|
+
})
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/react/engine.tsx
|
|
102
|
+
import * as React2 from "react";
|
|
103
|
+
|
|
104
|
+
// src/declare/sensitivity.ts
|
|
105
|
+
var DEFAULT_SENSITIVITY = Object.freeze({
|
|
106
|
+
exportable: true,
|
|
107
|
+
classification: "ordinary",
|
|
108
|
+
includedByDefault: true
|
|
109
|
+
});
|
|
110
|
+
function resolveSensitivity(value) {
|
|
111
|
+
return {
|
|
112
|
+
exportable: value.sensitivity?.exportable ?? DEFAULT_SENSITIVITY.exportable,
|
|
113
|
+
classification: value.sensitivity?.classification ?? DEFAULT_SENSITIVITY.classification,
|
|
114
|
+
includedByDefault: value.sensitivity?.includedByDefault ?? DEFAULT_SENSITIVITY.includedByDefault
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// src/actions/projection.ts
|
|
119
|
+
function toJson(value) {
|
|
120
|
+
if (value === void 0 || typeof value === "function" || typeof value === "symbol") return void 0;
|
|
121
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return value;
|
|
122
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : null;
|
|
123
|
+
if (typeof value === "bigint") return value.toString();
|
|
124
|
+
if (value instanceof Date) return value.toISOString();
|
|
125
|
+
if (Array.isArray(value)) return value.map((v) => toJson(v) ?? null);
|
|
126
|
+
if (typeof value === "object") {
|
|
127
|
+
const out = {};
|
|
128
|
+
for (const [k, v] of Object.entries(value)) {
|
|
129
|
+
const j = toJson(v);
|
|
130
|
+
if (j !== void 0) out[k] = j;
|
|
131
|
+
}
|
|
132
|
+
return out;
|
|
133
|
+
}
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
136
|
+
function projectValues(raw, declared, pathPrefix = "") {
|
|
137
|
+
const byName = new Map(declared.map((d) => [d.name, d]));
|
|
138
|
+
const values = {};
|
|
139
|
+
const omissions = [];
|
|
140
|
+
for (const [name, value] of Object.entries(raw)) {
|
|
141
|
+
const path = pathPrefix ? `${pathPrefix}.${name}` : name;
|
|
142
|
+
const decl = byName.get(name);
|
|
143
|
+
if (!decl) {
|
|
144
|
+
omissions.push({ path, reason: "filtered" });
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
const sensitivity = resolveSensitivity(decl);
|
|
148
|
+
if (sensitivity.classification !== "ordinary") {
|
|
149
|
+
omissions.push({ path, reason: "excluded", classification: sensitivity.classification });
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (!sensitivity.exportable) {
|
|
153
|
+
omissions.push({ path, reason: "excluded" });
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const json = toJson(value);
|
|
157
|
+
if (json === void 0) continue;
|
|
158
|
+
values[name] = json;
|
|
159
|
+
}
|
|
160
|
+
return { values, omissions };
|
|
161
|
+
}
|
|
162
|
+
function createProjectedReads(source) {
|
|
163
|
+
return {
|
|
164
|
+
async values(signal) {
|
|
165
|
+
if (!source.surface || !source.declaration) return { values: {}, omissions: [] };
|
|
166
|
+
const raw = await source.surface.readValues(signal);
|
|
167
|
+
const screenValues = source.declaration.values;
|
|
168
|
+
return projectValues(raw, screenValues);
|
|
169
|
+
},
|
|
170
|
+
async item(signal) {
|
|
171
|
+
const item = source.item;
|
|
172
|
+
if (!item || !source.declaration) return null;
|
|
173
|
+
const type = source.declaration.itemTypes?.find((t) => t.name === item.itemType);
|
|
174
|
+
if (!type) return { values: {}, omissions: [{ path: item.itemType, reason: "filtered" }] };
|
|
175
|
+
const raw = await item.readValues(signal);
|
|
176
|
+
return projectValues(raw, type.values, item.itemType);
|
|
177
|
+
},
|
|
178
|
+
async live(signal) {
|
|
179
|
+
if (!source.surface?.readLive) return {};
|
|
180
|
+
return source.surface.readLive(signal);
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// src/actions/run.ts
|
|
186
|
+
async function runAction(action, target, options) {
|
|
187
|
+
const { ports } = options;
|
|
188
|
+
if (action.requiresAuth && !target.auth.authenticated) {
|
|
189
|
+
if (!ports.auth) {
|
|
190
|
+
ports.diagnostics.capture(new Error(`requiresAuth action "${action.id}" ran signed out with no auth port`), {
|
|
191
|
+
area: "actions",
|
|
192
|
+
detail: { actionId: action.id }
|
|
193
|
+
});
|
|
194
|
+
return { status: "failed", error: new Error("sign-in unavailable") };
|
|
195
|
+
}
|
|
196
|
+
ports.auth.signInThenResume({ actionId: action.id, contentFingerprint: options.contentFingerprint ?? action.id });
|
|
197
|
+
return { status: "auth-pending" };
|
|
198
|
+
}
|
|
199
|
+
const reads = createProjectedReads(options.source ?? { surface: null, declaration: target.declaration, item: null });
|
|
200
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
201
|
+
try {
|
|
202
|
+
const outcome = await action.run(target, { reads, ports, signal });
|
|
203
|
+
return { status: "ran", outcome };
|
|
204
|
+
} catch (error) {
|
|
205
|
+
ports.diagnostics.capture(error, { area: "actions", detail: { actionId: action.id, stage: "run" } });
|
|
206
|
+
const label = typeof action.label === "string" ? action.label : action.id;
|
|
207
|
+
ports.notify?.error(`${label} did not finish.`, "Try again; if it keeps failing, report it from the feedback button.");
|
|
208
|
+
return { status: "failed", error };
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/menu/model.ts
|
|
213
|
+
var CATEGORY_GROUP = {
|
|
214
|
+
clipboard: "clipboard",
|
|
215
|
+
copy: "transfer",
|
|
216
|
+
export: "transfer",
|
|
217
|
+
save: "document",
|
|
218
|
+
share: "document",
|
|
219
|
+
edit: "editable",
|
|
220
|
+
history: "history",
|
|
221
|
+
ai: "ai",
|
|
222
|
+
ask: "ai",
|
|
223
|
+
listen: "tools",
|
|
224
|
+
study: "tools",
|
|
225
|
+
app: "tools",
|
|
226
|
+
feedback: "quick",
|
|
227
|
+
creator: "admin",
|
|
228
|
+
admin: "admin",
|
|
229
|
+
"surface-info": "surface-info"
|
|
230
|
+
};
|
|
231
|
+
var GROUP_ORDER = [
|
|
232
|
+
"clipboard",
|
|
233
|
+
"editable",
|
|
234
|
+
"transfer",
|
|
235
|
+
"document",
|
|
236
|
+
"history",
|
|
237
|
+
"ai",
|
|
238
|
+
"tools",
|
|
239
|
+
"quick",
|
|
240
|
+
"surface",
|
|
241
|
+
"admin",
|
|
242
|
+
"surface-info"
|
|
243
|
+
];
|
|
244
|
+
var CATEGORY_ORDER = [
|
|
245
|
+
"clipboard",
|
|
246
|
+
"edit",
|
|
247
|
+
"copy",
|
|
248
|
+
"export",
|
|
249
|
+
"save",
|
|
250
|
+
"share",
|
|
251
|
+
"history",
|
|
252
|
+
"ask",
|
|
253
|
+
"ai",
|
|
254
|
+
"listen",
|
|
255
|
+
"study",
|
|
256
|
+
"app",
|
|
257
|
+
"feedback",
|
|
258
|
+
"creator",
|
|
259
|
+
"admin",
|
|
260
|
+
"surface-info"
|
|
261
|
+
];
|
|
262
|
+
function translate(i18n, key, fallback) {
|
|
263
|
+
if (!i18n) return fallback;
|
|
264
|
+
try {
|
|
265
|
+
return i18n.t(key, fallback);
|
|
266
|
+
} catch {
|
|
267
|
+
return fallback;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function actionToNode(resolved, target, options = {}) {
|
|
271
|
+
const { action, eligibility } = resolved;
|
|
272
|
+
const rawLabel = typeof action.label === "function" ? action.label(target) : action.label;
|
|
273
|
+
const label = translate(options.i18n, action.labelKey ?? action.id, rawLabel);
|
|
274
|
+
const base = {
|
|
275
|
+
id: action.id,
|
|
276
|
+
actionId: action.id,
|
|
277
|
+
...action.icon !== void 0 ? { icon: action.icon } : {},
|
|
278
|
+
...action.placement !== void 0 ? { placement: action.placement } : {}
|
|
279
|
+
};
|
|
280
|
+
if (action.expand) {
|
|
281
|
+
const node = {
|
|
282
|
+
...base,
|
|
283
|
+
kind: "submenu",
|
|
284
|
+
label,
|
|
285
|
+
lazy: true,
|
|
286
|
+
loading: false,
|
|
287
|
+
children: [],
|
|
288
|
+
...action.emptyLabel !== void 0 ? { emptyLabel: action.emptyLabel } : {}
|
|
289
|
+
};
|
|
290
|
+
return node;
|
|
291
|
+
}
|
|
292
|
+
if (action.href !== void 0) {
|
|
293
|
+
const href = typeof action.href === "function" ? action.href(target) : action.href;
|
|
294
|
+
return { ...base, kind: "link", label, href };
|
|
295
|
+
}
|
|
296
|
+
if (action.toggle) {
|
|
297
|
+
return {
|
|
298
|
+
...base,
|
|
299
|
+
kind: "checkbox",
|
|
300
|
+
label,
|
|
301
|
+
checked: action.pressed?.(target) ?? false,
|
|
302
|
+
...action.description !== void 0 ? { description: action.description } : {}
|
|
303
|
+
};
|
|
304
|
+
}
|
|
305
|
+
const state = action.stateIcon?.(target) ?? null;
|
|
306
|
+
const pressed = action.pressed?.(target);
|
|
307
|
+
const hint = action.hint !== void 0 ? translate(options.i18n, action.hintKey ?? `${action.id}.hint`, action.hint) : void 0;
|
|
308
|
+
return {
|
|
309
|
+
...base,
|
|
310
|
+
kind: "item",
|
|
311
|
+
label,
|
|
312
|
+
...action.iconTone !== void 0 ? { iconTone: action.iconTone } : {},
|
|
313
|
+
...state ? { stateIcon: state } : {},
|
|
314
|
+
...action.description !== void 0 ? { description: action.description } : {},
|
|
315
|
+
...hint !== void 0 ? { hint } : {},
|
|
316
|
+
...pressed !== void 0 ? { pressed } : {},
|
|
317
|
+
...action.destructive ? { destructive: true } : {},
|
|
318
|
+
...action.preserveSelection ? { preserveSelection: true } : {},
|
|
319
|
+
...eligibility.status === "unavailable-verb" ? { unavailable: { sentence: eligibility.sentence } } : {}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
function buildMenuModel(target, resolved, options = {}) {
|
|
323
|
+
const ordered = resolved.map((r, index) => ({ r, index })).sort((a, b) => {
|
|
324
|
+
const ca = CATEGORY_ORDER.indexOf(a.r.action.category);
|
|
325
|
+
const cb = CATEGORY_ORDER.indexOf(b.r.action.category);
|
|
326
|
+
if (ca !== cb) return ca - cb;
|
|
327
|
+
const oa = a.r.action.order ?? 0;
|
|
328
|
+
const ob = b.r.action.order ?? 0;
|
|
329
|
+
if (oa !== ob) return oa - ob;
|
|
330
|
+
return a.index - b.index;
|
|
331
|
+
}).map((x) => x.r);
|
|
332
|
+
const sections = /* @__PURE__ */ new Map();
|
|
333
|
+
const roles = {};
|
|
334
|
+
const explicit = /* @__PURE__ */ new Map();
|
|
335
|
+
resolved.forEach((r, index) => {
|
|
336
|
+
const sec = r.action.section;
|
|
337
|
+
if (!sec) return;
|
|
338
|
+
const entry = explicit.get(sec.id) ?? { group: CATEGORY_GROUP[r.action.category], rows: [] };
|
|
339
|
+
entry.rows.push({ r, index });
|
|
340
|
+
explicit.set(sec.id, entry);
|
|
341
|
+
});
|
|
342
|
+
const placed = /* @__PURE__ */ new Set();
|
|
343
|
+
for (const r of ordered) {
|
|
344
|
+
const sec = r.action.section;
|
|
345
|
+
if (sec && placed.has(sec.id)) continue;
|
|
346
|
+
const group = sec ? explicit.get(sec.id)?.group ?? CATEGORY_GROUP[r.action.category] : CATEGORY_GROUP[r.action.category];
|
|
347
|
+
const sectionId = sec ? `section:${sec.id}` : group;
|
|
348
|
+
let section = sections.get(sectionId);
|
|
349
|
+
if (!section) {
|
|
350
|
+
section = {
|
|
351
|
+
id: sectionId,
|
|
352
|
+
group,
|
|
353
|
+
nodes: [],
|
|
354
|
+
...sec ? { label: translate(options.i18n, sec.labelKey ?? `section.${sec.id}`, sec.label) } : {},
|
|
355
|
+
...sec?.icon !== void 0 ? { icon: sec.icon } : {},
|
|
356
|
+
...sec?.primary ? { primary: true } : {}
|
|
357
|
+
};
|
|
358
|
+
sections.set(sectionId, section);
|
|
359
|
+
}
|
|
360
|
+
const rows = sec ? (explicit.get(sec.id)?.rows ?? []).sort((x, y) => (x.r.action.order ?? 0) - (y.r.action.order ?? 0) || x.index - y.index).map((x) => x.r) : [r];
|
|
361
|
+
if (sec) placed.add(sec.id);
|
|
362
|
+
for (const row of rows) {
|
|
363
|
+
section.nodes.push(actionToNode(row, target, options));
|
|
364
|
+
if (row.action.verb) roles[row.action.verb] = row.action.id;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
const list = [...sections.values()].sort((a, b) => {
|
|
368
|
+
if (Boolean(a.primary) !== Boolean(b.primary)) return a.primary ? -1 : 1;
|
|
369
|
+
return GROUP_ORDER.indexOf(a.group) - GROUP_ORDER.indexOf(b.group);
|
|
370
|
+
});
|
|
371
|
+
const selected = target.selection?.text?.trim();
|
|
372
|
+
const content = options.content?.trim();
|
|
373
|
+
const header = selected ? { label: "Selected", text: target.selection?.text ?? "" } : content ? { label: "Content", text: options.content ?? "" } : null;
|
|
374
|
+
return { header, sections: list, roles };
|
|
375
|
+
}
|
|
376
|
+
function withExpandedChildren(model, nodeId, children) {
|
|
377
|
+
const visit = (nodes) => nodes.map((n) => {
|
|
378
|
+
if (n.kind !== "submenu") return n;
|
|
379
|
+
if (n.id === nodeId) {
|
|
380
|
+
return children === "loading" ? { ...n, loading: true } : { ...n, lazy: false, loading: false, children };
|
|
381
|
+
}
|
|
382
|
+
return { ...n, children: visit(n.children) };
|
|
383
|
+
});
|
|
384
|
+
return { ...model, sections: model.sections.map((s) => ({ ...s, nodes: visit(s.nodes) })) };
|
|
385
|
+
}
|
|
386
|
+
function findNode(nodes, id) {
|
|
387
|
+
for (const n of nodes) {
|
|
388
|
+
if (n.id === id) return n;
|
|
389
|
+
if (n.kind === "submenu") {
|
|
390
|
+
const hit = findNode(n.children, id);
|
|
391
|
+
if (hit) return hit;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
return null;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// src/react/context.ts
|
|
398
|
+
import * as React from "react";
|
|
399
|
+
var KEY = /* @__PURE__ */ Symbol.for("ai-matrx.alchemy.actions-context");
|
|
400
|
+
var AlchemyActionsContext = globalThis[KEY] ??= React.createContext(null);
|
|
401
|
+
function useAlchemyActions() {
|
|
402
|
+
const value = React.useContext(AlchemyActionsContext);
|
|
403
|
+
if (!value) throw new Error("Alchemy actions: render inside <AlchemyActionsProvider> (@ai-matrx/alchemy/react/host).");
|
|
404
|
+
return value;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
// src/react/engine.tsx
|
|
408
|
+
import { jsx } from "react/jsx-runtime";
|
|
409
|
+
function useMenuEngine(target, options = {}) {
|
|
410
|
+
const { registry, ports } = useAlchemyActions();
|
|
411
|
+
const [resolved, setResolved] = React2.useState([]);
|
|
412
|
+
const [model, setModel] = React2.useState(null);
|
|
413
|
+
const [tick, setTick] = React2.useState(0);
|
|
414
|
+
const expanded = React2.useRef(/* @__PURE__ */ new Map());
|
|
415
|
+
const active = options.active ?? true;
|
|
416
|
+
const optionsRef = React2.useRef(options);
|
|
417
|
+
optionsRef.current = options;
|
|
418
|
+
React2.useEffect(() => registry.subscribe(() => setTick((t) => t + 1)), [registry]);
|
|
419
|
+
React2.useEffect(() => {
|
|
420
|
+
if (!target || !active) return;
|
|
421
|
+
let live = true;
|
|
422
|
+
void registry.resolve(target, optionsRef.current.restrict).then((list) => {
|
|
423
|
+
if (!live) return;
|
|
424
|
+
expanded.current.clear();
|
|
425
|
+
setResolved(list);
|
|
426
|
+
setModel(buildMenuModel(target, list, { ...ports.i18n ? { i18n: ports.i18n } : {}, content: optionsRef.current.content ?? null }));
|
|
427
|
+
});
|
|
428
|
+
return () => {
|
|
429
|
+
live = false;
|
|
430
|
+
};
|
|
431
|
+
}, [registry, ports, target, active, tick, options.revision]);
|
|
432
|
+
React2.useEffect(() => {
|
|
433
|
+
if (!target) return;
|
|
434
|
+
const offs = resolved.map((r) => r.action.subscribe?.(() => setTick((t) => t + 1), target)).filter((off) => typeof off === "function");
|
|
435
|
+
return () => offs.forEach((off) => off());
|
|
436
|
+
}, [resolved, target]);
|
|
437
|
+
const findAction = React2.useCallback(
|
|
438
|
+
(id) => resolved.find((r) => r.action.id === id)?.action ?? expanded.current.get(id),
|
|
439
|
+
[resolved]
|
|
440
|
+
);
|
|
441
|
+
const run = React2.useCallback(
|
|
442
|
+
async (nodeId) => {
|
|
443
|
+
if (!target || !model) return null;
|
|
444
|
+
const node = model.sections.map((s) => findNode(s.nodes, nodeId)).find(Boolean) ?? null;
|
|
445
|
+
const action = findAction(node && "actionId" in node && node.actionId ? node.actionId : nodeId);
|
|
446
|
+
if (!action) return null;
|
|
447
|
+
const o = optionsRef.current;
|
|
448
|
+
const result = await runAction(action, target, {
|
|
449
|
+
ports,
|
|
450
|
+
...o.source ? { source: o.source } : {},
|
|
451
|
+
...o.contentFingerprint ? { contentFingerprint: o.contentFingerprint } : {}
|
|
452
|
+
});
|
|
453
|
+
o.onRan?.(nodeId, result);
|
|
454
|
+
return result;
|
|
455
|
+
},
|
|
456
|
+
[target, model, findAction, ports]
|
|
457
|
+
);
|
|
458
|
+
const expand = React2.useCallback(
|
|
459
|
+
async (nodeId) => {
|
|
460
|
+
const action = findAction(nodeId);
|
|
461
|
+
if (!target || !action?.expand) return;
|
|
462
|
+
setModel((m) => m ? withExpandedChildren(m, nodeId, "loading") : m);
|
|
463
|
+
try {
|
|
464
|
+
const children = await action.expand(target, new AbortController().signal);
|
|
465
|
+
const nodes = children.map((child) => {
|
|
466
|
+
expanded.current.set(child.id, child);
|
|
467
|
+
return actionToNode({ action: child, eligibility: { status: "available" } }, target, ports.i18n ? { i18n: ports.i18n } : {});
|
|
468
|
+
});
|
|
469
|
+
setModel((m) => m ? withExpandedChildren(m, nodeId, nodes) : m);
|
|
470
|
+
} catch (error) {
|
|
471
|
+
ports.diagnostics.capture(error, { area: "menu", detail: { nodeId, stage: "expand" } });
|
|
472
|
+
setModel((m) => m ? withExpandedChildren(m, nodeId, []) : m);
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
[findAction, target, ports]
|
|
476
|
+
);
|
|
477
|
+
const icon = React2.useCallback(
|
|
478
|
+
(key, tone) => {
|
|
479
|
+
if (!key || !ports.icons) return null;
|
|
480
|
+
const Resolved = ports.icons.resolve(key);
|
|
481
|
+
return Resolved ? /* @__PURE__ */ jsx(Resolved, { className: `h-4 w-4 shrink-0 ${tone ?? ""}`, "aria-hidden": true }) : null;
|
|
482
|
+
},
|
|
483
|
+
[ports.icons]
|
|
484
|
+
);
|
|
485
|
+
return { model, resolved, run, expand, icon };
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// src/react/dropdown-nodes.tsx
|
|
489
|
+
import * as React3 from "react";
|
|
490
|
+
import {
|
|
491
|
+
DropdownMenuCheckboxItem,
|
|
492
|
+
DropdownMenuItem,
|
|
493
|
+
DropdownMenuLabel,
|
|
494
|
+
DropdownMenuSeparator,
|
|
495
|
+
DropdownMenuSub,
|
|
496
|
+
DropdownMenuSubContent,
|
|
497
|
+
DropdownMenuSubTrigger,
|
|
498
|
+
Tooltip,
|
|
499
|
+
TooltipContent,
|
|
500
|
+
TooltipTrigger
|
|
501
|
+
} from "@ai-matrx/design-system";
|
|
502
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
503
|
+
function NodeList({ nodes, engine }) {
|
|
504
|
+
return /* @__PURE__ */ jsx2(Fragment2, { children: nodes.map((node) => /* @__PURE__ */ jsx2(MenuNodeView, { node, engine }, node.id)) });
|
|
505
|
+
}
|
|
506
|
+
function SectionList({
|
|
507
|
+
sections,
|
|
508
|
+
engine
|
|
509
|
+
}) {
|
|
510
|
+
return /* @__PURE__ */ jsx2(Fragment2, { children: sections.map((section, index) => /* @__PURE__ */ jsxs(React3.Fragment, { children: [
|
|
511
|
+
index > 0 ? /* @__PURE__ */ jsx2(DropdownMenuSeparator, {}) : null,
|
|
512
|
+
sectionLabel(section) ? /* @__PURE__ */ jsx2(DropdownMenuLabel, { className: "text-xs font-medium text-muted-foreground", children: sectionLabel(section) }) : null,
|
|
513
|
+
/* @__PURE__ */ jsx2(NodeList, { nodes: section.nodes, engine })
|
|
514
|
+
] }, section.id)) });
|
|
515
|
+
}
|
|
516
|
+
function iconOf(node, engine) {
|
|
517
|
+
if (node.kind === "item" && node.stateIcon) {
|
|
518
|
+
const glyph = engine.icon(node.stateIcon.icon);
|
|
519
|
+
return node.stateIcon.spin ? /* @__PURE__ */ jsx2("span", { className: "inline-flex animate-spin", children: glyph }) : glyph;
|
|
520
|
+
}
|
|
521
|
+
if (!("icon" in node)) return null;
|
|
522
|
+
return engine.icon(node.icon, node.kind === "item" ? node.iconTone : void 0);
|
|
523
|
+
}
|
|
524
|
+
function MenuNodeView({ node, engine }) {
|
|
525
|
+
switch (node.kind) {
|
|
526
|
+
case "separator":
|
|
527
|
+
return /* @__PURE__ */ jsx2(DropdownMenuSeparator, {});
|
|
528
|
+
case "label":
|
|
529
|
+
return /* @__PURE__ */ jsx2(DropdownMenuLabel, { className: "text-xs font-medium text-muted-foreground", children: node.label });
|
|
530
|
+
case "submenu":
|
|
531
|
+
return /* @__PURE__ */ jsxs(
|
|
532
|
+
DropdownMenuSub,
|
|
533
|
+
{
|
|
534
|
+
onOpenChange: (open) => {
|
|
535
|
+
if (open && node.lazy && !node.loading) void engine.expand(node.id);
|
|
536
|
+
},
|
|
537
|
+
children: [
|
|
538
|
+
/* @__PURE__ */ jsxs(DropdownMenuSubTrigger, { "data-alchemy-node": node.id, className: "gap-2", children: [
|
|
539
|
+
iconOf(node, engine),
|
|
540
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: node.label })
|
|
541
|
+
] }),
|
|
542
|
+
/* @__PURE__ */ jsx2(DropdownMenuSubContent, { className: "max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto", children: node.loading ? /* @__PURE__ */ jsx2(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: "Loading\u2026" }) : node.children.length === 0 && !node.lazy ? /* @__PURE__ */ jsx2(DropdownMenuLabel, { className: "text-xs text-muted-foreground", children: node.emptyLabel ?? "Nothing here yet" }) : /* @__PURE__ */ jsx2(NodeList, { nodes: node.children, engine }) })
|
|
543
|
+
]
|
|
544
|
+
}
|
|
545
|
+
);
|
|
546
|
+
case "checkbox":
|
|
547
|
+
return /* @__PURE__ */ jsxs(
|
|
548
|
+
DropdownMenuCheckboxItem,
|
|
549
|
+
{
|
|
550
|
+
"data-alchemy-node": node.id,
|
|
551
|
+
checked: node.checked,
|
|
552
|
+
onSelect: () => void engine.run(node.id),
|
|
553
|
+
className: "gap-2",
|
|
554
|
+
children: [
|
|
555
|
+
iconOf(node, engine),
|
|
556
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: node.label })
|
|
557
|
+
]
|
|
558
|
+
}
|
|
559
|
+
);
|
|
560
|
+
case "link":
|
|
561
|
+
return /* @__PURE__ */ jsx2(DropdownMenuItem, { asChild: true, "data-alchemy-node": node.id, children: /* @__PURE__ */ jsxs("a", { href: node.href, target: node.target, className: "gap-2", children: [
|
|
562
|
+
iconOf(node, engine),
|
|
563
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: node.label })
|
|
564
|
+
] }) });
|
|
565
|
+
case "item":
|
|
566
|
+
return /* @__PURE__ */ jsx2(LeafItem, { node, engine });
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function LeafItem({ node, engine }) {
|
|
570
|
+
const row = /* @__PURE__ */ jsxs(
|
|
571
|
+
DropdownMenuItem,
|
|
572
|
+
{
|
|
573
|
+
"data-alchemy-node": node.id,
|
|
574
|
+
"aria-disabled": node.unavailable ? true : void 0,
|
|
575
|
+
"aria-pressed": node.pressed,
|
|
576
|
+
onSelect: (event) => {
|
|
577
|
+
if (node.unavailable) {
|
|
578
|
+
event.preventDefault();
|
|
579
|
+
return;
|
|
580
|
+
}
|
|
581
|
+
void engine.run(node.id);
|
|
582
|
+
},
|
|
583
|
+
className: `gap-2 ${node.unavailable ? "opacity-50" : ""} ${node.destructive ? "text-destructive" : ""}`,
|
|
584
|
+
children: [
|
|
585
|
+
iconOf(node, engine),
|
|
586
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
587
|
+
/* @__PURE__ */ jsx2("span", { className: "truncate", children: node.label }),
|
|
588
|
+
node.description ? /* @__PURE__ */ jsx2("span", { className: "truncate text-xs text-muted-foreground", children: node.description }) : null
|
|
589
|
+
] }),
|
|
590
|
+
node.hint ? /* @__PURE__ */ jsx2("span", { className: "ml-auto text-xs text-muted-foreground", children: node.hint }) : null
|
|
591
|
+
]
|
|
592
|
+
}
|
|
593
|
+
);
|
|
594
|
+
if (!node.unavailable) return row;
|
|
595
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
596
|
+
/* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: row }),
|
|
597
|
+
/* @__PURE__ */ jsx2(TooltipContent, { children: node.unavailable.sentence })
|
|
598
|
+
] });
|
|
599
|
+
}
|
|
600
|
+
function LeafButton({
|
|
601
|
+
node,
|
|
602
|
+
engine,
|
|
603
|
+
showLabel
|
|
604
|
+
}) {
|
|
605
|
+
if (node.kind !== "item" && node.kind !== "checkbox" && node.kind !== "link") return null;
|
|
606
|
+
const unavailable = node.kind === "item" ? node.unavailable : void 0;
|
|
607
|
+
const pressed = node.kind === "item" ? node.pressed : node.kind === "checkbox" ? node.checked : void 0;
|
|
608
|
+
const glyph = iconOf(node, engine);
|
|
609
|
+
const button = /* @__PURE__ */ jsxs(
|
|
610
|
+
"button",
|
|
611
|
+
{
|
|
612
|
+
type: "button",
|
|
613
|
+
"data-alchemy-node": node.id,
|
|
614
|
+
"aria-label": node.label,
|
|
615
|
+
"aria-disabled": unavailable ? true : void 0,
|
|
616
|
+
"aria-pressed": pressed,
|
|
617
|
+
onMouseDown: (e) => {
|
|
618
|
+
if (node.kind === "item" && node.preserveSelection) e.preventDefault();
|
|
619
|
+
},
|
|
620
|
+
onClick: () => {
|
|
621
|
+
if (unavailable) return;
|
|
622
|
+
if (node.kind === "link") {
|
|
623
|
+
window.location.assign(node.href);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
void engine.run(node.id);
|
|
627
|
+
},
|
|
628
|
+
className: `inline-flex h-7 min-w-7 items-center justify-center gap-1.5 rounded-md px-1.5 text-sm text-muted-foreground hover:bg-accent hover:text-foreground ${unavailable ? "cursor-default opacity-50 hover:bg-transparent" : ""} ${pressed ? "text-foreground" : ""}`,
|
|
629
|
+
children: [
|
|
630
|
+
glyph,
|
|
631
|
+
showLabel || !glyph ? /* @__PURE__ */ jsx2("span", { children: node.label }) : null
|
|
632
|
+
]
|
|
633
|
+
}
|
|
634
|
+
);
|
|
635
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
636
|
+
/* @__PURE__ */ jsx2(TooltipTrigger, { asChild: true, children: button }),
|
|
637
|
+
/* @__PURE__ */ jsx2(TooltipContent, { children: unavailable ? unavailable.sentence : node.label })
|
|
638
|
+
] });
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// src/react/menu.tsx
|
|
642
|
+
import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
643
|
+
function ContextMenuPanel({
|
|
644
|
+
target,
|
|
645
|
+
point,
|
|
646
|
+
open,
|
|
647
|
+
onOpenChange,
|
|
648
|
+
arrangement = "command",
|
|
649
|
+
density = "comfortable",
|
|
650
|
+
...options
|
|
651
|
+
}) {
|
|
652
|
+
const engine = useMenuEngine(target, { ...options, onRan: (id, r) => {
|
|
653
|
+
options.onRan?.(id, r);
|
|
654
|
+
onOpenChange(false);
|
|
655
|
+
} });
|
|
656
|
+
const [query, setQuery] = React4.useState("");
|
|
657
|
+
const arranged = engine.model ? context(engine.model, arrangement) : null;
|
|
658
|
+
const filtered = engine.model && query.trim() ? filterPalette(palette(engine.model), query) : null;
|
|
659
|
+
return /* @__PURE__ */ jsxs2(DropdownMenu, { open, onOpenChange, modal: false, children: [
|
|
660
|
+
/* @__PURE__ */ jsx3(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx3("span", { "aria-hidden": true, style: { position: "fixed", left: point.x, top: point.y, width: 0, height: 0 } }) }),
|
|
661
|
+
/* @__PURE__ */ jsx3(
|
|
662
|
+
DropdownMenuContent,
|
|
663
|
+
{
|
|
664
|
+
align: "start",
|
|
665
|
+
"data-alchemy-layout": `context-${arrangement}`,
|
|
666
|
+
onPointerUpCapture: (event) => {
|
|
667
|
+
if (event.button === 2) event.preventDefault();
|
|
668
|
+
},
|
|
669
|
+
className: `w-72 max-h-[var(--radix-dropdown-menu-content-available-height)] overflow-y-auto ${density === "compact" ? "text-xs" : ""}`,
|
|
670
|
+
children: /* @__PURE__ */ jsxs2(TooltipProvider, { children: [
|
|
671
|
+
engine.model?.header ? /* @__PURE__ */ jsxs2(DropdownMenuLabel2, { className: "truncate text-xs font-normal text-muted-foreground", title: engine.model.header.text, children: [
|
|
672
|
+
engine.model.header.label,
|
|
673
|
+
": ",
|
|
674
|
+
engine.model.header.text
|
|
675
|
+
] }) : null,
|
|
676
|
+
!arranged ? /* @__PURE__ */ jsx3("div", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: "Loading\u2026" }) : /* @__PURE__ */ jsxs2(Fragment3, { children: [
|
|
677
|
+
arranged.strip.length ? /* @__PURE__ */ jsx3("div", { role: "toolbar", "aria-label": "Clipboard", className: "flex items-center gap-0.5 px-1 py-1", children: arranged.strip.map((node) => /* @__PURE__ */ jsx3(LeafButton, { node, engine, showLabel: false }, node.id)) }) : null,
|
|
678
|
+
arranged.filterable ? /* @__PURE__ */ jsx3("div", { className: "px-1 pb-1", children: /* @__PURE__ */ jsx3(
|
|
679
|
+
"input",
|
|
680
|
+
{
|
|
681
|
+
"aria-label": "Filter actions",
|
|
682
|
+
placeholder: "Type to filter\u2026",
|
|
683
|
+
value: query,
|
|
684
|
+
onChange: (e) => setQuery(e.target.value),
|
|
685
|
+
onKeyDown: (e) => {
|
|
686
|
+
e.stopPropagation();
|
|
687
|
+
if (e.key === "Enter" && filtered?.leaves[0]) void engine.run(filtered.leaves[0].node.id);
|
|
688
|
+
},
|
|
689
|
+
className: "h-7 w-full rounded-md border border-border bg-transparent px-2 text-sm outline-none"
|
|
690
|
+
}
|
|
691
|
+
) }) : null,
|
|
692
|
+
(arranged.strip.length || arranged.filterable) && arranged.sections.length ? /* @__PURE__ */ jsx3(DropdownMenuSeparator2, {}) : null,
|
|
693
|
+
filtered ? filtered.leaves.length ? filtered.leaves.map(({ node, breadcrumb }) => /* @__PURE__ */ jsxs2(
|
|
694
|
+
DropdownMenuItem2,
|
|
695
|
+
{
|
|
696
|
+
"data-alchemy-node": node.id,
|
|
697
|
+
onSelect: () => {
|
|
698
|
+
if (node.kind === "submenu") void engine.expand(node.id);
|
|
699
|
+
else void engine.run(node.id);
|
|
700
|
+
},
|
|
701
|
+
className: "flex-col items-start gap-0",
|
|
702
|
+
children: [
|
|
703
|
+
/* @__PURE__ */ jsx3("span", { children: node.label }),
|
|
704
|
+
/* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: breadcrumb.join(" \u203A ") })
|
|
705
|
+
]
|
|
706
|
+
},
|
|
707
|
+
node.id
|
|
708
|
+
)) : /* @__PURE__ */ jsxs2("div", { className: "px-2 py-1.5 text-xs text-muted-foreground", children: [
|
|
709
|
+
"No action matches \u201C",
|
|
710
|
+
query,
|
|
711
|
+
"\u201D."
|
|
712
|
+
] }) : /* @__PURE__ */ jsx3(SectionList, { sections: arranged.sections, engine })
|
|
713
|
+
] })
|
|
714
|
+
] })
|
|
715
|
+
}
|
|
716
|
+
)
|
|
717
|
+
] });
|
|
718
|
+
}
|
|
719
|
+
export {
|
|
720
|
+
ContextMenuPanel
|
|
721
|
+
};
|
|
722
|
+
//# sourceMappingURL=react-menu.js.map
|