@ai-matrx/context-menu 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/builder.cjs +4185 -128
- package/dist/builder.cjs.map +1 -1
- package/dist/builder.d.cts +1 -1
- package/dist/builder.d.ts +1 -1
- package/dist/builder.js +4193 -136
- package/dist/builder.js.map +1 -1
- package/dist/design-store.cjs.map +1 -1
- package/dist/design-store.d.cts +1 -1
- package/dist/design-store.d.ts +1 -1
- package/dist/design-store.js.map +1 -1
- package/dist/index.cjs +202 -82
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +203 -83
- package/dist/index.js.map +1 -1
- package/dist/{model-CkLCR6WY.d.cts → model-C_7QZRE0.d.cts} +46 -4
- package/dist/{model-CkLCR6WY.d.ts → model-C_7QZRE0.d.ts} +46 -4
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -26,9 +26,11 @@ __export(src_exports, {
|
|
|
26
26
|
DEFAULT_LOOK: () => DEFAULT_LOOK,
|
|
27
27
|
DESIGN_FORMAT: () => DESIGN_FORMAT,
|
|
28
28
|
MENU_SURFACES: () => MENU_SURFACES,
|
|
29
|
+
MENU_TONES: () => MENU_TONES,
|
|
29
30
|
MenuPreview: () => MenuPreview,
|
|
30
31
|
SLOT_SOURCES: () => SLOT_SOURCES,
|
|
31
32
|
TEMPLATES: () => TEMPLATES,
|
|
33
|
+
UNAVAILABLE_MODES: () => UNAVAILABLE_MODES,
|
|
32
34
|
canMove: () => canMove,
|
|
33
35
|
catalogOption: () => catalogOption,
|
|
34
36
|
catalogUseCounts: () => catalogUseCounts,
|
|
@@ -55,6 +57,28 @@ __export(src_exports, {
|
|
|
55
57
|
module.exports = __toCommonJS(src_exports);
|
|
56
58
|
|
|
57
59
|
// src/design/model.ts
|
|
60
|
+
var MENU_TONES = [
|
|
61
|
+
"default",
|
|
62
|
+
"primary",
|
|
63
|
+
"success",
|
|
64
|
+
"warning",
|
|
65
|
+
"info",
|
|
66
|
+
"destructive",
|
|
67
|
+
"sky",
|
|
68
|
+
"blue",
|
|
69
|
+
"indigo",
|
|
70
|
+
"violet",
|
|
71
|
+
"fuchsia",
|
|
72
|
+
"rose",
|
|
73
|
+
"orange",
|
|
74
|
+
"amber",
|
|
75
|
+
"lime",
|
|
76
|
+
"emerald",
|
|
77
|
+
"teal",
|
|
78
|
+
"cyan",
|
|
79
|
+
"slate"
|
|
80
|
+
];
|
|
81
|
+
var UNAVAILABLE_MODES = ["disable", "hide", "required"];
|
|
58
82
|
var MENU_SURFACES = [
|
|
59
83
|
"text-selection",
|
|
60
84
|
"editable-field",
|
|
@@ -368,52 +392,90 @@ function slotOptions(fills, placed) {
|
|
|
368
392
|
// src/design/MenuPreview.tsx
|
|
369
393
|
var import_react = require("react");
|
|
370
394
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
371
|
-
function
|
|
372
|
-
if (
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
return node.label.toLowerCase().includes(q) || node.children.some((c) => matches(c, q));
|
|
395
|
+
function searchable(node) {
|
|
396
|
+
if (node.kind === "divider" || node.kind === "search") return "";
|
|
397
|
+
const hint = node.kind === "item" || node.kind === "submenu" ? node.hint ?? "" : "";
|
|
398
|
+
return [node.label, hint, ...node.keywords ?? []].join(" ").toLowerCase();
|
|
376
399
|
}
|
|
377
|
-
function
|
|
400
|
+
function searchMenu(nodes, q, trail = [], out = []) {
|
|
401
|
+
const words = q.split(/\s+/).filter(Boolean);
|
|
378
402
|
for (const n of nodes) {
|
|
379
|
-
if (n.kind === "item"
|
|
380
|
-
|
|
403
|
+
if (n.kind === "item") {
|
|
404
|
+
const text = `${searchable(n)} ${trail.join(" ").toLowerCase()}`;
|
|
405
|
+
if (words.every((w) => text.includes(w))) out.push({ node: n, path: trail.join(" \u203A ") });
|
|
406
|
+
} else if (isContainer(n)) {
|
|
407
|
+
searchMenu(n.children, q, n.kind === "submenu" ? [...trail, n.label] : n.label ? [...trail, n.label] : trail, out);
|
|
408
|
+
}
|
|
381
409
|
}
|
|
382
410
|
return out;
|
|
383
411
|
}
|
|
384
|
-
function MenuPreview({ design, renderIcon, highlightId, onSelectNode, onPick, className, style }) {
|
|
412
|
+
function MenuPreview({ design, renderIcon, highlightId, onSelectNode, onPick, availability = "available", className, style }) {
|
|
385
413
|
const [query, setQuery] = (0, import_react.useState)("");
|
|
386
414
|
const q = query.trim().toLowerCase();
|
|
387
415
|
const { look } = design;
|
|
388
|
-
const results = (0, import_react.useMemo)(() => q ? flatten(design.nodes, q) : null, [design.nodes, q]);
|
|
389
416
|
const placed = (0, import_react.useMemo)(() => placedCatalogIds(design.nodes), [design.nodes]);
|
|
390
|
-
const ctx = { design, renderIcon, highlightId, onSelectNode, onPick, placed };
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
)
|
|
417
|
+
const ctx = { design, renderIcon, highlightId, onSelectNode, onPick, placed, availability, query, setQuery };
|
|
418
|
+
const searchAt = design.nodes.findIndex((n) => n.kind === "search");
|
|
419
|
+
const topSearch = searchAt < 0 && look.search ? { id: "look-search", kind: "search", placeholder: "Type to filter\u2026", autofocus: true } : null;
|
|
420
|
+
const hits = (0, import_react.useMemo)(() => q ? searchMenu(design.nodes, q) : null, [design.nodes, q]);
|
|
421
|
+
const above = searchAt >= 0 ? design.nodes.slice(0, searchAt) : [];
|
|
422
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { role: "menu", "data-density": look.density, className: `cm-menu ${className ?? ""}`, style: { width: look.width, ...style }, children: [
|
|
423
|
+
topSearch && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SearchBox, { node: topSearch, ctx }),
|
|
424
|
+
design.nodes.length === 0 && !topSearch ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "Empty menu \u2014 drag options in" }) : hits ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
425
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: above, ctx }),
|
|
426
|
+
searchAt >= 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SearchBox, { node: design.nodes[searchAt], ctx }),
|
|
427
|
+
hits.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "No matches" }) : hits.map((h) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Item, { node: h.node, ctx, path: h.path }, h.node.id))
|
|
428
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Nodes, { nodes: design.nodes, ctx })
|
|
429
|
+
] });
|
|
430
|
+
}
|
|
431
|
+
function SearchBox({ node, ctx }) {
|
|
432
|
+
const ref = (0, import_react.useRef)(null);
|
|
433
|
+
(0, import_react.useEffect)(() => {
|
|
434
|
+
if (node.autofocus) ref.current?.focus({ preventScroll: true });
|
|
435
|
+
}, [node.autofocus]);
|
|
436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `cm-search ${ctx.highlightId === node.id ? "cm-hl" : ""}`, onClick: () => ctx.onSelectNode?.(node.id), children: [
|
|
437
|
+
ctx.renderIcon("Search", "cm-icon"),
|
|
438
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
439
|
+
"input",
|
|
440
|
+
{
|
|
441
|
+
ref,
|
|
442
|
+
value: ctx.query,
|
|
443
|
+
onChange: (e) => ctx.setQuery(e.target.value),
|
|
444
|
+
onKeyDown: (e) => {
|
|
445
|
+
if (e.key === "Escape" && ctx.query) {
|
|
446
|
+
e.stopPropagation();
|
|
447
|
+
ctx.setQuery("");
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
placeholder: node.placeholder || "Type to filter\u2026",
|
|
451
|
+
"aria-label": "Filter menu"
|
|
452
|
+
}
|
|
453
|
+
)
|
|
454
|
+
] });
|
|
455
|
+
}
|
|
456
|
+
function shown(node, ctx) {
|
|
457
|
+
if (ctx.availability === "available" || !node.unavailableWhen) {
|
|
458
|
+
return { hidden: false, greyed: node.kind === "item" && Boolean(node.disabled) };
|
|
459
|
+
}
|
|
460
|
+
const mode = node.unavailable ?? "disable";
|
|
461
|
+
if (mode === "hide") return { hidden: true, greyed: false };
|
|
462
|
+
if (mode === "required") return { hidden: false, greyed: false };
|
|
463
|
+
return { hidden: false, greyed: true };
|
|
407
464
|
}
|
|
408
465
|
function Nodes({ nodes, ctx }) {
|
|
409
466
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: nodes.map((n) => {
|
|
467
|
+
if (shown(n, ctx).hidden) return null;
|
|
410
468
|
if (n.kind === "divider") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { role: "separator", className: "cm-divider" }, n.id);
|
|
411
469
|
if (n.kind === "item") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Item, { node: n, ctx }, n.id);
|
|
412
470
|
if (n.kind === "submenu") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Submenu, { node: n, ctx }, n.id);
|
|
413
|
-
if (n.kind === "slot") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slot, { node: n, ctx }, n.id);
|
|
471
|
+
if (n.kind === "slot") return n.shape === "feature" ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(FeatureSlot, { node: n, ctx }, n.id) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Slot, { node: n, ctx }, n.id);
|
|
472
|
+
if (n.kind === "search") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SearchBox, { node: n, ctx }, n.id);
|
|
414
473
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Section, { node: n, ctx }, n.id);
|
|
415
474
|
}) });
|
|
416
475
|
}
|
|
476
|
+
function toneAttrs(tone, toneLabel) {
|
|
477
|
+
return tone && tone !== "default" ? { "data-tone": tone, ...toneLabel ? { "data-tone-label": "" } : {} } : {};
|
|
478
|
+
}
|
|
417
479
|
function Section({ node, ctx }) {
|
|
418
480
|
const [open, setOpen] = (0, import_react.useState)(!node.collapsible);
|
|
419
481
|
const layout = node.layout ?? "list";
|
|
@@ -435,11 +497,12 @@ function Section({ node, ctx }) {
|
|
|
435
497
|
}
|
|
436
498
|
),
|
|
437
499
|
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(
|
|
438
|
-
(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)
|
|
500
|
+
(c) => shown(c, ctx).hidden ? null : 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)
|
|
439
501
|
) })
|
|
440
502
|
] });
|
|
441
503
|
}
|
|
442
504
|
function Tile({ node, ctx }) {
|
|
505
|
+
const { greyed } = shown(node, ctx);
|
|
443
506
|
return (
|
|
444
507
|
// ui-exception: a menu row of the menu component itself
|
|
445
508
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -448,7 +511,8 @@ function Tile({ node, ctx }) {
|
|
|
448
511
|
type: "button",
|
|
449
512
|
role: "menuitem",
|
|
450
513
|
title: node.label + (node.shortcut ? ` ${node.shortcut}` : ""),
|
|
451
|
-
disabled:
|
|
514
|
+
disabled: greyed,
|
|
515
|
+
...toneAttrs(node.tone, node.toneLabel),
|
|
452
516
|
className: `cm-tile ${node.danger ? "cm-danger" : ""} ${node.ai ? "cm-ai" : ""} ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
|
|
453
517
|
onClick: () => {
|
|
454
518
|
ctx.onSelectNode?.(node.id);
|
|
@@ -459,31 +523,37 @@ function Tile({ node, ctx }) {
|
|
|
459
523
|
)
|
|
460
524
|
);
|
|
461
525
|
}
|
|
462
|
-
function Item({ node, ctx }) {
|
|
526
|
+
function Item({ node, ctx, path }) {
|
|
463
527
|
const { look } = ctx.design;
|
|
464
|
-
const [checked, setChecked] = (0, import_react.useState)(
|
|
528
|
+
const [checked, setChecked] = (0, import_react.useState)(Boolean(node.defaultOn));
|
|
529
|
+
(0, import_react.useEffect)(() => setChecked(Boolean(node.defaultOn)), [node.defaultOn]);
|
|
530
|
+
const { greyed } = shown(node, ctx);
|
|
531
|
+
const settable = node.toggle || node.switch;
|
|
532
|
+
const hint = path || (look.showHints ? node.hint : void 0);
|
|
465
533
|
return (
|
|
466
534
|
// ui-exception: a menu row of the menu component itself
|
|
467
535
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
468
536
|
"button",
|
|
469
537
|
{
|
|
470
538
|
type: "button",
|
|
471
|
-
role:
|
|
472
|
-
"aria-checked":
|
|
473
|
-
disabled:
|
|
539
|
+
role: settable ? "menuitemcheckbox" : "menuitem",
|
|
540
|
+
"aria-checked": settable ? checked : void 0,
|
|
541
|
+
disabled: greyed,
|
|
542
|
+
...toneAttrs(node.tone, node.toneLabel),
|
|
474
543
|
className: `cm-item ${node.danger ? "cm-danger" : ""} ${node.ai ? "cm-ai" : ""} ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
|
|
475
544
|
onClick: () => {
|
|
476
545
|
ctx.onSelectNode?.(node.id);
|
|
477
|
-
if (
|
|
546
|
+
if (settable) setChecked((c) => !c);
|
|
478
547
|
ctx.onPick?.(node);
|
|
479
548
|
},
|
|
480
549
|
children: [
|
|
481
550
|
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 }),
|
|
482
551
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cm-text", children: [
|
|
483
552
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children: node.label }),
|
|
484
|
-
|
|
553
|
+
hint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-hint", children: hint })
|
|
485
554
|
] }),
|
|
486
|
-
look.showShortcuts && node.shortcut && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("kbd", { className: "cm-shortcut", children: node.shortcut })
|
|
555
|
+
look.showShortcuts && node.shortcut && !node.switch && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("kbd", { className: "cm-shortcut", children: node.shortcut }),
|
|
556
|
+
node.switch && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-switch", "data-on": checked ? "" : void 0, "aria-hidden": "true" })
|
|
487
557
|
]
|
|
488
558
|
}
|
|
489
559
|
)
|
|
@@ -493,35 +563,46 @@ function Submenu({ node, ctx }) {
|
|
|
493
563
|
const { look } = ctx.design;
|
|
494
564
|
const [open, setOpen] = (0, import_react.useState)(false);
|
|
495
565
|
const [side, setSide] = (0, import_react.useState)("right");
|
|
496
|
-
const
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
566
|
+
const { greyed } = shown(node, ctx);
|
|
567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
568
|
+
"div",
|
|
569
|
+
{
|
|
570
|
+
className: "cm-sub",
|
|
571
|
+
onMouseEnter: (e) => {
|
|
572
|
+
if (greyed) return;
|
|
573
|
+
setSide(flyoutSide(e.currentTarget, look.width));
|
|
574
|
+
setOpen(true);
|
|
575
|
+
},
|
|
576
|
+
onMouseLeave: () => setOpen(false),
|
|
577
|
+
children: [
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
579
|
+
"button",
|
|
580
|
+
{
|
|
581
|
+
type: "button",
|
|
582
|
+
role: "menuitem",
|
|
583
|
+
"aria-haspopup": "menu",
|
|
584
|
+
"aria-expanded": open,
|
|
585
|
+
disabled: greyed,
|
|
586
|
+
...toneAttrs(node.tone, node.toneLabel),
|
|
587
|
+
className: `cm-item ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
|
|
588
|
+
onClick: () => {
|
|
589
|
+
ctx.onSelectNode?.(node.id);
|
|
590
|
+
setOpen(true);
|
|
591
|
+
},
|
|
592
|
+
children: [
|
|
593
|
+
look.showIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-icon-slot", children: node.icon ? ctx.renderIcon(node.icon, "cm-icon") : null }),
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "cm-text", children: [
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children: node.label }),
|
|
596
|
+
look.showHints && node.hint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-hint", children: node.hint })
|
|
597
|
+
] }),
|
|
598
|
+
ctx.renderIcon("ChevronRight", "cm-icon cm-chev")
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
),
|
|
602
|
+
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 }) })
|
|
603
|
+
]
|
|
604
|
+
}
|
|
605
|
+
);
|
|
525
606
|
}
|
|
526
607
|
function flyoutSide(row, width) {
|
|
527
608
|
const r = row.getBoundingClientRect();
|
|
@@ -530,37 +611,42 @@ function flyoutSide(row, width) {
|
|
|
530
611
|
if (r.left - width - 8 >= bounds.left) return "left";
|
|
531
612
|
return "below";
|
|
532
613
|
}
|
|
533
|
-
function
|
|
614
|
+
function SlotRow({ node, ctx, label, icon, count, more, onOpen }) {
|
|
534
615
|
const { look } = ctx.design;
|
|
535
616
|
const source = slotSource(node.fills);
|
|
536
|
-
|
|
537
|
-
const [open, setOpen] = (0, import_react.useState)(false);
|
|
538
|
-
const [side, setSide] = (0, import_react.useState)("right");
|
|
539
|
-
const count = source?.runtime ? "live" : String(options.length);
|
|
540
|
-
const row = (
|
|
617
|
+
return (
|
|
541
618
|
// ui-exception: a menu row of the menu component itself
|
|
542
619
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
543
620
|
"button",
|
|
544
621
|
{
|
|
545
622
|
type: "button",
|
|
546
623
|
role: "menuitem",
|
|
547
|
-
"aria-haspopup":
|
|
624
|
+
"aria-haspopup": more ? "menu" : void 0,
|
|
548
625
|
title: source ? `Placeholder: ${source.label}` : "Placeholder",
|
|
549
626
|
className: `cm-item cm-slot ${ctx.highlightId === node.id ? "cm-hl" : ""}`,
|
|
550
627
|
onClick: () => {
|
|
551
628
|
ctx.onSelectNode?.(node.id);
|
|
552
|
-
|
|
629
|
+
onOpen?.();
|
|
553
630
|
},
|
|
554
631
|
children: [
|
|
555
|
-
look.showIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-icon-slot", children: ctx.renderIcon(
|
|
556
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-text", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children:
|
|
557
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-count", children: count }),
|
|
558
|
-
|
|
632
|
+
look.showIcons && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-icon-slot", children: ctx.renderIcon(icon, "cm-icon") }),
|
|
633
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-text", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-label", children: label }) }),
|
|
634
|
+
count && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "cm-count", children: count }),
|
|
635
|
+
more && ctx.renderIcon("ChevronRight", "cm-icon cm-chev")
|
|
559
636
|
]
|
|
560
637
|
}
|
|
561
638
|
)
|
|
562
639
|
);
|
|
563
|
-
|
|
640
|
+
}
|
|
641
|
+
function Slot({ node, ctx }) {
|
|
642
|
+
const { look } = ctx.design;
|
|
643
|
+
const source = slotSource(node.fills);
|
|
644
|
+
const options = slotOptions(node.fills, ctx.placed);
|
|
645
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
646
|
+
const [side, setSide] = (0, import_react.useState)("right");
|
|
647
|
+
const icon = node.icon ?? source?.icon ?? "Ellipsis";
|
|
648
|
+
const count = source?.runtime ? "live" : String(options.length);
|
|
649
|
+
if (node.shape === "items") return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SlotRow, { node, ctx, label: node.label, icon, count });
|
|
564
650
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
565
651
|
"div",
|
|
566
652
|
{
|
|
@@ -571,13 +657,47 @@ function Slot({ node, ctx }) {
|
|
|
571
657
|
},
|
|
572
658
|
onMouseLeave: () => setOpen(false),
|
|
573
659
|
children: [
|
|
574
|
-
|
|
660
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SlotRow, { node, ctx, label: node.label, icon, count, more: true, onOpen: () => setOpen(true) }),
|
|
575
661
|
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: source?.runtime ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cm-runtime", children: [
|
|
576
662
|
"Filled at runtime: ",
|
|
577
663
|
source.label
|
|
578
|
-
] }) : options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "Nothing left \u2014 every option of this kind is placed" }) : options.map((o2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
664
|
+
] }) : options.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-empty", children: "Nothing left \u2014 every option of this kind is placed" }) : options.map((o2) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
665
|
+
Item,
|
|
666
|
+
{
|
|
667
|
+
node: { id: `slot-${node.id}-${o2.id}`, kind: "item", label: o2.label, icon: o2.icon, catalogId: o2.id, ...o2.shortcut ? { shortcut: o2.shortcut } : {}, ...o2.ai ? { ai: true } : {}, ...o2.danger ? { danger: true } : {} },
|
|
668
|
+
ctx
|
|
669
|
+
},
|
|
670
|
+
o2.id
|
|
671
|
+
)) })
|
|
579
672
|
]
|
|
580
673
|
}
|
|
581
674
|
);
|
|
582
675
|
}
|
|
676
|
+
function FeatureSlot({ node, ctx }) {
|
|
677
|
+
const { look } = ctx.design;
|
|
678
|
+
const n = Math.max(0, Math.min(12, node.featureItems ?? 4));
|
|
679
|
+
const [open, setOpen] = (0, import_react.useState)(false);
|
|
680
|
+
const [side, setSide] = (0, import_react.useState)("right");
|
|
681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `cm-section ${ctx.highlightId === node.id ? "cm-hl" : ""}`, "data-layout": "list", children: [
|
|
682
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", className: "cm-section-label cm-slot-label", onClick: () => ctx.onSelectNode?.(node.id), children: node.label || "This feature" }),
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "cm-section-body", children: [
|
|
684
|
+
Array.from({ length: n }, (_, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SlotRow, { node, ctx, label: `Feature option ${i + 1}`, icon: "Circle" }, i)),
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
686
|
+
"div",
|
|
687
|
+
{
|
|
688
|
+
className: "cm-sub",
|
|
689
|
+
onMouseEnter: (e) => {
|
|
690
|
+
setSide(flyoutSide(e.currentTarget, look.width));
|
|
691
|
+
setOpen(true);
|
|
692
|
+
},
|
|
693
|
+
onMouseLeave: () => setOpen(false),
|
|
694
|
+
children: [
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(SlotRow, { node, ctx, label: "More", icon: "Ellipsis", more: true, onOpen: () => setOpen(true) }),
|
|
696
|
+
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: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "cm-runtime", children: "The rest of this feature's options, filled at runtime" }) })
|
|
697
|
+
]
|
|
698
|
+
}
|
|
699
|
+
)
|
|
700
|
+
] })
|
|
701
|
+
] });
|
|
702
|
+
}
|
|
583
703
|
//# sourceMappingURL=index.cjs.map
|