@1agh/maude 0.41.0 → 0.43.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.
- package/apps/studio/.ai/cache/_stats.json +7 -0
- package/apps/studio/acp/bootstrap-brief.ts +12 -2
- package/apps/studio/annotations-layer.tsx +1055 -278
- package/apps/studio/annotations-model.ts +58 -0
- package/apps/studio/api.ts +173 -63
- package/apps/studio/bin/_html-playwright.mjs +26 -4
- package/apps/studio/bin/_ingest-footage.mjs +386 -0
- package/apps/studio/bin/_pdf-playwright.mjs +13 -2
- package/apps/studio/bin/_png-playwright.mjs +15 -2
- package/apps/studio/bin/_pptx-playwright.mjs +17 -4
- package/apps/studio/bin/_probe-footage-playwright.mjs +269 -0
- package/apps/studio/bin/_screenshot-playwright.mjs +17 -2
- package/apps/studio/bin/_svg-playwright.mjs +26 -4
- package/apps/studio/bin/_video-playwright.mjs +141 -71
- package/apps/studio/bin/ingest-footage.sh +27 -0
- package/apps/studio/bin/photo-adjust.sh +163 -0
- package/apps/studio/bin/photo-bg-remove.sh +160 -0
- package/apps/studio/bin/probe-footage.sh +28 -0
- package/apps/studio/bin/read-annotations.mjs +125 -2
- package/apps/studio/bin/screenshot.sh +53 -4
- package/apps/studio/canvas-edit.ts +459 -10
- package/apps/studio/canvas-lib.tsx +523 -5
- package/apps/studio/canvas-pipeline.ts +65 -7
- package/apps/studio/canvas-shell.tsx +156 -16
- package/apps/studio/client/app.jsx +476 -88
- package/apps/studio/client/export-center.jsx +460 -0
- package/apps/studio/client/github.js +4 -0
- package/apps/studio/client/panels/GitPanel.jsx +8 -0
- package/apps/studio/client/panels/RepoBranchSwitcher.jsx +133 -21
- package/apps/studio/client/panels/StickerPicker.jsx +160 -0
- package/apps/studio/client/panels/TimelinePanel.jsx +15 -2
- package/apps/studio/client/photo-knobs.jsx +437 -0
- package/apps/studio/client/styles/3-shell-maude.css +59 -0
- package/apps/studio/client/styles/4-components.css +150 -0
- package/apps/studio/commands/edit-source-command.ts +31 -4
- package/apps/studio/config.schema.json +2 -2
- package/apps/studio/context-menu.tsx +31 -6
- package/apps/studio/dist/client.bundle.js +5561 -19
- package/apps/studio/dist/comment-mount.js +2 -2
- package/apps/studio/dist/runtime/.min-sizes.json +1 -0
- package/apps/studio/dist/runtime/@imgly_background-removal.js +5543 -0
- package/apps/studio/dist/runtime/pixi-js.js +519 -519
- package/apps/studio/dist/styles.css +1 -1
- package/apps/studio/dom-selection.ts +25 -0
- package/apps/studio/export-dialog.tsx +18 -25
- package/apps/studio/exporters/_runtime.ts +104 -0
- package/apps/studio/exporters/html.ts +12 -20
- package/apps/studio/exporters/index.ts +14 -2
- package/apps/studio/exporters/jobs.ts +376 -0
- package/apps/studio/exporters/pdf.ts +16 -20
- package/apps/studio/exporters/png.ts +12 -20
- package/apps/studio/exporters/pptx.ts +22 -23
- package/apps/studio/exporters/scope.ts +1 -0
- package/apps/studio/exporters/svg.ts +14 -22
- package/apps/studio/exporters/video.ts +37 -19
- package/apps/studio/footage/schema.test.ts +195 -0
- package/apps/studio/footage/schema.ts +484 -0
- package/apps/studio/footage-store.ts +235 -0
- package/apps/studio/fs-watch.ts +10 -0
- package/apps/studio/git/endpoints.ts +68 -7
- package/apps/studio/git/service.ts +198 -20
- package/apps/studio/github/service.ts +67 -0
- package/apps/studio/handoff.ts +3 -2
- package/apps/studio/http.ts +318 -64
- package/apps/studio/input-router.tsx +10 -0
- package/apps/studio/inspect.ts +53 -1
- package/apps/studio/paths.ts +10 -0
- package/apps/studio/photo/filters.ts +285 -0
- package/apps/studio/photo/pipeline.ts +607 -0
- package/apps/studio/photo/schema.ts +367 -0
- package/apps/studio/photo-store.ts +154 -0
- package/apps/studio/runtime-bundle.ts +29 -6
- package/apps/studio/server.ts +8 -2
- package/apps/studio/stickers/figjam-doodle/manifest.json +104 -0
- package/apps/studio/stickers/figjam-doodle/slice1.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice10.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice11.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice12.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice13.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice14.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice15.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice16.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice17.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice18.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice19.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice2.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice20.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice21.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice22.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice23.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice24.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice3.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice4.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice5.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice6.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice7.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice8.png +0 -0
- package/apps/studio/stickers/figjam-doodle/slice9.png +0 -0
- package/apps/studio/stickers/life-style/best.png +0 -0
- package/apps/studio/stickers/life-style/come-on.png +0 -0
- package/apps/studio/stickers/life-style/cut.png +0 -0
- package/apps/studio/stickers/life-style/detox.png +0 -0
- package/apps/studio/stickers/life-style/just.png +0 -0
- package/apps/studio/stickers/life-style/manifest.json +68 -0
- package/apps/studio/stickers/life-style/mirror.png +0 -0
- package/apps/studio/stickers/life-style/nice.png +0 -0
- package/apps/studio/stickers/life-style/objects.png +0 -0
- package/apps/studio/stickers/life-style/ok.png +0 -0
- package/apps/studio/stickers/life-style/queen.png +0 -0
- package/apps/studio/stickers/life-style/star.png +0 -0
- package/apps/studio/stickers/life-style/sun.png +0 -0
- package/apps/studio/stickers/life-style/water.png +0 -0
- package/apps/studio/stickers/life-style/yeah.png +0 -0
- package/apps/studio/stickers/life-style/you-can.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/check-the-deets.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/cut-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/dope.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/fresh.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/hot.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/idea.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/keep-exploring.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/killed-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/love-it.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/manifest.json +88 -0
- package/apps/studio/stickers/opposing-thoughts/not-sure.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/ok.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/pure-gold.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/save-for-later.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/steal-this.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/take-a-peek.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/this-or-that.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/thoughts.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/vibes.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/winner.png +0 -0
- package/apps/studio/stickers/opposing-thoughts/wip.png +0 -0
- package/apps/studio/stickers/project-status/group-100.png +0 -0
- package/apps/studio/stickers/project-status/group-101.png +0 -0
- package/apps/studio/stickers/project-status/group-102.png +0 -0
- package/apps/studio/stickers/project-status/group-103.png +0 -0
- package/apps/studio/stickers/project-status/group-104.png +0 -0
- package/apps/studio/stickers/project-status/group-105.png +0 -0
- package/apps/studio/stickers/project-status/group-106.png +0 -0
- package/apps/studio/stickers/project-status/group-107.png +0 -0
- package/apps/studio/stickers/project-status/group-108.png +0 -0
- package/apps/studio/stickers/project-status/group-109.png +0 -0
- package/apps/studio/stickers/project-status/group-110.png +0 -0
- package/apps/studio/stickers/project-status/group-111.png +0 -0
- package/apps/studio/stickers/project-status/group-112.png +0 -0
- package/apps/studio/stickers/project-status/group-113.png +0 -0
- package/apps/studio/stickers/project-status/group-114.png +0 -0
- package/apps/studio/stickers/project-status/group-115.png +0 -0
- package/apps/studio/stickers/project-status/group-117.png +0 -0
- package/apps/studio/stickers/project-status/group-118.png +0 -0
- package/apps/studio/stickers/project-status/group-119.png +0 -0
- package/apps/studio/stickers/project-status/group-120.png +0 -0
- package/apps/studio/stickers/project-status/group-121.png +0 -0
- package/apps/studio/stickers/project-status/group-122.png +0 -0
- package/apps/studio/stickers/project-status/group-41.png +0 -0
- package/apps/studio/stickers/project-status/group-42.png +0 -0
- package/apps/studio/stickers/project-status/group-43.png +0 -0
- package/apps/studio/stickers/project-status/group-44.png +0 -0
- package/apps/studio/stickers/project-status/group-45.png +0 -0
- package/apps/studio/stickers/project-status/group-46.png +0 -0
- package/apps/studio/stickers/project-status/group-47.png +0 -0
- package/apps/studio/stickers/project-status/group-48.png +0 -0
- package/apps/studio/stickers/project-status/group-49.png +0 -0
- package/apps/studio/stickers/project-status/group-50.png +0 -0
- package/apps/studio/stickers/project-status/group-51.png +0 -0
- package/apps/studio/stickers/project-status/group-52.png +0 -0
- package/apps/studio/stickers/project-status/group-53.png +0 -0
- package/apps/studio/stickers/project-status/group-54.png +0 -0
- package/apps/studio/stickers/project-status/group-55.png +0 -0
- package/apps/studio/stickers/project-status/group-56.png +0 -0
- package/apps/studio/stickers/project-status/group-57.png +0 -0
- package/apps/studio/stickers/project-status/group-58.png +0 -0
- package/apps/studio/stickers/project-status/group-59.png +0 -0
- package/apps/studio/stickers/project-status/group-60.png +0 -0
- package/apps/studio/stickers/project-status/group-61.png +0 -0
- package/apps/studio/stickers/project-status/group-62.png +0 -0
- package/apps/studio/stickers/project-status/group-63.png +0 -0
- package/apps/studio/stickers/project-status/group-64.png +0 -0
- package/apps/studio/stickers/project-status/group-65.png +0 -0
- package/apps/studio/stickers/project-status/group-66.png +0 -0
- package/apps/studio/stickers/project-status/group-67.png +0 -0
- package/apps/studio/stickers/project-status/group-68.png +0 -0
- package/apps/studio/stickers/project-status/group-69.png +0 -0
- package/apps/studio/stickers/project-status/group-70.png +0 -0
- package/apps/studio/stickers/project-status/group-71.png +0 -0
- package/apps/studio/stickers/project-status/group-72.png +0 -0
- package/apps/studio/stickers/project-status/group-73.png +0 -0
- package/apps/studio/stickers/project-status/group-74.png +0 -0
- package/apps/studio/stickers/project-status/group-75.png +0 -0
- package/apps/studio/stickers/project-status/group-76.png +0 -0
- package/apps/studio/stickers/project-status/group-77.png +0 -0
- package/apps/studio/stickers/project-status/group-78.png +0 -0
- package/apps/studio/stickers/project-status/group-79.png +0 -0
- package/apps/studio/stickers/project-status/group-80.png +0 -0
- package/apps/studio/stickers/project-status/group-81.png +0 -0
- package/apps/studio/stickers/project-status/group-82.png +0 -0
- package/apps/studio/stickers/project-status/group-83.png +0 -0
- package/apps/studio/stickers/project-status/group-84.png +0 -0
- package/apps/studio/stickers/project-status/group-85.png +0 -0
- package/apps/studio/stickers/project-status/group-86.png +0 -0
- package/apps/studio/stickers/project-status/group-87.png +0 -0
- package/apps/studio/stickers/project-status/group-88.png +0 -0
- package/apps/studio/stickers/project-status/group-89.png +0 -0
- package/apps/studio/stickers/project-status/group-90.png +0 -0
- package/apps/studio/stickers/project-status/group-91.png +0 -0
- package/apps/studio/stickers/project-status/group-92.png +0 -0
- package/apps/studio/stickers/project-status/group-93.png +0 -0
- package/apps/studio/stickers/project-status/group-94.png +0 -0
- package/apps/studio/stickers/project-status/group-96.png +0 -0
- package/apps/studio/stickers/project-status/group-97.png +0 -0
- package/apps/studio/stickers/project-status/group-98.png +0 -0
- package/apps/studio/stickers/project-status/group-99.png +0 -0
- package/apps/studio/stickers/project-status/manifest.json +328 -0
- package/apps/studio/test/acp-bootstrap-brief.test.ts +11 -0
- package/apps/studio/test/acp-commands.test.ts +2 -1
- package/apps/studio/test/asset-api.test.ts +3 -3
- package/apps/studio/test/canvas-edit.test.ts +17 -6
- package/apps/studio/test/canvas-origin-gate.test.ts +19 -0
- package/apps/studio/test/dns-rebinding-guard.test.ts +27 -0
- package/apps/studio/test/dynamic-text-edit.test.ts +162 -0
- package/apps/studio/test/edit-source-command.test.ts +23 -0
- package/apps/studio/test/element-structural-edit.test.ts +46 -0
- package/apps/studio/test/export-center.test.tsx +287 -0
- package/apps/studio/test/export-shim-multi-capture.test.ts +83 -0
- package/apps/studio/test/exporters/history.test.ts +32 -3
- package/apps/studio/test/exporters/jobs.test.ts +263 -0
- package/apps/studio/test/footage-store.test.ts +100 -0
- package/apps/studio/test/git-branches.test.ts +97 -0
- package/apps/studio/test/github-api.test.ts +56 -1
- package/apps/studio/test/input-router.test.ts +33 -0
- package/apps/studio/test/inspect-script-syntax.test.ts +53 -0
- package/apps/studio/test/photo-canvas-bundle.test.ts +61 -0
- package/apps/studio/test/photo-edit-api.test.ts +201 -0
- package/apps/studio/test/photo-filters.test.ts +149 -0
- package/apps/studio/test/photo-pipeline.test.ts +106 -0
- package/apps/studio/test/photo-taxonomy.test.ts +96 -0
- package/apps/studio/test/read-annotations.test.ts +164 -0
- package/apps/studio/test/shell-importmap.test.ts +49 -0
- package/apps/studio/test/text-editability-stamp.test.ts +131 -0
- package/apps/studio/test/timeline-parse.test.ts +57 -0
- package/apps/studio/test/tool-palette-insert-anchor.test.ts +5 -3
- package/apps/studio/test/undo-stack.test.ts +33 -0
- package/apps/studio/test/video-asset.test.ts +5 -5
- package/apps/studio/test/video-render-bridge.test.ts +23 -1
- package/apps/studio/text-caret.ts +239 -0
- package/apps/studio/tool-palette.tsx +43 -20
- package/apps/studio/undo-stack.ts +94 -2
- package/apps/studio/use-annotation-resize.tsx +4 -4
- package/apps/studio/use-canvas-media-drop.tsx +38 -1
- package/apps/studio/use-selection-set.tsx +21 -0
- package/apps/studio/video-comp.tsx +48 -7
- package/apps/studio/whats-new.json +70 -0
- package/apps/studio/ws.ts +6 -0
- package/cli/commands/design.mjs +34 -3
- package/cli/lib/gitignore-block.mjs +2 -0
- package/package.json +10 -10
- package/plugins/design/templates/_shell.html +1 -0
|
@@ -46,6 +46,14 @@ export interface EditSourcePayload {
|
|
|
46
46
|
before: string | null;
|
|
47
47
|
/** Value after the edit. `null` = the edit removed the prop/attr (the reset path). */
|
|
48
48
|
after: string | null;
|
|
49
|
+
/**
|
|
50
|
+
* `op:'text'` only — which rendered instance this edit targeted (index among
|
|
51
|
+
* same-cd-id DOM nodes). Needed to re-apply a `{variable}` text edit through
|
|
52
|
+
* undo/redo: the engine traces the string back to the right `.map()` item or
|
|
53
|
+
* component-prop usage, and that resolution needs the occurrence. Undefined
|
|
54
|
+
* for literal text (the engine ignores it there) and for css/attr.
|
|
55
|
+
*/
|
|
56
|
+
occurrence?: number;
|
|
49
57
|
}
|
|
50
58
|
|
|
51
59
|
/**
|
|
@@ -60,6 +68,14 @@ export type EditSourceApplyFn = (apply: {
|
|
|
60
68
|
id: string;
|
|
61
69
|
key: string;
|
|
62
70
|
value: string | null;
|
|
71
|
+
/**
|
|
72
|
+
* `op:'text'` re-application only — the value CURRENTLY on disk (the side we
|
|
73
|
+
* replace FROM: `before` on redo, `after` on undo), so a `{variable}` edit
|
|
74
|
+
* can be traced to the right source string. Plus the occurrence. Ignored by
|
|
75
|
+
* css/attr and by literal-text edits.
|
|
76
|
+
*/
|
|
77
|
+
from?: string | null;
|
|
78
|
+
occurrence?: number;
|
|
63
79
|
}) => void | Promise<void>;
|
|
64
80
|
|
|
65
81
|
export const EDIT_SOURCE_KIND = 'edit-source';
|
|
@@ -72,16 +88,27 @@ export interface EditSourceCommandInit {
|
|
|
72
88
|
|
|
73
89
|
export function createEditSourceCommand(init: EditSourceCommandInit): EditCommand {
|
|
74
90
|
const { payload, applyFn } = init;
|
|
75
|
-
|
|
76
|
-
|
|
91
|
+
// `from` = the value on disk BEFORE this re-application (what a `{variable}`
|
|
92
|
+
// text resolver matches against). do() writes `after` over `before`; undo()
|
|
93
|
+
// writes `before` over `after`.
|
|
94
|
+
const apply = (value: string | null, from: string | null) =>
|
|
95
|
+
applyFn({
|
|
96
|
+
op: payload.op,
|
|
97
|
+
canvas: payload.canvas,
|
|
98
|
+
id: payload.id,
|
|
99
|
+
key: payload.key,
|
|
100
|
+
value,
|
|
101
|
+
from,
|
|
102
|
+
occurrence: payload.occurrence,
|
|
103
|
+
});
|
|
77
104
|
return {
|
|
78
105
|
kind: EDIT_SOURCE_KIND,
|
|
79
106
|
label: init.label ?? defaultLabel(payload),
|
|
80
107
|
async do() {
|
|
81
|
-
await apply(payload.after);
|
|
108
|
+
await apply(payload.after, payload.before);
|
|
82
109
|
},
|
|
83
110
|
async undo() {
|
|
84
|
-
await apply(payload.before);
|
|
111
|
+
await apply(payload.before, payload.after);
|
|
85
112
|
},
|
|
86
113
|
};
|
|
87
114
|
}
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"themeDefault": {
|
|
48
48
|
"type": "string",
|
|
49
49
|
"enum": ["dark", "light"],
|
|
50
|
-
"description": "Default theme attribute (data-theme) for new canvases.",
|
|
50
|
+
"description": "Default theme attribute (data-theme) for new canvases. Can only ever be a single theme name — it is NOT the signal for whether a DS ships more than one theme. For that, check 'designSystems[].themes'.",
|
|
51
51
|
"default": "dark"
|
|
52
52
|
},
|
|
53
53
|
"tokensCssRel": {
|
|
@@ -187,7 +187,7 @@
|
|
|
187
187
|
"themes": {
|
|
188
188
|
"type": "array",
|
|
189
189
|
"items": { "type": "string" },
|
|
190
|
-
"description": "
|
|
190
|
+
"description": "Authoritative list of theme names this DS's tokens CSS actually ships (e.g. ['dark','light']). This is the ONLY field that should be checked to decide whether a DS is dual-theme — 'themeDefault' can never hold 'both' (enum is dark|light only), so a single-theme entry MUST still list its one theme (e.g. ['dark']), not omit the field. Bootstrap/re-bootstrap always populates this from the theme-default discovery answer. Drives the System view's theme toggle, design-system-completeness-critic V18/V18c, and /design:new step 9's per-theme reality-check capture."
|
|
191
191
|
},
|
|
192
192
|
"newCanvasDir": {
|
|
193
193
|
"type": "string",
|
|
@@ -54,7 +54,12 @@ export interface MenuItem {
|
|
|
54
54
|
/** Right-aligned shortcut hint (e.g. `⌘C`, `⌫`). */
|
|
55
55
|
shortcut?: string;
|
|
56
56
|
destructive?: boolean;
|
|
57
|
-
|
|
57
|
+
/**
|
|
58
|
+
* A FUNCTION form is resolved per-click against `target` — same rationale as
|
|
59
|
+
* the function-form `submenu` below (e.g. "Open Timeline" only enabled when
|
|
60
|
+
* THIS right-clicked artboard actually contains a video sequence).
|
|
61
|
+
*/
|
|
62
|
+
disabled?: boolean | ((target: ContextTarget) => boolean);
|
|
58
63
|
/**
|
|
59
64
|
* Optional nested flyout (e.g. `Theme ▸ DS default / Light / Dark / Follow
|
|
60
65
|
* chrome`). When present the row opens a submenu on hover / ArrowRight /
|
|
@@ -70,6 +75,13 @@ export interface MenuItem {
|
|
|
70
75
|
submenu?: MenuItem[] | ((target: ContextTarget) => MenuItem[]);
|
|
71
76
|
/** Hover/title hint shown when the item is `disabled` (a11y affordance). */
|
|
72
77
|
disabledHint?: string;
|
|
78
|
+
/**
|
|
79
|
+
* Fully REMOVE the item for a target (vs. `disabled`, which greys it in place).
|
|
80
|
+
* Resolved per-click. Use when an entry is meaningless — not merely
|
|
81
|
+
* unavailable — for the right-clicked element (e.g. "Edit Photo…" only makes
|
|
82
|
+
* sense on an `<img>`, so it shouldn't appear at all on a `<div>`).
|
|
83
|
+
*/
|
|
84
|
+
hidden?: boolean | ((target: ContextTarget) => boolean);
|
|
73
85
|
onSelect: (target: ContextTarget) => void;
|
|
74
86
|
}
|
|
75
87
|
|
|
@@ -371,9 +383,19 @@ export function ContextMenuView({
|
|
|
371
383
|
};
|
|
372
384
|
}, [target.clientX, target.clientY, onClose, pos.x, pos.y]);
|
|
373
385
|
|
|
386
|
+
// Resolve per-target `hidden` and drop now-empty sections (so a section that
|
|
387
|
+
// held only a hidden item doesn't leave a dangling separator).
|
|
388
|
+
const visibleSections = sections
|
|
389
|
+
.map((section) =>
|
|
390
|
+
section.filter((item) => {
|
|
391
|
+
const h = typeof item.hidden === 'function' ? item.hidden(target) : item.hidden;
|
|
392
|
+
return !h;
|
|
393
|
+
})
|
|
394
|
+
)
|
|
395
|
+
.filter((section) => section.length > 0);
|
|
374
396
|
return (
|
|
375
397
|
<div ref={ref} className="dc-context-menu" role="menu" style={{ left: pos.x, top: pos.y }}>
|
|
376
|
-
{
|
|
398
|
+
{visibleSections.map((section, si) => {
|
|
377
399
|
const sectionKey = section.map((i) => i.id).join('|') || `s${si}`;
|
|
378
400
|
return (
|
|
379
401
|
<div key={sectionKey} role="group">
|
|
@@ -411,17 +433,20 @@ function MenuItemRow({
|
|
|
411
433
|
// Resolve a function-form submenu against THIS click's target (e.g.
|
|
412
434
|
// "Select layer" computing candidates from `target.clientX/clientY`).
|
|
413
435
|
const submenuItems = typeof item.submenu === 'function' ? item.submenu(target) : item.submenu;
|
|
436
|
+
// Same per-click resolution for a function-form `disabled` (e.g. "Open
|
|
437
|
+
// Timeline" only enabled on an artboard that actually contains video).
|
|
438
|
+
const disabled = typeof item.disabled === 'function' ? item.disabled(target) : item.disabled;
|
|
414
439
|
|
|
415
440
|
if (!submenuItems || submenuItems.length === 0) {
|
|
416
441
|
return (
|
|
417
442
|
<button
|
|
418
443
|
type="button"
|
|
419
444
|
role="menuitem"
|
|
420
|
-
disabled={
|
|
421
|
-
title={
|
|
445
|
+
disabled={disabled}
|
|
446
|
+
title={disabled ? item.disabledHint : undefined}
|
|
422
447
|
className={`dc-menu-item${item.destructive ? ' is-destructive' : ''}`}
|
|
423
448
|
onClick={() => {
|
|
424
|
-
if (
|
|
449
|
+
if (disabled) return;
|
|
425
450
|
item.onSelect(target);
|
|
426
451
|
onClose();
|
|
427
452
|
}}
|
|
@@ -464,7 +489,7 @@ function MenuItemRow({
|
|
|
464
489
|
role="menuitem"
|
|
465
490
|
aria-haspopup="menu"
|
|
466
491
|
aria-expanded={subOpen}
|
|
467
|
-
disabled={
|
|
492
|
+
disabled={disabled}
|
|
468
493
|
className="dc-menu-item"
|
|
469
494
|
onClick={() => (subOpen ? setSubOpen(false) : open())}
|
|
470
495
|
onKeyDown={(e) => {
|