@ai-matrx/context-menu 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +14 -1
  3. package/dist/builder.cjs +1665 -0
  4. package/dist/builder.cjs.map +1 -0
  5. package/dist/builder.d.cts +22 -0
  6. package/dist/builder.d.ts +22 -0
  7. package/dist/builder.js +1650 -0
  8. package/dist/builder.js.map +1 -0
  9. package/dist/design-store.cjs +195 -0
  10. package/dist/design-store.cjs.map +1 -0
  11. package/dist/design-store.d.cts +42 -0
  12. package/dist/design-store.d.ts +42 -0
  13. package/dist/design-store.js +175 -0
  14. package/dist/design-store.js.map +1 -0
  15. package/dist/engine.cjs +3069 -0
  16. package/dist/engine.cjs.map +1 -0
  17. package/dist/engine.d.cts +731 -0
  18. package/dist/engine.d.ts +731 -0
  19. package/dist/engine.js +3250 -0
  20. package/dist/engine.js.map +1 -0
  21. package/dist/grouping-CB3zlD1T.d.ts +623 -0
  22. package/dist/grouping-CGcWsltu.d.cts +623 -0
  23. package/dist/host-types-AOiEYwR8.d.cts +9 -0
  24. package/dist/host-types-AOiEYwR8.d.ts +9 -0
  25. package/dist/index.cjs +486 -0
  26. package/dist/index.cjs.map +1 -0
  27. package/dist/index.d.cts +46 -0
  28. package/dist/index.d.ts +46 -0
  29. package/dist/index.js +464 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/menu-content.cjs +3146 -0
  32. package/dist/menu-content.cjs.map +1 -0
  33. package/dist/menu-content.d.cts +30 -0
  34. package/dist/menu-content.d.ts +30 -0
  35. package/dist/menu-content.js +3197 -0
  36. package/dist/menu-content.js.map +1 -0
  37. package/dist/model-BdF0TqZ3.d.cts +107 -0
  38. package/dist/model-BdF0TqZ3.d.ts +107 -0
  39. package/dist/react.cjs +3322 -0
  40. package/dist/react.cjs.map +1 -0
  41. package/dist/react.d.cts +133 -0
  42. package/dist/react.d.ts +133 -0
  43. package/dist/react.js +3345 -0
  44. package/dist/react.js.map +1 -0
  45. package/package.json +170 -1
