@1agh/maude 0.24.0 → 0.25.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/package.json +8 -8
- package/plugins/design/dependencies.json +30 -2
- package/plugins/design/dev-server/annotations-context-toolbar.tsx +481 -78
- package/plugins/design/dev-server/annotations-layer.tsx +817 -170
- package/plugins/design/dev-server/api.ts +15 -1
- package/plugins/design/dev-server/bin/_enumerate-artboards-playwright.mjs +2 -2
- package/plugins/design/dev-server/bin/_html-playwright.mjs +2 -2
- package/plugins/design/dev-server/bin/_pdf-playwright.mjs +25 -8
- package/plugins/design/dev-server/bin/_png-playwright.mjs +20 -20
- package/plugins/design/dev-server/bin/_pptx-playwright.mjs +2 -2
- package/plugins/design/dev-server/bin/_pw-launch.mjs +61 -0
- package/plugins/design/dev-server/bin/_screenshot-playwright.mjs +2 -2
- package/plugins/design/dev-server/bin/_svg-playwright.mjs +125 -19
- package/plugins/design/dev-server/bin/smoke.sh +114 -12
- package/plugins/design/dev-server/canvas-arrowheads.ts +220 -0
- package/plugins/design/dev-server/canvas-comment-mount.tsx +8 -24
- package/plugins/design/dev-server/canvas-cursors.ts +130 -82
- package/plugins/design/dev-server/canvas-icons.tsx +169 -0
- package/plugins/design/dev-server/canvas-shell.tsx +113 -89
- package/plugins/design/dev-server/client/app.jsx +1084 -417
- package/plugins/design/dev-server/dist/client.bundle.js +242 -20
- package/plugins/design/dev-server/dist/comment-mount.js +40 -62
- package/plugins/design/dev-server/export-dialog.tsx +189 -1
- package/plugins/design/dev-server/exporters/html.ts +4 -1
- package/plugins/design/dev-server/exporters/index.ts +4 -1
- package/plugins/design/dev-server/exporters/pdf.ts +7 -1
- package/plugins/design/dev-server/exporters/png.ts +21 -2
- package/plugins/design/dev-server/exporters/pptx.ts +330 -201
- package/plugins/design/dev-server/exporters/scope.ts +107 -11
- package/plugins/design/dev-server/exporters/svg.ts +4 -1
- package/plugins/design/dev-server/http.ts +40 -9
- package/plugins/design/dev-server/input-router.tsx +9 -2
- package/plugins/design/dev-server/test/annotations-draw-modifiers.test.ts +206 -0
- package/plugins/design/dev-server/test/annotations-layer.test.ts +83 -3
- package/plugins/design/dev-server/test/annotations-roundtrip.test.ts +243 -0
- package/plugins/design/dev-server/test/canvas-cursors.test.ts +95 -6
- package/plugins/design/dev-server/test/canvas-route.test.ts +4 -1
- package/plugins/design/dev-server/test/exporters/png.test.ts +24 -1
- package/plugins/design/dev-server/test/exporters/pptx-deck.test.ts +112 -0
- package/plugins/design/dev-server/test/exporters/pw-launch.test.ts +49 -0
- package/plugins/design/dev-server/test/exporters/scope.test.ts +0 -0
- package/plugins/design/dev-server/test/fixtures/phase-21-annotations.svg +1 -0
- package/plugins/design/dev-server/test/input-router.test.ts +11 -4
- package/plugins/design/dev-server/test/sanitize-annotation-svg.test.ts +32 -0
- package/plugins/design/dev-server/test/use-annotation-resize.test.ts +200 -0
- package/plugins/design/dev-server/test/use-tool-mode.test.tsx +9 -11
- package/plugins/design/dev-server/tool-palette.tsx +140 -11
- package/plugins/design/dev-server/use-annotation-resize.tsx +208 -61
- package/plugins/design/dev-server/use-tool-mode.tsx +55 -9
- package/plugins/design/templates/_shell.html +36 -9
|
@@ -253,53 +253,19 @@ const HALO_CSS = `
|
|
|
253
253
|
transition: none !important;
|
|
254
254
|
}
|
|
255
255
|
}
|
|
256
|
-
/*
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
*
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
--cursor-rect: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><line x1='0.5' y1='8' x2='15.5' y2='8' stroke='%23111' stroke-width='1'/><line x1='8' y1='0.5' x2='8' y2='15.5' stroke='%23111' stroke-width='1'/><rect x='10.5' y='10.5' width='4' height='3' fill='white' stroke='%23111' stroke-width='1'/></svg>") 8 8;
|
|
270
|
-
--cursor-ellipse: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><line x1='0.5' y1='8' x2='15.5' y2='8' stroke='%23111' stroke-width='1'/><line x1='8' y1='0.5' x2='8' y2='15.5' stroke='%23111' stroke-width='1'/><ellipse cx='12.5' cy='12' rx='2.5' ry='1.5' fill='white' stroke='%23111' stroke-width='1'/></svg>") 8 8;
|
|
271
|
-
--cursor-arrow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><line x1='0.5' y1='8' x2='15.5' y2='8' stroke='%23111' stroke-width='1'/><line x1='8' y1='0.5' x2='8' y2='15.5' stroke='%23111' stroke-width='1'/><path d='M10 13 L15 13 M12.5 11 L15 13 L12.5 15' fill='none' stroke='%23111' stroke-width='1' stroke-linecap='round' stroke-linejoin='round'/></svg>") 8 8;
|
|
272
|
-
--cursor-eraser: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><rect x='3' y='9' width='8' height='5' rx='1' fill='%23ffb3da' stroke='%23111' stroke-width='1' transform='rotate(-20 7 11.5)'/><rect x='3' y='9' width='8' height='2' fill='%23d63b6e' transform='rotate(-20 7 10)' opacity='0.6'/></svg>") 8 14;
|
|
273
|
-
--cursor-comment: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16'><path d='M3 3 L14 3 L14 11 L8 11 L4 14 L4 11 L3 11 Z' fill='white' stroke='%23111' stroke-width='1' stroke-linejoin='round'/></svg>") 4 4;
|
|
274
|
-
}
|
|
275
|
-
.dc-canvas[data-active-tool="comment"],
|
|
276
|
-
.dc-canvas[data-active-tool="comment"] * {
|
|
277
|
-
cursor: var(--cursor-comment), crosshair !important;
|
|
278
|
-
}
|
|
279
|
-
.dc-canvas[data-active-tool="pen"],
|
|
280
|
-
.dc-canvas[data-active-tool="pen"] * {
|
|
281
|
-
cursor: var(--cursor-pen), crosshair !important;
|
|
282
|
-
}
|
|
283
|
-
.dc-canvas[data-active-tool="rect"],
|
|
284
|
-
.dc-canvas[data-active-tool="rect"] * {
|
|
285
|
-
cursor: var(--cursor-rect), crosshair !important;
|
|
286
|
-
}
|
|
287
|
-
.dc-canvas[data-active-tool="ellipse"],
|
|
288
|
-
.dc-canvas[data-active-tool="ellipse"] * {
|
|
289
|
-
cursor: var(--cursor-ellipse), crosshair !important;
|
|
290
|
-
}
|
|
291
|
-
.dc-canvas[data-active-tool="arrow"],
|
|
292
|
-
.dc-canvas[data-active-tool="arrow"] * {
|
|
293
|
-
cursor: var(--cursor-arrow), crosshair !important;
|
|
294
|
-
}
|
|
295
|
-
.dc-canvas[data-active-tool="hand"],
|
|
296
|
-
.dc-canvas[data-active-tool="hand"] * {
|
|
297
|
-
cursor: grab !important;
|
|
298
|
-
}
|
|
299
|
-
.dc-canvas[data-active-tool="eraser"],
|
|
300
|
-
.dc-canvas[data-active-tool="eraser"] * {
|
|
301
|
-
cursor: var(--cursor-eraser), cell !important;
|
|
302
|
-
}
|
|
256
|
+
/* Phase 24 — per-tool cursors are owned SOLELY by use-tool-mode.tsx, which
|
|
257
|
+
injects ONE unified Kenney-glyph rule ('* { cursor: <tool> !important }')
|
|
258
|
+
into the same document. The old T22 per-tool '.dc-canvas[data-active-tool=…]'
|
|
259
|
+
rules used to live here, but their higher specificity ('.class[attr] *'
|
|
260
|
+
beats '*') silently SHADOWED the new cursors for comment/pen/arrow/hand/
|
|
261
|
+
eraser — they kept showing the stale 16px glyphs (or their native fallback)
|
|
262
|
+
while move/shape/sticky/text (which had no shadowing rule) correctly showed
|
|
263
|
+
the Kenney set. Removing them lets the single source of truth win for every
|
|
264
|
+
tool. 'data-active-tool' is still set on '.dc-canvas' (see CanvasCore) and
|
|
265
|
+
keyed by canvas-lib's move-mode label cursor + use-cursor-modifiers — those
|
|
266
|
+
stay. See DDR-067 / Phase 24. NOTE: keep this comment backtick-free — it
|
|
267
|
+
lives inside the HALO_CSS template literal and a stray backtick closes it
|
|
268
|
+
(bun parse fail, DDR-067 §6). */
|
|
303
269
|
|
|
304
270
|
/* T31 — Level of detail. Below 0.35 zoom we hide pre-attentive chrome that
|
|
305
271
|
becomes visual noise (corner ticks, distance pills, active-artboard ring,
|
|
@@ -352,12 +318,12 @@ export function CanvasShell({
|
|
|
352
318
|
}) {
|
|
353
319
|
ensureHaloStyles();
|
|
354
320
|
|
|
355
|
-
//
|
|
356
|
-
// postMessage handler in CanvasRouter updates
|
|
357
|
-
//
|
|
358
|
-
//
|
|
359
|
-
//
|
|
360
|
-
//
|
|
321
|
+
// theme-default-follow — every un-pinned artboard tracks the chrome theme.
|
|
322
|
+
// When it flips (the theme postMessage handler in CanvasRouter updates
|
|
323
|
+
// `data-maude-theme` on <html>), re-theme them. A single observer per canvas
|
|
324
|
+
// (cleaned up on unmount) — no per-artboard listeners to leak. The rule is a
|
|
325
|
+
// CSS block keyed by data-dc-screen (see rebuildArtboardThemeStyle), so it
|
|
326
|
+
// survives React re-renders without flicker.
|
|
361
327
|
useEffect(() => {
|
|
362
328
|
if (typeof MutationObserver === 'undefined' || typeof document === 'undefined') return;
|
|
363
329
|
const obs = new MutationObserver(() => applyArtboardFollowers());
|
|
@@ -365,7 +331,23 @@ export function CanvasShell({
|
|
|
365
331
|
attributes: true,
|
|
366
332
|
attributeFilter: ['data-maude-theme'],
|
|
367
333
|
});
|
|
368
|
-
|
|
334
|
+
// Initial follow — theme every un-pinned artboard once the DS stylesheet has
|
|
335
|
+
// parsed. The observer only fires on a `data-maude-theme` CHANGE, which may
|
|
336
|
+
// not happen on first paint (the chrome theme can already equal the canvas
|
|
337
|
+
// default), so first paint needs its own trigger. `window 'load'` guarantees
|
|
338
|
+
// every <link>/<style> sheet is parsed → collectThemeDeclarations sees the
|
|
339
|
+
// DS tokens. Runs immediately if the document is already complete.
|
|
340
|
+
let onLoad: (() => void) | null = null;
|
|
341
|
+
if (document.readyState === 'complete') {
|
|
342
|
+
applyArtboardFollowers();
|
|
343
|
+
} else {
|
|
344
|
+
onLoad = () => applyArtboardFollowers();
|
|
345
|
+
window.addEventListener('load', onLoad, { once: true });
|
|
346
|
+
}
|
|
347
|
+
return () => {
|
|
348
|
+
obs.disconnect();
|
|
349
|
+
if (onLoad) window.removeEventListener('load', onLoad);
|
|
350
|
+
};
|
|
369
351
|
}, []);
|
|
370
352
|
|
|
371
353
|
// ToolProvider is mounted by DesignCanvas one level up (so the viewport
|
|
@@ -715,11 +697,14 @@ function CanvasCore({
|
|
|
715
697
|
}
|
|
716
698
|
|
|
717
699
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
718
|
-
//
|
|
719
|
-
//
|
|
720
|
-
//
|
|
721
|
-
//
|
|
722
|
-
//
|
|
700
|
+
// Artboard theme (D9 + theme-default-follow, 2026-05-31). The status-bar theme
|
|
701
|
+
// toggle (vpravo dole) is the SINGLE SOURCE OF TRUTH: the canvas-shell chrome
|
|
702
|
+
// AND every artboard follow it by default via `data-maude-theme`. The right-
|
|
703
|
+
// click `Theme ▸ DS default / Light / Dark / Follow chrome` submenu PINS one
|
|
704
|
+
// artboard to override that default — re-themed by stamping its content wrapper
|
|
705
|
+
// with the DS's theme-wrapper convention. (Before this date the default was the
|
|
706
|
+
// inverse — artboards kept their own DS theme and following was opt-in — which
|
|
707
|
+
// produced the recurring "canvas dark / chrome light" mismatch.)
|
|
723
708
|
//
|
|
724
709
|
// DS theme-wrapper conventions vary (`.mdcc[data-theme]`, `.app[data-theme]`,
|
|
725
710
|
// bare `[data-theme]`, …) and there's no reliable config flag, so we DETECT it
|
|
@@ -768,7 +753,12 @@ function detectDsThemeSupport(): DsThemeSupport {
|
|
|
768
753
|
}
|
|
769
754
|
}
|
|
770
755
|
document.body.removeChild(host);
|
|
771
|
-
|
|
756
|
+
// Cache only a POSITIVE detection. With follow-chrome now the artboard
|
|
757
|
+
// default, this can run on first paint — before the DS stylesheet has
|
|
758
|
+
// parsed — where the probe reads empty tokens and wrongly reports
|
|
759
|
+
// unsupported. Caching that would permanently disable theming; instead
|
|
760
|
+
// re-probe until support is confirmed (or the DS genuinely has one theme).
|
|
761
|
+
if (found.supported) _dsThemeSupport = found;
|
|
772
762
|
return found;
|
|
773
763
|
} catch {
|
|
774
764
|
return fallback;
|
|
@@ -830,12 +820,20 @@ function collectThemeDeclarations(theme: 'light' | 'dark'): string {
|
|
|
830
820
|
}
|
|
831
821
|
}
|
|
832
822
|
}
|
|
833
|
-
|
|
823
|
+
// Cache only a NON-EMPTY result — same first-paint race as detectDsThemeSupport:
|
|
824
|
+
// a scan that runs before the DS stylesheet parses finds nothing, and caching
|
|
825
|
+
// '' would freeze the artboard un-themed forever. Leave it uncached so the
|
|
826
|
+
// post-load rebuild (window 'load' / the theme MutationObserver) repopulates it.
|
|
827
|
+
if (decls) _themeDecls[theme] = decls;
|
|
834
828
|
return decls;
|
|
835
829
|
}
|
|
836
830
|
|
|
837
|
-
|
|
838
|
-
|
|
831
|
+
// Every artboard FOLLOWS the chrome theme by default (the status-bar toggle is
|
|
832
|
+
// the source of truth). A per-artboard pin OVERRIDES that: 'ds' = the design
|
|
833
|
+
// system's native theme (opt out of following entirely), 'light' / 'dark' = a
|
|
834
|
+
// fixed theme. Absence from this map = follow chrome.
|
|
835
|
+
type ArtboardPin = 'ds' | 'light' | 'dark';
|
|
836
|
+
const _artboardPins = new Map<string, ArtboardPin>();
|
|
839
837
|
|
|
840
838
|
function cssEsc(v: string): string {
|
|
841
839
|
return typeof CSS !== 'undefined' && CSS.escape ? CSS.escape(v) : v;
|
|
@@ -854,6 +852,21 @@ function artboardScopeSelector(screenId: string): string {
|
|
|
854
852
|
return `${base} [data-theme],${base}[data-theme]`;
|
|
855
853
|
}
|
|
856
854
|
|
|
855
|
+
// Like artboardScopeSelector but matches EVERY artboard except the pinned ones —
|
|
856
|
+
// backs the default-follow rule, which themes all un-pinned artboards in one
|
|
857
|
+
// declaration. Pinned ids are :not()-excluded so the per-screen pin rule never
|
|
858
|
+
// has to out-specify this global one (they target disjoint elements).
|
|
859
|
+
function globalArtboardScopeSelector(excludeIds: string[]): string {
|
|
860
|
+
const { wrapperClass } = detectDsThemeSupport();
|
|
861
|
+
const not = excludeIds.map((id) => `:not([data-dc-screen="${cssEsc(id)}"])`).join('');
|
|
862
|
+
const base = `[data-dc-screen]${not}`;
|
|
863
|
+
if (wrapperClass) {
|
|
864
|
+
const c = cssEsc(wrapperClass);
|
|
865
|
+
return `${base} .${c},${base}.${c}`;
|
|
866
|
+
}
|
|
867
|
+
return `${base} [data-theme],${base}[data-theme]`;
|
|
868
|
+
}
|
|
869
|
+
|
|
857
870
|
function rebuildArtboardThemeStyle(): void {
|
|
858
871
|
if (typeof document === 'undefined') return;
|
|
859
872
|
let el = document.getElementById('dc-artboard-theme-css') as HTMLStyleElement | null;
|
|
@@ -863,8 +876,20 @@ function rebuildArtboardThemeStyle(): void {
|
|
|
863
876
|
document.head.appendChild(el);
|
|
864
877
|
}
|
|
865
878
|
let css = '';
|
|
866
|
-
|
|
867
|
-
|
|
879
|
+
// (1) Default — every un-pinned artboard follows the chrome theme. Pinned
|
|
880
|
+
// artboards are :not()-excluded so this rule never competes with their
|
|
881
|
+
// per-screen rule below. When the DS doesn't define the chrome theme's tokens
|
|
882
|
+
// (collectThemeDeclarations → ''), nothing is emitted and the artboard keeps
|
|
883
|
+
// its native DS theme — there's no alternate palette to follow to.
|
|
884
|
+
const pinnedIds = [..._artboardPins.keys()];
|
|
885
|
+
const followDecls = collectThemeDeclarations(currentChromeTheme());
|
|
886
|
+
if (followDecls) css += `${globalArtboardScopeSelector(pinnedIds)}{${followDecls}}\n`;
|
|
887
|
+
// (2) Explicit per-artboard pins. 'ds' emits nothing (the :not() above already
|
|
888
|
+
// released that artboard back to its native DS theme); 'light' / 'dark'
|
|
889
|
+
// re-declare the chosen theme's tokens scoped to that one artboard.
|
|
890
|
+
for (const [screenId, pin] of _artboardPins) {
|
|
891
|
+
if (pin === 'ds') continue;
|
|
892
|
+
const decls = collectThemeDeclarations(pin);
|
|
868
893
|
if (decls) css += `${artboardScopeSelector(screenId)}{${decls}}\n`;
|
|
869
894
|
}
|
|
870
895
|
el.textContent = css;
|
|
@@ -877,28 +902,26 @@ function currentChromeTheme(): 'light' | 'dark' {
|
|
|
877
902
|
}
|
|
878
903
|
|
|
879
904
|
/**
|
|
880
|
-
*
|
|
881
|
-
*
|
|
882
|
-
*
|
|
905
|
+
* Pin a single artboard's theme (keyed by its stable `data-dc-screen` id), or
|
|
906
|
+
* clear the pin so it returns to the default — following the chrome theme.
|
|
907
|
+
* 'follow' → remove the pin (default: track the chrome theme toggle)
|
|
908
|
+
* 'ds' → pin to the design system's native theme (stop following)
|
|
909
|
+
* 'light' / 'dark' → pin to a fixed theme
|
|
883
910
|
*/
|
|
884
|
-
function setArtboardTheme(screenId: string,
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
_artboardFollowers.add(screenId);
|
|
888
|
-
_artboardThemes.set(screenId, currentChromeTheme());
|
|
889
|
-
} else if (theme === null) {
|
|
890
|
-
_artboardThemes.delete(screenId);
|
|
891
|
-
} else {
|
|
892
|
-
_artboardThemes.set(screenId, theme);
|
|
893
|
-
}
|
|
911
|
+
function setArtboardTheme(screenId: string, mode: 'follow' | ArtboardPin): void {
|
|
912
|
+
if (mode === 'follow') _artboardPins.delete(screenId);
|
|
913
|
+
else _artboardPins.set(screenId, mode);
|
|
894
914
|
rebuildArtboardThemeStyle();
|
|
895
915
|
}
|
|
896
916
|
|
|
897
|
-
/**
|
|
917
|
+
/**
|
|
918
|
+
* Re-theme every following artboard when the chrome theme flips. The
|
|
919
|
+
* default-follow rule in rebuildArtboardThemeStyle reads currentChromeTheme()
|
|
920
|
+
* live, so a plain rebuild re-points every un-pinned artboard at the new theme
|
|
921
|
+
* in one shot. Kept under the original name so the MutationObserver call site
|
|
922
|
+
* and the initial 'load' trigger stay untouched.
|
|
923
|
+
*/
|
|
898
924
|
function applyArtboardFollowers(): void {
|
|
899
|
-
if (_artboardFollowers.size === 0) return;
|
|
900
|
-
const t = currentChromeTheme();
|
|
901
|
-
for (const id of _artboardFollowers) _artboardThemes.set(id, t);
|
|
902
925
|
rebuildArtboardThemeStyle();
|
|
903
926
|
}
|
|
904
927
|
|
|
@@ -986,10 +1009,11 @@ function buildRegistry(deps: {
|
|
|
986
1009
|
},
|
|
987
1010
|
});
|
|
988
1011
|
|
|
989
|
-
//
|
|
990
|
-
// (target.artboardId) via an injected stylesheet (see setArtboardTheme).
|
|
991
|
-
//
|
|
992
|
-
//
|
|
1012
|
+
// Per-artboard theme PIN, keyed by the stable `data-dc-screen` id
|
|
1013
|
+
// (target.artboardId) via an injected stylesheet (see setArtboardTheme).
|
|
1014
|
+
// Following the chrome theme is the default; this submenu overrides it for one
|
|
1015
|
+
// artboard. The DS-supports-both probe gates Light / Dark / "Follow chrome"
|
|
1016
|
+
// (all no-ops on a single-theme DS); only "DS default" is always meaningful.
|
|
993
1017
|
const themeSupport = detectDsThemeSupport();
|
|
994
1018
|
const themeHint = 'This design system defines only one theme';
|
|
995
1019
|
const themeItem: MenuItem = {
|
|
@@ -1003,7 +1027,7 @@ function buildRegistry(deps: {
|
|
|
1003
1027
|
id: 'theme-ds-default',
|
|
1004
1028
|
label: 'DS default',
|
|
1005
1029
|
onSelect: (target) => {
|
|
1006
|
-
if (target.artboardId) setArtboardTheme(target.artboardId,
|
|
1030
|
+
if (target.artboardId) setArtboardTheme(target.artboardId, 'ds');
|
|
1007
1031
|
},
|
|
1008
1032
|
},
|
|
1009
1033
|
{
|
|
@@ -1026,11 +1050,11 @@ function buildRegistry(deps: {
|
|
|
1026
1050
|
},
|
|
1027
1051
|
{
|
|
1028
1052
|
id: 'theme-follow',
|
|
1029
|
-
label: 'Follow chrome',
|
|
1053
|
+
label: 'Follow chrome (default)',
|
|
1030
1054
|
disabled: !themeSupport.supported,
|
|
1031
1055
|
disabledHint: themeHint,
|
|
1032
1056
|
onSelect: (target) => {
|
|
1033
|
-
if (target.artboardId) setArtboardTheme(target.artboardId,
|
|
1057
|
+
if (target.artboardId) setArtboardTheme(target.artboardId, 'follow');
|
|
1034
1058
|
},
|
|
1035
1059
|
},
|
|
1036
1060
|
],
|