@monoes/monomindcli 2.14.1 → 2.15.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/.claude/helpers/control-start.cjs +10 -13
- package/.claude/skills/monodesign/scripts/context.mjs +4 -4
- package/.claude/skills/monodesign/scripts/critique-storage.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detect-csp.mjs +1 -6
- package/.claude/skills/monodesign/scripts/detector/browser/injected/index.mjs +16 -18
- package/.claude/skills/monodesign/scripts/detector/cli/main.mjs +3 -3
- package/.claude/skills/monodesign/scripts/detector/detect-antipatterns-browser.js +67 -47
- package/.claude/skills/monodesign/scripts/detector/engines/regex/detect-text.mjs +6 -6
- package/.claude/skills/monodesign/scripts/detector/engines/static-html/css-cascade.mjs +6 -5
- package/.claude/skills/monodesign/scripts/detector/engines/static-html/detect-html.mjs +6 -6
- package/.claude/skills/monodesign/scripts/detector/fix/index.mjs +3 -3
- package/.claude/skills/monodesign/scripts/detector/node/file-system.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/registry/antipatterns.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/rules/checks.mjs +24 -25
- package/.claude/skills/monodesign/scripts/detector/shared/color.mjs +2 -2
- package/.claude/skills/monodesign/scripts/detector/shared/constants.mjs +1 -1
- package/.claude/skills/monodesign/scripts/detector/shared/inline-ignores.mjs +2 -2
- package/.claude/skills/monodesign/scripts/hook-admin.mjs +6 -6
- package/.claude/skills/monodesign/scripts/hook-before-edit.mjs +4 -4
- package/.claude/skills/monodesign/scripts/hook-lib.mjs +20 -11
- package/.claude/skills/monodesign/scripts/hook.mjs +1 -1
- package/.claude/skills/monodesign/scripts/lib/design-parser.mjs +9 -42
- package/.claude/skills/monodesign/scripts/lib/is-generated.mjs +1 -1
- package/.claude/skills/monodesign/scripts/lib/monodesign-config.mjs +5 -5
- package/.claude/skills/monodesign/scripts/lib/monodesign-paths.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live/event-validation.mjs +13 -13
- package/.claude/skills/monodesign/scripts/live/manual-apply.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live/manual-edits-buffer.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live/session-store.mjs +5 -5
- package/.claude/skills/monodesign/scripts/live/svelte-component.mjs +13 -13
- package/.claude/skills/monodesign/scripts/live/sveltekit-adapter.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live/ui-core.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live-accept.mjs +24 -24
- package/.claude/skills/monodesign/scripts/live-browser-dom.js +8 -7
- package/.claude/skills/monodesign/scripts/live-browser-session.js +8 -7
- package/.claude/skills/monodesign/scripts/live-browser.js +405 -432
- package/.claude/skills/monodesign/scripts/live-commit-manual-edits.mjs +6 -6
- package/.claude/skills/monodesign/scripts/live-copy-edit-agent.mjs +2 -2
- package/.claude/skills/monodesign/scripts/live-discard-manual-edits.mjs +1 -1
- package/.claude/skills/monodesign/scripts/live-inject.mjs +7 -7
- package/.claude/skills/monodesign/scripts/live-insert.mjs +11 -11
- package/.claude/skills/monodesign/scripts/live-manual-edit-evidence.mjs +4 -4
- package/.claude/skills/monodesign/scripts/live-poll.mjs +5 -5
- package/.claude/skills/monodesign/scripts/live-server.mjs +10 -10
- package/.claude/skills/monodesign/scripts/live-wrap.mjs +31 -41
- package/.claude/skills/monodesign/scripts/live.mjs +5 -5
- package/.claude/skills/monodesign/scripts/palette.mjs +3 -1
- package/.claude/skills/monodesign/scripts/pin.mjs +1 -1
- package/dist/src/commands/doc-filters.d.ts.map +1 -1
- package/dist/src/commands/doc-filters.js +6 -0
- package/dist/src/commands/doc-filters.js.map +1 -1
- package/dist/src/commands/doc-library.d.ts +2 -1
- package/dist/src/commands/doc-library.d.ts.map +1 -1
- package/dist/src/commands/doc-library.js +66 -2
- package/dist/src/commands/doc-library.js.map +1 -1
- package/dist/src/commands/doc.d.ts.map +1 -1
- package/dist/src/commands/doc.js +2 -0
- package/dist/src/commands/doc.js.map +1 -1
- package/dist/src/commands/ui.d.ts.map +1 -1
- package/dist/src/commands/ui.js +60 -0
- package/dist/src/commands/ui.js.map +1 -1
- package/dist/src/knowledge/capture-envelope.d.ts +5 -0
- package/dist/src/knowledge/capture-envelope.d.ts.map +1 -1
- package/dist/src/knowledge/capture-envelope.js +2 -0
- package/dist/src/knowledge/capture-envelope.js.map +1 -1
- package/dist/src/knowledge/document-chunking.d.ts +42 -0
- package/dist/src/knowledge/document-chunking.d.ts.map +1 -0
- package/dist/src/knowledge/document-chunking.js +288 -0
- package/dist/src/knowledge/document-chunking.js.map +1 -0
- package/dist/src/knowledge/document-index.d.ts +124 -0
- package/dist/src/knowledge/document-index.d.ts.map +1 -0
- package/dist/src/knowledge/document-index.js +314 -0
- package/dist/src/knowledge/document-index.js.map +1 -0
- package/dist/src/knowledge/document-ingest.d.ts +23 -0
- package/dist/src/knowledge/document-ingest.d.ts.map +1 -0
- package/dist/src/knowledge/document-ingest.js +368 -0
- package/dist/src/knowledge/document-ingest.js.map +1 -0
- package/dist/src/knowledge/document-pipeline.d.ts +26 -208
- package/dist/src/knowledge/document-pipeline.d.ts.map +1 -1
- package/dist/src/knowledge/document-pipeline.js +25 -1104
- package/dist/src/knowledge/document-pipeline.js.map +1 -1
- package/dist/src/knowledge/document-search.d.ts +27 -0
- package/dist/src/knowledge/document-search.d.ts.map +1 -0
- package/dist/src/knowledge/document-search.js +138 -0
- package/dist/src/knowledge/document-search.js.map +1 -0
- package/dist/src/knowledge/document-store.d.ts +28 -0
- package/dist/src/knowledge/document-store.d.ts.map +1 -0
- package/dist/src/knowledge/document-store.js +61 -0
- package/dist/src/knowledge/document-store.js.map +1 -0
- package/dist/src/knowledge/document-types.d.ts +103 -0
- package/dist/src/knowledge/document-types.d.ts.map +1 -0
- package/dist/src/knowledge/document-types.js +12 -0
- package/dist/src/knowledge/document-types.js.map +1 -0
- package/dist/src/knowledge/highlights.d.ts +168 -0
- package/dist/src/knowledge/highlights.d.ts.map +1 -0
- package/dist/src/knowledge/highlights.js +311 -0
- package/dist/src/knowledge/highlights.js.map +1 -0
- package/dist/src/knowledge/lookup.d.ts +80 -0
- package/dist/src/knowledge/lookup.d.ts.map +1 -0
- package/dist/src/knowledge/lookup.js +156 -0
- package/dist/src/knowledge/lookup.js.map +1 -0
- package/dist/src/knowledge/okf-bundle.d.ts +19 -0
- package/dist/src/knowledge/okf-bundle.d.ts.map +1 -0
- package/dist/src/knowledge/okf-bundle.js +106 -0
- package/dist/src/knowledge/okf-bundle.js.map +1 -0
- package/dist/src/knowledge/profile-store.d.ts +134 -0
- package/dist/src/knowledge/profile-store.d.ts.map +1 -0
- package/dist/src/knowledge/profile-store.js +237 -0
- package/dist/src/knowledge/profile-store.js.map +1 -0
- package/dist/src/orgrt/agent-runner.d.ts +4 -0
- package/dist/src/orgrt/agent-runner.d.ts.map +1 -1
- package/dist/src/orgrt/agent-runner.js +22 -0
- package/dist/src/orgrt/agent-runner.js.map +1 -1
- package/dist/src/orgrt/antigravity-runner.d.ts.map +1 -1
- package/dist/src/orgrt/antigravity-runner.js +2 -1
- package/dist/src/orgrt/antigravity-runner.js.map +1 -1
- package/dist/src/orgrt/authority-mask.d.ts +32 -0
- package/dist/src/orgrt/authority-mask.d.ts.map +1 -0
- package/dist/src/orgrt/authority-mask.js +135 -0
- package/dist/src/orgrt/authority-mask.js.map +1 -0
- package/dist/src/orgrt/codex-runner.d.ts.map +1 -1
- package/dist/src/orgrt/codex-runner.js +2 -1
- package/dist/src/orgrt/codex-runner.js.map +1 -1
- package/dist/src/orgrt/copilot-runner.d.ts.map +1 -1
- package/dist/src/orgrt/copilot-runner.js +2 -1
- package/dist/src/orgrt/copilot-runner.js.map +1 -1
- package/dist/src/orgrt/crush-runner.d.ts.map +1 -1
- package/dist/src/orgrt/crush-runner.js +6 -1
- package/dist/src/orgrt/crush-runner.js.map +1 -1
- package/dist/src/orgrt/daemon.d.ts +4 -0
- package/dist/src/orgrt/daemon.d.ts.map +1 -1
- package/dist/src/orgrt/daemon.js +13 -2
- package/dist/src/orgrt/daemon.js.map +1 -1
- package/dist/src/orgrt/decisions.d.ts +9 -0
- package/dist/src/orgrt/decisions.d.ts.map +1 -1
- package/dist/src/orgrt/decisions.js +32 -5
- package/dist/src/orgrt/decisions.js.map +1 -1
- package/dist/src/orgrt/file-roots.d.ts +2 -1
- package/dist/src/orgrt/file-roots.d.ts.map +1 -1
- package/dist/src/orgrt/file-roots.js +7 -3
- package/dist/src/orgrt/file-roots.js.map +1 -1
- package/dist/src/orgrt/grok-runner.d.ts.map +1 -1
- package/dist/src/orgrt/grok-runner.js +2 -1
- package/dist/src/orgrt/grok-runner.js.map +1 -1
- package/dist/src/orgrt/hermes-runner.d.ts.map +1 -1
- package/dist/src/orgrt/hermes-runner.js +2 -1
- package/dist/src/orgrt/hermes-runner.js.map +1 -1
- package/dist/src/orgrt/inbox.d.ts.map +1 -1
- package/dist/src/orgrt/inbox.js +70 -4
- package/dist/src/orgrt/inbox.js.map +1 -1
- package/dist/src/orgrt/kimicode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/kimicode-runner.js +2 -1
- package/dist/src/orgrt/kimicode-runner.js.map +1 -1
- package/dist/src/orgrt/opencode-runner.d.ts.map +1 -1
- package/dist/src/orgrt/opencode-runner.js +3 -2
- package/dist/src/orgrt/opencode-runner.js.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-rpc-runner.js +3 -2
- package/dist/src/orgrt/pi-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/pi-runner.d.ts.map +1 -1
- package/dist/src/orgrt/pi-runner.js +2 -1
- package/dist/src/orgrt/pi-runner.js.map +1 -1
- package/dist/src/orgrt/policy.d.ts.map +1 -1
- package/dist/src/orgrt/policy.js +3 -0
- package/dist/src/orgrt/policy.js.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-rpc-runner.js +3 -2
- package/dist/src/orgrt/qwen-rpc-runner.js.map +1 -1
- package/dist/src/orgrt/qwen-runner.d.ts.map +1 -1
- package/dist/src/orgrt/qwen-runner.js +2 -1
- package/dist/src/orgrt/qwen-runner.js.map +1 -1
- package/dist/src/orgrt/role-sandbox.d.ts +21 -0
- package/dist/src/orgrt/role-sandbox.d.ts.map +1 -1
- package/dist/src/orgrt/role-sandbox.js +31 -6
- package/dist/src/orgrt/role-sandbox.js.map +1 -1
- package/dist/src/orgrt/session.d.ts.map +1 -1
- package/dist/src/orgrt/session.js +21 -2
- package/dist/src/orgrt/session.js.map +1 -1
- package/dist/src/orgrt/task-dag.d.ts +3 -0
- package/dist/src/orgrt/task-dag.d.ts.map +1 -1
- package/dist/src/orgrt/task-dag.js +1 -0
- package/dist/src/orgrt/task-dag.js.map +1 -1
- package/dist/src/orgrt/types.d.ts +5 -0
- package/dist/src/orgrt/types.d.ts.map +1 -1
- package/dist/src/orgrt/types.js +23 -1
- package/dist/src/orgrt/types.js.map +1 -1
- package/dist/src/ui/dashboard.html +28 -848
- package/dist/src/ui/human-auth.mjs +103 -0
- package/dist/src/ui/org-hil.mjs +86 -37
- package/dist/src/ui/org-runtime.mjs +21 -13
- package/dist/src/ui/routes-org.mjs +49 -445
- package/dist/src/ui/server.mjs +90 -2
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* configure (pick action + go), generating (progressive dots), and cycling
|
|
10
10
|
* (prev/next + accept/discard). Feels like Spotlight, not a modal.
|
|
11
11
|
*/
|
|
12
|
-
(
|
|
12
|
+
(() => {
|
|
13
|
+
// biome-ignore lint/suspicious/noRedundantUseStrict: served to the page as a classic <script> (not an ES module despite package type=module), so this directive is what enables strict mode
|
|
13
14
|
'use strict';
|
|
14
15
|
if (typeof window === 'undefined') return;
|
|
15
16
|
|
|
@@ -57,7 +58,8 @@
|
|
|
57
58
|
const Z = { highlight: 100001, bar: 100005, picker: 100007, toast: 100010 };
|
|
58
59
|
const EASE = 'cubic-bezier(0.22, 1, 0.36, 1)'; // ease-out-quint
|
|
59
60
|
const PREFIX = 'monodesign-live';
|
|
60
|
-
const MONODESIGN_COMMAND =
|
|
61
|
+
const MONODESIGN_COMMAND = `${window.__MONODESIGN_COMMAND_PREFIX__ || '/'}monodesign`;
|
|
62
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:663
|
|
61
63
|
const PICK_CURSOR_STYLE_ID = PREFIX + '-pick-cursor-style';
|
|
62
64
|
const MANUAL_APPLY_STATE_TTL_MS = 15 * 60 * 1000;
|
|
63
65
|
const sessionState = window.__MONODESIGN_LIVE_SESSION__?.createLiveBrowserSessionState({
|
|
@@ -77,7 +79,7 @@
|
|
|
77
79
|
', height 140ms ' + EASE +
|
|
78
80
|
', opacity 150ms ease';
|
|
79
81
|
const TOOLTIP_TRANSITION =
|
|
80
|
-
|
|
82
|
+
`top 140ms ${EASE}, left 140ms ${EASE}, opacity 150ms ease`;
|
|
81
83
|
|
|
82
84
|
const SKIP_TAGS = new Set([
|
|
83
85
|
'html', 'head', 'body', 'script', 'style', 'link', 'meta', 'noscript', 'br', 'wbr',
|
|
@@ -98,20 +100,20 @@
|
|
|
98
100
|
|
|
99
101
|
const LIVE_CHROME_MOUNT_CONTRACT = ['root', 'transport', 'state', 'actions'];
|
|
100
102
|
const LIVE_UI_SURFACES = [
|
|
101
|
-
{ key: 'global-bottom-bar', ids: [PREFIX
|
|
102
|
-
{ key: 'pending-copy-edit-dock', ids: [PREFIX
|
|
103
|
-
{ key: 'element-selection-chrome', ids: [PREFIX
|
|
104
|
-
{ key: 'action-picker', ids: [PREFIX
|
|
105
|
-
{ key: 'edit-chrome', ids: [PREFIX
|
|
106
|
-
{ key: 'generating-row', ids: [PREFIX
|
|
107
|
-
{ key: 'variant-cycling-row', ids: [PREFIX
|
|
108
|
-
{ key: 'variant-params-panel', ids: [PREFIX
|
|
109
|
-
{ key: 'saving-confirmed-rows', ids: [PREFIX
|
|
110
|
-
{ key: 'insert-mode-chrome', ids: [PREFIX
|
|
111
|
-
{ key: 'annotation-chrome', ids: [PREFIX
|
|
112
|
-
{ key: 'design-system-panel', ids: [PREFIX
|
|
113
|
-
{ key: 'toasts-and-errors', ids: [PREFIX
|
|
114
|
-
{ key: 'css-isolation-boundary', ids: [PREFIX
|
|
103
|
+
{ key: 'global-bottom-bar', ids: [`${PREFIX}-global-bar`, `${PREFIX}-global-bar-brand`, `${PREFIX}-pick-toggle`, `${PREFIX}-insert-toggle`, `${PREFIX}-detect-toggle`, `${PREFIX}-detect-badge`, `${PREFIX}-design-toggle`, `${PREFIX}-page-chat`, `${PREFIX}-page-chat-input`, `${PREFIX}-page-chat-voice`] },
|
|
104
|
+
{ key: 'pending-copy-edit-dock', ids: [`${PREFIX}-pending-dock`] },
|
|
105
|
+
{ key: 'element-selection-chrome', ids: [`${PREFIX}-highlight`, `${PREFIX}-tooltip`, `${PREFIX}-bar`, `${PREFIX}-selection-pill`, `${PREFIX}-input`, `${PREFIX}-configure-voice`, `${PREFIX}-configure-bar-tooltip`] },
|
|
106
|
+
{ key: 'action-picker', ids: [`${PREFIX}-picker`] },
|
|
107
|
+
{ key: 'edit-chrome', ids: [`${PREFIX}-edit-badge`] },
|
|
108
|
+
{ key: 'generating-row', ids: [`${PREFIX}-bar`, `${PREFIX}-shader`] },
|
|
109
|
+
{ key: 'variant-cycling-row', ids: [`${PREFIX}-bar`, `${PREFIX}-params-panel`] },
|
|
110
|
+
{ key: 'variant-params-panel', ids: [`${PREFIX}-params-panel`] },
|
|
111
|
+
{ key: 'saving-confirmed-rows', ids: [`${PREFIX}-bar`] },
|
|
112
|
+
{ key: 'insert-mode-chrome', ids: [`${PREFIX}-insert-line`, `${PREFIX}-insert-placeholder`, `${PREFIX}-placeholder-resize`, `${PREFIX}-insert-input`, `${PREFIX}-insert-voice`, `${PREFIX}-insert-create`, `${PREFIX}-insert-create-tooltip`] },
|
|
113
|
+
{ key: 'annotation-chrome', ids: [`${PREFIX}-annot`, `${PREFIX}-annot-svg`, `${PREFIX}-annot-pins`, `${PREFIX}-annot-clear`] },
|
|
114
|
+
{ key: 'design-system-panel', ids: [`${PREFIX}-design-host`] },
|
|
115
|
+
{ key: 'toasts-and-errors', ids: [`${PREFIX}-toast`] },
|
|
116
|
+
{ key: 'css-isolation-boundary', ids: [`${PREFIX}-root`] },
|
|
115
117
|
];
|
|
116
118
|
const LIVE_UI_COMPONENT_IDS = [...new Set(LIVE_UI_SURFACES.flatMap((surface) => surface.ids))];
|
|
117
119
|
|
|
@@ -218,7 +220,6 @@
|
|
|
218
220
|
rectIsUsableAnchor,
|
|
219
221
|
makeFrozenAnchor,
|
|
220
222
|
id8,
|
|
221
|
-
cssId,
|
|
222
223
|
liveUiRoot,
|
|
223
224
|
uiAppend,
|
|
224
225
|
uiAppendStyle,
|
|
@@ -264,10 +265,10 @@
|
|
|
264
265
|
|
|
265
266
|
function initHighlight() {
|
|
266
267
|
highlightEl = document.createElement('div');
|
|
267
|
-
highlightEl.id = PREFIX
|
|
268
|
+
highlightEl.id = `${PREFIX}-highlight`;
|
|
268
269
|
Object.assign(highlightEl.style, {
|
|
269
270
|
position: 'fixed', top: '0', left: '0', width: '0', height: '0',
|
|
270
|
-
border:
|
|
271
|
+
border: `2px solid ${C.brand}`, borderRadius: '3px',
|
|
271
272
|
pointerEvents: 'none', zIndex: Z.highlight, boxSizing: 'border-box',
|
|
272
273
|
transition: HIGHLIGHT_TRANSITION,
|
|
273
274
|
display: 'none', opacity: '0',
|
|
@@ -275,7 +276,7 @@
|
|
|
275
276
|
uiAppend(highlightEl);
|
|
276
277
|
|
|
277
278
|
tooltipEl = document.createElement('div');
|
|
278
|
-
tooltipEl.id = PREFIX
|
|
279
|
+
tooltipEl.id = `${PREFIX}-tooltip`;
|
|
279
280
|
Object.assign(tooltipEl.style, {
|
|
280
281
|
position: 'fixed',
|
|
281
282
|
background: C.ink, color: C.white,
|
|
@@ -304,8 +305,8 @@
|
|
|
304
305
|
if (!el || !highlightEl) return;
|
|
305
306
|
if (el.hasAttribute?.('data-monodesign-insert-placeholder')) return;
|
|
306
307
|
const r = el.getBoundingClientRect();
|
|
307
|
-
const top =
|
|
308
|
-
const width =
|
|
308
|
+
const top = `${r.top - 2}px`, left = `${r.left - 2}px`;
|
|
309
|
+
const width = `${r.width + 4}px`, height = `${r.height + 4}px`;
|
|
309
310
|
const showTagTooltip = shouldShowHighlightTagTooltip();
|
|
310
311
|
|
|
311
312
|
const hiWasHidden = highlightEl.style.display === 'none' || highlightEl.style.opacity === '0';
|
|
@@ -326,8 +327,8 @@
|
|
|
326
327
|
}
|
|
327
328
|
|
|
328
329
|
const tipTop = r.top - 20;
|
|
329
|
-
const tipY =
|
|
330
|
-
const tipX = Math.max(4, r.left)
|
|
330
|
+
const tipY = `${tipTop < 4 ? r.bottom + 4 : tipTop}px`;
|
|
331
|
+
const tipX = `${Math.max(4, r.left)}px`;
|
|
331
332
|
tooltipEl.textContent = desc(el);
|
|
332
333
|
if (hiWasHidden) {
|
|
333
334
|
tooltipEl.style.transition = 'none';
|
|
@@ -361,7 +362,7 @@
|
|
|
361
362
|
let annotSvgEl = null;
|
|
362
363
|
let annotPinsEl = null;
|
|
363
364
|
let annotClearChipEl = null;
|
|
364
|
-
|
|
365
|
+
const annotState = { comments: [], strokes: [] };
|
|
365
366
|
let annotActive = false;
|
|
366
367
|
// `annotPointer` is either:
|
|
367
368
|
// { kind: 'new', x0, y0, moved, strokeEl, strokePoints } creating a stroke/pin
|
|
@@ -374,7 +375,7 @@
|
|
|
374
375
|
|
|
375
376
|
function initAnnotOverlay() {
|
|
376
377
|
annotOverlayEl = document.createElement('div');
|
|
377
|
-
annotOverlayEl.id = PREFIX
|
|
378
|
+
annotOverlayEl.id = `${PREFIX}-annot`;
|
|
378
379
|
Object.assign(annotOverlayEl.style, {
|
|
379
380
|
position: 'fixed', top: '0', left: '0', width: '0', height: '0',
|
|
380
381
|
pointerEvents: 'auto', zIndex: Z.highlight + 2,
|
|
@@ -383,7 +384,7 @@
|
|
|
383
384
|
});
|
|
384
385
|
|
|
385
386
|
annotSvgEl = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
386
|
-
annotSvgEl.id = PREFIX
|
|
387
|
+
annotSvgEl.id = `${PREFIX}-annot-svg`;
|
|
387
388
|
Object.assign(annotSvgEl.style, {
|
|
388
389
|
position: 'absolute', top: '0', left: '0',
|
|
389
390
|
width: '100%', height: '100%',
|
|
@@ -394,7 +395,7 @@
|
|
|
394
395
|
annotOverlayEl.appendChild(annotSvgEl);
|
|
395
396
|
|
|
396
397
|
annotPinsEl = document.createElement('div');
|
|
397
|
-
annotPinsEl.id = PREFIX
|
|
398
|
+
annotPinsEl.id = `${PREFIX}-annot-pins`;
|
|
398
399
|
Object.assign(annotPinsEl.style, {
|
|
399
400
|
position: 'absolute', inset: '0',
|
|
400
401
|
pointerEvents: 'none',
|
|
@@ -402,7 +403,7 @@
|
|
|
402
403
|
annotOverlayEl.appendChild(annotPinsEl);
|
|
403
404
|
|
|
404
405
|
annotClearChipEl = document.createElement('div');
|
|
405
|
-
annotClearChipEl.id = PREFIX
|
|
406
|
+
annotClearChipEl.id = `${PREFIX}-annot-clear`;
|
|
406
407
|
annotClearChipEl.dataset.annotClear = 'true';
|
|
407
408
|
annotClearChipEl.textContent = 'Clear';
|
|
408
409
|
Object.assign(annotClearChipEl.style, {
|
|
@@ -418,7 +419,7 @@
|
|
|
418
419
|
annotOverlayEl.appendChild(annotClearChipEl);
|
|
419
420
|
|
|
420
421
|
placeholderResizeLayerEl = document.createElement('div');
|
|
421
|
-
placeholderResizeLayerEl.id = PREFIX
|
|
422
|
+
placeholderResizeLayerEl.id = `${PREFIX}-placeholder-resize`;
|
|
422
423
|
Object.assign(placeholderResizeLayerEl.style, {
|
|
423
424
|
position: 'absolute',
|
|
424
425
|
inset: '0',
|
|
@@ -468,10 +469,10 @@
|
|
|
468
469
|
if (!annotOverlayEl || !el) return;
|
|
469
470
|
const r = el.getBoundingClientRect();
|
|
470
471
|
Object.assign(annotOverlayEl.style, {
|
|
471
|
-
top: r.top
|
|
472
|
-
width: r.width
|
|
472
|
+
top: `${r.top}px`, left: `${r.left}px`,
|
|
473
|
+
width: `${r.width}px`, height: `${r.height}px`,
|
|
473
474
|
});
|
|
474
|
-
annotSvgEl.setAttribute('viewBox',
|
|
475
|
+
annotSvgEl.setAttribute('viewBox', `0 0 ${r.width} ${r.height}`);
|
|
475
476
|
syncPlaceholderResizeHandles();
|
|
476
477
|
}
|
|
477
478
|
|
|
@@ -658,9 +659,9 @@
|
|
|
658
659
|
|
|
659
660
|
function pointsToPath(points) {
|
|
660
661
|
if (!points || points.length === 0) return '';
|
|
661
|
-
let d =
|
|
662
|
+
let d = `M${points[0][0].toFixed(1)} ${points[0][1].toFixed(1)}`;
|
|
662
663
|
for (let i = 1; i < points.length; i++) {
|
|
663
|
-
d +=
|
|
664
|
+
d += ` L${points[i][0].toFixed(1)} ${points[i][1].toFixed(1)}`;
|
|
664
665
|
}
|
|
665
666
|
return d;
|
|
666
667
|
}
|
|
@@ -722,7 +723,7 @@
|
|
|
722
723
|
if (interactive) wrap.dataset.annotPin = String(idx);
|
|
723
724
|
Object.assign(wrap.style, {
|
|
724
725
|
position: 'absolute',
|
|
725
|
-
left:
|
|
726
|
+
left: `${comment.x - 7}px`, top: `${comment.y - 7}px`,
|
|
726
727
|
pointerEvents: interactive ? 'auto' : 'none',
|
|
727
728
|
display: 'flex', alignItems: 'flex-start', gap: '6px',
|
|
728
729
|
cursor: interactive ? 'grab' : 'default',
|
|
@@ -731,7 +732,7 @@
|
|
|
731
732
|
const dot = document.createElement('div');
|
|
732
733
|
Object.assign(dot.style, {
|
|
733
734
|
width: '14px', height: '14px', borderRadius: '50%',
|
|
734
|
-
background: C.brand, border:
|
|
735
|
+
background: C.brand, border: `2px solid ${C.white}`,
|
|
735
736
|
boxShadow: '0 1px 3px rgba(0,0,0,0.25)',
|
|
736
737
|
flexShrink: '0',
|
|
737
738
|
});
|
|
@@ -754,7 +755,7 @@
|
|
|
754
755
|
}
|
|
755
756
|
|
|
756
757
|
function beginEditPin(idx) {
|
|
757
|
-
const wrapEl = annotPinsEl.querySelector(
|
|
758
|
+
const wrapEl = annotPinsEl.querySelector(`[data-annot-pin="${idx}"]`);
|
|
758
759
|
if (!wrapEl) return;
|
|
759
760
|
// Strip any existing bubble (but keep the dot)
|
|
760
761
|
wrapEl.querySelectorAll('div:not(:first-child)').forEach(n => n.remove());
|
|
@@ -765,7 +766,7 @@
|
|
|
765
766
|
background: C.ink, color: C.white,
|
|
766
767
|
fontFamily: FONT, fontSize: '12px', lineHeight: '1.4',
|
|
767
768
|
padding: '4px 8px', borderRadius: '3px',
|
|
768
|
-
border:
|
|
769
|
+
border: `1px solid ${C.brand}`,
|
|
769
770
|
outline: 'none', marginTop: '-2px',
|
|
770
771
|
width: '220px', pointerEvents: 'auto',
|
|
771
772
|
});
|
|
@@ -834,12 +835,12 @@
|
|
|
834
835
|
const wrap = document.createElement('div');
|
|
835
836
|
Object.assign(wrap.style, {
|
|
836
837
|
position: 'absolute', top: '0', left: '0',
|
|
837
|
-
width: rect.width
|
|
838
|
+
width: `${rect.width}px`, height: `${rect.height}px`,
|
|
838
839
|
pointerEvents: 'none', overflow: 'visible',
|
|
839
840
|
});
|
|
840
841
|
if (strokes.length > 0) {
|
|
841
842
|
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
842
|
-
svg.setAttribute('viewBox',
|
|
843
|
+
svg.setAttribute('viewBox', `0 0 ${rect.width} ${rect.height}`);
|
|
843
844
|
Object.assign(svg.style, {
|
|
844
845
|
position: 'absolute', top: '0', left: '0',
|
|
845
846
|
width: '100%', height: '100%', overflow: 'visible',
|
|
@@ -868,7 +869,7 @@
|
|
|
868
869
|
//
|
|
869
870
|
|
|
870
871
|
function stripManualEditRuntimeState(root) {
|
|
871
|
-
if (
|
|
872
|
+
if (root?.nodeType !== 1) return;
|
|
872
873
|
unwrapMixedContentTextNodes(root);
|
|
873
874
|
const nodes = [root, ...root.querySelectorAll('[data-monodesign-editable], [data-monodesign-original-text], [data-monodesign-text-wrap]')];
|
|
874
875
|
for (const node of nodes) {
|
|
@@ -891,7 +892,7 @@
|
|
|
891
892
|
}
|
|
892
893
|
|
|
893
894
|
function sanitizedContextOuterHTML(el, maxLength) {
|
|
894
|
-
if (!el
|
|
895
|
+
if (!el?.cloneNode) return '';
|
|
895
896
|
const clone = el.cloneNode(true);
|
|
896
897
|
stripManualEditRuntimeState(clone);
|
|
897
898
|
return clone.outerHTML ? clone.outerHTML.slice(0, maxLength) : '';
|
|
@@ -932,8 +933,8 @@
|
|
|
932
933
|
cssCustomProperties: props,
|
|
933
934
|
parentContext: el.parentElement
|
|
934
935
|
? '<' + el.parentElement.tagName.toLowerCase()
|
|
935
|
-
+ (el.parentElement.id ?
|
|
936
|
-
+ (el.parentElement.className ?
|
|
936
|
+
+ (el.parentElement.id ? ` id="${el.parentElement.id}"` : '')
|
|
937
|
+
+ (el.parentElement.className ? ` class="${el.parentElement.className}"` : '')
|
|
937
938
|
+ '>'
|
|
938
939
|
: null,
|
|
939
940
|
boundingRect: { width: Math.round(r.width), height: Math.round(r.height) },
|
|
@@ -967,7 +968,7 @@
|
|
|
967
968
|
}
|
|
968
969
|
|
|
969
970
|
function isUsefulManualEditContext(candidate, leafEl, editedTexts) {
|
|
970
|
-
if (!candidate
|
|
971
|
+
if (!candidate?.contains(leafEl)) return false;
|
|
971
972
|
if (!candidate.id && candidate.classList.length === 0 && candidate.children.length < 2) return false;
|
|
972
973
|
return collectManualContextPieces(candidate, editedTexts).length > 0;
|
|
973
974
|
}
|
|
@@ -1026,16 +1027,16 @@
|
|
|
1026
1027
|
function initBar() {
|
|
1027
1028
|
BP = barPaletteForTheme(detectPageTheme());
|
|
1028
1029
|
barEl = document.createElement('div');
|
|
1029
|
-
barEl.id = PREFIX
|
|
1030
|
+
barEl.id = `${PREFIX}-bar`;
|
|
1030
1031
|
Object.assign(barEl.style, {
|
|
1031
1032
|
position: 'fixed', zIndex: Z.bar,
|
|
1032
1033
|
display: 'none', opacity: '0',
|
|
1033
1034
|
transform: 'translateY(6px)',
|
|
1034
1035
|
background: BP.surface,
|
|
1035
|
-
border:
|
|
1036
|
+
border: `1px solid ${BP.border}`,
|
|
1036
1037
|
borderRadius: '8px',
|
|
1037
1038
|
boxShadow: BP.shadow,
|
|
1038
|
-
transition:
|
|
1039
|
+
transition: `box-shadow 0.2s ease, opacity 0.25s ${EASE}, transform 0.3s ${EASE}`,
|
|
1039
1040
|
fontFamily: FONT, fontSize: '13px', color: BP.text,
|
|
1040
1041
|
padding: '5px',
|
|
1041
1042
|
maxWidth: '560px', minWidth: '340px',
|
|
@@ -1061,7 +1062,7 @@
|
|
|
1061
1062
|
: GLOBAL_BAR_RESERVE;
|
|
1062
1063
|
const top = window.innerHeight - barH - reserve;
|
|
1063
1064
|
const left = Math.max(GAP, (window.innerWidth - barW) / 2);
|
|
1064
|
-
Object.assign(barEl.style, { top: top
|
|
1065
|
+
Object.assign(barEl.style, { top: `${top}px`, left: `${left}px` });
|
|
1065
1066
|
return;
|
|
1066
1067
|
}
|
|
1067
1068
|
|
|
@@ -1086,7 +1087,7 @@
|
|
|
1086
1087
|
let left = r.left + (r.width - barW) / 2;
|
|
1087
1088
|
if (left < GAP) left = GAP;
|
|
1088
1089
|
if (left + barW > window.innerWidth - GAP) left = window.innerWidth - barW - GAP;
|
|
1089
|
-
Object.assign(barEl.style, { top: top
|
|
1090
|
+
Object.assign(barEl.style, { top: `${top}px`, left: `${left}px` });
|
|
1090
1091
|
}
|
|
1091
1092
|
|
|
1092
1093
|
function showBar(mode) {
|
|
@@ -1183,13 +1184,13 @@
|
|
|
1183
1184
|
barEl.style.padding = '5px';
|
|
1184
1185
|
barEl.style.background = BP.surface;
|
|
1185
1186
|
barEl.style.overflow = '';
|
|
1186
|
-
barEl.style.border =
|
|
1187
|
+
barEl.style.border = `1px solid ${BP.border}`;
|
|
1187
1188
|
barEl.style.borderColor = BP.border;
|
|
1188
1189
|
barEl.style.boxShadow = BP.shadow;
|
|
1189
1190
|
}
|
|
1190
1191
|
|
|
1191
1192
|
function syncConfigureInputChrome() {
|
|
1192
|
-
const input = uiGetById(PREFIX
|
|
1193
|
+
const input = uiGetById(`${PREFIX}-input`) || uiGetById(`${PREFIX}-insert-input`);
|
|
1193
1194
|
const surface = barEl?.dataset.configureSurface === 'true' ? barEl : null;
|
|
1194
1195
|
if (!surface || !input) return;
|
|
1195
1196
|
const focused = activeElementDeep() === input;
|
|
@@ -1231,6 +1232,7 @@
|
|
|
1231
1232
|
};
|
|
1232
1233
|
}
|
|
1233
1234
|
|
|
1235
|
+
// biome-ignore-start lint/style/useTemplate: padding source pinned by tests/live-browser-regression.test.mjs:778 (a comment inside the body would overflow its {0,120} window)
|
|
1234
1236
|
function configureInputShellStyle() {
|
|
1235
1237
|
return {
|
|
1236
1238
|
display: 'flex', alignItems: 'center', gap: '6px',
|
|
@@ -1238,6 +1240,7 @@
|
|
|
1238
1240
|
padding: '0 6px 0 ' + CONFIGURE_BAR_INSET,
|
|
1239
1241
|
};
|
|
1240
1242
|
}
|
|
1243
|
+
// biome-ignore-end lint/style/useTemplate: see above
|
|
1241
1244
|
|
|
1242
1245
|
function configureSelectionPillStyle(extra = {}) {
|
|
1243
1246
|
const P = configureBarPalette();
|
|
@@ -1260,12 +1263,13 @@
|
|
|
1260
1263
|
};
|
|
1261
1264
|
}
|
|
1262
1265
|
|
|
1266
|
+
// biome-ignore lint/correctness/noUnusedVariables: kept as the configure-row chip style contract pinned by tests/live-browser-regression.test.mjs
|
|
1263
1267
|
function configureModifierPillStyle(extra = {}) {
|
|
1264
1268
|
const P = configureBarPalette();
|
|
1265
1269
|
return {
|
|
1266
1270
|
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
|
1267
1271
|
gap: '2px', height: 'auto', minHeight: CONFIGURE_ROW_TRACK_H,
|
|
1268
|
-
padding: CONFIGURE_PILL_PAD_Y
|
|
1272
|
+
padding: `${CONFIGURE_PILL_PAD_Y} 8px`, flexShrink: '0',
|
|
1269
1273
|
boxSizing: 'border-box',
|
|
1270
1274
|
border: '1px solid transparent',
|
|
1271
1275
|
borderRadius: CONFIGURE_PILL_RADIUS,
|
|
@@ -1307,21 +1311,6 @@
|
|
|
1307
1311
|
});
|
|
1308
1312
|
}
|
|
1309
1313
|
|
|
1310
|
-
function bindConfigureModifierPillHover(btn, controlsLocked) {
|
|
1311
|
-
btn.addEventListener('mouseenter', () => {
|
|
1312
|
-
if (controlsLocked) return;
|
|
1313
|
-
const P = configureBarPalette();
|
|
1314
|
-
btn.style.color = P.text;
|
|
1315
|
-
btn.style.background = P.toggleActive;
|
|
1316
|
-
});
|
|
1317
|
-
btn.addEventListener('mouseleave', () => {
|
|
1318
|
-
if (controlsLocked) return;
|
|
1319
|
-
const P = configureBarPalette();
|
|
1320
|
-
btn.style.color = P.textDim;
|
|
1321
|
-
btn.style.background = 'transparent';
|
|
1322
|
-
});
|
|
1323
|
-
}
|
|
1324
|
-
|
|
1325
1314
|
let configureBarTooltipEl = null;
|
|
1326
1315
|
|
|
1327
1316
|
function ensureConfigureBarTooltip() {
|
|
@@ -1336,7 +1325,7 @@
|
|
|
1336
1325
|
padding: '6px 9px',
|
|
1337
1326
|
borderRadius: '7px',
|
|
1338
1327
|
background: P.chatSurface,
|
|
1339
|
-
border:
|
|
1328
|
+
border: `1px solid ${P.hairline}`,
|
|
1340
1329
|
boxShadow: P.shadow,
|
|
1341
1330
|
color: P.text,
|
|
1342
1331
|
fontFamily: FONT,
|
|
@@ -1347,7 +1336,7 @@
|
|
|
1347
1336
|
whiteSpace: 'normal',
|
|
1348
1337
|
wordBreak: 'break-word',
|
|
1349
1338
|
});
|
|
1350
|
-
configureBarTooltipEl.id = PREFIX
|
|
1339
|
+
configureBarTooltipEl.id = `${PREFIX}-configure-bar-tooltip`;
|
|
1351
1340
|
uiAppend(configureBarTooltipEl);
|
|
1352
1341
|
return configureBarTooltipEl;
|
|
1353
1342
|
}
|
|
@@ -1364,8 +1353,8 @@
|
|
|
1364
1353
|
const tipH = tip.offsetHeight;
|
|
1365
1354
|
const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
|
|
1366
1355
|
const top = Math.max(8, r.top - tipH - 8);
|
|
1367
|
-
tip.style.left = left
|
|
1368
|
-
tip.style.top = top
|
|
1356
|
+
tip.style.left = `${left}px`;
|
|
1357
|
+
tip.style.top = `${top}px`;
|
|
1369
1358
|
}
|
|
1370
1359
|
|
|
1371
1360
|
function hideConfigureBarTooltip() {
|
|
@@ -1386,8 +1375,8 @@
|
|
|
1386
1375
|
let node = el;
|
|
1387
1376
|
while (node && node.nodeType === 1 && node !== document.body) {
|
|
1388
1377
|
let part = node.tagName.toLowerCase();
|
|
1389
|
-
if (node.id) part +=
|
|
1390
|
-
else if (node.classList?.length) part +=
|
|
1378
|
+
if (node.id) part += `#${node.id}`;
|
|
1379
|
+
else if (node.classList?.length) part += `.${[...node.classList].slice(0, 2).join('.')}`;
|
|
1391
1380
|
parts.unshift(part);
|
|
1392
1381
|
node = node.parentElement;
|
|
1393
1382
|
if (parts.length >= maxDepth) break;
|
|
@@ -1398,7 +1387,7 @@
|
|
|
1398
1387
|
function variantCountTooltipText(count) {
|
|
1399
1388
|
const n = Number(count) || selectedCount;
|
|
1400
1389
|
const word = n === 1 ? 'variant' : 'variants';
|
|
1401
|
-
return
|
|
1390
|
+
return `Click to change \u00b7 ${n} ${word}`;
|
|
1402
1391
|
}
|
|
1403
1392
|
|
|
1404
1393
|
function removeConfigureSelection() {
|
|
@@ -1416,9 +1405,9 @@
|
|
|
1416
1405
|
const path = elementPath(targetEl);
|
|
1417
1406
|
const P = configureBarPalette();
|
|
1418
1407
|
const pill = el('button', configureSelectionPillStyle({ minWidth: '32px' }));
|
|
1419
|
-
pill.id = PREFIX
|
|
1408
|
+
pill.id = `${PREFIX}-selection-pill`;
|
|
1420
1409
|
pill.type = 'button';
|
|
1421
|
-
pill.setAttribute('aria-label',
|
|
1410
|
+
pill.setAttribute('aria-label', `Selected element: ${tag}`);
|
|
1422
1411
|
pill.disabled = controlsLocked;
|
|
1423
1412
|
pill.style.cursor = controlsLocked ? 'not-allowed' : 'pointer';
|
|
1424
1413
|
pill.style.opacity = controlsLocked ? '0.58' : '1';
|
|
@@ -1451,7 +1440,7 @@
|
|
|
1451
1440
|
clearFace.style.opacity = armed ? '1' : '0';
|
|
1452
1441
|
pill.style.background = armed ? P.toggleActive : 'transparent';
|
|
1453
1442
|
pill.style.border = CONFIGURE_SELECTION_PILL_BORDER;
|
|
1454
|
-
pill.setAttribute('aria-label', armed ? 'Clear selection' :
|
|
1443
|
+
pill.setAttribute('aria-label', armed ? 'Clear selection' : `Selected element: ${tag}`);
|
|
1455
1444
|
};
|
|
1456
1445
|
const arm = () => {
|
|
1457
1446
|
if (controlsLocked) {
|
|
@@ -1523,7 +1512,7 @@
|
|
|
1523
1512
|
const count = el('button', configureInlineControlStyle({
|
|
1524
1513
|
fontFamily: MONO, fontWeight: '600', letterSpacing: '0',
|
|
1525
1514
|
}));
|
|
1526
|
-
count.textContent =
|
|
1515
|
+
count.textContent = `\u00D7${selectedCount}`;
|
|
1527
1516
|
count.disabled = controlsLocked;
|
|
1528
1517
|
count.style.cursor = controlsLocked ? 'not-allowed' : 'pointer';
|
|
1529
1518
|
count.style.opacity = controlsLocked ? '0.58' : '1';
|
|
@@ -1539,7 +1528,7 @@
|
|
|
1539
1528
|
boxSizing: 'border-box',
|
|
1540
1529
|
width: CONFIGURE_BAR_H, height: '100%', flexShrink: '0',
|
|
1541
1530
|
padding: '0', margin: '0',
|
|
1542
|
-
border: 'none', borderRight:
|
|
1531
|
+
border: 'none', borderRight: `1px solid ${BP.hairline}`,
|
|
1543
1532
|
borderRadius: '0', background: 'transparent',
|
|
1544
1533
|
color: BP.textDim, cursor: 'pointer',
|
|
1545
1534
|
transition: 'color 0.12s ease, background 0.12s ease',
|
|
@@ -1559,7 +1548,7 @@
|
|
|
1559
1548
|
function buildConfigureTrailingCluster(controls, voiceBtn, submitBtn) {
|
|
1560
1549
|
const cluster = el('div', {
|
|
1561
1550
|
display: 'inline-flex', alignItems: 'stretch', flexShrink: '0',
|
|
1562
|
-
height: '100%', borderLeft:
|
|
1551
|
+
height: '100%', borderLeft: `1px solid ${BP.hairline}`,
|
|
1563
1552
|
});
|
|
1564
1553
|
if (controls.length) {
|
|
1565
1554
|
const controlsWrap = el('div', {
|
|
@@ -1569,7 +1558,7 @@
|
|
|
1569
1558
|
controls.forEach((control) => controlsWrap.appendChild(control));
|
|
1570
1559
|
cluster.appendChild(controlsWrap);
|
|
1571
1560
|
}
|
|
1572
|
-
voiceBtn.style.borderLeft =
|
|
1561
|
+
voiceBtn.style.borderLeft = `1px solid ${BP.hairline}`;
|
|
1573
1562
|
cluster.appendChild(voiceBtn);
|
|
1574
1563
|
cluster.appendChild(submitBtn);
|
|
1575
1564
|
return cluster;
|
|
@@ -1580,7 +1569,7 @@
|
|
|
1580
1569
|
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
|
1581
1570
|
boxSizing: 'border-box', width: CONFIGURE_BAR_H, height: CONFIGURE_BAR_H,
|
|
1582
1571
|
padding: '0', flexShrink: '0',
|
|
1583
|
-
border: 'none', borderLeft:
|
|
1572
|
+
border: 'none', borderLeft: `1px solid ${BP.hairline}`,
|
|
1584
1573
|
borderRadius: '0',
|
|
1585
1574
|
background: BP.accent, color: C.ink,
|
|
1586
1575
|
cursor: controlsLocked ? 'not-allowed' : 'pointer',
|
|
@@ -1622,7 +1611,7 @@
|
|
|
1622
1611
|
}
|
|
1623
1612
|
|
|
1624
1613
|
function detectInsertAxis(parent) {
|
|
1625
|
-
if (
|
|
1614
|
+
if (parent?.nodeType !== 1) return 'column';
|
|
1626
1615
|
const st = getComputedStyle(parent);
|
|
1627
1616
|
return detectInsertAxisFromStyle({
|
|
1628
1617
|
display: st.display,
|
|
@@ -1784,12 +1773,12 @@
|
|
|
1784
1773
|
placeholder.style.width = '';
|
|
1785
1774
|
if (sizing.kind === 'flex') {
|
|
1786
1775
|
placeholder.style.flex = sizing.flex;
|
|
1787
|
-
placeholder.style.minWidth = sizing.minWidth
|
|
1776
|
+
placeholder.style.minWidth = `${sizing.minWidth}px`;
|
|
1788
1777
|
} else if (sizing.kind === 'percent') {
|
|
1789
1778
|
placeholder.style.width = '100%';
|
|
1790
1779
|
placeholder.style.maxWidth = '100%';
|
|
1791
1780
|
} else if (sizing.kind === 'explicit') {
|
|
1792
|
-
placeholder.style.width = sizing.width
|
|
1781
|
+
placeholder.style.width = `${sizing.width}px`;
|
|
1793
1782
|
}
|
|
1794
1783
|
}
|
|
1795
1784
|
|
|
@@ -1801,7 +1790,7 @@
|
|
|
1801
1790
|
placeholder.style.flex = '';
|
|
1802
1791
|
placeholder.style.minWidth = '';
|
|
1803
1792
|
placeholder.style.maxWidth = '';
|
|
1804
|
-
placeholder.style.width = w
|
|
1793
|
+
placeholder.style.width = `${w}px`;
|
|
1805
1794
|
placeholder.dataset.monodesignPlaceholderWidth = 'explicit';
|
|
1806
1795
|
}
|
|
1807
1796
|
|
|
@@ -1863,12 +1852,12 @@
|
|
|
1863
1852
|
function ensureInsertLine() {
|
|
1864
1853
|
if (insertLineEl) return insertLineEl;
|
|
1865
1854
|
insertLineEl = document.createElement('div');
|
|
1866
|
-
insertLineEl.id = PREFIX
|
|
1855
|
+
insertLineEl.id = `${PREFIX}-insert-line`;
|
|
1867
1856
|
Object.assign(insertLineEl.style, {
|
|
1868
1857
|
position: 'fixed',
|
|
1869
1858
|
zIndex: String(Z.highlight),
|
|
1870
1859
|
height: '0',
|
|
1871
|
-
borderTop:
|
|
1860
|
+
borderTop: `2px dotted ${C.brand}`,
|
|
1872
1861
|
pointerEvents: 'none',
|
|
1873
1862
|
display: 'none',
|
|
1874
1863
|
opacity: '0.9',
|
|
@@ -1885,22 +1874,22 @@
|
|
|
1885
1874
|
if (coords.axis === 'row') {
|
|
1886
1875
|
Object.assign(line.style, {
|
|
1887
1876
|
display: 'block',
|
|
1888
|
-
top: coords.top
|
|
1889
|
-
left: coords.left
|
|
1877
|
+
top: `${coords.top}px`,
|
|
1878
|
+
left: `${coords.left}px`,
|
|
1890
1879
|
width: '0',
|
|
1891
|
-
height: coords.height
|
|
1880
|
+
height: `${coords.height}px`,
|
|
1892
1881
|
borderTop: 'none',
|
|
1893
|
-
borderLeft:
|
|
1882
|
+
borderLeft: `2px dotted ${C.brand}`,
|
|
1894
1883
|
});
|
|
1895
1884
|
} else {
|
|
1896
1885
|
Object.assign(line.style, {
|
|
1897
1886
|
display: 'block',
|
|
1898
|
-
top: coords.top
|
|
1899
|
-
left: coords.left
|
|
1900
|
-
width: coords.width
|
|
1887
|
+
top: `${coords.top}px`,
|
|
1888
|
+
left: `${coords.left}px`,
|
|
1889
|
+
width: `${coords.width}px`,
|
|
1901
1890
|
height: '0',
|
|
1902
1891
|
borderLeft: 'none',
|
|
1903
|
-
borderTop:
|
|
1892
|
+
borderTop: `2px dotted ${C.brand}`,
|
|
1904
1893
|
});
|
|
1905
1894
|
}
|
|
1906
1895
|
insertHoverAnchor = resolved.anchor;
|
|
@@ -1975,7 +1964,7 @@
|
|
|
1975
1964
|
if (anchor) return anchor;
|
|
1976
1965
|
}
|
|
1977
1966
|
if (currentSessionId && (state === 'GENERATING' || state === 'CYCLING')) {
|
|
1978
|
-
const wrapper = document.querySelector(
|
|
1967
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
1979
1968
|
if (wrapper) {
|
|
1980
1969
|
const variantCount = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])').length;
|
|
1981
1970
|
if (variantCount > 0 && visibleVariant > 0) {
|
|
@@ -2034,7 +2023,7 @@
|
|
|
2034
2023
|
const tag = (snap.anchorTag || 'div').toLowerCase();
|
|
2035
2024
|
const cls = (snap.anchorClasses || '').split(/\s+/).filter(Boolean)[0];
|
|
2036
2025
|
const needle = snap.anchorText || '';
|
|
2037
|
-
const sel = cls ? tag
|
|
2026
|
+
const sel = cls ? `${tag}.${cls}` : tag;
|
|
2038
2027
|
const candidates = document.querySelectorAll(sel);
|
|
2039
2028
|
for (const candidate of candidates) {
|
|
2040
2029
|
if (own(candidate)) continue;
|
|
@@ -2046,14 +2035,14 @@
|
|
|
2046
2035
|
|
|
2047
2036
|
function isInsertGeneratingSession() {
|
|
2048
2037
|
if (state !== 'GENERATING' || !currentSessionId) return false;
|
|
2049
|
-
const wrapper = document.querySelector(
|
|
2038
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
2050
2039
|
return !!wrapper && wrapper.dataset.monodesignMode === 'insert';
|
|
2051
2040
|
}
|
|
2052
2041
|
|
|
2053
2042
|
/** Recreate the dotted placeholder if Astro/Vite HMR removed it mid-generation. */
|
|
2054
2043
|
function ensureInsertPlaceholder() {
|
|
2055
2044
|
if (!isInsertGeneratingSession()) return placeholderElement;
|
|
2056
|
-
const wrapper = document.querySelector(
|
|
2045
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
2057
2046
|
const variantCount = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])').length;
|
|
2058
2047
|
if (variantCount > 0) return placeholderElement;
|
|
2059
2048
|
if (placeholderElement && document.body.contains(placeholderElement)) return placeholderElement;
|
|
@@ -2083,10 +2072,10 @@
|
|
|
2083
2072
|
const ph = placeholderElement;
|
|
2084
2073
|
if (!ph) return;
|
|
2085
2074
|
materializePlaceholderWidth(ph);
|
|
2086
|
-
ph.style.width = width
|
|
2087
|
-
ph.style.height = height
|
|
2088
|
-
ph.style.marginLeft = marginLeft ? marginLeft
|
|
2089
|
-
ph.style.marginTop = marginTop ? marginTop
|
|
2075
|
+
ph.style.width = `${width}px`;
|
|
2076
|
+
ph.style.height = `${height}px`;
|
|
2077
|
+
ph.style.marginLeft = marginLeft ? `${marginLeft}px` : '';
|
|
2078
|
+
ph.style.marginTop = marginTop ? `${marginTop}px` : '';
|
|
2090
2079
|
positionAnnotOverlay(ph);
|
|
2091
2080
|
positionBar();
|
|
2092
2081
|
}
|
|
@@ -2113,12 +2102,12 @@
|
|
|
2113
2102
|
pointerEvents: 'auto',
|
|
2114
2103
|
cursor: cursorForPlaceholderEdge(spec.edge),
|
|
2115
2104
|
});
|
|
2116
|
-
if (spec.top != null) handle.style.top = spec.top
|
|
2117
|
-
if (spec.bottom != null) handle.style.bottom = spec.bottom
|
|
2118
|
-
if (spec.left != null) handle.style.left = spec.left
|
|
2119
|
-
if (spec.right != null) handle.style.right = spec.right
|
|
2120
|
-
if (spec.width != null) handle.style.width = spec.width
|
|
2121
|
-
if (spec.height != null) handle.style.height = spec.height
|
|
2105
|
+
if (spec.top != null) handle.style.top = `${spec.top}px`;
|
|
2106
|
+
if (spec.bottom != null) handle.style.bottom = `${spec.bottom}px`;
|
|
2107
|
+
if (spec.left != null) handle.style.left = `${spec.left}px`;
|
|
2108
|
+
if (spec.right != null) handle.style.right = `${spec.right}px`;
|
|
2109
|
+
if (spec.width != null) handle.style.width = `${spec.width}px`;
|
|
2110
|
+
if (spec.height != null) handle.style.height = `${spec.height}px`;
|
|
2122
2111
|
handle.dataset.monodesignPlaceholderResize = spec.edge;
|
|
2123
2112
|
handle.setAttribute('aria-label', 'Resize placeholder');
|
|
2124
2113
|
handle.title = 'Drag to resize';
|
|
@@ -2173,13 +2162,14 @@
|
|
|
2173
2162
|
anchorFlex: ast.flex,
|
|
2174
2163
|
});
|
|
2175
2164
|
const placeholder = document.createElement('div');
|
|
2176
|
-
placeholder.id = PREFIX
|
|
2165
|
+
placeholder.id = `${PREFIX}-insert-placeholder`;
|
|
2177
2166
|
placeholder.setAttribute('data-monodesign-insert-placeholder', 'true');
|
|
2178
2167
|
placeholder.setAttribute('aria-hidden', 'true');
|
|
2179
2168
|
Object.assign(placeholder.style, {
|
|
2180
2169
|
boxSizing: 'border-box',
|
|
2181
|
-
height: PLACEHOLDER_DEFAULT_HEIGHT
|
|
2182
|
-
minHeight: PLACEHOLDER_MIN_HEIGHT
|
|
2170
|
+
height: `${PLACEHOLDER_DEFAULT_HEIGHT}px`,
|
|
2171
|
+
minHeight: `${PLACEHOLDER_MIN_HEIGHT}px`,
|
|
2172
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:643
|
|
2183
2173
|
border: '2px dotted ' + BP.accent,
|
|
2184
2174
|
borderRadius: '0',
|
|
2185
2175
|
background: 'transparent',
|
|
@@ -2204,7 +2194,7 @@
|
|
|
2204
2194
|
}
|
|
2205
2195
|
|
|
2206
2196
|
function isInsertCreateEnabled(btn) {
|
|
2207
|
-
btn = btn || uiGetById(PREFIX
|
|
2197
|
+
btn = btn || uiGetById(`${PREFIX}-insert-create`);
|
|
2208
2198
|
return !!btn && btn.getAttribute('aria-disabled') !== 'true';
|
|
2209
2199
|
}
|
|
2210
2200
|
|
|
@@ -2221,7 +2211,7 @@
|
|
|
2221
2211
|
padding: '6px 9px',
|
|
2222
2212
|
borderRadius: '7px',
|
|
2223
2213
|
background: BP.chatSurface,
|
|
2224
|
-
border:
|
|
2214
|
+
border: `1px solid ${BP.hairline}`,
|
|
2225
2215
|
boxShadow: BP.shadow,
|
|
2226
2216
|
color: BP.text,
|
|
2227
2217
|
fontFamily: FONT,
|
|
@@ -2229,7 +2219,7 @@
|
|
|
2229
2219
|
fontWeight: '500',
|
|
2230
2220
|
lineHeight: '1.35',
|
|
2231
2221
|
});
|
|
2232
|
-
insertCreateTooltipEl.id = PREFIX
|
|
2222
|
+
insertCreateTooltipEl.id = `${PREFIX}-insert-create-tooltip`;
|
|
2233
2223
|
uiAppend(insertCreateTooltipEl);
|
|
2234
2224
|
return insertCreateTooltipEl;
|
|
2235
2225
|
}
|
|
@@ -2244,8 +2234,8 @@
|
|
|
2244
2234
|
const tipH = tip.offsetHeight;
|
|
2245
2235
|
const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
|
|
2246
2236
|
const top = Math.max(8, r.top - tipH - 8);
|
|
2247
|
-
tip.style.left = left
|
|
2248
|
-
tip.style.top = top
|
|
2237
|
+
tip.style.left = `${left}px`;
|
|
2238
|
+
tip.style.top = `${top}px`;
|
|
2249
2239
|
}
|
|
2250
2240
|
|
|
2251
2241
|
function hideInsertCreateTooltip() {
|
|
@@ -2262,8 +2252,8 @@
|
|
|
2262
2252
|
}
|
|
2263
2253
|
|
|
2264
2254
|
function syncInsertCreateButton(btn, input) {
|
|
2265
|
-
btn = btn || uiGetById(PREFIX
|
|
2266
|
-
input = input || uiGetById(PREFIX
|
|
2255
|
+
btn = btn || uiGetById(`${PREFIX}-insert-create`);
|
|
2256
|
+
input = input || uiGetById(`${PREFIX}-insert-input`);
|
|
2267
2257
|
if (!btn || !input) return;
|
|
2268
2258
|
const gate = insertCreateGateState(input);
|
|
2269
2259
|
const ok = canCreateInsert(gate);
|
|
@@ -2280,7 +2270,7 @@
|
|
|
2280
2270
|
} else {
|
|
2281
2271
|
btn.style.background = 'transparent';
|
|
2282
2272
|
btn.style.color = BP.textDim;
|
|
2283
|
-
btn.style.border =
|
|
2273
|
+
btn.style.border = `1px solid ${BP.hairline}`;
|
|
2284
2274
|
btn.style.opacity = '0.72';
|
|
2285
2275
|
btn.style.cursor = 'not-allowed';
|
|
2286
2276
|
}
|
|
@@ -2288,9 +2278,9 @@
|
|
|
2288
2278
|
|
|
2289
2279
|
/** Stylesheet shared by the replace and insert configure rows. */
|
|
2290
2280
|
function ensureConfigureInputStyle() {
|
|
2291
|
-
if (uiGetById(PREFIX
|
|
2281
|
+
if (uiGetById(`${PREFIX}-configure-input-style`)) return;
|
|
2292
2282
|
const s = document.createElement('style');
|
|
2293
|
-
s.id = PREFIX
|
|
2283
|
+
s.id = `${PREFIX}-configure-input-style`;
|
|
2294
2284
|
s.textContent =
|
|
2295
2285
|
'@keyframes monodesign-configure-voice-pulse { 0%, 100% { opacity: 0.55; } 50% { opacity: 1; } }' +
|
|
2296
2286
|
'#' + PREFIX + '-input, #' + PREFIX + '-insert-input { box-sizing: border-box; height: ' + CONFIGURE_ROW_TRACK_H + '; line-height: ' + CONFIGURE_ROW_TRACK_H + '; padding: 0; margin: 0; caret-color: ' + CONFIGURE_PILL_TEXT + '; }' +
|
|
@@ -2310,7 +2300,7 @@
|
|
|
2310
2300
|
const inputShell = el('div', configureInputShellStyle());
|
|
2311
2301
|
|
|
2312
2302
|
const input = document.createElement('input');
|
|
2313
|
-
input.id = PREFIX
|
|
2303
|
+
input.id = `${PREFIX}-input`;
|
|
2314
2304
|
input.type = 'text';
|
|
2315
2305
|
input.placeholder = '';
|
|
2316
2306
|
input.setAttribute('aria-label', 'Describe the change');
|
|
@@ -2336,7 +2326,7 @@
|
|
|
2336
2326
|
onClick: (e) => {
|
|
2337
2327
|
e.stopPropagation();
|
|
2338
2328
|
if (controlsLocked) { showManualApplyBusyToast(); return; }
|
|
2339
|
-
count.textContent =
|
|
2329
|
+
count.textContent = `\u00D7${cycleSelectedCount()}`;
|
|
2340
2330
|
if (count.matches(':hover')) {
|
|
2341
2331
|
showConfigureBarTooltip(count, variantCountTooltipText(selectedCount));
|
|
2342
2332
|
}
|
|
@@ -2364,7 +2354,7 @@
|
|
|
2364
2354
|
});
|
|
2365
2355
|
|
|
2366
2356
|
const voiceBtn = buildConfigureVoiceButton({
|
|
2367
|
-
id: PREFIX
|
|
2357
|
+
id: `${PREFIX}-configure-voice`,
|
|
2368
2358
|
controlsLocked,
|
|
2369
2359
|
onClick: (e) => {
|
|
2370
2360
|
e.stopPropagation();
|
|
@@ -2400,7 +2390,7 @@
|
|
|
2400
2390
|
const inputShell = el('div', configureInputShellStyle());
|
|
2401
2391
|
|
|
2402
2392
|
const input = document.createElement('input');
|
|
2403
|
-
input.id = PREFIX
|
|
2393
|
+
input.id = `${PREFIX}-insert-input`;
|
|
2404
2394
|
input.type = 'text';
|
|
2405
2395
|
input.placeholder = '';
|
|
2406
2396
|
input.setAttribute('aria-label', 'Describe the new element');
|
|
@@ -2417,7 +2407,7 @@
|
|
|
2417
2407
|
onClick: (e) => {
|
|
2418
2408
|
e.stopPropagation();
|
|
2419
2409
|
if (controlsLocked) { showManualApplyBusyToast(); return; }
|
|
2420
|
-
count.textContent =
|
|
2410
|
+
count.textContent = `\u00D7${cycleSelectedCount()}`;
|
|
2421
2411
|
if (count.matches(':hover')) {
|
|
2422
2412
|
showConfigureBarTooltip(count, variantCountTooltipText(selectedCount));
|
|
2423
2413
|
}
|
|
@@ -2453,7 +2443,7 @@
|
|
|
2453
2443
|
input.addEventListener('blur', () => syncConfigureInputChrome());
|
|
2454
2444
|
|
|
2455
2445
|
const voiceBtn = buildConfigureVoiceButton({
|
|
2456
|
-
id: PREFIX
|
|
2446
|
+
id: `${PREFIX}-insert-voice`,
|
|
2457
2447
|
controlsLocked,
|
|
2458
2448
|
onClick: (e) => {
|
|
2459
2449
|
e.stopPropagation();
|
|
@@ -2473,6 +2463,7 @@
|
|
|
2473
2463
|
handleInsertCreate();
|
|
2474
2464
|
},
|
|
2475
2465
|
});
|
|
2466
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:688
|
|
2476
2467
|
create.id = PREFIX + '-insert-create';
|
|
2477
2468
|
create.addEventListener('mouseenter', () => {
|
|
2478
2469
|
if (controlsLocked) return;
|
|
@@ -2520,7 +2511,7 @@
|
|
|
2520
2511
|
status.textContent = recoveryWaitingForAnchor
|
|
2521
2512
|
? 'Variants ready. Reveal the selected element to resume.'
|
|
2522
2513
|
: (arrivedVariants < expectedVariants
|
|
2523
|
-
?
|
|
2514
|
+
? `Generating ${expectedVariants} variants...`
|
|
2524
2515
|
: 'Done');
|
|
2525
2516
|
row.appendChild(status);
|
|
2526
2517
|
|
|
@@ -2542,7 +2533,7 @@
|
|
|
2542
2533
|
|
|
2543
2534
|
// Prev
|
|
2544
2535
|
const prev = navBtn('\u2190');
|
|
2545
|
-
prev.id = PREFIX
|
|
2536
|
+
prev.id = `${PREFIX}-variant-prev`;
|
|
2546
2537
|
prev.addEventListener('click', (e) => { e.stopPropagation(); cycleVariant(-1); });
|
|
2547
2538
|
if (visibleVariant <= 1) prev.style.opacity = '0.3';
|
|
2548
2539
|
row.appendChild(prev);
|
|
@@ -2555,13 +2546,13 @@
|
|
|
2555
2546
|
fontFamily: MONO, fontSize: '11px', fontWeight: '500',
|
|
2556
2547
|
color: BP.textDim, minWidth: '24px', textAlign: 'center',
|
|
2557
2548
|
});
|
|
2558
|
-
counter.id = PREFIX
|
|
2559
|
-
counter.textContent = visibleVariant
|
|
2549
|
+
counter.id = `${PREFIX}-variant-counter`;
|
|
2550
|
+
counter.textContent = `${visibleVariant}/${arrivedVariants}`;
|
|
2560
2551
|
row.appendChild(counter);
|
|
2561
2552
|
|
|
2562
2553
|
// Next
|
|
2563
2554
|
const next = navBtn('\u2192');
|
|
2564
|
-
next.id = PREFIX
|
|
2555
|
+
next.id = `${PREFIX}-variant-next`;
|
|
2565
2556
|
next.addEventListener('click', (e) => { e.stopPropagation(); cycleVariant(1); });
|
|
2566
2557
|
if (visibleVariant >= arrivedVariants) next.style.opacity = '0.3';
|
|
2567
2558
|
row.appendChild(next);
|
|
@@ -2598,7 +2589,7 @@
|
|
|
2598
2589
|
});
|
|
2599
2590
|
tuneBadge.textContent = String(visParams.length);
|
|
2600
2591
|
tune.appendChild(tuneBadge);
|
|
2601
|
-
tune.title =
|
|
2592
|
+
tune.title = `Tune this variant (${visParams.length} knob${visParams.length === 1 ? '' : 's'})`;
|
|
2602
2593
|
tune.addEventListener('mouseenter', () => {
|
|
2603
2594
|
if (!tuneOpen) tune.style.background = BP.accentSoft;
|
|
2604
2595
|
});
|
|
@@ -2633,7 +2624,7 @@
|
|
|
2633
2624
|
// Discard
|
|
2634
2625
|
const discard = el('button', {
|
|
2635
2626
|
padding: '4px 6px', borderRadius: '5px',
|
|
2636
|
-
border:
|
|
2627
|
+
border: `1px solid ${BP.hairline}`, background: 'transparent',
|
|
2637
2628
|
fontFamily: FONT, fontSize: '11px', color: BP.textDim,
|
|
2638
2629
|
cursor: 'pointer', transition: 'color 0.12s ease, border-color 0.12s ease',
|
|
2639
2630
|
});
|
|
@@ -2658,7 +2649,7 @@
|
|
|
2658
2649
|
});
|
|
2659
2650
|
const spinner = el('div', {
|
|
2660
2651
|
width: '14px', height: '14px', borderRadius: '50%',
|
|
2661
|
-
border:
|
|
2652
|
+
border: `2px solid ${BP.hairline}`,
|
|
2662
2653
|
borderTopColor: BP.accent,
|
|
2663
2654
|
animation: 'monodesign-spin 0.6s linear infinite',
|
|
2664
2655
|
flexShrink: '0',
|
|
@@ -2712,7 +2703,7 @@
|
|
|
2712
2703
|
const dotBg = active ? C.brand
|
|
2713
2704
|
: arrived ? BP.textDim
|
|
2714
2705
|
: 'transparent';
|
|
2715
|
-
const dotBorder = arrived ? 'none' :
|
|
2706
|
+
const dotBorder = arrived ? 'none' : `1.5px solid ${BP.hairline}`;
|
|
2716
2707
|
const dot = el('div', {
|
|
2717
2708
|
width: active ? '8px' : '6px',
|
|
2718
2709
|
height: active ? '8px' : '6px',
|
|
@@ -2720,7 +2711,7 @@
|
|
|
2720
2711
|
background: dotBg,
|
|
2721
2712
|
border: dotBorder,
|
|
2722
2713
|
boxSizing: 'border-box',
|
|
2723
|
-
transition:
|
|
2714
|
+
transition: `all 0.2s ${EASE}`,
|
|
2724
2715
|
cursor: (clickable && arrived) ? 'pointer' : 'default',
|
|
2725
2716
|
transform: arrived ? 'scale(1)' : 'scale(0.85)',
|
|
2726
2717
|
opacity: arrived ? (active ? '1' : '0.6') : '0.4',
|
|
@@ -2740,7 +2731,7 @@
|
|
|
2740
2731
|
function navBtn(text) {
|
|
2741
2732
|
const b = el('button', {
|
|
2742
2733
|
width: '26px', height: '26px', borderRadius: '5px',
|
|
2743
|
-
border:
|
|
2734
|
+
border: `1px solid ${BP.hairline}`, background: 'transparent',
|
|
2744
2735
|
color: BP.text, fontFamily: FONT, fontSize: '13px',
|
|
2745
2736
|
cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
|
|
2746
2737
|
transition: 'border-color 0.12s ease, background 0.12s ease',
|
|
@@ -2771,15 +2762,15 @@
|
|
|
2771
2762
|
function initActionPicker() {
|
|
2772
2763
|
const P = barPaletteForTheme(detectPageTheme());
|
|
2773
2764
|
pickerEl = document.createElement('div');
|
|
2774
|
-
pickerEl.id = PREFIX
|
|
2765
|
+
pickerEl.id = `${PREFIX}-picker`;
|
|
2775
2766
|
Object.assign(pickerEl.style, {
|
|
2776
2767
|
position: 'fixed', zIndex: Z.picker,
|
|
2777
2768
|
display: 'none', opacity: '0',
|
|
2778
2769
|
transform: 'scale(0.96) translateY(4px)',
|
|
2779
2770
|
transformOrigin: 'bottom right',
|
|
2780
|
-
transition:
|
|
2771
|
+
transition: `opacity 0.18s ${EASE}, transform 0.2s ${EASE}`,
|
|
2781
2772
|
background: P.surface,
|
|
2782
|
-
border:
|
|
2773
|
+
border: `1px solid ${P.border}`,
|
|
2783
2774
|
borderRadius: '8px',
|
|
2784
2775
|
boxShadow: P.shadow,
|
|
2785
2776
|
padding: '6px',
|
|
@@ -2823,11 +2814,11 @@
|
|
|
2823
2814
|
chip.addEventListener('click', (e) => {
|
|
2824
2815
|
e.preventDefault();
|
|
2825
2816
|
e.stopPropagation();
|
|
2826
|
-
const prompt = uiGetById(PREFIX
|
|
2817
|
+
const prompt = uiGetById(`${PREFIX}-input`)?.value || '';
|
|
2827
2818
|
selectedAction = action.value;
|
|
2828
2819
|
hideActionPicker();
|
|
2829
2820
|
updateBarContent('configure');
|
|
2830
|
-
const input = uiGetById(PREFIX
|
|
2821
|
+
const input = uiGetById(`${PREFIX}-input`);
|
|
2831
2822
|
if (input && prompt) input.value = prompt;
|
|
2832
2823
|
});
|
|
2833
2824
|
grid.appendChild(chip);
|
|
@@ -2862,8 +2853,8 @@
|
|
|
2862
2853
|
let left = barRect.right - pickerW;
|
|
2863
2854
|
left = Math.max(8, Math.min(left, window.innerWidth - pickerW - 8));
|
|
2864
2855
|
Object.assign(pickerEl.style, {
|
|
2865
|
-
top: top
|
|
2866
|
-
left: left
|
|
2856
|
+
top: `${top}px`,
|
|
2857
|
+
left: `${left}px`,
|
|
2867
2858
|
});
|
|
2868
2859
|
requestAnimationFrame(() => {
|
|
2869
2860
|
pickerEl.style.opacity = '1';
|
|
@@ -2926,7 +2917,6 @@
|
|
|
2926
2917
|
//
|
|
2927
2918
|
|
|
2928
2919
|
let paramsPanelEl = null; // outer wrapper (overflow:hidden, clips the slide)
|
|
2929
|
-
let paramsPanelInner = null; // translating content (carries bg, padding, knobs)
|
|
2930
2920
|
let paramsPanelBody = null; // grid holding the knob cells
|
|
2931
2921
|
let paramsCurrentValues = {}; // {paramId: value} - mirror of the visible variant's live values
|
|
2932
2922
|
let tuneOpen = false; // whether the Tune popover is open right now
|
|
@@ -2948,7 +2938,7 @@
|
|
|
2948
2938
|
// hides everything initially; as it grows, content is revealed from
|
|
2949
2939
|
// the bar edge outward.
|
|
2950
2940
|
paramsPanelEl = document.createElement('div');
|
|
2951
|
-
paramsPanelEl.id = PREFIX
|
|
2941
|
+
paramsPanelEl.id = `${PREFIX}-params-panel`;
|
|
2952
2942
|
Object.assign(paramsPanelEl.style, {
|
|
2953
2943
|
position: 'fixed', zIndex: String(Z.bar - 1),
|
|
2954
2944
|
background: P.surfaceDeep,
|
|
@@ -2963,7 +2953,7 @@
|
|
|
2963
2953
|
// transition support across engines. Closed state clips from the far
|
|
2964
2954
|
// edge; open = inset(0) shows everything.
|
|
2965
2955
|
clipPath: 'inset(0 0 100% 0)',
|
|
2966
|
-
transition:
|
|
2956
|
+
transition: `clip-path 0.44s ${EASE}`,
|
|
2967
2957
|
|
|
2968
2958
|
// Park off-screen until positionParamsPanel places it. These are NOT
|
|
2969
2959
|
// in the transition list, so they snap instantly - no fly-in from the
|
|
@@ -2983,7 +2973,6 @@
|
|
|
2983
2973
|
// click-through) and 'auto' (open) on its own. Just silence the host's
|
|
2984
2974
|
// outside-interaction listeners while the panel is open.
|
|
2985
2975
|
defangOutsideHandlers(paramsPanelEl, { setPointerEvents: false });
|
|
2986
|
-
paramsPanelInner = paramsPanelEl; // compatibility alias for the rest of the code
|
|
2987
2976
|
}
|
|
2988
2977
|
|
|
2989
2978
|
|
|
@@ -3006,9 +2995,9 @@
|
|
|
3006
2995
|
|| svelteComponentSession.wrapperEl
|
|
3007
2996
|
|| null;
|
|
3008
2997
|
}
|
|
3009
|
-
const wrapper = document.querySelector(
|
|
2998
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
3010
2999
|
if (!wrapper) return null;
|
|
3011
|
-
return wrapper.querySelector(
|
|
3000
|
+
return wrapper.querySelector(`[data-monodesign-variant="${visibleVariant}"]`);
|
|
3012
3001
|
}
|
|
3013
3002
|
|
|
3014
3003
|
function parseVariantParams(variantEl) {
|
|
@@ -3035,7 +3024,7 @@
|
|
|
3035
3024
|
|
|
3036
3025
|
function applyParamValue(variantEl, param, value) {
|
|
3037
3026
|
if (!variantEl) return;
|
|
3038
|
-
const attr =
|
|
3027
|
+
const attr = `data-p-${param.id}`;
|
|
3039
3028
|
if (param.kind === 'toggle') {
|
|
3040
3029
|
const on = !!value;
|
|
3041
3030
|
if (on) variantEl.setAttribute(attr, 'on');
|
|
@@ -3049,8 +3038,9 @@
|
|
|
3049
3038
|
// so there is no React hydration to mismatch. Drive range/toggle --p-* inline
|
|
3050
3039
|
// on the mounted element so scoped preview CSS resolves them.
|
|
3051
3040
|
if (svelteComponentSession?.sessionId === currentSessionId) {
|
|
3041
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:335
|
|
3052
3042
|
if (param.kind === 'range') variantEl.style.setProperty('--p-' + param.id, String(value));
|
|
3053
|
-
else if (param.kind === 'toggle') variantEl.style.setProperty(
|
|
3043
|
+
else if (param.kind === 'toggle') variantEl.style.setProperty(`--p-${param.id}`, value ? '1' : '0');
|
|
3054
3044
|
return;
|
|
3055
3045
|
}
|
|
3056
3046
|
// range/toggle --p-* custom properties are driven through the injected
|
|
@@ -3069,7 +3059,7 @@
|
|
|
3069
3059
|
function formatRangeValue(input) {
|
|
3070
3060
|
const max = parseFloat(input.max), min = parseFloat(input.min);
|
|
3071
3061
|
const v = parseFloat(input.value);
|
|
3072
|
-
if (!isFinite(v)) return input.value;
|
|
3062
|
+
if (!Number.isFinite(v)) return input.value;
|
|
3073
3063
|
return (max - min) <= 2 ? v.toFixed(2) : String(Math.round(v));
|
|
3074
3064
|
}
|
|
3075
3065
|
|
|
@@ -3131,7 +3121,7 @@
|
|
|
3131
3121
|
left: initial ? '18px' : '2px',
|
|
3132
3122
|
width: '16px', height: '16px', borderRadius: '50%',
|
|
3133
3123
|
background: 'oklch(98% 0 0)',
|
|
3134
|
-
transition:
|
|
3124
|
+
transition: `left 0.18s ${EASE}`,
|
|
3135
3125
|
boxShadow: '0 1px 2px oklch(0% 0 0 / 0.2)',
|
|
3136
3126
|
});
|
|
3137
3127
|
track.appendChild(knob);
|
|
@@ -3154,7 +3144,7 @@
|
|
|
3154
3144
|
readout.textContent = activeOpt ? activeOpt.label : String(p.default);
|
|
3155
3145
|
const segRow = el('div', {
|
|
3156
3146
|
display: 'grid',
|
|
3157
|
-
gridTemplateColumns:
|
|
3147
|
+
gridTemplateColumns: `repeat(${opts.length}, 1fr)`,
|
|
3158
3148
|
gap: '1px', padding: '2px',
|
|
3159
3149
|
background: P.hairline, borderRadius: '5px',
|
|
3160
3150
|
});
|
|
@@ -3209,15 +3199,15 @@
|
|
|
3209
3199
|
const MIXED_WRAP_SKIP = { script: 1, style: 1, template: 1, noscript: 1, svg: 1, code: 1, pre: 1 };
|
|
3210
3200
|
|
|
3211
3201
|
function collectEditableTextRows(rootEl, opts) {
|
|
3212
|
-
if (
|
|
3213
|
-
const isOwn =
|
|
3202
|
+
if (rootEl?.nodeType !== 1) return [];
|
|
3203
|
+
const isOwn = opts?.isOwn || (() => false);
|
|
3214
3204
|
const rows = [];
|
|
3215
3205
|
|
|
3216
3206
|
function visit(el) {
|
|
3217
|
-
if (
|
|
3207
|
+
if (el?.nodeType !== 1) return;
|
|
3218
3208
|
const tag = el.tagName.toLowerCase();
|
|
3219
3209
|
if (MIXED_WRAP_SKIP[tag]) return;
|
|
3220
|
-
if (el.hasAttribute
|
|
3210
|
+
if (el.hasAttribute?.('contenteditable')) return;
|
|
3221
3211
|
if (el !== rootEl && isOwn(el)) return;
|
|
3222
3212
|
|
|
3223
3213
|
const children = Array.from(el.childNodes);
|
|
@@ -3251,7 +3241,7 @@
|
|
|
3251
3241
|
}
|
|
3252
3242
|
|
|
3253
3243
|
function wrapMixedContentTextNodes(rootEl) {
|
|
3254
|
-
if (
|
|
3244
|
+
if (rootEl?.nodeType !== 1) return;
|
|
3255
3245
|
const tag = rootEl.tagName.toLowerCase();
|
|
3256
3246
|
if (MIXED_WRAP_SKIP[tag]) return;
|
|
3257
3247
|
if (rootEl.hasAttribute('contenteditable')) return;
|
|
@@ -3270,13 +3260,13 @@
|
|
|
3270
3260
|
}
|
|
3271
3261
|
}
|
|
3272
3262
|
for (const child of Array.from(rootEl.children)) {
|
|
3273
|
-
if (!child.dataset
|
|
3263
|
+
if (!child.dataset?.monodesignTextWrap) {
|
|
3274
3264
|
wrapMixedContentTextNodes(child);
|
|
3275
3265
|
}
|
|
3276
3266
|
}
|
|
3277
3267
|
}
|
|
3278
3268
|
function unwrapMixedContentTextNodes(rootEl) {
|
|
3279
|
-
if (
|
|
3269
|
+
if (rootEl?.nodeType !== 1) return;
|
|
3280
3270
|
const wraps = rootEl.querySelectorAll('[data-monodesign-text-wrap="true"]');
|
|
3281
3271
|
for (const wrap of wraps) {
|
|
3282
3272
|
const parent = wrap.parentNode;
|
|
@@ -3339,7 +3329,7 @@
|
|
|
3339
3329
|
// (mixed-content paragraphs included). Mirrors what the wrap+walk path
|
|
3340
3330
|
// will produce in enableInlineEdit.
|
|
3341
3331
|
function check(node) {
|
|
3342
|
-
if (
|
|
3332
|
+
if (node?.nodeType !== 1) return false;
|
|
3343
3333
|
const tag = node.tagName.toLowerCase();
|
|
3344
3334
|
if (MIXED_WRAP_SKIP[tag]) return false;
|
|
3345
3335
|
if (node !== el && own(node)) return false;
|
|
@@ -3363,9 +3353,11 @@
|
|
|
3363
3353
|
enableInlineEdit(selectedElement);
|
|
3364
3354
|
// Focus first editable element and position cursor at end
|
|
3365
3355
|
if (inlineEditRows.length > 0) {
|
|
3356
|
+
// biome-ignore lint/complexity/useOptionalChain: exact text pinned by tests/live-browser-regression.test.mjs
|
|
3366
3357
|
const firstEditable = inlineEditRows[0] && inlineEditRows[0].el;
|
|
3367
3358
|
setTimeout(() => {
|
|
3368
3359
|
const el = firstEditable;
|
|
3360
|
+
// biome-ignore lint/complexity/useOptionalChain: test-pinned
|
|
3369
3361
|
if (!el || !el.isConnected || state !== 'EDITING') return;
|
|
3370
3362
|
el.focus();
|
|
3371
3363
|
const range = document.createRange();
|
|
@@ -3460,7 +3452,7 @@
|
|
|
3460
3452
|
}
|
|
3461
3453
|
|
|
3462
3454
|
function sourceHintForElement(el) {
|
|
3463
|
-
if (!el
|
|
3455
|
+
if (!el?.getAttribute) return null;
|
|
3464
3456
|
const file = el.getAttribute('data-astro-source-file');
|
|
3465
3457
|
const loc = el.getAttribute('data-astro-source-loc');
|
|
3466
3458
|
if (file || loc) {
|
|
@@ -3479,12 +3471,12 @@
|
|
|
3479
3471
|
const match = String(loc || '').match(/^(\d+)(?::(\d+))?/);
|
|
3480
3472
|
return {
|
|
3481
3473
|
line: match ? Number(match[1]) : null,
|
|
3482
|
-
column: match
|
|
3474
|
+
column: match?.[2] ? Number(match[2]) : null,
|
|
3483
3475
|
};
|
|
3484
3476
|
}
|
|
3485
3477
|
|
|
3486
3478
|
function documentRefForElement(el) {
|
|
3487
|
-
if (
|
|
3479
|
+
if (el?.nodeType !== 1) return null;
|
|
3488
3480
|
const parts = [];
|
|
3489
3481
|
let cur = el;
|
|
3490
3482
|
while (cur && cur.nodeType === 1) {
|
|
@@ -3502,11 +3494,11 @@
|
|
|
3502
3494
|
|
|
3503
3495
|
function documentRefSegment(el) {
|
|
3504
3496
|
const tag = el.tagName.toLowerCase();
|
|
3505
|
-
return tag + documentRefIdSuffix(el) + documentRefClassSuffix(el)
|
|
3497
|
+
return `${tag + documentRefIdSuffix(el) + documentRefClassSuffix(el)}:nth-of-type(${indexAmongSameTag(el)})`;
|
|
3506
3498
|
}
|
|
3507
3499
|
|
|
3508
3500
|
function documentRefIdSuffix(el) {
|
|
3509
|
-
return el.id ?
|
|
3501
|
+
return el.id ? `#${normalizeDocumentRefToken(el.id)}` : '';
|
|
3510
3502
|
}
|
|
3511
3503
|
|
|
3512
3504
|
function documentRefClassSuffix(el) {
|
|
@@ -3517,7 +3509,7 @@
|
|
|
3517
3509
|
classes.push(normalizeDocumentRefToken(cls));
|
|
3518
3510
|
if (classes.length === 2) break;
|
|
3519
3511
|
}
|
|
3520
|
-
return classes.length ?
|
|
3512
|
+
return classes.length ? `.${classes.join('.')}` : '';
|
|
3521
3513
|
}
|
|
3522
3514
|
|
|
3523
3515
|
function normalizeDocumentRefToken(value) {
|
|
@@ -3604,7 +3596,7 @@
|
|
|
3604
3596
|
}
|
|
3605
3597
|
const forbidden = forbiddenManualTextChars(newText);
|
|
3606
3598
|
if (forbidden.length > 0) {
|
|
3607
|
-
showToast(
|
|
3599
|
+
showToast(`Save rejected: newText cannot contain ${forbidden.join(' ')} (plain text only; ask the AI to insert markup)`, 5500);
|
|
3608
3600
|
return;
|
|
3609
3601
|
}
|
|
3610
3602
|
const locator = buildLocatorForLeaf(row.el, selectedElement);
|
|
@@ -3632,6 +3624,7 @@
|
|
|
3632
3624
|
const container = copyEditContainerContext(contextElement);
|
|
3633
3625
|
if (container) for (const op of ops) op.container = container;
|
|
3634
3626
|
try {
|
|
3627
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:18
|
|
3635
3628
|
const res = await fetch('http://localhost:' + PORT + '/manual-edit-stash', {
|
|
3636
3629
|
method: 'POST',
|
|
3637
3630
|
headers: { 'Content-Type': 'application/json' },
|
|
@@ -3645,7 +3638,7 @@
|
|
|
3645
3638
|
});
|
|
3646
3639
|
if (!res.ok) {
|
|
3647
3640
|
const errBody = await res.json().catch(() => ({}));
|
|
3648
|
-
throw new Error(errBody.error || (
|
|
3641
|
+
throw new Error(errBody.error || (`HTTP ${res.status}`));
|
|
3649
3642
|
}
|
|
3650
3643
|
const stashResult = await res.json();
|
|
3651
3644
|
updatePendingCounter(stashResult.pendingCount || 0);
|
|
@@ -3659,7 +3652,7 @@
|
|
|
3659
3652
|
console.error('[monodesign] manual edit stash failed:', err);
|
|
3660
3653
|
const detail = String(err?.message || '');
|
|
3661
3654
|
if (detail.includes('newText cannot contain') || detail.includes('newText cannot be empty')) {
|
|
3662
|
-
showToast(
|
|
3655
|
+
showToast(`Save rejected: ${detail.replace(/^manual_edits:\s*/, '')}`, 5500);
|
|
3663
3656
|
} else {
|
|
3664
3657
|
showToast('Save failed - retry or cancel', 4000);
|
|
3665
3658
|
}
|
|
@@ -3676,13 +3669,14 @@
|
|
|
3676
3669
|
const width = globalBarEl.offsetWidth;
|
|
3677
3670
|
const height = globalBarEl.offsetHeight;
|
|
3678
3671
|
if (!width || !height) return;
|
|
3679
|
-
pendingDockEl.style.left = Math.round((window.innerWidth / 2) - (width / 2) - 18)
|
|
3672
|
+
pendingDockEl.style.left = `${Math.round((window.innerWidth / 2) - (width / 2) - 18)}px`;
|
|
3680
3673
|
pendingDockEl.style.top = 'auto';
|
|
3674
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:204
|
|
3681
3675
|
pendingDockEl.style.bottom = Math.round(14 + (height / 2)) + 'px';
|
|
3682
3676
|
}
|
|
3683
3677
|
|
|
3684
3678
|
function playPendingIntroAnimation() {
|
|
3685
|
-
if (!pendingPillEl
|
|
3679
|
+
if (!pendingPillEl?.animate || (matchMedia?.('(prefers-reduced-motion: reduce)').matches)) return;
|
|
3686
3680
|
if (pendingIntroAnimation) pendingIntroAnimation.cancel();
|
|
3687
3681
|
pendingIntroAnimation = pendingPillEl.animate([
|
|
3688
3682
|
{
|
|
@@ -3709,9 +3703,9 @@
|
|
|
3709
3703
|
}
|
|
3710
3704
|
|
|
3711
3705
|
function ensureSpinKeyframes() {
|
|
3712
|
-
if (uiGetById(PREFIX
|
|
3706
|
+
if (uiGetById(`${PREFIX}-keyframes`)) return;
|
|
3713
3707
|
const style = document.createElement('style');
|
|
3714
|
-
style.id = PREFIX
|
|
3708
|
+
style.id = `${PREFIX}-keyframes`;
|
|
3715
3709
|
style.textContent = '@keyframes monodesign-spin { to { transform: rotate(360deg); } }';
|
|
3716
3710
|
uiAppendStyle(style);
|
|
3717
3711
|
}
|
|
@@ -3725,7 +3719,7 @@
|
|
|
3725
3719
|
}
|
|
3726
3720
|
|
|
3727
3721
|
function manualApplyStateKey() {
|
|
3728
|
-
return PREFIX
|
|
3722
|
+
return `${PREFIX}:manual-apply:${PORT}:${TOKEN}:${location.pathname}`;
|
|
3729
3723
|
}
|
|
3730
3724
|
|
|
3731
3725
|
function readStoredManualApplyState() {
|
|
@@ -3790,13 +3784,14 @@
|
|
|
3790
3784
|
if (stored?.phase === 'repairing') {
|
|
3791
3785
|
const attempt = Number(stored.repairAttempt) || 1;
|
|
3792
3786
|
const max = Number(stored.repairMaxAttempts) || 3;
|
|
3793
|
-
return
|
|
3787
|
+
return `Fixing apply issue, attempt ${attempt}/${max}`;
|
|
3794
3788
|
}
|
|
3795
3789
|
if (stored?.phase === 'verifying') return 'Verifying copy edits';
|
|
3796
3790
|
const remaining = Number.isFinite(Number(stored?.remainingCount))
|
|
3797
3791
|
? Number(stored.remainingCount)
|
|
3798
3792
|
: Number(fallbackCount) || 0;
|
|
3799
3793
|
return remaining > 0
|
|
3794
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:151
|
|
3800
3795
|
? 'Applying ' + remaining + ' copy edit' + (remaining === 1 ? '' : 's')
|
|
3801
3796
|
: 'Verifying copy edits';
|
|
3802
3797
|
}
|
|
@@ -3846,10 +3841,10 @@
|
|
|
3846
3841
|
closeTunePopover();
|
|
3847
3842
|
}
|
|
3848
3843
|
if (barEl && barEl.style.display !== 'none' && state === 'CONFIGURING') {
|
|
3849
|
-
const input = uiGetById(PREFIX
|
|
3844
|
+
const input = uiGetById(`${PREFIX}-input`);
|
|
3850
3845
|
const prompt = input ? input.value : '';
|
|
3851
3846
|
updateBarContent('configure');
|
|
3852
|
-
const nextInput = uiGetById(PREFIX
|
|
3847
|
+
const nextInput = uiGetById(`${PREFIX}-input`);
|
|
3853
3848
|
if (nextInput) nextInput.value = prompt;
|
|
3854
3849
|
}
|
|
3855
3850
|
if (editBadgeEl && editBadgeEl.style.display !== 'none') {
|
|
@@ -3928,7 +3923,7 @@
|
|
|
3928
3923
|
}
|
|
3929
3924
|
pendingPillLabelEl.textContent = pendingApplyLabel(currentPageCount);
|
|
3930
3925
|
pendingPillCountEl.textContent = String(currentPageCount);
|
|
3931
|
-
pendingPillEl.setAttribute('aria-label',
|
|
3926
|
+
pendingPillEl.setAttribute('aria-label', `Apply ${currentPageCount} copy edit${currentPageCount === 1 ? '' : 's'} to source`);
|
|
3932
3927
|
pendingPillEl.style.display = 'inline-flex';
|
|
3933
3928
|
pendingTrashBtn.style.display = 'inline-flex';
|
|
3934
3929
|
pendingDockEl.style.display = 'inline-flex';
|
|
@@ -3947,7 +3942,7 @@
|
|
|
3947
3942
|
async function fetchPendingCount() {
|
|
3948
3943
|
try {
|
|
3949
3944
|
const res = await fetch(
|
|
3950
|
-
|
|
3945
|
+
`http://localhost:${PORT}/manual-edit-stash?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
|
|
3951
3946
|
);
|
|
3952
3947
|
if (!res.ok) return;
|
|
3953
3948
|
const data = await res.json();
|
|
@@ -3960,19 +3955,19 @@
|
|
|
3960
3955
|
async function onPendingPillClick() {
|
|
3961
3956
|
const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
|
|
3962
3957
|
if (count <= 0 || pendingApplyInFlight) return;
|
|
3963
|
-
const ok = confirm(
|
|
3958
|
+
const ok = confirm(`Apply ${count} copy edit${count === 1 ? '' : 's'} to source?`);
|
|
3964
3959
|
if (!ok) return;
|
|
3965
3960
|
let waitForSseCompletion = false;
|
|
3966
3961
|
resetManualApplyProgress(count);
|
|
3967
3962
|
setPendingApplyLoading(true, count);
|
|
3968
3963
|
try {
|
|
3969
3964
|
const res = await fetch(
|
|
3970
|
-
|
|
3965
|
+
`http://localhost:${PORT}/manual-edit-commit?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}&async=1`,
|
|
3971
3966
|
{ method: 'POST', keepalive: true },
|
|
3972
3967
|
);
|
|
3973
3968
|
if (!res.ok) {
|
|
3974
3969
|
const errBody = await res.json().catch(() => ({}));
|
|
3975
|
-
throw new Error(errBody.error || (
|
|
3970
|
+
throw new Error(errBody.error || (`HTTP ${res.status}`));
|
|
3976
3971
|
}
|
|
3977
3972
|
const result = await res.json();
|
|
3978
3973
|
if (res.status === 202 || result.status === 'started') {
|
|
@@ -3983,11 +3978,11 @@
|
|
|
3983
3978
|
updatePendingCounter(remaining);
|
|
3984
3979
|
if (result.failed && result.failed.length > 0) {
|
|
3985
3980
|
console.warn('[monodesign] some copy edits failed:', result.failed);
|
|
3986
|
-
showToast(
|
|
3981
|
+
showToast(`Applied ${result.applied?.length || 0}, ${result.failed.length} failed - see console`, 5000);
|
|
3987
3982
|
} else {
|
|
3988
3983
|
const n = Array.isArray(result.applied) ? result.applied.length : (result.cleared || 0);
|
|
3989
3984
|
if (n > 0) {
|
|
3990
|
-
showToast(
|
|
3985
|
+
showToast(`Applied ${n} edit${n === 1 ? '' : 's'}`, 2500);
|
|
3991
3986
|
} else {
|
|
3992
3987
|
console.warn('[monodesign] apply returned no verified edits:', result);
|
|
3993
3988
|
showToast('No edits applied - see console', 4000);
|
|
@@ -4008,21 +4003,21 @@
|
|
|
4008
4003
|
async function onPendingTrashClick() {
|
|
4009
4004
|
const count = parseInt(pendingPillEl?.dataset.count || '0', 10);
|
|
4010
4005
|
if (count <= 0 || pendingApplyInFlight) return;
|
|
4011
|
-
const ok = confirm(
|
|
4006
|
+
const ok = confirm(`Discard ${count} copy edit${count === 1 ? '' : 's'} on this page?`);
|
|
4012
4007
|
if (!ok) return;
|
|
4013
4008
|
try {
|
|
4014
4009
|
const res = await fetch(
|
|
4015
|
-
|
|
4010
|
+
`http://localhost:${PORT}/manual-edit-discard?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
|
|
4016
4011
|
{ method: 'POST' },
|
|
4017
4012
|
);
|
|
4018
|
-
if (!res.ok) throw new Error(
|
|
4013
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4019
4014
|
const result = await res.json().catch(() => ({}));
|
|
4020
4015
|
const restoreFailures = restoreDiscardedManualEdits(result.entries || []);
|
|
4021
4016
|
updatePendingCounter(0);
|
|
4022
4017
|
if (restoreFailures > 0) {
|
|
4023
|
-
showToast(
|
|
4018
|
+
showToast(`Discarded ${count} copy edit${count === 1 ? '' : 's'} - refresh to reset ${restoreFailures}`, 4000);
|
|
4024
4019
|
} else {
|
|
4025
|
-
showToast(
|
|
4020
|
+
showToast(`Discarded ${count} copy edit${count === 1 ? '' : 's'}`, 2500);
|
|
4026
4021
|
}
|
|
4027
4022
|
} catch (err) {
|
|
4028
4023
|
console.error('[monodesign] discard failed:', err);
|
|
@@ -4061,10 +4056,10 @@
|
|
|
4061
4056
|
updateManualApplyRepairState({ attempt: 1, maxAttempts: 3 }, 'repairing');
|
|
4062
4057
|
try {
|
|
4063
4058
|
const res = await fetch(
|
|
4064
|
-
|
|
4059
|
+
`http://localhost:${PORT}/manual-edit-commit?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}&async=1&repair=1`,
|
|
4065
4060
|
{ method: 'POST', keepalive: true },
|
|
4066
4061
|
);
|
|
4067
|
-
if (!res.ok) throw new Error(
|
|
4062
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4068
4063
|
if (pendingKeepFixingBtn) pendingKeepFixingBtn.style.display = 'none';
|
|
4069
4064
|
if (pendingRollbackBtn) pendingRollbackBtn.style.display = 'none';
|
|
4070
4065
|
if (pendingTrashBtn) pendingTrashBtn.style.display = 'inline-flex';
|
|
@@ -4080,14 +4075,14 @@
|
|
|
4080
4075
|
if (!ok) return;
|
|
4081
4076
|
try {
|
|
4082
4077
|
const res = await fetch(
|
|
4083
|
-
|
|
4078
|
+
`http://localhost:${PORT}/manual-edit-repair-decision?token=${encodeURIComponent(TOKEN)}&pageUrl=${encodeURIComponent(location.pathname)}`,
|
|
4084
4079
|
{
|
|
4085
4080
|
method: 'POST',
|
|
4086
4081
|
headers: { 'Content-Type': 'application/json' },
|
|
4087
4082
|
body: JSON.stringify({ token: TOKEN, pageUrl: location.pathname, action: 'rollback' }),
|
|
4088
4083
|
},
|
|
4089
4084
|
);
|
|
4090
|
-
if (!res.ok) throw new Error(
|
|
4085
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
4091
4086
|
const result = await res.json().catch(() => ({}));
|
|
4092
4087
|
clearStoredManualApplyState();
|
|
4093
4088
|
updatePendingCounter(numberOrNull(result.remainingCount) || 0);
|
|
@@ -4174,9 +4169,9 @@
|
|
|
4174
4169
|
const failedCount = numberOrNull(msg.failedCount) || 0;
|
|
4175
4170
|
const appliedCount = numberOrNull(msg.appliedCount) || numberOrNull(msg.cleared) || 0;
|
|
4176
4171
|
if (failedCount > 0) {
|
|
4177
|
-
showToast(
|
|
4172
|
+
showToast(`Applied ${appliedCount}, ${failedCount} failed - see console`, 5000);
|
|
4178
4173
|
} else if (appliedCount > 0) {
|
|
4179
|
-
showToast(
|
|
4174
|
+
showToast(`Applied ${appliedCount} edit${appliedCount === 1 ? '' : 's'}`, 2500);
|
|
4180
4175
|
}
|
|
4181
4176
|
}
|
|
4182
4177
|
return;
|
|
@@ -4219,7 +4214,7 @@
|
|
|
4219
4214
|
}
|
|
4220
4215
|
|
|
4221
4216
|
function mixedTextWrapRestoreHint(el) {
|
|
4222
|
-
if (
|
|
4217
|
+
if (el?.dataset?.monodesignTextWrap !== 'true' || !el.parentElement) return null;
|
|
4223
4218
|
const siblings = directMixedTextRestoreNodes(el.parentElement);
|
|
4224
4219
|
const textIndex = siblings.indexOf(el);
|
|
4225
4220
|
return {
|
|
@@ -4231,7 +4226,7 @@
|
|
|
4231
4226
|
|
|
4232
4227
|
function restoreMixedTextNodeManualEdit(op) {
|
|
4233
4228
|
const restore = op?.restore;
|
|
4234
|
-
if (
|
|
4229
|
+
if (restore?.kind !== 'mixedTextNode' || typeof op?.originalText !== 'string') return false;
|
|
4235
4230
|
const parent = queryManualEditRef(restore.parentRef);
|
|
4236
4231
|
if (!parent) return false;
|
|
4237
4232
|
const textNodes = directMixedTextRestoreNodes(parent).filter((node) => node.nodeType === 3);
|
|
@@ -4264,7 +4259,7 @@
|
|
|
4264
4259
|
}
|
|
4265
4260
|
const tag = op?.tag || op?.leaf?.tagName || '*';
|
|
4266
4261
|
const classes = Array.isArray(op?.classes) ? op.classes : (Array.isArray(op?.leaf?.classes) ? op.leaf.classes : []);
|
|
4267
|
-
const selector = (tag === '*' ? '' : tag) + classes.map((cls) =>
|
|
4262
|
+
const selector = (tag === '*' ? '' : tag) + classes.map((cls) => `.${cssIdent(cls)}`).join('') || '*';
|
|
4268
4263
|
let matches = [];
|
|
4269
4264
|
try {
|
|
4270
4265
|
matches = Array.from(document.querySelectorAll(selector));
|
|
@@ -4317,7 +4312,7 @@
|
|
|
4317
4312
|
if (el.tagName.toLowerCase() !== segment.tag) return false;
|
|
4318
4313
|
if (segment.id && el.id !== segment.id) return false;
|
|
4319
4314
|
for (const cls of segment.classes) {
|
|
4320
|
-
if (!el.classList
|
|
4315
|
+
if (!el.classList?.contains(cls)) return false;
|
|
4321
4316
|
}
|
|
4322
4317
|
if (segment.nth && indexAmongSameTag(el) !== segment.nth) return false;
|
|
4323
4318
|
return true;
|
|
@@ -4340,7 +4335,7 @@
|
|
|
4340
4335
|
|
|
4341
4336
|
function usesShadowChromeRoot() {
|
|
4342
4337
|
const root = liveUiRoot();
|
|
4343
|
-
return root && root !== document.body && root.host && root.host.id === PREFIX
|
|
4338
|
+
return root && root !== document.body && root.host && root.host.id === `${PREFIX}-root`;
|
|
4344
4339
|
}
|
|
4345
4340
|
|
|
4346
4341
|
function setImportantStyle(el, name, value) {
|
|
@@ -4350,7 +4345,7 @@
|
|
|
4350
4345
|
function initEditBadgeHitProxies() {
|
|
4351
4346
|
if (!usesShadowChromeRoot() || editBadgeProxyRoot) return;
|
|
4352
4347
|
editBadgeProxyRoot = document.createElement('div');
|
|
4353
|
-
editBadgeProxyRoot.id = PREFIX
|
|
4348
|
+
editBadgeProxyRoot.id = `${PREFIX}-edit-badge-hit-proxies`;
|
|
4354
4349
|
editBadgeProxyRoot.setAttribute('aria-hidden', 'true');
|
|
4355
4350
|
const styles = {
|
|
4356
4351
|
all: 'initial',
|
|
@@ -4364,7 +4359,7 @@
|
|
|
4364
4359
|
overflow: 'visible',
|
|
4365
4360
|
};
|
|
4366
4361
|
for (const [name, value] of Object.entries(styles)) {
|
|
4367
|
-
setImportantStyle(editBadgeProxyRoot, name.replace(/[A-Z]/g, (m) =>
|
|
4362
|
+
setImportantStyle(editBadgeProxyRoot, name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`), value);
|
|
4368
4363
|
}
|
|
4369
4364
|
document.body.appendChild(editBadgeProxyRoot);
|
|
4370
4365
|
}
|
|
@@ -4375,10 +4370,10 @@
|
|
|
4375
4370
|
const styles = {
|
|
4376
4371
|
all: 'initial',
|
|
4377
4372
|
position: 'fixed',
|
|
4378
|
-
left: rect.left
|
|
4379
|
-
top: rect.top
|
|
4380
|
-
width: rect.width
|
|
4381
|
-
height: rect.height
|
|
4373
|
+
left: `${rect.left}px`,
|
|
4374
|
+
top: `${rect.top}px`,
|
|
4375
|
+
width: `${rect.width}px`,
|
|
4376
|
+
height: `${rect.height}px`,
|
|
4382
4377
|
margin: '0',
|
|
4383
4378
|
padding: '0',
|
|
4384
4379
|
border: '0',
|
|
@@ -4391,7 +4386,7 @@
|
|
|
4391
4386
|
zIndex: String(Z.toast + 2),
|
|
4392
4387
|
};
|
|
4393
4388
|
for (const [name, value] of Object.entries(styles)) {
|
|
4394
|
-
setImportantStyle(proxy, name.replace(/[A-Z]/g, (m) =>
|
|
4389
|
+
setImportantStyle(proxy, name.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`), value);
|
|
4395
4390
|
}
|
|
4396
4391
|
}
|
|
4397
4392
|
|
|
@@ -4495,7 +4490,7 @@
|
|
|
4495
4490
|
|
|
4496
4491
|
function initEditBadge() {
|
|
4497
4492
|
editBadgeEl = document.createElement('div');
|
|
4498
|
-
editBadgeEl.id = PREFIX
|
|
4493
|
+
editBadgeEl.id = `${PREFIX}-edit-badge`;
|
|
4499
4494
|
Object.assign(editBadgeEl.style, {
|
|
4500
4495
|
position: 'fixed',
|
|
4501
4496
|
zIndex: String(Z.highlight + 1),
|
|
@@ -4507,9 +4502,9 @@
|
|
|
4507
4502
|
initEditBadgeHitProxies();
|
|
4508
4503
|
|
|
4509
4504
|
// Remove focus rings on edit badge buttons + contenteditable elements
|
|
4510
|
-
if (!uiGetById(PREFIX
|
|
4505
|
+
if (!uiGetById(`${PREFIX}-edit-badge-focus-style`)) {
|
|
4511
4506
|
const s = document.createElement('style');
|
|
4512
|
-
s.id = PREFIX
|
|
4507
|
+
s.id = `${PREFIX}-edit-badge-focus-style`;
|
|
4513
4508
|
s.textContent =
|
|
4514
4509
|
'#' + PREFIX + '-edit-badge button { outline: none !important; box-shadow: 0 2px 8px rgba(0,0,0,0.1) !important; }' +
|
|
4515
4510
|
'#' + PREFIX + '-edit-badge button:focus { outline: none !important; }' +
|
|
@@ -4530,8 +4525,8 @@
|
|
|
4530
4525
|
const bw = editBadgeEl.offsetWidth;
|
|
4531
4526
|
// Match showHighlight's 2px outset so the badge right edge lines up with the outline.
|
|
4532
4527
|
const outlineRight = r.right + 2;
|
|
4533
|
-
editBadgeEl.style.top = Math.max(4, r.top - 28)
|
|
4534
|
-
editBadgeEl.style.left = Math.min(window.innerWidth - bw - 4, outlineRight - bw)
|
|
4528
|
+
editBadgeEl.style.top = `${Math.max(4, r.top - 28)}px`;
|
|
4529
|
+
editBadgeEl.style.left = `${Math.min(window.innerWidth - bw - 4, outlineRight - bw)}px`;
|
|
4535
4530
|
syncEditBadgeHitProxies();
|
|
4536
4531
|
}
|
|
4537
4532
|
|
|
@@ -4560,7 +4555,7 @@
|
|
|
4560
4555
|
color: color,
|
|
4561
4556
|
background: SURFACE,
|
|
4562
4557
|
padding: '2px 8px',
|
|
4563
|
-
border:
|
|
4558
|
+
border: `1px solid ${borderColor || color}`,
|
|
4564
4559
|
borderRadius: '6px',
|
|
4565
4560
|
boxSizing: 'border-box',
|
|
4566
4561
|
minHeight: '22px',
|
|
@@ -4599,7 +4594,7 @@
|
|
|
4599
4594
|
btn.style.cursor = 'not-allowed';
|
|
4600
4595
|
btn.style.opacity = '0.55';
|
|
4601
4596
|
btn.disabled = true;
|
|
4602
|
-
const disabledTip = EDIT_COPY_LABEL
|
|
4597
|
+
const disabledTip = `${EDIT_COPY_LABEL} is disabled while the current copy edit is applying`;
|
|
4603
4598
|
btn.addEventListener('mouseenter', () => showConfigureBarTooltip(btn, disabledTip));
|
|
4604
4599
|
btn.addEventListener('mouseleave', hideConfigureBarTooltip);
|
|
4605
4600
|
} else {
|
|
@@ -4668,20 +4663,20 @@
|
|
|
4668
4663
|
const prevDirection = paramsPanelEl.dataset.tuneDirection;
|
|
4669
4664
|
|
|
4670
4665
|
// top/left/width are NOT in the transition list, so they snap instantly.
|
|
4671
|
-
paramsPanelEl.style.left = br.left
|
|
4672
|
-
paramsPanelEl.style.width = br.width
|
|
4666
|
+
paramsPanelEl.style.left = `${br.left}px`;
|
|
4667
|
+
paramsPanelEl.style.width = `${br.width}px`;
|
|
4673
4668
|
|
|
4674
4669
|
if (direction === 'below') {
|
|
4675
|
-
paramsPanelEl.style.top =
|
|
4670
|
+
paramsPanelEl.style.top = `${br.bottom - TUNE_OVERLAP}px`;
|
|
4676
4671
|
paramsPanelEl.style.borderRadius = '0 0 10px 10px';
|
|
4677
|
-
paramsPanelEl.style.paddingTop =
|
|
4672
|
+
paramsPanelEl.style.paddingTop = `${14 + TUNE_OVERLAP}px`;
|
|
4678
4673
|
paramsPanelEl.style.paddingBottom = '14px';
|
|
4679
4674
|
} else {
|
|
4680
4675
|
const ih = paramsPanelEl.offsetHeight || 80;
|
|
4681
|
-
paramsPanelEl.style.top =
|
|
4676
|
+
paramsPanelEl.style.top = `${br.top - ih + TUNE_OVERLAP}px`;
|
|
4682
4677
|
paramsPanelEl.style.borderRadius = '10px 10px 0 0';
|
|
4683
4678
|
paramsPanelEl.style.paddingTop = '14px';
|
|
4684
|
-
paramsPanelEl.style.paddingBottom =
|
|
4679
|
+
paramsPanelEl.style.paddingBottom = `${14 + TUNE_OVERLAP}px`;
|
|
4685
4680
|
}
|
|
4686
4681
|
paramsPanelEl.dataset.tuneDirection = direction;
|
|
4687
4682
|
|
|
@@ -4802,10 +4797,10 @@
|
|
|
4802
4797
|
const shown = svelteComponentSession?.sessionId === currentSessionId && svelteComponentSession.mountedVariant > 0
|
|
4803
4798
|
? svelteComponentSession.mountedVariant
|
|
4804
4799
|
: visibleVariant;
|
|
4805
|
-
const counter = uiGetById(PREFIX
|
|
4806
|
-
if (counter && arrivedVariants > 0) counter.textContent = shown
|
|
4807
|
-
const prev = uiGetById(PREFIX
|
|
4808
|
-
const next = uiGetById(PREFIX
|
|
4800
|
+
const counter = uiGetById(`${PREFIX}-variant-counter`);
|
|
4801
|
+
if (counter && arrivedVariants > 0) counter.textContent = `${shown}/${arrivedVariants}`;
|
|
4802
|
+
const prev = uiGetById(`${PREFIX}-variant-prev`);
|
|
4803
|
+
const next = uiGetById(`${PREFIX}-variant-next`);
|
|
4809
4804
|
if (prev) prev.style.opacity = shown <= 1 ? '0.3' : '1';
|
|
4810
4805
|
if (next) next.style.opacity = shown >= arrivedVariants ? '0.3' : '1';
|
|
4811
4806
|
if (currentSessionId && state === 'CYCLING') saveSession();
|
|
@@ -4821,7 +4816,7 @@
|
|
|
4821
4816
|
scheduleCyclingBarSync(sessionId, num);
|
|
4822
4817
|
return true;
|
|
4823
4818
|
}
|
|
4824
|
-
const wrapper = document.querySelector(
|
|
4819
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
4825
4820
|
if (!wrapper) return false;
|
|
4826
4821
|
updateVariantStateStylesheet(sessionId, num);
|
|
4827
4822
|
// Unconditional refresh - covers first-reveal (no-op if state isn't
|
|
@@ -4837,7 +4832,7 @@
|
|
|
4837
4832
|
|
|
4838
4833
|
function parseOriginalMarkupElement(originalMarkup) {
|
|
4839
4834
|
const parser = new DOMParser();
|
|
4840
|
-
const doc = parser.parseFromString(
|
|
4835
|
+
const doc = parser.parseFromString(`<div id="monodesign-anchor">${originalMarkup}</div>`, 'text/html');
|
|
4841
4836
|
return doc.getElementById('monodesign-anchor')?.firstElementChild || null;
|
|
4842
4837
|
}
|
|
4843
4838
|
|
|
@@ -4854,7 +4849,7 @@
|
|
|
4854
4849
|
}
|
|
4855
4850
|
|
|
4856
4851
|
function buildPickedAnchorSnapshot(el) {
|
|
4857
|
-
if (
|
|
4852
|
+
if (el?.nodeType !== 1) return null;
|
|
4858
4853
|
return {
|
|
4859
4854
|
tag: el.tagName,
|
|
4860
4855
|
id: el.id || '',
|
|
@@ -5002,7 +4997,7 @@
|
|
|
5002
4997
|
// A wrapper can land incomplete ("wrap HMR landed, variant insert did
|
|
5003
4998
|
// not"); injectVariantsFromSource owns both cases - it replaces an
|
|
5004
4999
|
// existing wrapper from source and clears recoveryWaitingForAnchor.
|
|
5005
|
-
const wrapperLanded = !!document.querySelector(
|
|
5000
|
+
const wrapperLanded = !!document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5006
5001
|
if (!wrapperLanded) {
|
|
5007
5002
|
const liveEl = resolveLiveInjectionAnchor(originalMarkup);
|
|
5008
5003
|
if (!liveEl?.parentElement) return;
|
|
@@ -5045,8 +5040,8 @@
|
|
|
5045
5040
|
async function loadSvelteComponentParams(manifest) {
|
|
5046
5041
|
const dir = String(manifest?.componentDir || '').replace(/^\/+/, '');
|
|
5047
5042
|
if (!dir) return {};
|
|
5048
|
-
const paramsPath = dir
|
|
5049
|
-
const url =
|
|
5043
|
+
const paramsPath = `${dir}/params.json`;
|
|
5044
|
+
const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(paramsPath)}`;
|
|
5050
5045
|
try {
|
|
5051
5046
|
const res = await fetch(url);
|
|
5052
5047
|
if (!res.ok) return {};
|
|
@@ -5065,8 +5060,8 @@
|
|
|
5065
5060
|
async function loadSvelteComponentVariantSource(manifest, variantNum) {
|
|
5066
5061
|
const dir = String(manifest?.componentDir || '').replace(/^\/+/, '');
|
|
5067
5062
|
if (!dir || !variantNum) return '';
|
|
5068
|
-
const sourcePath = dir
|
|
5069
|
-
const url =
|
|
5063
|
+
const sourcePath = `${dir}/v${variantNum}.svelte`;
|
|
5064
|
+
const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(sourcePath)}`;
|
|
5070
5065
|
try {
|
|
5071
5066
|
const res = await fetch(url);
|
|
5072
5067
|
if (!res.ok) return '';
|
|
@@ -5105,7 +5100,7 @@
|
|
|
5105
5100
|
}
|
|
5106
5101
|
|
|
5107
5102
|
function scopeCssToSveltePreview(css, sessionId) {
|
|
5108
|
-
const prefix =
|
|
5103
|
+
const prefix = `[data-monodesign-variants="${String(sessionId).replace(/"/g, '\\"')}"] `;
|
|
5109
5104
|
return scopeCssBlock(String(css || ''), prefix).trim();
|
|
5110
5105
|
}
|
|
5111
5106
|
|
|
@@ -5132,11 +5127,11 @@
|
|
|
5132
5127
|
}
|
|
5133
5128
|
const body = css.slice(open + 1, close);
|
|
5134
5129
|
if (shouldScopeNestedCssAtRule(prelude)) {
|
|
5135
|
-
out += prelude
|
|
5130
|
+
out += `${prelude} {\n${scopeCssBlock(body, prefix)}\n}`;
|
|
5136
5131
|
} else if (prelude.startsWith('@')) {
|
|
5137
|
-
out += prelude
|
|
5132
|
+
out += `${prelude} {${body}}`;
|
|
5138
5133
|
} else {
|
|
5139
|
-
out += prefixCssSelectors(prelude, prefix)
|
|
5134
|
+
out += `${prefixCssSelectors(prelude, prefix)} {${body}}`;
|
|
5140
5135
|
}
|
|
5141
5136
|
i = close + 1;
|
|
5142
5137
|
}
|
|
@@ -5221,7 +5216,7 @@
|
|
|
5221
5216
|
if (!sourceOriginal) return values;
|
|
5222
5217
|
const map = buildSvelteExpressionTextMap(sourceOriginal, liveEl);
|
|
5223
5218
|
for (const entry of contract) {
|
|
5224
|
-
const token =
|
|
5219
|
+
const token = `{${entry.expr}}`;
|
|
5225
5220
|
values[entry.prop] = map.get(token) || '';
|
|
5226
5221
|
}
|
|
5227
5222
|
return values;
|
|
@@ -5234,8 +5229,8 @@
|
|
|
5234
5229
|
const previousAnchor = getMountedSvelteComponentAnchor(svelteComponentSession) || selectedElement;
|
|
5235
5230
|
svelteComponentSession.swapAnchor = makeFrozenAnchor(previousAnchor) || svelteComponentSession.swapAnchor || null;
|
|
5236
5231
|
const runtime = await loadSvelteRuntime(manifest.runtimeModule);
|
|
5237
|
-
const modulePath =
|
|
5238
|
-
const moduleUrl = new URL(modulePath, location.origin).href
|
|
5232
|
+
const modulePath = `/${String(manifest.componentDir || '').replace(/^\/+/, '')}/v${variantNum}.svelte`;
|
|
5233
|
+
const moduleUrl = `${new URL(modulePath, location.origin).href}?t=${Date.now()}`;
|
|
5239
5234
|
const mod = await import(/* @vite-ignore */ moduleUrl);
|
|
5240
5235
|
const Component = mod.default;
|
|
5241
5236
|
if (svelteComponentSession.mountedInstance && runtime.unmount) {
|
|
@@ -5275,7 +5270,7 @@
|
|
|
5275
5270
|
if (svelteComponentSession?.sessionId === sessionId) {
|
|
5276
5271
|
svelteComponentSession.swapAnchor = null;
|
|
5277
5272
|
}
|
|
5278
|
-
console.error(
|
|
5273
|
+
console.error(`[monodesign] Failed to mount Svelte variant ${variantNum} for ${sessionId}:`, err);
|
|
5279
5274
|
return false;
|
|
5280
5275
|
}
|
|
5281
5276
|
}
|
|
@@ -5332,7 +5327,7 @@
|
|
|
5332
5327
|
}
|
|
5333
5328
|
|
|
5334
5329
|
async function injectSvelteComponentsFromManifest(manifestPath, sessionId) {
|
|
5335
|
-
const url =
|
|
5330
|
+
const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(manifestPath)}`;
|
|
5336
5331
|
try {
|
|
5337
5332
|
const res = await fetch(url);
|
|
5338
5333
|
if (!res.ok) throw new Error(String(res.status));
|
|
@@ -5349,7 +5344,7 @@
|
|
|
5349
5344
|
});
|
|
5350
5345
|
if (state !== 'CYCLING') setLiveState('GENERATING');
|
|
5351
5346
|
|
|
5352
|
-
const existingWrapper = document.querySelector(
|
|
5347
|
+
const existingWrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5353
5348
|
if (existingWrapper && svelteComponentSession?.sessionId === sessionId) {
|
|
5354
5349
|
recoveryWaitingForAnchor = false;
|
|
5355
5350
|
svelteComponentSession.paramsByVariant = paramsByVariant;
|
|
@@ -5445,7 +5440,7 @@
|
|
|
5445
5440
|
refreshParamsPanel();
|
|
5446
5441
|
positionBar();
|
|
5447
5442
|
saveSession();
|
|
5448
|
-
console.log(
|
|
5443
|
+
console.log(`[monodesign] Mounted ${arrivedVariants} Svelte component variants.`);
|
|
5449
5444
|
} catch (err) {
|
|
5450
5445
|
console.error('[monodesign] Failed to mount Svelte component variants:', err);
|
|
5451
5446
|
abortSvelteComponentInjection(sessionId, 'Could not load variants. Fix the error and re-run.');
|
|
@@ -5477,7 +5472,7 @@
|
|
|
5477
5472
|
if (svelteComponentSession?.sessionId === sessionId) {
|
|
5478
5473
|
teardownSvelteComponentSession(true);
|
|
5479
5474
|
} else {
|
|
5480
|
-
const orphan = document.querySelector(
|
|
5475
|
+
const orphan = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5481
5476
|
if (orphan) orphan.remove();
|
|
5482
5477
|
}
|
|
5483
5478
|
} catch (err) {
|
|
@@ -5513,7 +5508,7 @@
|
|
|
5513
5508
|
return;
|
|
5514
5509
|
}
|
|
5515
5510
|
rememberSessionFileMeta({ file: filePath });
|
|
5516
|
-
const url =
|
|
5511
|
+
const url = `http://localhost:${PORT}/source?token=${TOKEN}&path=${encodeURIComponent(filePath)}`;
|
|
5517
5512
|
fetch(url)
|
|
5518
5513
|
.then(r => { if (!r.ok) throw new Error(r.status); return r.text(); })
|
|
5519
5514
|
.then(html => {
|
|
@@ -5521,15 +5516,15 @@
|
|
|
5521
5516
|
let srcWrapper = null;
|
|
5522
5517
|
|
|
5523
5518
|
// Full-file parse works for HTML/JSX; Astro/Vue sources need marker extraction.
|
|
5524
|
-
const startMark =
|
|
5525
|
-
const endMark =
|
|
5519
|
+
const startMark = `<!-- monodesign-variants-start ${sessionId} -->`;
|
|
5520
|
+
const endMark = `<!-- monodesign-variants-end ${sessionId} -->`;
|
|
5526
5521
|
const startIdx = html.indexOf(startMark);
|
|
5527
5522
|
const endIdx = html.indexOf(endMark);
|
|
5528
5523
|
const block = startIdx !== -1 && endIdx !== -1 && endIdx > startIdx
|
|
5529
5524
|
? html.slice(startIdx + startMark.length, endIdx).trim()
|
|
5530
5525
|
: html;
|
|
5531
5526
|
const doc = parser.parseFromString(normalizeSourceFallbackBlock(block, filePath), 'text/html');
|
|
5532
|
-
srcWrapper = doc.querySelector(
|
|
5527
|
+
srcWrapper = doc.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5533
5528
|
if (!srcWrapper) {
|
|
5534
5529
|
console.warn('[monodesign] Variant wrapper not found in source file.');
|
|
5535
5530
|
return;
|
|
@@ -5539,7 +5534,7 @@
|
|
|
5539
5534
|
const wrapper = srcWrapper.cloneNode(true);
|
|
5540
5535
|
|
|
5541
5536
|
// Wrapper already in DOM (wrap HMR landed, variant insert did not).
|
|
5542
|
-
const existingWrapper = document.querySelector(
|
|
5537
|
+
const existingWrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5543
5538
|
if (existingWrapper) {
|
|
5544
5539
|
existingWrapper.parentElement.replaceChild(wrapper, existingWrapper);
|
|
5545
5540
|
} else {
|
|
@@ -5571,6 +5566,7 @@
|
|
|
5571
5566
|
// when a late HMR/source reinjection lands after they have cycled.
|
|
5572
5567
|
const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
|
|
5573
5568
|
arrivedVariants = variants.length;
|
|
5569
|
+
// biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
|
|
5574
5570
|
expectedVariants = parseInt(wrapper.dataset.monodesignVariantCount || arrivedVariants);
|
|
5575
5571
|
if (arrivedVariants <= 0) {
|
|
5576
5572
|
recoverEmptyCycling('source-fallback-empty');
|
|
@@ -5594,7 +5590,7 @@
|
|
|
5594
5590
|
refreshParamsPanel();
|
|
5595
5591
|
positionBar();
|
|
5596
5592
|
saveSession();
|
|
5597
|
-
console.log(
|
|
5593
|
+
console.log(`[monodesign] Injected ${arrivedVariants} variants from source file.`);
|
|
5598
5594
|
})
|
|
5599
5595
|
.catch(err => {
|
|
5600
5596
|
console.error('[monodesign] Failed to fetch source:', err);
|
|
@@ -5607,16 +5603,16 @@
|
|
|
5607
5603
|
return String(block)
|
|
5608
5604
|
.replace(
|
|
5609
5605
|
/<style\b([^>]*)>\s*\{\s*`([\s\S]*?)`\s*\}\s*<\/style>/g,
|
|
5610
|
-
(_match, attrs, css) =>
|
|
5606
|
+
(_match, attrs, css) => `<style${attrs}>${css}</style>`,
|
|
5611
5607
|
)
|
|
5612
5608
|
.replace(/\bclassName\s*=\s*\{\s*`([^`]*?)`\s*\}/g, (_match, value) => {
|
|
5613
5609
|
const literalClasses = value.replace(/\$\{[^}]*\}/g, ' ').replace(/\s+/g, ' ').trim();
|
|
5614
|
-
return literalClasses ?
|
|
5610
|
+
return literalClasses ? `class="${escapeHtml(literalClasses)}"` : '';
|
|
5615
5611
|
})
|
|
5616
5612
|
.replace(/\bclassName\s*=/g, 'class=')
|
|
5617
5613
|
.replace(/\sstyle=\{\{([\s\S]*?)\}\}/g, (_match, body) => {
|
|
5618
5614
|
const css = jsxStyleObjectToCss(body);
|
|
5619
|
-
return css ?
|
|
5615
|
+
return css ? ` style="${escapeHtml(css)}"` : '';
|
|
5620
5616
|
});
|
|
5621
5617
|
}
|
|
5622
5618
|
|
|
@@ -5628,16 +5624,16 @@
|
|
|
5628
5624
|
const prop = jsxStylePropToCss(match[1]);
|
|
5629
5625
|
const value = match[2] ?? match[3] ?? match[4] ?? '';
|
|
5630
5626
|
if (!prop || value === '') continue;
|
|
5631
|
-
declarations.push(prop
|
|
5627
|
+
declarations.push(`${prop}: ${value}`);
|
|
5632
5628
|
}
|
|
5633
5629
|
return declarations.join('; ');
|
|
5634
5630
|
}
|
|
5635
5631
|
|
|
5636
5632
|
function jsxStylePropToCss(prop) {
|
|
5637
|
-
|
|
5633
|
+
const out = String(prop || '').trim().replace(/^["']|["']$/g, '');
|
|
5638
5634
|
if (!out) return '';
|
|
5639
5635
|
if (out.startsWith('--')) return out;
|
|
5640
|
-
return out.replace(/[A-Z]/g, (ch) =>
|
|
5636
|
+
return out.replace(/[A-Z]/g, (ch) => `-${ch.toLowerCase()}`).replace(/^-ms-/, '-ms-');
|
|
5641
5637
|
}
|
|
5642
5638
|
|
|
5643
5639
|
function buildSvelteExpressionTextMap(sourceOriginal, liveOriginal) {
|
|
@@ -5668,7 +5664,7 @@
|
|
|
5668
5664
|
}
|
|
5669
5665
|
|
|
5670
5666
|
const match = liveText.match(expressionTextMatcher(sourceText, [token]));
|
|
5671
|
-
if (match
|
|
5667
|
+
if (match?.[1]) map.set(token, match[1].trim());
|
|
5672
5668
|
continue;
|
|
5673
5669
|
}
|
|
5674
5670
|
|
|
@@ -5693,7 +5689,7 @@
|
|
|
5693
5689
|
pattern += '(.*?)';
|
|
5694
5690
|
cursor = index + token.length;
|
|
5695
5691
|
}
|
|
5696
|
-
pattern += escapeRegExp(sourceText.slice(cursor)).replace(/\s+/g, '\\s*')
|
|
5692
|
+
pattern += `${escapeRegExp(sourceText.slice(cursor)).replace(/\s+/g, '\\s*')}$`;
|
|
5697
5693
|
return new RegExp(pattern);
|
|
5698
5694
|
}
|
|
5699
5695
|
|
|
@@ -5763,7 +5759,7 @@
|
|
|
5763
5759
|
if (anchor && !anchor.__monodesignFrozenAnchor) selectedElement = anchor;
|
|
5764
5760
|
return;
|
|
5765
5761
|
}
|
|
5766
|
-
const wrapper = document.querySelector(
|
|
5762
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
5767
5763
|
if (!wrapper) return;
|
|
5768
5764
|
const visEl = pickVariantContent(wrapper, visibleVariant);
|
|
5769
5765
|
if (visEl) selectedElement = visEl;
|
|
@@ -5773,7 +5769,7 @@
|
|
|
5773
5769
|
if (svelteComponentSession?.sessionId === sessionId && svelteComponentSession.mountedVariant > 0) {
|
|
5774
5770
|
return svelteComponentSession.mountedVariant;
|
|
5775
5771
|
}
|
|
5776
|
-
const wrapper = document.querySelector(
|
|
5772
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
5777
5773
|
if (!wrapper) return 0;
|
|
5778
5774
|
const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
|
|
5779
5775
|
for (const variant of variants) {
|
|
@@ -5792,7 +5788,7 @@
|
|
|
5792
5788
|
// (it wraps all of them and gets correct bounds).
|
|
5793
5789
|
function pickVariantContent(wrapper, index) {
|
|
5794
5790
|
if (!wrapper) return null;
|
|
5795
|
-
const variantDiv = wrapper.querySelector(
|
|
5791
|
+
const variantDiv = wrapper.querySelector(`[data-monodesign-variant="${index}"]`);
|
|
5796
5792
|
if (!variantDiv) return null;
|
|
5797
5793
|
const NON_VISUAL = new Set(['STYLE', 'SCRIPT', 'LINK', 'META', 'TEMPLATE']);
|
|
5798
5794
|
const visual = [];
|
|
@@ -5819,11 +5815,11 @@
|
|
|
5819
5815
|
// single variant (`… > [data-monodesign-variant="N"]`); without it, targets
|
|
5820
5816
|
// every variant via the bare `[data-monodesign-variant]` attribute.
|
|
5821
5817
|
function variantStateSelector(sessionId, num) {
|
|
5822
|
-
const wrapper =
|
|
5818
|
+
const wrapper = `[data-monodesign-variants="${sessionId}"]`;
|
|
5823
5819
|
const variant = num == null
|
|
5824
5820
|
? '[data-monodesign-variant]'
|
|
5825
|
-
:
|
|
5826
|
-
return wrapper
|
|
5821
|
+
: `[data-monodesign-variant="${num}"]`;
|
|
5822
|
+
return `${wrapper} > ${variant}`;
|
|
5827
5823
|
}
|
|
5828
5824
|
|
|
5829
5825
|
// Serialize the visible variant's knob values into `--p-<id>` custom-property
|
|
@@ -5832,8 +5828,8 @@
|
|
|
5832
5828
|
function variantParamDecls(values) {
|
|
5833
5829
|
return Object.entries(values || {})
|
|
5834
5830
|
.map(([id, val]) => {
|
|
5835
|
-
if (typeof val === 'number') return
|
|
5836
|
-
if (typeof val === 'boolean') return
|
|
5831
|
+
if (typeof val === 'number') return ` --p-${id}: ${val};`;
|
|
5832
|
+
if (typeof val === 'boolean') return ` --p-${id}: ${val ? '1' : '0'};`;
|
|
5837
5833
|
return '';
|
|
5838
5834
|
})
|
|
5839
5835
|
.join('');
|
|
@@ -5858,7 +5854,7 @@
|
|
|
5858
5854
|
const showVisible = variantStateSelector(sessionId, num)
|
|
5859
5855
|
+ ' { ' + VARIANT_SHOW_DECL + variantParamDecls(paramsCurrentValues) + ' }';
|
|
5860
5856
|
|
|
5861
|
-
styleEl.textContent = hideOthers
|
|
5857
|
+
styleEl.textContent = `${hideOthers}\n${showVisible}\n`;
|
|
5862
5858
|
}
|
|
5863
5859
|
|
|
5864
5860
|
function removeVariantStateStylesheet() {
|
|
@@ -5869,7 +5865,7 @@
|
|
|
5869
5865
|
// session's wrapper (HMR patches, variant inserts, cycle swaps).
|
|
5870
5866
|
function startScrollLock(sessionId, initialTargetY) {
|
|
5871
5867
|
stopScrollLock();
|
|
5872
|
-
scrollLockTargetY = typeof initialTargetY === 'number' && isFinite(initialTargetY)
|
|
5868
|
+
scrollLockTargetY = typeof initialTargetY === 'number' && Number.isFinite(initialTargetY)
|
|
5873
5869
|
? initialTargetY
|
|
5874
5870
|
: window.scrollY;
|
|
5875
5871
|
|
|
@@ -5892,7 +5888,7 @@
|
|
|
5892
5888
|
(document.head || document.documentElement).appendChild(anchorLockStyle);
|
|
5893
5889
|
}
|
|
5894
5890
|
|
|
5895
|
-
const correct = (
|
|
5891
|
+
const correct = (_why) => {
|
|
5896
5892
|
scrollLockRaf = null;
|
|
5897
5893
|
if (scrollLockTargetY == null) return;
|
|
5898
5894
|
const before = window.scrollY;
|
|
@@ -5909,12 +5905,12 @@
|
|
|
5909
5905
|
|
|
5910
5906
|
scrollLockObserver = new MutationObserver((mutations) => {
|
|
5911
5907
|
for (const m of mutations) {
|
|
5912
|
-
if (m.target?.closest?.(
|
|
5908
|
+
if (m.target?.closest?.(`[data-monodesign-variants="${sessionId}"]`)) {
|
|
5913
5909
|
schedule('mutation-in-wrapper');
|
|
5914
5910
|
return;
|
|
5915
5911
|
}
|
|
5916
5912
|
for (const n of m.addedNodes) {
|
|
5917
|
-
if (n.nodeType === 1 && (n.matches?.(
|
|
5913
|
+
if (n.nodeType === 1 && (n.matches?.(`[data-monodesign-variants="${sessionId}"]`) || n.querySelector?.(`[data-monodesign-variants="${sessionId}"]`))) {
|
|
5918
5914
|
schedule('wrapper-added');
|
|
5919
5915
|
return;
|
|
5920
5916
|
}
|
|
@@ -5935,9 +5931,8 @@
|
|
|
5935
5931
|
let userGestureAt = 0;
|
|
5936
5932
|
const USER_GESTURE_WINDOW_MS = 250;
|
|
5937
5933
|
|
|
5938
|
-
const reanchor = (
|
|
5934
|
+
const reanchor = (_why) => {
|
|
5939
5935
|
if (scrollLockRaf != null) { cancelAnimationFrame(scrollLockRaf); scrollLockRaf = null; }
|
|
5940
|
-
const prevTarget = scrollLockTargetY;
|
|
5941
5936
|
scrollLockTargetY = window.scrollY;
|
|
5942
5937
|
writeScrollY(scrollLockTargetY);
|
|
5943
5938
|
};
|
|
@@ -5949,7 +5944,7 @@
|
|
|
5949
5944
|
window.addEventListener('touchstart', () => markGesture('touchstart'), { passive: true, ...sig });
|
|
5950
5945
|
window.addEventListener('touchmove', () => markGesture('touchmove'), { passive: true, ...sig });
|
|
5951
5946
|
window.addEventListener('keydown', (e) => {
|
|
5952
|
-
if (['PageDown', 'PageUp', ' ', 'End', 'Home', 'ArrowDown', 'ArrowUp'].includes(e.key)) markGesture(
|
|
5947
|
+
if (['PageDown', 'PageUp', ' ', 'End', 'Home', 'ArrowDown', 'ArrowUp'].includes(e.key)) markGesture(`key:${e.key}`);
|
|
5953
5948
|
}, sig);
|
|
5954
5949
|
|
|
5955
5950
|
// Correct on EVERY scroll event: whether it's the browser's
|
|
@@ -6014,7 +6009,7 @@
|
|
|
6014
6009
|
}
|
|
6015
6010
|
if (!dominated) return;
|
|
6016
6011
|
|
|
6017
|
-
const wrapper = document.querySelector(
|
|
6012
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
6018
6013
|
if (!wrapper) return;
|
|
6019
6014
|
|
|
6020
6015
|
const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
|
|
@@ -6061,6 +6056,7 @@
|
|
|
6061
6056
|
if (visEl) selectedElement = visEl;
|
|
6062
6057
|
}
|
|
6063
6058
|
|
|
6059
|
+
// biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
|
|
6064
6060
|
const expected = parseInt(wrapper.dataset.monodesignVariantCount || '0');
|
|
6065
6061
|
if (expected > 0) expectedVariants = expected;
|
|
6066
6062
|
|
|
@@ -6134,7 +6130,7 @@
|
|
|
6134
6130
|
const SSE_MAX_RETRIES = 20; // generous: heartbeats keep the connection alive, so retries mean real trouble
|
|
6135
6131
|
|
|
6136
6132
|
function connectSSE() {
|
|
6137
|
-
evtSource = new EventSource(
|
|
6133
|
+
evtSource = new EventSource(`http://localhost:${PORT}/events?token=${TOKEN}`);
|
|
6138
6134
|
|
|
6139
6135
|
evtSource.onopen = () => {
|
|
6140
6136
|
sseRetries = 0; // reset on successful (re)connect
|
|
@@ -6235,7 +6231,7 @@
|
|
|
6235
6231
|
}
|
|
6236
6232
|
if (maybeCompleteSteer(msg)) break;
|
|
6237
6233
|
console.error('[monodesign] Error:', msg.message);
|
|
6238
|
-
showToast(
|
|
6234
|
+
showToast(`Error: ${msg.message}`, 5000);
|
|
6239
6235
|
hideBar();
|
|
6240
6236
|
renderEditBadge('hidden');
|
|
6241
6237
|
setLiveState('PICKING');
|
|
@@ -6246,7 +6242,7 @@
|
|
|
6246
6242
|
evtSource.onerror = () => {
|
|
6247
6243
|
sseRetries++;
|
|
6248
6244
|
if (sseRetries <= SSE_MAX_RETRIES) {
|
|
6249
|
-
console.log(
|
|
6245
|
+
console.log(`[monodesign] SSE connection lost. Retry ${sseRetries}/${SSE_MAX_RETRIES}...`);
|
|
6250
6246
|
return; // EventSource auto-reconnects
|
|
6251
6247
|
}
|
|
6252
6248
|
// Server is gone. Clean up gracefully.
|
|
@@ -6283,6 +6279,7 @@
|
|
|
6283
6279
|
function sendEvent(msg, opts) {
|
|
6284
6280
|
msg.token = TOKEN;
|
|
6285
6281
|
function handleFailure(err) {
|
|
6282
|
+
// biome-ignore lint/complexity/useOptionalChain: exact text pinned by tests/live-browser-source.test.mjs
|
|
6286
6283
|
if (opts && opts.throwOnError) {
|
|
6287
6284
|
console.error('[monodesign] Failed to send event:', err);
|
|
6288
6285
|
throw err;
|
|
@@ -6290,13 +6287,14 @@
|
|
|
6290
6287
|
console.debug('[monodesign] Dropped optional live event:', err);
|
|
6291
6288
|
return null;
|
|
6292
6289
|
}
|
|
6293
|
-
return fetch(
|
|
6290
|
+
return fetch(`http://localhost:${PORT}/events`, {
|
|
6294
6291
|
method: 'POST',
|
|
6295
6292
|
headers: { 'Content-Type': 'application/json' },
|
|
6296
6293
|
body: JSON.stringify(msg),
|
|
6297
6294
|
}).then(async res => {
|
|
6298
6295
|
if (res.ok) return res;
|
|
6299
6296
|
const body = await res.json().catch(() => ({}));
|
|
6297
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:278
|
|
6300
6298
|
return handleFailure(new Error(body.error || ('HTTP ' + res.status + ' ' + res.statusText)));
|
|
6301
6299
|
}).catch(handleFailure);
|
|
6302
6300
|
}
|
|
@@ -6543,14 +6541,16 @@
|
|
|
6543
6541
|
if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return false;
|
|
6544
6542
|
if (!/^(INPUT|TEXTAREA)$/.test(deepActive.tagName || '')) return false;
|
|
6545
6543
|
if (deepActive.value) return false;
|
|
6544
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:491
|
|
6546
6545
|
if (deepActive.id === PREFIX + '-input' && state === 'CONFIGURING') return true;
|
|
6546
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:496
|
|
6547
6547
|
if (deepActive.id === PREFIX + '-page-chat-input' && state === 'PICKING') return true;
|
|
6548
6548
|
return false;
|
|
6549
6549
|
}
|
|
6550
6550
|
|
|
6551
6551
|
function handleKeyDown(e) {
|
|
6552
6552
|
// When the annotation input is focused, let it handle its own keys.
|
|
6553
|
-
if (annotEditing
|
|
6553
|
+
if (annotEditing?.input && e.target === annotEditing.input) return;
|
|
6554
6554
|
const deepActive = activeElementDeep();
|
|
6555
6555
|
if (
|
|
6556
6556
|
deepActive
|
|
@@ -6670,7 +6670,7 @@
|
|
|
6670
6670
|
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
|
6671
6671
|
if (!selectedElement || state !== 'CONFIGURING') return;
|
|
6672
6672
|
stopVoice({ suppressSubmit: true });
|
|
6673
|
-
const input = uiGetById(PREFIX
|
|
6673
|
+
const input = uiGetById(`${PREFIX}-input`);
|
|
6674
6674
|
const prompt = input ? input.value.trim() : '';
|
|
6675
6675
|
|
|
6676
6676
|
// Commit any pending pin edit BEFORE we snapshot annotations.
|
|
@@ -6744,7 +6744,7 @@
|
|
|
6744
6744
|
|
|
6745
6745
|
function handleInsertCreate() {
|
|
6746
6746
|
if (!placeholderElement || !insertAnchorElement || state !== 'CONFIGURING' || configureKind !== 'insert') return;
|
|
6747
|
-
const input = uiGetById(PREFIX
|
|
6747
|
+
const input = uiGetById(`${PREFIX}-insert-input`);
|
|
6748
6748
|
const prompt = input ? input.value.trim() : '';
|
|
6749
6749
|
if (annotEditing) finalizeEditingPin();
|
|
6750
6750
|
const snapshot = {
|
|
@@ -6809,7 +6809,7 @@
|
|
|
6809
6809
|
if (msLoadPromise) return msLoadPromise;
|
|
6810
6810
|
msLoadPromise = new Promise((resolve, reject) => {
|
|
6811
6811
|
const s = document.createElement('script');
|
|
6812
|
-
s.src =
|
|
6812
|
+
s.src = `http://localhost:${PORT}/modern-screenshot.js`;
|
|
6813
6813
|
s.onload = () => resolve(window.modernScreenshot);
|
|
6814
6814
|
s.onerror = () => { msLoadPromise = null; reject(new Error('modern-screenshot failed to load')); };
|
|
6815
6815
|
uiAppendStyle(s);
|
|
@@ -6854,12 +6854,12 @@
|
|
|
6854
6854
|
const buf = await res.arrayBuffer();
|
|
6855
6855
|
const ext = url.toLowerCase().match(FONT_EXT_RE)?.[1] || 'woff2';
|
|
6856
6856
|
const mime = FONT_MIME[ext] || 'application/octet-stream';
|
|
6857
|
-
map.set(url,
|
|
6857
|
+
map.set(url, `data:${mime};base64,${bufferToBase64(buf)}`);
|
|
6858
6858
|
} catch { /* skip; fall through to URL */ }
|
|
6859
6859
|
}));
|
|
6860
6860
|
return cssText.replace(urlRe, (orig, q, url) => {
|
|
6861
6861
|
const data = map.get(url);
|
|
6862
|
-
return data ?
|
|
6862
|
+
return data ? `url(${q}${data}${q})` : orig;
|
|
6863
6863
|
});
|
|
6864
6864
|
}
|
|
6865
6865
|
async function collectFontCssText() {
|
|
@@ -6933,20 +6933,20 @@
|
|
|
6933
6933
|
if (!node || node === document.body || nodes.includes(node)) return;
|
|
6934
6934
|
nodes.push(node);
|
|
6935
6935
|
};
|
|
6936
|
-
add(document.getElementById(PREFIX
|
|
6936
|
+
add(document.getElementById(`${PREFIX}-root`));
|
|
6937
6937
|
[
|
|
6938
|
-
PREFIX
|
|
6939
|
-
PREFIX
|
|
6940
|
-
PREFIX
|
|
6941
|
-
PREFIX
|
|
6942
|
-
PREFIX
|
|
6943
|
-
PREFIX
|
|
6944
|
-
PREFIX
|
|
6945
|
-
PREFIX
|
|
6946
|
-
PREFIX
|
|
6947
|
-
PREFIX
|
|
6948
|
-
PREFIX
|
|
6949
|
-
PREFIX
|
|
6938
|
+
`${PREFIX}-highlight`,
|
|
6939
|
+
`${PREFIX}-tooltip`,
|
|
6940
|
+
`${PREFIX}-bar`,
|
|
6941
|
+
`${PREFIX}-picker`,
|
|
6942
|
+
`${PREFIX}-params-panel`,
|
|
6943
|
+
`${PREFIX}-insert-line`,
|
|
6944
|
+
`${PREFIX}-insert-placeholder`,
|
|
6945
|
+
`${PREFIX}-insert-create-tooltip`,
|
|
6946
|
+
`${PREFIX}-annot`,
|
|
6947
|
+
`${PREFIX}-design-host`,
|
|
6948
|
+
`${PREFIX}-toast`,
|
|
6949
|
+
`${PREFIX}-shader`,
|
|
6950
6950
|
].forEach((id) => add(uiGetById(id)));
|
|
6951
6951
|
return nodes;
|
|
6952
6952
|
}
|
|
@@ -7313,7 +7313,7 @@ void main() {
|
|
|
7313
7313
|
for (let p = 0; p < w * h; p += stride) {
|
|
7314
7314
|
const i = p * 4;
|
|
7315
7315
|
if (data[i + 3] < 16) continue;
|
|
7316
|
-
const key =
|
|
7316
|
+
const key = `${data[i] >> 4},${data[i + 1] >> 4},${data[i + 2] >> 4}`;
|
|
7317
7317
|
const bucket = buckets.get(key) || { count: 0, r: 0, g: 0, b: 0 };
|
|
7318
7318
|
bucket.count += 1;
|
|
7319
7319
|
bucket.r += data[i];
|
|
@@ -7357,7 +7357,7 @@ void main() {
|
|
|
7357
7357
|
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
|
7358
7358
|
const info = gl.getShaderInfoLog(sh);
|
|
7359
7359
|
gl.deleteShader(sh);
|
|
7360
|
-
throw new Error(
|
|
7360
|
+
throw new Error(`shader compile failed: ${info}`);
|
|
7361
7361
|
}
|
|
7362
7362
|
return sh;
|
|
7363
7363
|
}
|
|
@@ -7368,8 +7368,8 @@ void main() {
|
|
|
7368
7368
|
if (!anchor) return;
|
|
7369
7369
|
const r = anchor.getBoundingClientRect();
|
|
7370
7370
|
Object.assign(shaderState.canvas.style, {
|
|
7371
|
-
top: r.top
|
|
7372
|
-
width: r.width
|
|
7371
|
+
top: `${r.top}px`, left: `${r.left}px`,
|
|
7372
|
+
width: `${r.width}px`, height: `${r.height}px`,
|
|
7373
7373
|
});
|
|
7374
7374
|
}
|
|
7375
7375
|
|
|
@@ -7387,16 +7387,17 @@ void main() {
|
|
|
7387
7387
|
canvas.remove();
|
|
7388
7388
|
const objectUrl = URL.createObjectURL(blob);
|
|
7389
7389
|
const fallback = document.createElement('div');
|
|
7390
|
-
fallback.id = PREFIX
|
|
7390
|
+
fallback.id = `${PREFIX}-shader`;
|
|
7391
7391
|
// Copy positioning via cssText. Object.assign across CSSStyleDeclaration
|
|
7392
7392
|
// throws in modern Chromium because the source's indexed properties
|
|
7393
7393
|
// (style[0], [1], ...) are read-only and the engine forbids writing
|
|
7394
7394
|
// them on the destination.
|
|
7395
7395
|
fallback.style.cssText = canvas.style.cssText;
|
|
7396
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:62
|
|
7396
7397
|
fallback.style.backgroundImage = 'url("' + objectUrl + '")';
|
|
7397
7398
|
fallback.style.backgroundSize = '100% 100%';
|
|
7398
7399
|
fallback.style.backgroundRepeat = 'no-repeat';
|
|
7399
|
-
fallback.style.outline =
|
|
7400
|
+
fallback.style.outline = `2px dashed ${C.brand}`;
|
|
7400
7401
|
fallback.style.outlineOffset = '-2px';
|
|
7401
7402
|
uiAppend(fallback);
|
|
7402
7403
|
shaderState = { canvas: fallback, gl: null, program: null, texture: null, rafId: 0, startTime: 0, objectUrl };
|
|
@@ -7406,15 +7407,15 @@ void main() {
|
|
|
7406
7407
|
hideShaderOverlay();
|
|
7407
7408
|
if (!blob || !el) return;
|
|
7408
7409
|
const canvas = document.createElement('canvas');
|
|
7409
|
-
canvas.id = PREFIX
|
|
7410
|
+
canvas.id = `${PREFIX}-shader`;
|
|
7410
7411
|
const dpr = Math.min(window.devicePixelRatio || 1, 2);
|
|
7411
7412
|
const radius = getComputedStyle(el).borderRadius;
|
|
7412
7413
|
canvas.width = Math.max(1, Math.floor(rect.width * dpr));
|
|
7413
7414
|
canvas.height = Math.max(1, Math.floor(rect.height * dpr));
|
|
7414
7415
|
Object.assign(canvas.style, {
|
|
7415
7416
|
position: 'fixed',
|
|
7416
|
-
top: rect.top
|
|
7417
|
-
width: rect.width
|
|
7417
|
+
top: `${rect.top}px`, left: `${rect.left}px`,
|
|
7418
|
+
width: `${rect.width}px`, height: `${rect.height}px`,
|
|
7418
7419
|
borderRadius: radius,
|
|
7419
7420
|
overflow: 'hidden',
|
|
7420
7421
|
pointerEvents: 'none',
|
|
@@ -7440,7 +7441,7 @@ void main() {
|
|
|
7440
7441
|
gl.attachShader(program, fs);
|
|
7441
7442
|
gl.linkProgram(program);
|
|
7442
7443
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
7443
|
-
throw new Error(
|
|
7444
|
+
throw new Error(`program link failed: ${gl.getProgramInfoLog(program)}`);
|
|
7444
7445
|
}
|
|
7445
7446
|
// Full-screen quad
|
|
7446
7447
|
const buf = gl.createBuffer();
|
|
@@ -7529,7 +7530,7 @@ void main() {
|
|
|
7529
7530
|
variantId: String(visibleVariant),
|
|
7530
7531
|
pageUrl: location.pathname,
|
|
7531
7532
|
};
|
|
7532
|
-
const acceptWrapper = document.querySelector(
|
|
7533
|
+
const acceptWrapper = document.querySelector(`[data-monodesign-variants="${currentSessionId}"]`);
|
|
7533
7534
|
if (Object.keys(paramsCurrentValues).length > 0) {
|
|
7534
7535
|
acceptPayload.paramValues = { ...paramsCurrentValues };
|
|
7535
7536
|
}
|
|
@@ -7586,8 +7587,9 @@ void main() {
|
|
|
7586
7587
|
}
|
|
7587
7588
|
|
|
7588
7589
|
function scheduleAcceptCleanup(accepted) {
|
|
7589
|
-
setTimeout(
|
|
7590
|
+
setTimeout(() => {
|
|
7590
7591
|
if (!accepted?.isSvelteComponent && !acceptedDomAlreadyClean(accepted)) {
|
|
7592
|
+
// biome-ignore lint/complexity/useArrowFunction: tests/live-browser-source.test.mjs pins this fallback as `setTimeout(function() {`
|
|
7591
7593
|
setTimeout(function() {
|
|
7592
7594
|
if (pendingAcceptedSession?.id !== accepted?.id) return;
|
|
7593
7595
|
if (!accepted?.isSvelteComponent) ensureAcceptedDomClean(accepted);
|
|
@@ -7600,8 +7602,8 @@ void main() {
|
|
|
7600
7602
|
}
|
|
7601
7603
|
|
|
7602
7604
|
function snapshotAcceptedVariantDom(sessionId, variantId) {
|
|
7603
|
-
const wrapper = document.querySelector(
|
|
7604
|
-
const accepted = wrapper?.querySelector?.(
|
|
7605
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${sessionId}"]`);
|
|
7606
|
+
const accepted = wrapper?.querySelector?.(`[data-monodesign-variant="${variantId}"]`);
|
|
7605
7607
|
const root = accepted?.firstElementChild || null;
|
|
7606
7608
|
return {
|
|
7607
7609
|
acceptedHtml: accepted ? accepted.innerHTML : '',
|
|
@@ -7613,11 +7615,11 @@ void main() {
|
|
|
7613
7615
|
}
|
|
7614
7616
|
|
|
7615
7617
|
function selectorForAcceptedRoot(root) {
|
|
7616
|
-
if (!root
|
|
7618
|
+
if (!root?.tagName) return '';
|
|
7617
7619
|
const tag = root.tagName.toLowerCase();
|
|
7618
7620
|
const classes = [...(root.classList || [])].filter(Boolean);
|
|
7619
7621
|
if (classes.length === 0) return tag;
|
|
7620
|
-
return tag + classes.map((cls) =>
|
|
7622
|
+
return tag + classes.map((cls) => `.${cssIdent(cls)}`).join('');
|
|
7621
7623
|
}
|
|
7622
7624
|
|
|
7623
7625
|
function acceptedDomAlreadyClean(pending) {
|
|
@@ -7638,7 +7640,7 @@ void main() {
|
|
|
7638
7640
|
}
|
|
7639
7641
|
for (const wrapper of wrappers) {
|
|
7640
7642
|
if (!wrapper?.isConnected) continue;
|
|
7641
|
-
const accepted = wrapper.querySelector?.(
|
|
7643
|
+
const accepted = wrapper.querySelector?.(`[data-monodesign-variant="${variantId}"]`);
|
|
7642
7644
|
if (!accepted) {
|
|
7643
7645
|
wrapper.remove();
|
|
7644
7646
|
continue;
|
|
@@ -7656,7 +7658,9 @@ void main() {
|
|
|
7656
7658
|
function findAcceptedRuntimeWrappers(sessionId) {
|
|
7657
7659
|
if (!sessionId) return [];
|
|
7658
7660
|
return [...new Set([
|
|
7661
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:344
|
|
7659
7662
|
...document.querySelectorAll('[data-monodesign-variants="' + sessionId + '"]'),
|
|
7663
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-source.test.mjs:344
|
|
7660
7664
|
...document.querySelectorAll('[data-monodesign-carbonize="' + sessionId + '"]'),
|
|
7661
7665
|
])];
|
|
7662
7666
|
}
|
|
@@ -7685,7 +7689,7 @@ void main() {
|
|
|
7685
7689
|
|
|
7686
7690
|
function reloadAfterMissingAcceptedDom(pending) {
|
|
7687
7691
|
if (acceptedDomAlreadyClean(pending)) return;
|
|
7688
|
-
if (pending?.id && document.querySelector(
|
|
7692
|
+
if (pending?.id && document.querySelector(`[data-monodesign-variants="${pending.id}"]`)) return;
|
|
7689
7693
|
location.reload();
|
|
7690
7694
|
}
|
|
7691
7695
|
|
|
@@ -7707,28 +7711,6 @@ void main() {
|
|
|
7707
7711
|
setLiveState('PICKING');
|
|
7708
7712
|
}
|
|
7709
7713
|
|
|
7710
|
-
function commitAcceptedVariantToDom(sessionId, variantId) {
|
|
7711
|
-
const wrapper = document.querySelector('[data-monodesign-variants="' + sessionId + '"]');
|
|
7712
|
-
if (!wrapper) return false;
|
|
7713
|
-
const accepted = wrapper.querySelector('[data-monodesign-variant="' + variantId + '"]');
|
|
7714
|
-
if (!accepted || !accepted.firstElementChild) return false;
|
|
7715
|
-
const parent = wrapper.parentElement;
|
|
7716
|
-
if (!parent) return false;
|
|
7717
|
-
|
|
7718
|
-
const style = wrapper.querySelector('style[data-monodesign-css]');
|
|
7719
|
-
if (style && !document.querySelector('style[data-monodesign-accepted-css="' + sessionId + '"]')) {
|
|
7720
|
-
const promotedStyle = style.cloneNode(true);
|
|
7721
|
-
promotedStyle.setAttribute('data-monodesign-accepted-css', sessionId);
|
|
7722
|
-
parent.insertBefore(promotedStyle, wrapper);
|
|
7723
|
-
}
|
|
7724
|
-
|
|
7725
|
-
const committed = accepted.cloneNode(true);
|
|
7726
|
-
committed.removeAttribute('hidden');
|
|
7727
|
-
committed.style.display = 'contents';
|
|
7728
|
-
parent.replaceChild(committed, wrapper);
|
|
7729
|
-
return true;
|
|
7730
|
-
}
|
|
7731
|
-
|
|
7732
7714
|
function handleDiscard() {
|
|
7733
7715
|
if (pendingApplyInFlight) { showManualApplyBusyToast(); return; }
|
|
7734
7716
|
if (!currentSessionId) return;
|
|
@@ -7934,11 +7916,11 @@ void main() {
|
|
|
7934
7916
|
// reconciler later tries to remove a wrapper we already removed.
|
|
7935
7917
|
// Schedule a 2s fallback that does the manual swap only if HMR hasn't
|
|
7936
7918
|
// replaced the wrapper by then (keeps static-server / no-HMR flows alive).
|
|
7937
|
-
const wrapper = document.querySelector(
|
|
7919
|
+
const wrapper = document.querySelector(`[data-monodesign-variants="${cleanupSessionId}"]`);
|
|
7938
7920
|
if (wrapper) wrapper.style.display = 'none';
|
|
7939
|
-
setTimeout(
|
|
7921
|
+
setTimeout(() => {
|
|
7940
7922
|
if (!cleanupSessionId) return;
|
|
7941
|
-
const lateWrapper = document.querySelector(
|
|
7923
|
+
const lateWrapper = document.querySelector(`[data-monodesign-variants="${cleanupSessionId}"]`);
|
|
7942
7924
|
if (!lateWrapper) return;
|
|
7943
7925
|
const orig = lateWrapper.querySelector('[data-monodesign-variant="original"]');
|
|
7944
7926
|
if (orig) {
|
|
@@ -7990,17 +7972,17 @@ void main() {
|
|
|
7990
7972
|
? Math.max(16, window.innerHeight - barRect.top + 12)
|
|
7991
7973
|
: 16;
|
|
7992
7974
|
const currentToast = el('div', {
|
|
7993
|
-
position: 'fixed', bottom: barTopFromBottom
|
|
7975
|
+
position: 'fixed', bottom: `${barTopFromBottom}px`, left: '50%',
|
|
7994
7976
|
transform: 'translateX(-50%) translateY(8px)',
|
|
7995
7977
|
background: C.ink, color: C.white,
|
|
7996
7978
|
fontFamily: FONT, fontSize: '12px',
|
|
7997
7979
|
padding: '8px 16px', borderRadius: '8px',
|
|
7998
7980
|
zIndex: Z.toast, opacity: '0',
|
|
7999
|
-
transition:
|
|
7981
|
+
transition: `opacity 0.25s ${EASE}, transform 0.25s ${EASE}`,
|
|
8000
7982
|
pointerEvents: 'none', maxWidth: '420px', textAlign: 'center',
|
|
8001
7983
|
});
|
|
8002
7984
|
toastEl = currentToast;
|
|
8003
|
-
currentToast.id = PREFIX
|
|
7985
|
+
currentToast.id = `${PREFIX}-toast`;
|
|
8004
7986
|
currentToast.textContent = message;
|
|
8005
7987
|
uiAppend(currentToast);
|
|
8006
7988
|
requestAnimationFrame(() => {
|
|
@@ -8085,6 +8067,7 @@ void main() {
|
|
|
8085
8067
|
}
|
|
8086
8068
|
|
|
8087
8069
|
currentSessionId = sessionId;
|
|
8070
|
+
// biome-ignore lint/correctness/useParseIntRadix: data-monodesign-variant-count can be hand-written in page source (reference/live.md), so a 0x value is not provably excluded
|
|
8088
8071
|
expectedVariants = parseInt(wrapper.dataset.monodesignVariantCount || '0');
|
|
8089
8072
|
const variants = wrapper.querySelectorAll('[data-monodesign-variant]:not([data-monodesign-variant="original"])');
|
|
8090
8073
|
arrivedVariants = variants.length;
|
|
@@ -8214,14 +8197,6 @@ void main() {
|
|
|
8214
8197
|
} catch { /* ignore */ }
|
|
8215
8198
|
}
|
|
8216
8199
|
|
|
8217
|
-
function loadPickPref() {
|
|
8218
|
-
return loadInteractionPrefs().pickActive;
|
|
8219
|
-
}
|
|
8220
|
-
|
|
8221
|
-
function savePickPref() {
|
|
8222
|
-
saveInteractionPrefs();
|
|
8223
|
-
}
|
|
8224
|
-
|
|
8225
8200
|
let pickActive = loadInteractionPrefs().pickActive;
|
|
8226
8201
|
let insertActive = loadInteractionPrefs().insertActive;
|
|
8227
8202
|
let configureKind = 'replace';
|
|
@@ -8268,7 +8243,6 @@ void main() {
|
|
|
8268
8243
|
/** @type {{ mode: 'steer'|'configure', input: HTMLInputElement, submit: () => void, beforeStart?: () => void } | null} */
|
|
8269
8244
|
let voiceCtx = null;
|
|
8270
8245
|
const PAGE_CHAT_COLLAPSED_W = '104px';
|
|
8271
|
-
const PAGE_CHAT_PROCESSING_W = '76px';
|
|
8272
8246
|
const PAGE_CHAT_PLACEHOLDER_COLLAPSED = 'Steer…';
|
|
8273
8247
|
const PAGE_CHAT_PLACEHOLDER_EXPANDED = 'Steer the page…';
|
|
8274
8248
|
const STEER_AWAIT_TIMEOUT_MS = 120000;
|
|
@@ -8360,10 +8334,10 @@ void main() {
|
|
|
8360
8334
|
|
|
8361
8335
|
function globalBarModeToggles() {
|
|
8362
8336
|
return [
|
|
8363
|
-
uiGetById(PREFIX
|
|
8364
|
-
uiGetById(PREFIX
|
|
8365
|
-
uiGetById(PREFIX
|
|
8366
|
-
uiGetById(PREFIX
|
|
8337
|
+
uiGetById(`${PREFIX}-pick-toggle`),
|
|
8338
|
+
uiGetById(`${PREFIX}-insert-toggle`),
|
|
8339
|
+
uiGetById(`${PREFIX}-detect-toggle`),
|
|
8340
|
+
uiGetById(`${PREFIX}-design-toggle`),
|
|
8367
8341
|
].filter(Boolean);
|
|
8368
8342
|
}
|
|
8369
8343
|
|
|
@@ -8390,13 +8364,13 @@ void main() {
|
|
|
8390
8364
|
}
|
|
8391
8365
|
|
|
8392
8366
|
function pageChatExpandedWidth() {
|
|
8393
|
-
if (!pageChatEl || !globalBarEl) return PAGE_CHAT_EXPANDED_MAX_W
|
|
8367
|
+
if (!pageChatEl || !globalBarEl) return `${PAGE_CHAT_EXPANDED_MAX_W}px`;
|
|
8394
8368
|
const currentChatWidth = pageChatEl.getBoundingClientRect().width || pageChatCollapsedWidthPx();
|
|
8395
8369
|
const barWidth = Math.max(globalBarEl.getBoundingClientRect().width || 0, globalBarEl.scrollWidth || 0);
|
|
8396
8370
|
const nonChatWidth = Math.max(0, barWidth - currentChatWidth);
|
|
8397
8371
|
const available = window.innerWidth - 16 - nonChatWidth;
|
|
8398
8372
|
const next = Math.max(pageChatCollapsedWidthPx(), Math.min(PAGE_CHAT_EXPANDED_MAX_W, available));
|
|
8399
|
-
return Math.round(next)
|
|
8373
|
+
return `${Math.round(next)}px`;
|
|
8400
8374
|
}
|
|
8401
8375
|
|
|
8402
8376
|
function syncPageChatExpandedWidth() {
|
|
@@ -8549,7 +8523,7 @@ void main() {
|
|
|
8549
8523
|
function steerFocusTargetLabel(el) {
|
|
8550
8524
|
if (!el || el === document.body) return 'body';
|
|
8551
8525
|
if (el === document.documentElement) return 'html';
|
|
8552
|
-
if (el.id) return el.tagName.toLowerCase()
|
|
8526
|
+
if (el.id) return `${el.tagName.toLowerCase()}#${el.id}`;
|
|
8553
8527
|
return el.tagName?.toLowerCase() || String(el);
|
|
8554
8528
|
}
|
|
8555
8529
|
|
|
@@ -8582,7 +8556,7 @@ void main() {
|
|
|
8582
8556
|
|
|
8583
8557
|
function focusConfigureInput(reason) {
|
|
8584
8558
|
steerFocusLog('focusConfigureInput', { reason });
|
|
8585
|
-
const inputId = configureKind === 'insert' ? PREFIX
|
|
8559
|
+
const inputId = configureKind === 'insert' ? `${PREFIX}-insert-input` : `${PREFIX}-input`;
|
|
8586
8560
|
const input = uiGetById(inputId);
|
|
8587
8561
|
if (!input) {
|
|
8588
8562
|
steerFocusLog('focusConfigureInput missing', { reason });
|
|
@@ -8689,8 +8663,8 @@ void main() {
|
|
|
8689
8663
|
display: 'inline-block',
|
|
8690
8664
|
width: '4px', height: '4px', borderRadius: '50%',
|
|
8691
8665
|
background: P.patinaPale,
|
|
8692
|
-
boxShadow:
|
|
8693
|
-
animation:
|
|
8666
|
+
boxShadow: `0 0 6px ${P.patinaSoft}`,
|
|
8667
|
+
animation: `monodesign-steer-dot 1.05s ease-in-out ${i * 0.14}s infinite`,
|
|
8694
8668
|
}));
|
|
8695
8669
|
}
|
|
8696
8670
|
return wrap;
|
|
@@ -8734,7 +8708,7 @@ void main() {
|
|
|
8734
8708
|
return true;
|
|
8735
8709
|
}
|
|
8736
8710
|
|
|
8737
|
-
function focusPageChatInput(
|
|
8711
|
+
function focusPageChatInput(_reason) {
|
|
8738
8712
|
if (!preparePageChatInputForTyping() || steerLocked) return false;
|
|
8739
8713
|
try { pageChatInput.focus({ preventScroll: true }); } catch { pageChatInput.focus(); }
|
|
8740
8714
|
const focused = activeElementDeep() === pageChatInput;
|
|
@@ -8876,7 +8850,7 @@ void main() {
|
|
|
8876
8850
|
case 'aborted':
|
|
8877
8851
|
return null;
|
|
8878
8852
|
default:
|
|
8879
|
-
return
|
|
8853
|
+
return `Voice input failed (${code})`;
|
|
8880
8854
|
}
|
|
8881
8855
|
}
|
|
8882
8856
|
|
|
@@ -8894,7 +8868,7 @@ void main() {
|
|
|
8894
8868
|
} else if (voiceCtx?.mode === 'configure') {
|
|
8895
8869
|
// The bar shows either the replace row's voice button or the insert
|
|
8896
8870
|
// row's - both run voice through the 'configure' mode.
|
|
8897
|
-
const voiceBtn = uiGetById(PREFIX
|
|
8871
|
+
const voiceBtn = uiGetById(`${PREFIX}-configure-voice`) || uiGetById(`${PREFIX}-insert-voice`);
|
|
8898
8872
|
if (voiceBtn) {
|
|
8899
8873
|
voiceBtn.dataset.active = listening ? 'true' : 'false';
|
|
8900
8874
|
voiceBtn.dataset.listening = listening ? 'true' : 'false';
|
|
@@ -8906,7 +8880,7 @@ void main() {
|
|
|
8906
8880
|
}
|
|
8907
8881
|
|
|
8908
8882
|
function releaseVoiceEngine(opts) {
|
|
8909
|
-
if (opts
|
|
8883
|
+
if (opts?.suppressSubmit) voiceSuppressSubmit = true;
|
|
8910
8884
|
const rec = voiceRecognition;
|
|
8911
8885
|
voiceRecognition = null;
|
|
8912
8886
|
if (!rec) return;
|
|
@@ -8915,7 +8889,7 @@ void main() {
|
|
|
8915
8889
|
rec.onerror = null;
|
|
8916
8890
|
rec.onend = null;
|
|
8917
8891
|
try {
|
|
8918
|
-
if (opts
|
|
8892
|
+
if (opts?.abort) rec.abort();
|
|
8919
8893
|
else rec.stop();
|
|
8920
8894
|
} catch { /* already ended */ }
|
|
8921
8895
|
}
|
|
@@ -8924,7 +8898,7 @@ void main() {
|
|
|
8924
8898
|
releaseVoiceEngine(opts);
|
|
8925
8899
|
syncVoiceUi(false);
|
|
8926
8900
|
voiceCtx = null;
|
|
8927
|
-
if (opts
|
|
8901
|
+
if (opts?.message) showToast(String(opts.message), opts.duration || 4000);
|
|
8928
8902
|
}
|
|
8929
8903
|
|
|
8930
8904
|
function finishVoiceSession() {
|
|
@@ -8965,7 +8939,7 @@ void main() {
|
|
|
8965
8939
|
if (ctx.beforeStart) ctx.beforeStart();
|
|
8966
8940
|
|
|
8967
8941
|
voiceInterimBase = ctx.input.value.trim()
|
|
8968
|
-
? ctx.input.value.trim()
|
|
8942
|
+
? `${ctx.input.value.trim()} `
|
|
8969
8943
|
: '';
|
|
8970
8944
|
|
|
8971
8945
|
const rec = new Ctor();
|
|
@@ -9028,7 +9002,7 @@ void main() {
|
|
|
9028
9002
|
|
|
9029
9003
|
function configureVoiceContext() {
|
|
9030
9004
|
const input = uiGetById(
|
|
9031
|
-
configureKind === 'insert' ? PREFIX
|
|
9005
|
+
configureKind === 'insert' ? `${PREFIX}-insert-input` : `${PREFIX}-input`,
|
|
9032
9006
|
);
|
|
9033
9007
|
return {
|
|
9034
9008
|
mode: 'configure',
|
|
@@ -9099,7 +9073,7 @@ void main() {
|
|
|
9099
9073
|
}
|
|
9100
9074
|
|
|
9101
9075
|
function expandPageChat(opts) {
|
|
9102
|
-
const focus =
|
|
9076
|
+
const focus = opts?.focus !== false;
|
|
9103
9077
|
if (!pageChatEl || !pageChatInput || steerLocked) return;
|
|
9104
9078
|
preparePageChatInputForTyping();
|
|
9105
9079
|
syncPageChatChrome();
|
|
@@ -9134,7 +9108,7 @@ void main() {
|
|
|
9134
9108
|
function initPageChat(parent, P) {
|
|
9135
9109
|
pageChatEl = el('div', {
|
|
9136
9110
|
display: 'inline-flex', alignItems: 'center',
|
|
9137
|
-
height: '28px', margin:
|
|
9111
|
+
height: '28px', margin: `0 4px 0 ${GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_GAP}px`,
|
|
9138
9112
|
borderRadius: '7px',
|
|
9139
9113
|
background: P.chatSurface,
|
|
9140
9114
|
border: '1px solid transparent',
|
|
@@ -9144,6 +9118,7 @@ void main() {
|
|
|
9144
9118
|
width: PAGE_CHAT_COLLAPSED_W,
|
|
9145
9119
|
transition: 'border-color 0.15s ease',
|
|
9146
9120
|
});
|
|
9121
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:388
|
|
9147
9122
|
pageChatEl.id = PREFIX + '-page-chat';
|
|
9148
9123
|
pageChatEl.dataset.expanded = 'false';
|
|
9149
9124
|
pageChatEl.title = 'Steer the page';
|
|
@@ -9166,7 +9141,7 @@ void main() {
|
|
|
9166
9141
|
pageChatHint.textContent = 'Steer';
|
|
9167
9142
|
|
|
9168
9143
|
pageChatInput = document.createElement('input');
|
|
9169
|
-
pageChatInput.id = PREFIX
|
|
9144
|
+
pageChatInput.id = `${PREFIX}-page-chat-input`;
|
|
9170
9145
|
pageChatInput.type = 'text';
|
|
9171
9146
|
pageChatInput.placeholder = PAGE_CHAT_PLACEHOLDER_COLLAPSED;
|
|
9172
9147
|
pageChatInput.setAttribute('aria-label', 'Steer the page');
|
|
@@ -9187,7 +9162,7 @@ void main() {
|
|
|
9187
9162
|
color: P.textDim, cursor: 'pointer',
|
|
9188
9163
|
transition: 'color 0.12s ease, background 0.12s ease',
|
|
9189
9164
|
});
|
|
9190
|
-
pageChatVoiceBtn.id = PREFIX
|
|
9165
|
+
pageChatVoiceBtn.id = `${PREFIX}-page-chat-voice`;
|
|
9191
9166
|
pageChatVoiceBtn.type = 'button';
|
|
9192
9167
|
pageChatVoiceBtn.setAttribute('aria-label', 'Voice input');
|
|
9193
9168
|
pageChatVoiceBtn.innerHTML = ICON_PAGE_VOICE;
|
|
@@ -9197,9 +9172,9 @@ void main() {
|
|
|
9197
9172
|
pageChatEl.appendChild(pageChatInput);
|
|
9198
9173
|
pageChatEl.appendChild(pageChatVoiceBtn);
|
|
9199
9174
|
|
|
9200
|
-
if (!uiGetById(PREFIX
|
|
9175
|
+
if (!uiGetById(`${PREFIX}-page-chat-style`)) {
|
|
9201
9176
|
const s = document.createElement('style');
|
|
9202
|
-
s.id = PREFIX
|
|
9177
|
+
s.id = `${PREFIX}-page-chat-style`;
|
|
9203
9178
|
s.textContent =
|
|
9204
9179
|
'@keyframes monodesign-steer-dot { 0%, 70%, 100% { opacity: 0.28; transform: scale(0.82); } 35% { opacity: 1; transform: scale(1); } }' +
|
|
9205
9180
|
'@keyframes monodesign-steer-processing { 0%, 100% { border-color: oklch(70% 0.12 188 / 0.28); box-shadow: 0 0 0 0 oklch(70% 0.12 188 / 0); } 50% { border-color: oklch(82% 0.07 188 / 0.55); box-shadow: 0 0 14px oklch(70% 0.12 188 / 0.18); } }' +
|
|
@@ -9328,7 +9303,7 @@ void main() {
|
|
|
9328
9303
|
padding: '6px 9px',
|
|
9329
9304
|
borderRadius: '7px',
|
|
9330
9305
|
background: P.chatSurface,
|
|
9331
|
-
border:
|
|
9306
|
+
border: `1px solid ${P.hairline}`,
|
|
9332
9307
|
boxShadow: P.shadow,
|
|
9333
9308
|
color: P.text,
|
|
9334
9309
|
fontFamily: FONT,
|
|
@@ -9338,7 +9313,7 @@ void main() {
|
|
|
9338
9313
|
letterSpacing: '0.01em',
|
|
9339
9314
|
whiteSpace: 'normal',
|
|
9340
9315
|
});
|
|
9341
|
-
agentPollTooltipEl.id = PREFIX
|
|
9316
|
+
agentPollTooltipEl.id = `${PREFIX}-agent-poll-tooltip`;
|
|
9342
9317
|
agentPollTooltipEl.textContent = AGENT_DISCONNECTED_TIP;
|
|
9343
9318
|
uiAppend(agentPollTooltipEl);
|
|
9344
9319
|
return agentPollTooltipEl;
|
|
@@ -9355,8 +9330,8 @@ void main() {
|
|
|
9355
9330
|
const tipH = tip.offsetHeight;
|
|
9356
9331
|
const left = Math.max(8, Math.min(window.innerWidth - tipW - 8, r.left + r.width / 2 - tipW / 2));
|
|
9357
9332
|
const top = Math.max(8, r.top - tipH - 8);
|
|
9358
|
-
tip.style.left = left
|
|
9359
|
-
tip.style.top = top
|
|
9333
|
+
tip.style.left = `${left}px`;
|
|
9334
|
+
tip.style.top = `${top}px`;
|
|
9360
9335
|
}
|
|
9361
9336
|
|
|
9362
9337
|
function hideAgentPollTooltip() {
|
|
@@ -9373,7 +9348,7 @@ void main() {
|
|
|
9373
9348
|
}
|
|
9374
9349
|
|
|
9375
9350
|
function fetchAgentPollingStatus() {
|
|
9376
|
-
fetch(
|
|
9351
|
+
fetch(`http://localhost:${PORT}/status?token=${TOKEN}`, { cache: 'no-store' })
|
|
9377
9352
|
.then((res) => (res.ok ? res.json() : null))
|
|
9378
9353
|
.then((data) => {
|
|
9379
9354
|
if (data && typeof data.agentPolling === 'boolean') syncAgentPollingUi(data.agentPolling);
|
|
@@ -9394,9 +9369,9 @@ void main() {
|
|
|
9394
9369
|
// Custom focus-visible for bar buttons. Browser default is a heavy
|
|
9395
9370
|
// blue ring that looks jarring on the dark capsule. Replace with a
|
|
9396
9371
|
// soft accent-tinted inner ring that respects the bar's palette.
|
|
9397
|
-
if (!uiGetById(PREFIX
|
|
9372
|
+
if (!uiGetById(`${PREFIX}-bar-focus-style`)) {
|
|
9398
9373
|
const s = document.createElement('style');
|
|
9399
|
-
s.id = PREFIX
|
|
9374
|
+
s.id = `${PREFIX}-bar-focus-style`;
|
|
9400
9375
|
s.textContent =
|
|
9401
9376
|
'#' + PREFIX + '-global-bar button:focus { outline: none; }' +
|
|
9402
9377
|
'#' + PREFIX + '-global-bar button:focus-visible {' +
|
|
@@ -9417,7 +9392,7 @@ void main() {
|
|
|
9417
9392
|
gap: '0',
|
|
9418
9393
|
width: 'max-content',
|
|
9419
9394
|
background: P.surface,
|
|
9420
|
-
border:
|
|
9395
|
+
border: `1px solid ${P.border}`,
|
|
9421
9396
|
borderRadius: '8px',
|
|
9422
9397
|
boxShadow: P.shadow,
|
|
9423
9398
|
fontFamily: FONT, fontSize: '12px', lineHeight: '1',
|
|
@@ -9425,21 +9400,21 @@ void main() {
|
|
|
9425
9400
|
overflow: 'hidden', // clip the full-bleed brand mark to the bar radius
|
|
9426
9401
|
maxWidth: 'calc(100vw - 16px)',
|
|
9427
9402
|
boxSizing: 'border-box',
|
|
9428
|
-
transition:
|
|
9403
|
+
transition: `opacity 0.3s ${EASE}, transform 0.3s ${EASE}`,
|
|
9429
9404
|
});
|
|
9430
|
-
globalBarEl.id = PREFIX
|
|
9405
|
+
globalBarEl.id = `${PREFIX}-global-bar`;
|
|
9431
9406
|
globalBarEl.dataset.theme = theme;
|
|
9432
9407
|
|
|
9433
9408
|
// Brand mark - kinpaku Monodesign icon (site header / favicon paths).
|
|
9434
9409
|
const brand = el('span', {
|
|
9435
9410
|
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
|
|
9436
9411
|
alignSelf: 'stretch', position: 'relative',
|
|
9437
|
-
padding:
|
|
9412
|
+
padding: `0 ${GLOBAL_BAR_SECTION_GAP - GLOBAL_BAR_INNER_PAD_LEFT}px 0 14px`,
|
|
9438
9413
|
background: 'transparent',
|
|
9439
9414
|
color: P.accent,
|
|
9440
9415
|
flexShrink: '0',
|
|
9441
9416
|
});
|
|
9442
|
-
brand.id = PREFIX
|
|
9417
|
+
brand.id = `${PREFIX}-global-bar-brand`;
|
|
9443
9418
|
brand.dataset.agentConnected = 'false';
|
|
9444
9419
|
brand.setAttribute('role', 'img');
|
|
9445
9420
|
brand.setAttribute('aria-label', 'Monodesign live mode - agent not polling');
|
|
@@ -9455,7 +9430,7 @@ void main() {
|
|
|
9455
9430
|
position: 'absolute', right: '-1px', bottom: '7px',
|
|
9456
9431
|
width: '6px', height: '6px', borderRadius: '50%',
|
|
9457
9432
|
background: 'oklch(77% 0.13 82)',
|
|
9458
|
-
boxShadow:
|
|
9433
|
+
boxShadow: `0 0 0 2px ${P.surface}`,
|
|
9459
9434
|
display: 'none', pointerEvents: 'none',
|
|
9460
9435
|
});
|
|
9461
9436
|
agentDot.dataset.agentDot = 'true';
|
|
@@ -9472,10 +9447,10 @@ void main() {
|
|
|
9472
9447
|
// Inner wrapper: holds the toggles with normal bar padding.
|
|
9473
9448
|
const inner = el('div', {
|
|
9474
9449
|
display: 'flex', alignItems: 'center',
|
|
9475
|
-
padding:
|
|
9450
|
+
padding: `4px 5px 4px ${GLOBAL_BAR_INNER_PAD_LEFT}px`, gap: `${GLOBAL_BAR_INNER_GAP}px`,
|
|
9476
9451
|
flex: '0 0 auto',
|
|
9477
9452
|
});
|
|
9478
|
-
inner.id = PREFIX
|
|
9453
|
+
inner.id = `${PREFIX}-global-bar-inner`;
|
|
9479
9454
|
globalBarEl.appendChild(inner);
|
|
9480
9455
|
|
|
9481
9456
|
// Button factory: icon-only at rest, label slides in on hover/active.
|
|
@@ -9522,7 +9497,7 @@ void main() {
|
|
|
9522
9497
|
|
|
9523
9498
|
// Pick toggle - restored from localStorage; both pick and insert may be off.
|
|
9524
9499
|
const pickBtn = makeIconBtn({
|
|
9525
|
-
id: PREFIX
|
|
9500
|
+
id: `${PREFIX}-pick-toggle`,
|
|
9526
9501
|
svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><circle cx="12" cy="12" r="10"/><line x1="22" y1="12" x2="18" y2="12"/><line x1="6" y1="12" x2="2" y2="12"/><line x1="12" y1="6" x2="12" y2="2"/><line x1="12" y1="22" x2="12" y2="18"/></svg>',
|
|
9527
9502
|
label: 'Pick',
|
|
9528
9503
|
ariaLabel: 'Pick element',
|
|
@@ -9531,6 +9506,7 @@ void main() {
|
|
|
9531
9506
|
inner.appendChild(pickBtn);
|
|
9532
9507
|
|
|
9533
9508
|
const insertBtn = makeIconBtn({
|
|
9509
|
+
// biome-ignore lint/style/useTemplate: source pinned by tests/live-browser-regression.test.mjs:620
|
|
9534
9510
|
id: PREFIX + '-insert-toggle',
|
|
9535
9511
|
svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><path d="M12 5v14"/><path d="M5 12h14"/></svg>',
|
|
9536
9512
|
label: 'Insert',
|
|
@@ -9541,7 +9517,7 @@ void main() {
|
|
|
9541
9517
|
|
|
9542
9518
|
// Detect toggle
|
|
9543
9519
|
const detectBtn = makeIconBtn({
|
|
9544
|
-
id: PREFIX
|
|
9520
|
+
id: `${PREFIX}-detect-toggle`,
|
|
9545
9521
|
svg: '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0"><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></svg>',
|
|
9546
9522
|
label: 'Detect',
|
|
9547
9523
|
ariaLabel: 'Detect anti-patterns',
|
|
@@ -9553,13 +9529,13 @@ void main() {
|
|
|
9553
9529
|
background: P.accent, color: C.ink,
|
|
9554
9530
|
display: 'none', fontFamily: MONO, marginLeft: '4px',
|
|
9555
9531
|
});
|
|
9556
|
-
detectBadge.id = PREFIX
|
|
9532
|
+
detectBadge.id = `${PREFIX}-detect-badge`;
|
|
9557
9533
|
detectBtn.appendChild(detectBadge);
|
|
9558
9534
|
inner.appendChild(detectBtn);
|
|
9559
9535
|
|
|
9560
9536
|
// DESIGN.md panel toggle - quartet of color squares as the mark.
|
|
9561
9537
|
const designBtn = makeIconBtn({
|
|
9562
|
-
id: PREFIX
|
|
9538
|
+
id: `${PREFIX}-design-toggle`,
|
|
9563
9539
|
svg: `<span style="display:inline-grid;grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;width:14px;height:14px;border-radius:3px;overflow:hidden;box-shadow:inset 0 0 0 1px oklch(92% 0 0 / 0.13);flex-shrink:0">
|
|
9564
9540
|
<span style="background:oklch(84% 0.19 80.46)"></span>
|
|
9565
9541
|
<span style="background:oklch(70% 0.12 188)"></span>
|
|
@@ -9589,7 +9565,7 @@ void main() {
|
|
|
9589
9565
|
fontFamily: FONT,
|
|
9590
9566
|
pointerEvents: 'auto',
|
|
9591
9567
|
});
|
|
9592
|
-
pendingDockEl.id = PREFIX
|
|
9568
|
+
pendingDockEl.id = `${PREFIX}-pending-dock`;
|
|
9593
9569
|
|
|
9594
9570
|
pendingPillEl = el('button', {
|
|
9595
9571
|
display: 'none',
|
|
@@ -9666,7 +9642,7 @@ void main() {
|
|
|
9666
9642
|
justifyContent: 'center',
|
|
9667
9643
|
padding: '0', boxSizing: 'border-box',
|
|
9668
9644
|
width: '30px', height: '30px', borderRadius: '999px',
|
|
9669
|
-
border:
|
|
9645
|
+
border: `1px solid ${P.hairline}`,
|
|
9670
9646
|
background: P.chatSurface,
|
|
9671
9647
|
color: P.textDim,
|
|
9672
9648
|
overflow: 'visible',
|
|
@@ -9692,7 +9668,7 @@ void main() {
|
|
|
9692
9668
|
lineHeight: '1',
|
|
9693
9669
|
whiteSpace: 'nowrap',
|
|
9694
9670
|
textAlign: 'center',
|
|
9695
|
-
transition:
|
|
9671
|
+
transition: `opacity 0.16s ease, transform 0.18s ${EASE}`,
|
|
9696
9672
|
});
|
|
9697
9673
|
pendingTrashTooltipEl.textContent = 'Discard copy edits';
|
|
9698
9674
|
pendingTrashTooltipEl.setAttribute('role', 'tooltip');
|
|
@@ -9725,7 +9701,7 @@ void main() {
|
|
|
9725
9701
|
height: '30px',
|
|
9726
9702
|
padding: '0 12px',
|
|
9727
9703
|
borderRadius: '999px',
|
|
9728
|
-
border:
|
|
9704
|
+
border: `1px solid ${accent ? P.accent : P.hairline}`,
|
|
9729
9705
|
background: accent ? P.accent : P.chatSurface,
|
|
9730
9706
|
color: accent ? C.ink : P.textDim,
|
|
9731
9707
|
fontFamily: FONT,
|
|
@@ -9778,7 +9754,7 @@ void main() {
|
|
|
9778
9754
|
color: P.textDim, fontFamily: FONT, fontSize: '0', lineHeight: '0',
|
|
9779
9755
|
cursor: 'pointer', transition: 'color 0.12s ease, background 0.12s ease',
|
|
9780
9756
|
});
|
|
9781
|
-
exitBtn.id = PREFIX
|
|
9757
|
+
exitBtn.id = `${PREFIX}-exit`;
|
|
9782
9758
|
exitBtn.innerHTML = '<svg width="14" height="14" viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="3" y1="3" x2="11" y2="11"/><line x1="11" y1="3" x2="3" y2="11"/></svg>';
|
|
9783
9759
|
exitBtn.title = 'Exit live mode';
|
|
9784
9760
|
exitBtn.addEventListener('mouseenter', () => { exitBtn.style.color = 'oklch(58% 0.15 35)'; exitBtn.style.background = P.exitHover; });
|
|
@@ -9827,11 +9803,11 @@ void main() {
|
|
|
9827
9803
|
}
|
|
9828
9804
|
|
|
9829
9805
|
function updateGlobalBarState() {
|
|
9830
|
-
const detectToggle = uiGetById(PREFIX
|
|
9831
|
-
const detectBadge = uiGetById(PREFIX
|
|
9832
|
-
const pickToggle = uiGetById(PREFIX
|
|
9833
|
-
const insertToggle = uiGetById(PREFIX
|
|
9834
|
-
const designToggle = uiGetById(PREFIX
|
|
9806
|
+
const detectToggle = uiGetById(`${PREFIX}-detect-toggle`);
|
|
9807
|
+
const detectBadge = uiGetById(`${PREFIX}-detect-badge`);
|
|
9808
|
+
const pickToggle = uiGetById(`${PREFIX}-pick-toggle`);
|
|
9809
|
+
const insertToggle = uiGetById(`${PREFIX}-insert-toggle`);
|
|
9810
|
+
const designToggle = uiGetById(`${PREFIX}-design-toggle`);
|
|
9835
9811
|
const theme = globalBarEl?.dataset.theme || 'light';
|
|
9836
9812
|
const P = barPaletteForTheme(theme);
|
|
9837
9813
|
|
|
@@ -9860,6 +9836,7 @@ void main() {
|
|
|
9860
9836
|
// If the bar is currently under the cursor, keep all labels expanded -
|
|
9861
9837
|
// otherwise clicking a toggle that deactivates (e.g. closing DESIGN.md)
|
|
9862
9838
|
// would collapse its label while the user's mouse is still on the bar.
|
|
9839
|
+
// biome-ignore lint/complexity/useOptionalChain: `?.` would pass undefined instead of null, which switches syncGlobalBarExpandedLabels onto its default-parameter path
|
|
9863
9840
|
syncGlobalBarExpandedLabels(globalBarEl && globalBarEl.matches(':hover'));
|
|
9864
9841
|
|
|
9865
9842
|
if (detectBadge) {
|
|
@@ -9964,7 +9941,7 @@ void main() {
|
|
|
9964
9941
|
if (detectScriptLoaded) return;
|
|
9965
9942
|
detectScriptLoaded = true;
|
|
9966
9943
|
const s = document.createElement('script');
|
|
9967
|
-
s.src =
|
|
9944
|
+
s.src = `http://localhost:${PORT}/detect.js`;
|
|
9968
9945
|
s.dataset.monodesignExtension = 'true';
|
|
9969
9946
|
document.head.appendChild(s);
|
|
9970
9947
|
}
|
|
@@ -10039,7 +10016,7 @@ void main() {
|
|
|
10039
10016
|
if (tooltipEl) { tooltipEl.remove(); tooltipEl = null; }
|
|
10040
10017
|
if (barEl) { barEl.remove(); barEl = null; }
|
|
10041
10018
|
if (pickerEl) { pickerEl.remove(); pickerEl = null; }
|
|
10042
|
-
if (paramsPanelEl) { paramsPanelEl.remove(); paramsPanelEl = null;
|
|
10019
|
+
if (paramsPanelEl) { paramsPanelEl.remove(); paramsPanelEl = null; paramsPanelBody = null; }
|
|
10043
10020
|
if (editBadgeProxyRoot) { editBadgeProxyRoot.remove(); editBadgeProxyRoot = null; editBadgeProxyByTarget = new Map(); }
|
|
10044
10021
|
if (evtSource) { evtSource.close(); evtSource = null; }
|
|
10045
10022
|
document.removeEventListener('mousemove', handleMouseMove, true);
|
|
@@ -10064,7 +10041,7 @@ void main() {
|
|
|
10064
10041
|
|
|
10065
10042
|
let designHost = null;
|
|
10066
10043
|
let designShadow = null;
|
|
10067
|
-
|
|
10044
|
+
const designState = {
|
|
10068
10045
|
open: false,
|
|
10069
10046
|
tab: 'visual', // 'visual' | 'raw'
|
|
10070
10047
|
parsed: null, // parseDesignMd output (frontmatter + body sections)
|
|
@@ -10106,7 +10083,7 @@ void main() {
|
|
|
10106
10083
|
|
|
10107
10084
|
function initDesignPanel() {
|
|
10108
10085
|
designHost = document.createElement('div');
|
|
10109
|
-
designHost.id = PREFIX
|
|
10086
|
+
designHost.id = `${PREFIX}-design-host`;
|
|
10110
10087
|
Object.assign(designHost.style, {
|
|
10111
10088
|
position: 'fixed', top: '0', left: '0',
|
|
10112
10089
|
width: '0', height: '0',
|
|
@@ -10674,7 +10651,7 @@ void main() {
|
|
|
10674
10651
|
}
|
|
10675
10652
|
|
|
10676
10653
|
function findProseDescription(proseColors, key, displayName) {
|
|
10677
|
-
if (!proseColors
|
|
10654
|
+
if (!proseColors?.groups) return null;
|
|
10678
10655
|
const needles = [key, displayName].filter(Boolean).map((s) => s.toLowerCase());
|
|
10679
10656
|
for (const g of proseColors.groups) {
|
|
10680
10657
|
for (const c of g.colors || []) {
|
|
@@ -10773,7 +10750,7 @@ void main() {
|
|
|
10773
10750
|
// The system's actual sample size for this role, shown as small mono meta below.
|
|
10774
10751
|
if (t.sampleSize) {
|
|
10775
10752
|
const scale = document.createElement('div');
|
|
10776
|
-
scale.style.cssText =
|
|
10753
|
+
scale.style.cssText = `font-family:${MONO}; font-size: 10px; color:${DP.meta}; margin-top: 2px;`;
|
|
10777
10754
|
scale.textContent = t.sampleSize;
|
|
10778
10755
|
tile.appendChild(scale);
|
|
10779
10756
|
}
|
|
@@ -10924,7 +10901,7 @@ void main() {
|
|
|
10924
10901
|
const groups = [];
|
|
10925
10902
|
for (const c of components) {
|
|
10926
10903
|
const last = groups[groups.length - 1];
|
|
10927
|
-
if (last
|
|
10904
|
+
if (last?.[0].kind && c.kind === last[0].kind) {
|
|
10928
10905
|
last.push(c);
|
|
10929
10906
|
} else {
|
|
10930
10907
|
groups.push([c]);
|
|
@@ -10933,7 +10910,7 @@ void main() {
|
|
|
10933
10910
|
return groups;
|
|
10934
10911
|
}
|
|
10935
10912
|
|
|
10936
|
-
function titleForKind(kind,
|
|
10913
|
+
function titleForKind(kind, _count) {
|
|
10937
10914
|
const labels = {
|
|
10938
10915
|
button: 'Buttons',
|
|
10939
10916
|
input: 'Inputs',
|
|
@@ -10942,7 +10919,7 @@ void main() {
|
|
|
10942
10919
|
card: 'Cards',
|
|
10943
10920
|
custom: 'Components',
|
|
10944
10921
|
};
|
|
10945
|
-
return labels[kind] || (kind ? kind.charAt(0).toUpperCase() + kind.slice(1)
|
|
10922
|
+
return labels[kind] || (kind ? `${kind.charAt(0).toUpperCase() + kind.slice(1)}s` : 'Components');
|
|
10946
10923
|
}
|
|
10947
10924
|
|
|
10948
10925
|
// Collapsibles.
|
|
@@ -11018,7 +10995,7 @@ void main() {
|
|
|
11018
10995
|
if (n.northStar) {
|
|
11019
10996
|
const star = document.createElement('span');
|
|
11020
10997
|
star.className = 'north-star';
|
|
11021
|
-
star.textContent =
|
|
10998
|
+
star.textContent = `“${n.northStar}”`;
|
|
11022
10999
|
ov.appendChild(star);
|
|
11023
11000
|
}
|
|
11024
11001
|
if (n.overview) {
|
|
@@ -11165,10 +11142,6 @@ void main() {
|
|
|
11165
11142
|
return s;
|
|
11166
11143
|
}
|
|
11167
11144
|
|
|
11168
|
-
function highlightBold(text) {
|
|
11169
|
-
return inlineMd(text);
|
|
11170
|
-
}
|
|
11171
|
-
|
|
11172
11145
|
function escapeHtml(s) {
|
|
11173
11146
|
return String(s)
|
|
11174
11147
|
.replace(/&/g, '&')
|
|
@@ -11182,7 +11155,7 @@ void main() {
|
|
|
11182
11155
|
if (!text) return;
|
|
11183
11156
|
try {
|
|
11184
11157
|
navigator.clipboard.writeText(text);
|
|
11185
|
-
showToast(
|
|
11158
|
+
showToast(`Copied: ${text}`);
|
|
11186
11159
|
} catch { /* ignore */ }
|
|
11187
11160
|
}
|
|
11188
11161
|
|
|
@@ -11219,12 +11192,12 @@ void main() {
|
|
|
11219
11192
|
if (!wrapper) return;
|
|
11220
11193
|
scout.disconnect();
|
|
11221
11194
|
if (resumeSession()) {
|
|
11222
|
-
console.log(
|
|
11195
|
+
console.log(`[monodesign] Resumed deferred session ${currentSessionId} (post-hydration).`);
|
|
11223
11196
|
}
|
|
11224
11197
|
});
|
|
11225
11198
|
scout.observe(document.body, { childList: true, subtree: true });
|
|
11226
11199
|
} else {
|
|
11227
|
-
console.log(
|
|
11200
|
+
console.log(`[monodesign] Resumed active variant session ${currentSessionId} (${arrivedVariants}/${expectedVariants} variants).`);
|
|
11228
11201
|
}
|
|
11229
11202
|
|
|
11230
11203
|
if (state === 'IDLE' && (pickActive || insertActive)) setLiveState('PICKING');
|