package/dist/index.cjs ADDED
@@ -0,0 +1,486 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var src_exports = {};
23
+ __export(src_exports, {
24
+ CATALOG: () => CATALOG,
25
+ CATALOG_GROUPS: () => CATALOG_GROUPS,
26
+ DEFAULT_LOOK: () => DEFAULT_LOOK,
27
+ DESIGN_FORMAT: () => DESIGN_FORMAT,
28
+ MENU_SURFACES: () => MENU_SURFACES,
29
+ MenuPreview: () => MenuPreview,
30
+ TEMPLATES: () => TEMPLATES,
31
+ canMove: () => canMove,
32
+ catalogOption: () => catalogOption,
33
+ cloneNode: () => cloneNode,
34
+ contains: () => contains,
35
+ countItems: () => countItems,
36
+ duplicateNode: () => duplicateNode,
37
+ emptyDesign: () => emptyDesign,
38
+ insertNode: () => insertNode,
39
+ isContainer: () => isContainer,
40
+ locate: () => locate,
41
+ moveNode: () => moveNode,
42
+ newId: () => newId,
43
+ parseDesign: () => parseDesign,
44
+ removeNode: () => removeNode,
45
+ serializeDesign: () => serializeDesign,
46
+ unwrapNode: () => unwrapNode,
47
+ updateNode: () => updateNode,
48
+ wrapNode: () => wrapNode
49
+ });
50
+ module.exports = __toCommonJS(src_exports);
51
+
52
+ // src/design/model.ts
53
+ var MENU_SURFACES = [
54
+ "text-selection",
55
+ "editable-field",
56
+ "table-row",
57
+ "page",
58
+ "chat-message",
59
+ "file",
60
+ "anywhere"
61
+ ];
62
+ var DEFAULT_LOOK = {
63
+ density: "comfortable",
64
+ width: 280,
65
+ showIcons: true,
66
+ showShortcuts: true,
67
+ showHints: false,
68
+ search: false
69
+ };
70
+ var DESIGN_FORMAT = 1;
71
+ function newId(prefix = "n") {
72
+ const rnd = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID().slice(0, 8) : Math.random().toString(36).slice(2, 10);
73
+ return `${prefix}_${rnd}`;
74
+ }
75
+ function emptyDesign(name = "Untitled menu") {
76
+ return { designId: newId("d"), name, surface: "anywhere", look: { ...DEFAULT_LOOK }, nodes: [], notes: "" };
77
+ }
78
+ function isContainer(node) {
79
+ return node.kind === "section" || node.kind === "submenu";
80
+ }
81
+ function cloneNode(node) {
82
+ const copy = { ...node, id: newId(node.kind[0]) };
83
+ if (isContainer(copy)) copy.children = copy.children.map(cloneNode);
84
+ return copy;
85
+ }
86
+ function locate(nodes, id, parentId = null, depth = 0) {
87
+ for (let i = 0; i < nodes.length; i++) {
88
+ const node = nodes[i];
89
+ if (node.id === id) return { node, parentId, index: i, depth };
90
+ if (isContainer(node)) {
91
+ const inner = locate(node.children, id, node.id, depth + 1);
92
+ if (inner) return inner;
93
+ }
94
+ }
95
+ return null;
96
+ }
97
+ function contains(node, id) {
98
+ if (node.id === id) return true;
99
+ return isContainer(node) && node.children.some((c) => contains(c, id));
100
+ }
101
+ function countItems(nodes) {
102
+ let n = 0;
103
+ for (const node of nodes) {
104
+ if (node.kind === "item") n += 1;
105
+ else if (isContainer(node)) n += countItems(node.children) + (node.kind === "submenu" ? 1 : 0);
106
+ }
107
+ return n;
108
+ }
109
+ function mapChildren(nodes, parentId, fn) {
110
+ if (parentId === null) return fn([...nodes]);
111
+ return nodes.map((node) => {
112
+ if (!isContainer(node)) return node;
113
+ if (node.id === parentId) return { ...node, children: fn([...node.children]) };
114
+ return { ...node, children: mapChildren(node.children, parentId, fn) };
115
+ });
116
+ }
117
+ function insertNode(nodes, parentId, index, node) {
118
+ return mapChildren(nodes, parentId, (list) => {
119
+ list.splice(Math.max(0, Math.min(index, list.length)), 0, node);
120
+ return list;
121
+ });
122
+ }
123
+ function removeNode(nodes, id) {
124
+ return nodes.filter((n) => n.id !== id).map((n) => isContainer(n) ? { ...n, children: removeNode(n.children, id) } : n);
125
+ }
126
+ function updateNode(nodes, id, patch) {
127
+ return nodes.map((n) => {
128
+ if (n.id === id) return { ...n, ...patch, id: n.id, kind: n.kind };
129
+ if (isContainer(n)) return { ...n, children: updateNode(n.children, id, patch) };
130
+ return n;
131
+ });
132
+ }
133
+ function canMove(nodes, id, parentId) {
134
+ const from = locate(nodes, id);
135
+ return Boolean(from) && (parentId === null || !contains(from.node, parentId));
136
+ }
137
+ function moveNode(nodes, id, parentId, index) {
138
+ const from = locate(nodes, id);
139
+ if (!from) return nodes;
140
+ if (parentId !== null && contains(from.node, parentId)) return nodes;
141
+ let target = index;
142
+ if (from.parentId === parentId && from.index < index) target -= 1;
143
+ return insertNode(removeNode(nodes, id), parentId, target, from.node);
144
+ }
145
+ function duplicateNode(nodes, id) {
146
+ const at = locate(nodes, id);
147
+ if (!at) return [...nodes];
148
+ return insertNode(nodes, at.parentId, at.index + 1, cloneNode(at.node));
149
+ }
150
+ function wrapNode(nodes, id, kind) {
151
+ const at = locate(nodes, id);
152
+ if (!at) return [...nodes];
153
+ const wrapper = kind === "section" ? { id: newId("s"), kind: "section", label: "New section", children: [at.node] } : { id: newId("m"), kind: "submenu", label: "More", icon: "ChevronRight", children: [at.node] };
154
+ return insertNode(removeNode(nodes, id), at.parentId, at.index, wrapper);
155
+ }
156
+ function unwrapNode(nodes, id) {
157
+ const at = locate(nodes, id);
158
+ if (!at || !isContainer(at.node)) return [...nodes];
159
+ let out = removeNode(nodes, id);
160
+ at.node.children.forEach((child, i) => {
161
+ out = insertNode(out, at.parentId, at.index + i, child);
162
+ });
163
+ return out;
164
+ }
165
+ function parseDesign(raw) {
166
+ let value = raw;
167
+ if (typeof raw === "string") {
168
+ try {
169
+ value = JSON.parse(raw);
170
+ } catch {
171
+ return emptyDesign("Unreadable design");
172
+ }
173
+ }
174
+ const v = value ?? {};
175
+ const d = v.design ?? v;
176
+ return {
177
+ designId: typeof d.designId === "string" ? d.designId : newId("d"),
178
+ name: typeof d.name === "string" ? d.name : "Untitled menu",
179
+ surface: MENU_SURFACES.includes(d.surface) ? d.surface : "anywhere",
180
+ look: { ...DEFAULT_LOOK, ...d.look ?? {} },
181
+ nodes: Array.isArray(d.nodes) ? d.nodes : [],
182
+ notes: typeof d.notes === "string" ? d.notes : ""
183
+ };
184
+ }
185
+ function serializeDesign(design) {
186
+ return JSON.stringify({ format: DESIGN_FORMAT, design });
187
+ }
188
+
189
+ // src/design/catalog.ts
190
+ var o = (id, label, icon, group, extra = {}) => ({ id, label, icon, group, status: "live", ...extra });
191
+ var CATALOG = [
192
+ // Clipboard — the verb strip
193
+ o("cm:copy", "Copy", "Copy", "Clipboard", { shortcut: "\u2318C" }),
194
+ o("cm:cut", "Cut", "Scissors", "Clipboard", { shortcut: "\u2318X" }),
195
+ o("cm:paste", "Paste", "ClipboardPaste", "Clipboard", { shortcut: "\u2318V" }),
196
+ o("cm:undo", "Undo", "Undo2", "Clipboard", { shortcut: "\u2318Z" }),
197
+ o("cm:redo", "Redo", "Redo2", "Clipboard", { shortcut: "\u21E7\u2318Z" }),
198
+ o("cm:find", "Find & Replace", "Search", "Clipboard", { shortcut: "\u2318F" }),
199
+ o("cm:select-all", "Select All", "TextSelect", "Clipboard", { shortcut: "\u2318A" }),
200
+ o("cm:copy-as", "Copy as\u2026", "CopyPlus", "Clipboard"),
201
+ o("cm:json", "Copy as JSON", "Braces", "Clipboard"),
202
+ o("copy-html-page", "Copy as HTML page", "FileCode", "Clipboard"),
203
+ o("cm:insert-reference", "Insert / Copy reference\u2026", "AtSign", "Clipboard"),
204
+ // Edit
205
+ o("cm:save", "Save", "Save", "Edit", { shortcut: "\u2318S" }),
206
+ o("duplicate", "Duplicate", "CopyPlus", "Edit"),
207
+ o("rename", "Rename", "PenLine", "Edit"),
208
+ o("edit", "Edit", "Pencil", "Edit"),
209
+ o("favorite", "Add to favorites", "Star", "Edit"),
210
+ o("archive", "Archive", "Archive", "Edit", { danger: true }),
211
+ o("cm:delete", "Delete", "Trash2", "Edit", { danger: true }),
212
+ // AI
213
+ o("cm:chat", "Chat about this", "MessageSquare", "AI", { ai: true }),
214
+ o("cm:quick-actions", "Quick Actions", "Zap", "AI", { ai: true }),
215
+ o("cm:placement:ai-action", "AI Actions", "Sparkles", "AI", { ai: true }),
216
+ o("cm:placement:content-block", "Content blocks", "Blocks", "AI", { ai: true }),
217
+ o("cm:placement:organization-tool", "Org Items", "Building2", "AI", { ai: true }),
218
+ o("cm:placement:user-tool", "My Items", "User", "AI", { ai: true }),
219
+ o("cm:placement:quick-action", "Quick actions (placement)", "Zap", "AI", { ai: true }),
220
+ o("cm:placement:bound-agent", "Agents", "Bot", "AI", { ai: true }),
221
+ o("send-to-agent", "Send to agent\u2026", "Send", "AI", { ai: true }),
222
+ o("continue-in-chat", "Continue in chat", "MessagesSquare", "AI", { ai: true }),
223
+ o("regenerate-response", "Regenerate", "RefreshCw", "AI", { ai: true }),
224
+ o("code-block-chart", "Make a chart", "ChartColumn", "AI", { ai: true }),
225
+ o("ai-improve", "Improve writing", "Wand2", "AI", { ai: true, status: "proposed" }),
226
+ o("ai-summarize", "Summarize", "ListCollapse", "AI", { ai: true, status: "proposed" }),
227
+ o("ai-explain", "Explain", "Lightbulb", "AI", { ai: true, status: "proposed" }),
228
+ o("ai-translate", "Translate\u2026", "Languages", "AI", { ai: true, status: "proposed" }),
229
+ // Save & export
230
+ o("cm:export", "Export", "FileOutput", "Save & export"),
231
+ o("cm:convert", "Convert to\u2026", "ArrowRightLeft", "Save & export"),
232
+ o("save-as-file", "Save as file", "FileDown", "Save & export"),
233
+ o("download-pdf", "Download PDF", "FileText", "Save & export"),
234
+ o("download-docx", "Download Word", "FileType", "Save & export"),
235
+ o("download-html", "Download HTML", "FileCode2", "Save & export"),
236
+ o("print", "Print", "Printer", "Save & export", { shortcut: "\u2318P" }),
237
+ // Share & publish
238
+ o("cm:share", "Share\u2026", "Share2", "Share & publish"),
239
+ o("share-link", "Copy share link", "Link", "Share & publish"),
240
+ o("send-google-doc", "Send to Google Docs", "FileUp", "Share & publish"),
241
+ o("email-to-me", "Email to me", "Mail", "Share & publish"),
242
+ o("html-preview", "Preview as web page", "Eye", "Share & publish"),
243
+ o("share-webpage", "Publish as web page", "Globe", "Share & publish"),
244
+ // Organize
245
+ o("cm:attach", "Attach to\u2026", "Paperclip", "Organize"),
246
+ o("set-context-value", "Set as context", "Pin", "Organize"),
247
+ o("pin-message", "Pin", "Pin", "Organize"),
248
+ o("notes-and-comments", "Notes & comments", "StickyNote", "Organize"),
249
+ o("move", "Move to folder\u2026", "FolderInput", "Organize"),
250
+ o("tags", "Tags\u2026", "Tags", "Organize"),
251
+ // History & compare
252
+ o("cm:view-history", "View history", "History", "History & compare"),
253
+ o("edit-history", "Edit history", "GitCommitVertical", "History & compare"),
254
+ o("fork-at-message", "Fork from here", "GitBranch", "History & compare"),
255
+ o("cm:compare", "Compare\u2026", "GitCompareArrows", "History & compare"),
256
+ o("compare-with-clipboard", "Compare with clipboard", "ClipboardList", "History & compare"),
257
+ o("set-compare-base", "Set as compare base", "Flag", "History & compare"),
258
+ // Listen
259
+ o("cm:speak", "Read aloud", "Volume2", "Listen"),
260
+ o("cm:listen", "Dictate", "Mic", "Listen"),
261
+ o("tts-voice-settings", "Voice settings", "AudioLines", "Listen"),
262
+ // Page rows: notes
263
+ o("notes:close-tab", "Close tab", "X", "Page: notes"),
264
+ o("notes:close-others", "Close other tabs", "PanelTopClose", "Page: notes"),
265
+ o("notes:export-md", "Export as Markdown", "FileDown", "Page: notes"),
266
+ o("notes:share-clipboard", "Copy to clipboard", "ClipboardCopy", "Page: notes"),
267
+ o("notes:convert-artifacts", "Convert to artifacts", "Shapes", "Page: notes"),
268
+ o("notes:trash", "Move to Trash", "Trash2", "Page: notes", { danger: true }),
269
+ // Page rows: a record (quiz row, table row)
270
+ o("row:open", "Open", "SquareArrowOutUpRight", "Page: record"),
271
+ o("row:open-tab", "Open in new tab", "ExternalLink", "Page: record"),
272
+ o("row:take", "Take", "Play", "Page: record"),
273
+ o("row:results", "Results", "ChartBar", "Page: record"),
274
+ o("row:manage", "Manage", "Settings2", "Page: record"),
275
+ o("row:restore", "Restore", "ArchiveRestore", "Page: record"),
276
+ // Page rows: chat message
277
+ o("regenerate-latest", "Regenerate latest", "RotateCcw", "Page: chat message", { ai: true }),
278
+ o("fork-and-regenerate", "Fork and regenerate", "GitFork", "Page: chat message", { ai: true }),
279
+ o("feedback-up", "Good response", "ThumbsUp", "Page: chat message"),
280
+ o("feedback-down", "Bad response", "ThumbsDown", "Page: chat message"),
281
+ // Tools & admin
282
+ o("cm:x:surface", "This page (location, context, agents)", "MapPin", "Tools & admin"),
283
+ o("cm:admin", "Admin tools", "Shield", "Tools & admin"),
284
+ o("feedback", "Send feedback", "MessageSquareWarning", "Tools & admin"),
285
+ o("keyboard-shortcuts", "Keyboard shortcuts", "Keyboard", "Tools & admin", { status: "proposed" })
286
+ ];
287
+ var CATALOG_GROUPS = [...new Set(CATALOG.map((c) => c.group))];
288
+ function catalogOption(id) {
289
+ return CATALOG.find((c) => c.id === id);
290
+ }
291
+ var seq = 0;
292
+ var tid = (p) => `${p}_t${Date.now().toString(36)}${(seq++).toString(36)}`;
293
+ function itemFrom(id) {
294
+ const c = catalogOption(id);
295
+ return {
296
+ id: tid("i"),
297
+ kind: "item",
298
+ catalogId: id,
299
+ label: c?.label ?? id,
300
+ icon: c?.icon ?? "Circle",
301
+ ...c?.shortcut ? { shortcut: c.shortcut } : {},
302
+ ...c?.danger ? { danger: true } : {},
303
+ ...c?.ai ? { ai: true } : {}
304
+ };
305
+ }
306
+ var strip = (label, ids) => ({
307
+ id: tid("s"),
308
+ kind: "section",
309
+ label,
310
+ layout: "row",
311
+ children: ids.map(itemFrom)
312
+ });
313
+ var sub = (label, icon, ids) => ({
314
+ id: tid("m"),
315
+ kind: "submenu",
316
+ label,
317
+ icon,
318
+ children: ids.map(itemFrom)
319
+ });
320
+ var TEMPLATES = [
321
+ { id: "strip-thing", label: "Icon strip \u2014 a thing", icon: "Rows2", build: () => strip("", ["cm:copy", "cm:share", "duplicate", "favorite", "save-as-file", "archive"]) },
322
+ { id: "strip-edit", label: "Icon strip \u2014 editable text", icon: "Rows2", build: () => strip("", ["cm:cut", "cm:copy", "cm:paste", "cm:undo", "cm:redo", "cm:find"]) },
323
+ { id: "strip-read", label: "Icon strip \u2014 read-only text", icon: "Rows2", build: () => strip("", ["cm:copy", "cm:speak", "cm:find", "cm:share"]) },
324
+ { id: "sub-intelligence", label: "Intelligence \u25B8", icon: "Sparkles", build: () => sub("Intelligence", "Sparkles", ["cm:chat", "cm:placement:ai-action", "cm:placement:bound-agent", "send-to-agent"]) },
325
+ { id: "sub-save-share", label: "Save & share \u25B8", icon: "Share2", build: () => sub("Save & share", "Share2", ["cm:copy-as", "save-as-file", "cm:convert", "share-webpage", "cm:share"]) },
326
+ { id: "sub-organize", label: "Organize \u25B8", icon: "Tags", build: () => sub("Organize", "Tags", ["cm:attach", "pin-message", "cm:view-history", "cm:compare"]) },
327
+ { id: "sub-tools", label: "Tools \u25B8", icon: "Wrench", build: () => sub("Tools", "Wrench", ["cm:speak", "cm:quick-actions", "feedback", "cm:x:surface", "cm:admin"]) }
328
+ ];
329
+
330
+ // src/design/MenuPreview.tsx
331
+ var import_react = require("react");
332
+ var import_jsx_runtime = require("react/jsx-runtime");
333
+ function matches(node, q) {
334
+ if (!q) return true;
335
+ if (node.kind === "divider") return false;
336
+ if (node.kind === "item") return node.label.toLowerCase().includes(q);
337
+ return node.label.toLowerCase().includes(q) || node.children.some((c) => matches(c, q));
338
+ }
339
+ function flatten(nodes, q, out = []) {
340
+ for (const n of nodes) {
341
+ if (n.kind === "item" && matches(n, q)) out.push(n);
342
+ else if (isContainer(n)) flatten(n.children, q, out);
343
+ }
344
+ return out;
345
+ }
346
+ function MenuPreview({ design, renderIcon, highlightId, onSelectNode, onPick, className, style }) {
347
+ const [query, setQuery] = (0, import_react.useState)("");
348
+ const q = query.trim().toLowerCase();
349
+ const { look } = design;
350
+ const results = (0, import_react.useMemo)(() => q ? flatten(design.nodes, q) : null, [design.nodes, q]);
351
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
352
+ "div",
353
+ {
354
+ role: "menu",
355
+ "data-density": look.density,
356
+ className: `cm-menu ${className ?? ""}`,
357
+ style: { width: look.width, ...style },
358
+ children: [
359
+ look.search && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cm-search", children: [
360
+ renderIcon("Search", "cm-icon"),
361
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("input", { value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Type to filter\u2026", "aria-label": "Filter menu" })
362
+ ] }),
363
+ results ? results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "No matches" }) : results.map((n) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Item, { node: n, ctx: { design, renderIcon, highlightId, onSelectNode, onPick } }, n.id)) : design.nodes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "Empty menu \u2014 drag options in" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: design.nodes, ctx: { design, renderIcon, highlightId, onSelectNode, onPick } })
364
+ ]
365
+ }
366
+ );
367
+ }
368
+ function Nodes({ nodes, ctx }) {
369
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: nodes.map((n) => {
370
+ if (n.kind === "divider") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "separator", className: "cm-divider" }, n.id);
371
+ if (n.kind === "item") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Item, { node: n, ctx }, n.id);
372
+ if (n.kind === "submenu") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Submenu, { node: n, ctx }, n.id);
373
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { node: n, ctx }, n.id);
374
+ }) });
375
+ }
376
+ function Section({ node, ctx }) {
377
+ const [open, setOpen] = (0, import_react.useState)(!node.collapsible);
378
+ const layout = node.layout ?? "list";
379
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `cm-section ${ctx.highlightId === node.id ? "cm-hl" : ""}`, "data-layout": layout, children: [
380
+ node.label && // ui-exception: a menu row of the menu component itself
381
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
382
+ "button",
383
+ {
384
+ type: "button",
385
+ className: "cm-section-label",
386
+ onClick: () => {
387
+ ctx.onSelectNode?.(node.id);
388
+ if (node.collapsible) setOpen((o2) => !o2);
389
+ },
390
+ children: [
391
+ node.label,
392
+ node.collapsible && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-caret", children: open ? "\u25BE" : "\u25B8" })
393
+ ]
394
+ }
395
+ ),
396
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-section-body", children: layout === "list" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: node.children, ctx }) : node.children.map(
397
+ (c) => c.kind === "item" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tile, { node: c, ctx }, c.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: [c], ctx }, c.id)
398
+ ) })
399
+ ] });
400
+ }
401
+ function Tile({ node, ctx }) {
402
+ return (
403
+ // ui-exception: a menu row of the menu component itself
404
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
405
+ "button",
406
+ {
407
+ type: "button",
408
+ role: "menuitem",
409
+ title: node.label + (node.shortcut ? ` ${node.shortcut}` : ""),
410
+ disabled: node.disabled,
411
+ className: `cm-tile ${node.danger ? "cm-danger" : ""} ${node.ai ? "cm-ai" : ""} ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
412
+ onClick: () => {
413
+ ctx.onSelectNode?.(node.id);
414
+ ctx.onPick?.(node);
415
+ },
416
+ children: ctx.renderIcon(node.icon ?? "Circle", "cm-icon")
417
+ }
418
+ )
419
+ );
420
+ }
421
+ function Item({ node, ctx }) {
422
+ const { look } = ctx.design;
423
+ const [checked, setChecked] = (0, import_react.useState)(false);
424
+ return (
425
+ // ui-exception: a menu row of the menu component itself
426
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
427
+ "button",
428
+ {
429
+ type: "button",
430
+ role: node.toggle ? "menuitemcheckbox" : "menuitem",
431
+ "aria-checked": node.toggle ? checked : void 0,
432
+ disabled: node.disabled,
433
+ className: `cm-item ${node.danger ? "cm-danger" : ""} ${node.ai ? "cm-ai" : ""} ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
434
+ onClick: () => {
435
+ ctx.onSelectNode?.(node.id);
436
+ if (node.toggle) setChecked((c) => !c);
437
+ ctx.onPick?.(node);
438
+ },
439
+ children: [
440
+ look.showIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-icon-slot", children: node.toggle ? checked ? ctx.renderIcon("Check", "cm-icon") : null : node.icon ? ctx.renderIcon(node.icon, "cm-icon") : null }),
441
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cm-text", children: [
442
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children: node.label }),
443
+ look.showHints && node.hint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-hint", children: node.hint })
444
+ ] }),
445
+ look.showShortcuts && node.shortcut && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("kbd", { className: "cm-shortcut", children: node.shortcut })
446
+ ]
447
+ }
448
+ )
449
+ );
450
+ }
451
+ function Submenu({ node, ctx }) {
452
+ const { look } = ctx.design;
453
+ const [open, setOpen] = (0, import_react.useState)(false);
454
+ const [side, setSide] = (0, import_react.useState)("right");
455
+ const show = (el) => {
456
+ const r = el.getBoundingClientRect();
457
+ setSide(r.right + look.width + 8 > window.innerWidth ? "left" : "right");
458
+ setOpen(true);
459
+ };
460
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cm-sub", onMouseEnter: (e) => show(e.currentTarget), onMouseLeave: () => setOpen(false), children: [
461
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
462
+ "button",
463
+ {
464
+ type: "button",
465
+ role: "menuitem",
466
+ "aria-haspopup": "menu",
467
+ "aria-expanded": open,
468
+ className: `cm-item ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
469
+ onClick: () => {
470
+ ctx.onSelectNode?.(node.id);
471
+ setOpen(true);
472
+ },
473
+ children: [
474
+ look.showIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-icon-slot", children: node.icon ? ctx.renderIcon(node.icon, "cm-icon") : null }),
475
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cm-text", children: [
476
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children: node.label }),
477
+ look.showHints && node.hint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-hint", children: node.hint })
478
+ ] }),
479
+ ctx.renderIcon("ChevronRight", "cm-icon cm-chev")
480
+ ]
481
+ }
482
+ ),
483
+ open && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "menu", className: "cm-menu cm-flyout", "data-side": side, "data-density": look.density, style: { width: look.width }, children: node.children.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "Empty submenu" }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: node.children, ctx }) })
484
+ ] });
485
+ }
486
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/design/model.ts","../src/design/catalog.ts","../src/design/MenuPreview.tsx"],"sourcesContent":["// @ai-matrx/context-menu — the menu design model, the option catalog, and the menu renderer.\n// The live context menu engine is moving here from matrx-frontend (features/context-menu-v3).\nexport * from \"./design/model\";\nexport * from \"./design/catalog\";\nexport { MenuPreview, type MenuPreviewProps } from \"./design/MenuPreview\";\n","// src/design/model.ts — @ai-matrx/context-menu: THE MENU DESIGN.\n//\n// A design is the whole menu a person drew in the builder: an ordered tree of items, sections,\n// submenus and dividers, plus the few presentation choices that change how it reads. It is plain\n// JSON (no functions, no React) so it saves as one record, travels in a URL or a chat, and is the\n// exact thing the real menu is later built from. Every edit is a pure function returning a new\n// design; nothing here mutates.\n\nexport type MenuNodeKind = \"item\" | \"section\" | \"submenu\" | \"divider\";\n\ninterface NodeBase {\n /** Stable within the design. */\n id: string;\n /** The catalog option this was dragged from, when it came from one. */\n catalogId?: string;\n /** A designer's note on this one entry (\"only on a table row\", \"merge with Copy\"). */\n note?: string;\n}\n\nexport interface MenuItemNode extends NodeBase {\n kind: \"item\";\n label: string;\n /** A lucide icon name (`Sparkles`, `Copy`). */\n icon?: string;\n /** Shown right-aligned (`⌘C`). */\n shortcut?: string;\n /** One short line under the label. */\n hint?: string;\n /** Shown greyed out — the design says \"this exists here but is unavailable now\". */\n disabled?: boolean;\n /** Red, for actions that remove or discard. */\n danger?: boolean;\n /** A checkbox-style toggle item. */\n toggle?: boolean;\n /** Drawn as a highlighted, AI-flavoured item. */\n ai?: boolean;\n}\n\nexport interface MenuSectionNode extends NodeBase {\n kind: \"section\";\n /** The small heading. Empty = an unlabelled group. */\n label: string;\n children: MenuNode[];\n /** Starts folded; a click on the heading opens it. */\n collapsible?: boolean;\n /** How the section's items are laid out. */\n layout?: \"list\" | \"grid\" | \"row\";\n}\n\nexport interface MenuSubmenuNode extends NodeBase {\n kind: \"submenu\";\n label: string;\n icon?: string;\n hint?: string;\n children: MenuNode[];\n}\n\nexport interface MenuDividerNode extends NodeBase {\n kind: \"divider\";\n}\n\nexport type MenuNode = MenuItemNode | MenuSectionNode | MenuSubmenuNode | MenuDividerNode;\nexport type MenuContainerNode = MenuSectionNode | MenuSubmenuNode;\n\n/** Where the menu opens; the builder previews each the way it appears there. */\nexport const MENU_SURFACES = [\n \"text-selection\",\n \"editable-field\",\n \"table-row\",\n \"page\",\n \"chat-message\",\n \"file\",\n \"anywhere\",\n] as const;\nexport type MenuSurface = (typeof MENU_SURFACES)[number];\n\nexport interface MenuLook {\n density: \"compact\" | \"comfortable\";\n width: number;\n showIcons: boolean;\n showShortcuts: boolean;\n showHints: boolean;\n /** A search box at the top of the menu. */\n search: boolean;\n}\n\nexport const DEFAULT_LOOK: MenuLook = {\n density: \"comfortable\",\n width: 280,\n showIcons: true,\n showShortcuts: true,\n showHints: false,\n search: false,\n};\n\nexport interface MenuDesign {\n /** The design's identity; every version shares it. */\n designId: string;\n name: string;\n surface: MenuSurface;\n look: MenuLook;\n nodes: MenuNode[];\n /** Free notes for whoever builds it. */\n notes: string;\n}\n\nexport const DESIGN_FORMAT = 1;\n\n// ── ids ──────────────────────────────────────────────────────────────────────\n\nexport function newId(prefix = \"n\"): string {\n const rnd =\n typeof crypto !== \"undefined\" && \"randomUUID\" in crypto\n ? crypto.randomUUID().slice(0, 8)\n : Math.random().toString(36).slice(2, 10);\n return `${prefix}_${rnd}`;\n}\n\nexport function emptyDesign(name = \"Untitled menu\"): MenuDesign {\n return { designId: newId(\"d\"), name, surface: \"anywhere\", look: { ...DEFAULT_LOOK }, nodes: [], notes: \"\" };\n}\n\nexport function isContainer(node: MenuNode): node is MenuContainerNode {\n return node.kind === \"section\" || node.kind === \"submenu\";\n}\n\n/** A deep copy with every id renewed — what a duplicate or a second drop of a template gets. */\nexport function cloneNode<N extends MenuNode>(node: N): N {\n const copy = { ...node, id: newId(node.kind[0]) } as N;\n if (isContainer(copy)) (copy as MenuContainerNode).children = (copy as MenuContainerNode).children.map(cloneNode);\n return copy;\n}\n\n// ── reading the tree ─────────────────────────────────────────────────────────\n\nexport interface Located {\n node: MenuNode;\n /** The container's id, or null at the top. */\n parentId: string | null;\n index: number;\n depth: number;\n}\n\nexport function locate(nodes: readonly MenuNode[], id: string, parentId: string | null = null, depth = 0): Located | null {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i] as MenuNode;\n if (node.id === id) return { node, parentId, index: i, depth };\n if (isContainer(node)) {\n const inner = locate(node.children, id, node.id, depth + 1);\n if (inner) return inner;\n }\n }\n return null;\n}\n\nexport function contains(node: MenuNode, id: string): boolean {\n if (node.id === id) return true;\n return isContainer(node) && node.children.some((c) => contains(c, id));\n}\n\nexport function countItems(nodes: readonly MenuNode[]): number {\n let n = 0;\n for (const node of nodes) {\n if (node.kind === \"item\") n += 1;\n else if (isContainer(node)) n += countItems(node.children) + (node.kind === \"submenu\" ? 1 : 0);\n }\n return n;\n}\n\n// ── editing the tree (pure) ──────────────────────────────────────────────────\n\nfunction mapChildren(nodes: readonly MenuNode[], parentId: string | null, fn: (list: MenuNode[]) => MenuNode[]): MenuNode[] {\n if (parentId === null) return fn([...nodes]);\n return nodes.map((node) => {\n if (!isContainer(node)) return node;\n if (node.id === parentId) return { ...node, children: fn([...node.children]) };\n return { ...node, children: mapChildren(node.children, parentId, fn) };\n });\n}\n\nexport function insertNode(nodes: readonly MenuNode[], parentId: string | null, index: number, node: MenuNode): MenuNode[] {\n return mapChildren(nodes, parentId, (list) => {\n list.splice(Math.max(0, Math.min(index, list.length)), 0, node);\n return list;\n });\n}\n\nexport function removeNode(nodes: readonly MenuNode[], id: string): MenuNode[] {\n return nodes\n .filter((n) => n.id !== id)\n .map((n) => (isContainer(n) ? { ...n, children: removeNode(n.children, id) } : n));\n}\n\nexport function updateNode(nodes: readonly MenuNode[], id: string, patch: Partial<MenuNode>): MenuNode[] {\n return nodes.map((n) => {\n if (n.id === id) return { ...n, ...patch, id: n.id, kind: n.kind } as MenuNode;\n if (isContainer(n)) return { ...n, children: updateNode(n.children, id, patch) };\n return n;\n });\n}\n\n/**\n * Move `id` to `index` inside `parentId`. Refuses (returns the tree unchanged) a move into itself\n * or its own descendant. `index` is in the destination list as it reads BEFORE the move.\n */\nexport function canMove(nodes: readonly MenuNode[], id: string, parentId: string | null): boolean {\n const from = locate(nodes, id);\n return Boolean(from) && (parentId === null || !contains((from as Located).node, parentId));\n}\n\nexport function moveNode(nodes: readonly MenuNode[], id: string, parentId: string | null, index: number): MenuNode[] {\n const from = locate(nodes, id);\n // A refused move answers the SAME array, so a caller can tell \"nothing happened\" by identity.\n if (!from) return nodes as MenuNode[];\n if (parentId !== null && contains(from.node, parentId)) return nodes as MenuNode[];\n let target = index;\n if (from.parentId === parentId && from.index < index) target -= 1;\n return insertNode(removeNode(nodes, id), parentId, target, from.node);\n}\n\nexport function duplicateNode(nodes: readonly MenuNode[], id: string): MenuNode[] {\n const at = locate(nodes, id);\n if (!at) return [...nodes];\n return insertNode(nodes, at.parentId, at.index + 1, cloneNode(at.node));\n}\n\n/** Wrap a node into a new section (or submenu) in its place. */\nexport function wrapNode(nodes: readonly MenuNode[], id: string, kind: \"section\" | \"submenu\"): MenuNode[] {\n const at = locate(nodes, id);\n if (!at) return [...nodes];\n const wrapper: MenuContainerNode =\n kind === \"section\"\n ? { id: newId(\"s\"), kind: \"section\", label: \"New section\", children: [at.node] }\n : { id: newId(\"m\"), kind: \"submenu\", label: \"More\", icon: \"ChevronRight\", children: [at.node] };\n return insertNode(removeNode(nodes, id), at.parentId, at.index, wrapper);\n}\n\n/** Replace a container by its children. */\nexport function unwrapNode(nodes: readonly MenuNode[], id: string): MenuNode[] {\n const at = locate(nodes, id);\n if (!at || !isContainer(at.node)) return [...nodes];\n let out = removeNode(nodes, id);\n at.node.children.forEach((child, i) => {\n out = insertNode(out, at.parentId, at.index + i, child);\n });\n return out;\n}\n\n// ── reading a saved design defensively ──────────────────────────────────────\n\n/** A saved document back into a design; anything unreadable becomes an empty design, never a throw. */\nexport function parseDesign(raw: unknown): MenuDesign {\n let value: unknown = raw;\n if (typeof raw === \"string\") {\n try {\n value = JSON.parse(raw);\n } catch {\n return emptyDesign(\"Unreadable design\");\n }\n }\n const v = (value ?? {}) as Partial<MenuDesign> & { design?: MenuDesign };\n const d = v.design ?? v;\n return {\n designId: typeof d.designId === \"string\" ? d.designId : newId(\"d\"),\n name: typeof d.name === \"string\" ? d.name : \"Untitled menu\",\n surface: MENU_SURFACES.includes(d.surface as MenuSurface) ? (d.surface as MenuSurface) : \"anywhere\",\n look: { ...DEFAULT_LOOK, ...(d.look ?? {}) },\n nodes: Array.isArray(d.nodes) ? (d.nodes as MenuNode[]) : [],\n notes: typeof d.notes === \"string\" ? d.notes : \"\",\n };\n}\n\nexport function serializeDesign(design: MenuDesign): string {\n return JSON.stringify({ format: DESIGN_FORMAT, design });\n}\n","// src/design/catalog.ts — @ai-matrx/context-menu: EVERY OPTION A MENU CAN OFFER, as a palette.\n//\n// The builder's left column. Each entry is something the live menu shows somewhere today, taken\n// from the real menu's own lists in matrx-frontend (features/context-menu-v3):\n// - regroup/engine-rows.ts → the engine rows (`cm:*`)\n// - regroup/proposed-grouping.ts → the 13 \"grouped by what you get\" groups and their rules\n// - proposed/proposed-arrangement.ts → the three icon strips and the object-first submenus\n// - the page rows the demos show (notes, quiz row, table row, chat message)\n// Ids are the live menu's ids wherever one exists, so a saved design names the real row.\n// When the menu source moves into this package, this list is generated from it instead.\n\nimport type { MenuNode } from \"./model\";\n\nexport type CatalogGroup =\n | \"Clipboard\"\n | \"Edit\"\n | \"AI\"\n | \"Save & export\"\n | \"Share & publish\"\n | \"Organize\"\n | \"History & compare\"\n | \"Listen\"\n | \"Page: notes\"\n | \"Page: record\"\n | \"Page: chat message\"\n | \"Tools & admin\";\n\nexport interface CatalogOption {\n /** The live menu's id where one exists (`cm:copy`), else this catalog's own. */\n id: string;\n label: string;\n icon: string;\n group: CatalogGroup;\n shortcut?: string;\n hint?: string;\n danger?: boolean;\n ai?: boolean;\n /** \"Live\" = drawn by today's menu; \"Proposed\" = only in a proposal page so far. */\n status: \"live\" | \"proposed\";\n}\n\nconst o = (\n id: string,\n label: string,\n icon: string,\n group: CatalogGroup,\n extra: Partial<Omit<CatalogOption, \"id\" | \"label\" | \"icon\" | \"group\">> = {},\n): CatalogOption => ({ id, label, icon, group, status: \"live\", ...extra });\n\nexport const CATALOG: readonly CatalogOption[] = [\n // Clipboard — the verb strip\n o(\"cm:copy\", \"Copy\", \"Copy\", \"Clipboard\", { shortcut: \"⌘C\" }),\n o(\"cm:cut\", \"Cut\", \"Scissors\", \"Clipboard\", { shortcut: \"⌘X\" }),\n o(\"cm:paste\", \"Paste\", \"ClipboardPaste\", \"Clipboard\", { shortcut: \"⌘V\" }),\n o(\"cm:undo\", \"Undo\", \"Undo2\", \"Clipboard\", { shortcut: \"⌘Z\" }),\n o(\"cm:redo\", \"Redo\", \"Redo2\", \"Clipboard\", { shortcut: \"⇧⌘Z\" }),\n o(\"cm:find\", \"Find & Replace\", \"Search\", \"Clipboard\", { shortcut: \"⌘F\" }),\n o(\"cm:select-all\", \"Select All\", \"TextSelect\", \"Clipboard\", { shortcut: \"⌘A\" }),\n o(\"cm:copy-as\", \"Copy as…\", \"CopyPlus\", \"Clipboard\"),\n o(\"cm:json\", \"Copy as JSON\", \"Braces\", \"Clipboard\"),\n o(\"copy-html-page\", \"Copy as HTML page\", \"FileCode\", \"Clipboard\"),\n o(\"cm:insert-reference\", \"Insert / Copy reference…\", \"AtSign\", \"Clipboard\"),\n\n // Edit\n o(\"cm:save\", \"Save\", \"Save\", \"Edit\", { shortcut: \"⌘S\" }),\n o(\"duplicate\", \"Duplicate\", \"CopyPlus\", \"Edit\"),\n o(\"rename\", \"Rename\", \"PenLine\", \"Edit\"),\n o(\"edit\", \"Edit\", \"Pencil\", \"Edit\"),\n o(\"favorite\", \"Add to favorites\", \"Star\", \"Edit\"),\n o(\"archive\", \"Archive\", \"Archive\", \"Edit\", { danger: true }),\n o(\"cm:delete\", \"Delete\", \"Trash2\", \"Edit\", { danger: true }),\n\n // AI\n o(\"cm:chat\", \"Chat about this\", \"MessageSquare\", \"AI\", { ai: true }),\n o(\"cm:quick-actions\", \"Quick Actions\", \"Zap\", \"AI\", { ai: true }),\n o(\"cm:placement:ai-action\", \"AI Actions\", \"Sparkles\", \"AI\", { ai: true }),\n o(\"cm:placement:content-block\", \"Content blocks\", \"Blocks\", \"AI\", { ai: true }),\n o(\"cm:placement:organization-tool\", \"Org Items\", \"Building2\", \"AI\", { ai: true }),\n o(\"cm:placement:user-tool\", \"My Items\", \"User\", \"AI\", { ai: true }),\n o(\"cm:placement:quick-action\", \"Quick actions (placement)\", \"Zap\", \"AI\", { ai: true }),\n o(\"cm:placement:bound-agent\", \"Agents\", \"Bot\", \"AI\", { ai: true }),\n o(\"send-to-agent\", \"Send to agent…\", \"Send\", \"AI\", { ai: true }),\n o(\"continue-in-chat\", \"Continue in chat\", \"MessagesSquare\", \"AI\", { ai: true }),\n o(\"regenerate-response\", \"Regenerate\", \"RefreshCw\", \"AI\", { ai: true }),\n o(\"code-block-chart\", \"Make a chart\", \"ChartColumn\", \"AI\", { ai: true }),\n o(\"ai-improve\", \"Improve writing\", \"Wand2\", \"AI\", { ai: true, status: \"proposed\" }),\n o(\"ai-summarize\", \"Summarize\", \"ListCollapse\", \"AI\", { ai: true, status: \"proposed\" }),\n o(\"ai-explain\", \"Explain\", \"Lightbulb\", \"AI\", { ai: true, status: \"proposed\" }),\n o(\"ai-translate\", \"Translate…\", \"Languages\", \"AI\", { ai: true, status: \"proposed\" }),\n\n // Save & export\n o(\"cm:export\", \"Export\", \"FileOutput\", \"Save & export\"),\n o(\"cm:convert\", \"Convert to…\", \"ArrowRightLeft\", \"Save & export\"),\n o(\"save-as-file\", \"Save as file\", \"FileDown\", \"Save & export\"),\n o(\"download-pdf\", \"Download PDF\", \"FileText\", \"Save & export\"),\n o(\"download-docx\", \"Download Word\", \"FileType\", \"Save & export\"),\n o(\"download-html\", \"Download HTML\", \"FileCode2\", \"Save & export\"),\n o(\"print\", \"Print\", \"Printer\", \"Save & export\", { shortcut: \"⌘P\" }),\n\n // Share & publish\n o(\"cm:share\", \"Share…\", \"Share2\", \"Share & publish\"),\n o(\"share-link\", \"Copy share link\", \"Link\", \"Share & publish\"),\n o(\"send-google-doc\", \"Send to Google Docs\", \"FileUp\", \"Share & publish\"),\n o(\"email-to-me\", \"Email to me\", \"Mail\", \"Share & publish\"),\n o(\"html-preview\", \"Preview as web page\", \"Eye\", \"Share & publish\"),\n o(\"share-webpage\", \"Publish as web page\", \"Globe\", \"Share & publish\"),\n\n // Organize\n o(\"cm:attach\", \"Attach to…\", \"Paperclip\", \"Organize\"),\n o(\"set-context-value\", \"Set as context\", \"Pin\", \"Organize\"),\n o(\"pin-message\", \"Pin\", \"Pin\", \"Organize\"),\n o(\"notes-and-comments\", \"Notes & comments\", \"StickyNote\", \"Organize\"),\n o(\"move\", \"Move to folder…\", \"FolderInput\", \"Organize\"),\n o(\"tags\", \"Tags…\", \"Tags\", \"Organize\"),\n\n // History & compare\n o(\"cm:view-history\", \"View history\", \"History\", \"History & compare\"),\n o(\"edit-history\", \"Edit history\", \"GitCommitVertical\", \"History & compare\"),\n o(\"fork-at-message\", \"Fork from here\", \"GitBranch\", \"History & compare\"),\n o(\"cm:compare\", \"Compare…\", \"GitCompareArrows\", \"History & compare\"),\n o(\"compare-with-clipboard\", \"Compare with clipboard\", \"ClipboardList\", \"History & compare\"),\n o(\"set-compare-base\", \"Set as compare base\", \"Flag\", \"History & compare\"),\n\n // Listen\n o(\"cm:speak\", \"Read aloud\", \"Volume2\", \"Listen\"),\n o(\"cm:listen\", \"Dictate\", \"Mic\", \"Listen\"),\n o(\"tts-voice-settings\", \"Voice settings\", \"AudioLines\", \"Listen\"),\n\n // Page rows: notes\n o(\"notes:close-tab\", \"Close tab\", \"X\", \"Page: notes\"),\n o(\"notes:close-others\", \"Close other tabs\", \"PanelTopClose\", \"Page: notes\"),\n o(\"notes:export-md\", \"Export as Markdown\", \"FileDown\", \"Page: notes\"),\n o(\"notes:share-clipboard\", \"Copy to clipboard\", \"ClipboardCopy\", \"Page: notes\"),\n o(\"notes:convert-artifacts\", \"Convert to artifacts\", \"Shapes\", \"Page: notes\"),\n o(\"notes:trash\", \"Move to Trash\", \"Trash2\", \"Page: notes\", { danger: true }),\n\n // Page rows: a record (quiz row, table row)\n o(\"row:open\", \"Open\", \"SquareArrowOutUpRight\", \"Page: record\"),\n o(\"row:open-tab\", \"Open in new tab\", \"ExternalLink\", \"Page: record\"),\n o(\"row:take\", \"Take\", \"Play\", \"Page: record\"),\n o(\"row:results\", \"Results\", \"ChartBar\", \"Page: record\"),\n o(\"row:manage\", \"Manage\", \"Settings2\", \"Page: record\"),\n o(\"row:restore\", \"Restore\", \"ArchiveRestore\", \"Page: record\"),\n\n // Page rows: chat message\n o(\"regenerate-latest\", \"Regenerate latest\", \"RotateCcw\", \"Page: chat message\", { ai: true }),\n o(\"fork-and-regenerate\", \"Fork and regenerate\", \"GitFork\", \"Page: chat message\", { ai: true }),\n o(\"feedback-up\", \"Good response\", \"ThumbsUp\", \"Page: chat message\"),\n o(\"feedback-down\", \"Bad response\", \"ThumbsDown\", \"Page: chat message\"),\n\n // Tools & admin\n o(\"cm:x:surface\", \"This page (location, context, agents)\", \"MapPin\", \"Tools & admin\"),\n o(\"cm:admin\", \"Admin tools\", \"Shield\", \"Tools & admin\"),\n o(\"feedback\", \"Send feedback\", \"MessageSquareWarning\", \"Tools & admin\"),\n o(\"keyboard-shortcuts\", \"Keyboard shortcuts\", \"Keyboard\", \"Tools & admin\", { status: \"proposed\" }),\n];\n\nexport const CATALOG_GROUPS: readonly CatalogGroup[] = [...new Set(CATALOG.map((c) => c.group))];\n\nexport function catalogOption(id: string): CatalogOption | undefined {\n return CATALOG.find((c) => c.id === id);\n}\n\n/** Ready-made pieces: dropping one inserts the whole block. */\nexport interface CatalogTemplate {\n id: string;\n label: string;\n icon: string;\n build: () => MenuNode;\n}\n\nlet seq = 0;\nconst tid = (p: string) => `${p}_t${Date.now().toString(36)}${(seq++).toString(36)}`;\n\nfunction itemFrom(id: string): MenuNode {\n const c = catalogOption(id);\n return {\n id: tid(\"i\"),\n kind: \"item\",\n catalogId: id,\n label: c?.label ?? id,\n icon: c?.icon ?? \"Circle\",\n ...(c?.shortcut ? { shortcut: c.shortcut } : {}),\n ...(c?.danger ? { danger: true } : {}),\n ...(c?.ai ? { ai: true } : {}),\n };\n}\n\nconst strip = (label: string, ids: string[]): MenuNode => ({\n id: tid(\"s\"),\n kind: \"section\",\n label,\n layout: \"row\",\n children: ids.map(itemFrom),\n});\n\nconst sub = (label: string, icon: string, ids: string[]): MenuNode => ({\n id: tid(\"m\"),\n kind: \"submenu\",\n label,\n icon,\n children: ids.map(itemFrom),\n});\n\nexport const TEMPLATES: readonly CatalogTemplate[] = [\n { id: \"strip-thing\", label: \"Icon strip — a thing\", icon: \"Rows2\", build: () => strip(\"\", [\"cm:copy\", \"cm:share\", \"duplicate\", \"favorite\", \"save-as-file\", \"archive\"]) },\n { id: \"strip-edit\", label: \"Icon strip — editable text\", icon: \"Rows2\", build: () => strip(\"\", [\"cm:cut\", \"cm:copy\", \"cm:paste\", \"cm:undo\", \"cm:redo\", \"cm:find\"]) },\n { id: \"strip-read\", label: \"Icon strip — read-only text\", icon: \"Rows2\", build: () => strip(\"\", [\"cm:copy\", \"cm:speak\", \"cm:find\", \"cm:share\"]) },\n { id: \"sub-intelligence\", label: \"Intelligence ▸\", icon: \"Sparkles\", build: () => sub(\"Intelligence\", \"Sparkles\", [\"cm:chat\", \"cm:placement:ai-action\", \"cm:placement:bound-agent\", \"send-to-agent\"]) },\n { id: \"sub-save-share\", label: \"Save & share ▸\", icon: \"Share2\", build: () => sub(\"Save & share\", \"Share2\", [\"cm:copy-as\", \"save-as-file\", \"cm:convert\", \"share-webpage\", \"cm:share\"]) },\n { id: \"sub-organize\", label: \"Organize ▸\", icon: \"Tags\", build: () => sub(\"Organize\", \"Tags\", [\"cm:attach\", \"pin-message\", \"cm:view-history\", \"cm:compare\"]) },\n { id: \"sub-tools\", label: \"Tools ▸\", icon: \"Wrench\", build: () => sub(\"Tools\", \"Wrench\", [\"cm:speak\", \"cm:quick-actions\", \"feedback\", \"cm:x:surface\", \"cm:admin\"]) },\n];\n","// src/design/MenuPreview.tsx — @ai-matrx/context-menu: DRAWS A DESIGN AS THE MENU IT DESCRIBES.\n//\n// The same component draws the builder's live preview and the right-click test menu, so what the\n// designer sees is what opens. Icons come from the host (`renderIcon`), so this file has no icon set.\n\nimport { useMemo, useState, type CSSProperties, type ReactNode } from \"react\";\nimport { isContainer, type MenuDesign, type MenuItemNode, type MenuNode, type MenuSubmenuNode } from \"./model\";\n\nexport interface MenuPreviewProps {\n design: MenuDesign;\n renderIcon: (name: string, className?: string) => ReactNode;\n /** The entry highlighted as \"selected in the builder\". */\n highlightId?: string | null;\n /** A click on any entry. */\n onSelectNode?: (id: string) => void;\n /** A click on an item (the menu's action). */\n onPick?: (item: MenuItemNode) => void;\n className?: string;\n style?: CSSProperties;\n}\n\nfunction matches(node: MenuNode, q: string): boolean {\n if (!q) return true;\n if (node.kind === \"divider\") return false;\n if (node.kind === \"item\") return node.label.toLowerCase().includes(q);\n return node.label.toLowerCase().includes(q) || node.children.some((c) => matches(c, q));\n}\n\n/** While searching: one flat list of matching items, the way a command palette reads. */\nfunction flatten(nodes: readonly MenuNode[], q: string, out: MenuItemNode[] = []): MenuItemNode[] {\n for (const n of nodes) {\n if (n.kind === \"item\" && matches(n, q)) out.push(n);\n else if (isContainer(n)) flatten(n.children, q, out);\n }\n return out;\n}\n\nexport function MenuPreview({ design, renderIcon, highlightId, onSelectNode, onPick, className, style }: MenuPreviewProps) {\n const [query, setQuery] = useState(\"\");\n const q = query.trim().toLowerCase();\n const { look } = design;\n const results = useMemo(() => (q ? flatten(design.nodes, q) : null), [design.nodes, q]);\n\n return (\n <div\n role=\"menu\"\n data-density={look.density}\n className={`cm-menu ${className ?? \"\"}`}\n style={{ width: look.width, ...style }}\n >\n {look.search && (\n <div className=\"cm-search\">\n {renderIcon(\"Search\", \"cm-icon\")}\n {/* ui-exception: the menu's own filter row — this file IS the menu component */}\n <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder=\"Type to filter…\" aria-label=\"Filter menu\" />\n </div>\n )}\n {results ? (\n results.length === 0 ? (\n <div className=\"cm-empty\">No matches</div>\n ) : (\n results.map((n) => <Item key={n.id} node={n} ctx={{ design, renderIcon, highlightId, onSelectNode, onPick }} />)\n )\n ) : design.nodes.length === 0 ? (\n <div className=\"cm-empty\">Empty menu — drag options in</div>\n ) : (\n <Nodes nodes={design.nodes} ctx={{ design, renderIcon, highlightId, onSelectNode, onPick }} />\n )}\n </div>\n );\n}\n\ninterface Ctx {\n design: MenuDesign;\n renderIcon: MenuPreviewProps[\"renderIcon\"];\n highlightId: string | null | undefined;\n onSelectNode: MenuPreviewProps[\"onSelectNode\"];\n onPick: MenuPreviewProps[\"onPick\"];\n}\n\nfunction Nodes({ nodes, ctx }: { nodes: readonly MenuNode[]; ctx: Ctx }) {\n return (\n <>\n {nodes.map((n) => {\n if (n.kind === \"divider\") return <div key={n.id} role=\"separator\" className=\"cm-divider\" />;\n if (n.kind === \"item\") return <Item key={n.id} node={n} ctx={ctx} />;\n if (n.kind === \"submenu\") return <Submenu key={n.id} node={n} ctx={ctx} />;\n return <Section key={n.id} node={n} ctx={ctx} />;\n })}\n </>\n );\n}\n\nfunction Section({ node, ctx }: { node: Extract<MenuNode, { kind: \"section\" }>; ctx: Ctx }) {\n const [open, setOpen] = useState(!node.collapsible);\n const layout = node.layout ?? \"list\";\n return (\n <div className={`cm-section ${ctx.highlightId === node.id ? \"cm-hl\" : \"\"}`} data-layout={layout}>\n {node.label && (\n // ui-exception: a menu row of the menu component itself\n <button\n type=\"button\"\n className=\"cm-section-label\"\n onClick={() => {\n ctx.onSelectNode?.(node.id);\n if (node.collapsible) setOpen((o) => !o);\n }}\n >\n {node.label}\n {node.collapsible && <span className=\"cm-caret\">{open ? \"▾\" : \"▸\"}</span>}\n </button>\n )}\n {open && (\n <div className=\"cm-section-body\">\n {layout === \"list\" ? (\n <Nodes nodes={node.children} ctx={ctx} />\n ) : (\n node.children.map((c) =>\n c.kind === \"item\" ? <Tile key={c.id} node={c} ctx={ctx} /> : <Nodes key={c.id} nodes={[c]} ctx={ctx} />,\n )\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction Tile({ node, ctx }: { node: MenuItemNode; ctx: Ctx }) {\n return (\n // ui-exception: a menu row of the menu component itself\n <button\n type=\"button\"\n role=\"menuitem\"\n title={node.label + (node.shortcut ? ` ${node.shortcut}` : \"\")}\n disabled={node.disabled}\n className={`cm-tile ${node.danger ? \"cm-danger\" : \"\"} ${node.ai ? \"cm-ai\" : \"\"} ${ctx.highlightId === node.id ? \"cm-hl\" : \"\"}`}\n onClick={() => {\n ctx.onSelectNode?.(node.id);\n ctx.onPick?.(node);\n }}\n >\n {ctx.renderIcon(node.icon ?? \"Circle\", \"cm-icon\")}\n </button>\n );\n}\n\nfunction Item({ node, ctx }: { node: MenuItemNode; ctx: Ctx }) {\n const { look } = ctx.design;\n const [checked, setChecked] = useState(false);\n return (\n // ui-exception: a menu row of the menu component itself\n <button\n type=\"button\"\n role={node.toggle ? \"menuitemcheckbox\" : \"menuitem\"}\n aria-checked={node.toggle ? checked : undefined}\n disabled={node.disabled}\n className={`cm-item ${node.danger ? \"cm-danger\" : \"\"} ${node.ai ? \"cm-ai\" : \"\"} ${ctx.highlightId === node.id ? \"cm-hl\" : \"\"}`}\n onClick={() => {\n ctx.onSelectNode?.(node.id);\n if (node.toggle) setChecked((c) => !c);\n ctx.onPick?.(node);\n }}\n >\n {look.showIcons && <span className=\"cm-icon-slot\">{node.toggle ? (checked ? ctx.renderIcon(\"Check\", \"cm-icon\") : null) : node.icon ? ctx.renderIcon(node.icon, \"cm-icon\") : null}</span>}\n <span className=\"cm-text\">\n <span className=\"cm-label\">{node.label}</span>\n {look.showHints && node.hint && <span className=\"cm-hint\">{node.hint}</span>}\n </span>\n {look.showShortcuts && node.shortcut && <kbd className=\"cm-shortcut\">{node.shortcut}</kbd>}\n </button>\n );\n}\n\nfunction Submenu({ node, ctx }: { node: MenuSubmenuNode; ctx: Ctx }) {\n const { look } = ctx.design;\n const [open, setOpen] = useState(false);\n const [side, setSide] = useState<\"right\" | \"left\">(\"right\");\n const show = (el: HTMLElement) => {\n // No room on the right → open to the left, the way a native menu flips at a screen edge.\n const r = el.getBoundingClientRect();\n setSide(r.right + look.width + 8 > window.innerWidth ? \"left\" : \"right\");\n setOpen(true);\n };\n return (\n <div className=\"cm-sub\" onMouseEnter={(e) => show(e.currentTarget)} onMouseLeave={() => setOpen(false)}>\n {/* ui-exception: a menu row of the menu component itself */}\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-haspopup=\"menu\"\n aria-expanded={open}\n className={`cm-item ${ctx.highlightId === node.id ? \"cm-hl\" : \"\"}`}\n onClick={() => {\n ctx.onSelectNode?.(node.id);\n setOpen(true);\n }}\n >\n {look.showIcons && <span className=\"cm-icon-slot\">{node.icon ? ctx.renderIcon(node.icon, \"cm-icon\") : null}</span>}\n <span className=\"cm-text\">\n <span className=\"cm-label\">{node.label}</span>\n {look.showHints && node.hint && <span className=\"cm-hint\">{node.hint}</span>}\n </span>\n {ctx.renderIcon(\"ChevronRight\", \"cm-icon cm-chev\")}\n </button>\n {open && (\n <div role=\"menu\" className=\"cm-menu cm-flyout\" data-side={side} data-density={look.density} style={{ width: look.width }}>\n {node.children.length === 0 ? <div className=\"cm-empty\">Empty submenu</div> : <Nodes nodes={node.children} ctx={ctx} />}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":"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","names":["o"]}