mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-11 21:57:14 +03:00
The list of Live chrome surfaces was inlined into live-browser.js as a function-scope const when live/ui-core.mjs was deleted for having zero in-repo references. It had one out-of-repo reference. The private impeccable-site repo imports it at build time: its Live UI lab must hold a snapshot for every surface Live defines, and the site build fails with the surface name when one is missing. Inlining put the list out of reach of every Node importer, so the site had to regex it back out of the browser script, and the guard only kept passing because the site's materialized copy of skill/ was stale. A guard that reads a list the site itself maintains guards nothing, so the fix is a real export rather than a better parser. skill/scripts/live/ui-surfaces.mjs is now the single definition. The browser-runtime constraint is unchanged and satisfied the same way the command palette already solves it: live-browser.js is served raw and injected as a classic <script>, so it cannot import an ES module. The /live.js assembler serializes the module into window.__IMPECCABLE_LIVE_UI_SURFACES__ in the prelude it already writes for the token, port and vocabulary, and live-browser.js reads the global. assembleLiveBrowserScript defaults the value from the module rather than taking it from live-server.mjs, so the bundle carries the canonical inventory by construction instead of by a caller remembering to pass it. The emitted inventory is byte-identical to the inlined one. tests/live-ui-surfaces.test.mjs pins both halves of the seam: the module is the definition (live-browser.js must not redeclare it), the prefix the module builds ids from matches the PREFIX live-browser.js hardcodes, and the assembled bundle still carries the list. live-server.test.mjs gets the matching integration check against a served /live.js. One existing assertion changed. live-browser-regression.test.mjs checked that the steer Send control is registered as live chrome by matching the text of the inline literal's last line. That encoded where the list was written, not what it contains; it now asserts membership in the imported LIVE_UI_COMPONENT_IDS, which is the behaviour it was after. Verified with the full default suite plus a live-e2e fixture run (vite8-react-modal), so the overlay is exercised end to end in a browser. AI-assisted via Claude Code under maintainer direction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
76 lines
3.5 KiB
JavaScript
76 lines
3.5 KiB
JavaScript
/**
|
|
* Canonical inventory of the Live overlay's UI surfaces: one entry per piece of
|
|
* chrome Live mounts on the user's page, with the element ids that make it up.
|
|
*
|
|
* Single source of truth, consumed by:
|
|
* - skill/scripts/live/browser-script-parts.mjs — serializes this into
|
|
* window.__IMPECCABLE_LIVE_UI_SURFACES__ in the /live.js prelude.
|
|
* - skill/scripts/live-browser.js — publishes it on
|
|
* window.__IMPECCABLE_LIVE_CHROME_CORE__ for adapters and E2E probes. That
|
|
* file is served raw and injected as a classic <script>, so it cannot
|
|
* import this module at runtime; it reads the injected global instead, the
|
|
* same path live/vocabulary.mjs already takes for the command palette.
|
|
* - the private impeccable-site repo — site/components/LiveUiGallery.astro
|
|
* and tests/live-ui-lab.test.mjs import LIVE_UI_SURFACES at build time and
|
|
* fail the site build when the Live UI lab has no snapshot for a surface
|
|
* defined here. That guard only guards if it reads this list rather than a
|
|
* copy the site keeps, so this module must stay importable from Node.
|
|
* Renaming a key or the module is a breaking change for that build; the
|
|
* list was briefly inlined into live-browser.js and the site had to parse
|
|
* it back out with a regex.
|
|
*
|
|
* Add a surface here and both the browser bundle and the site lab follow.
|
|
*/
|
|
|
|
/** Id prefix every Live chrome element carries. Mirrored by PREFIX in live-browser.js. */
|
|
export const LIVE_UI_PREFIX = 'impeccable-live';
|
|
|
|
const id = (suffix) => `${LIVE_UI_PREFIX}-${suffix}`;
|
|
|
|
/**
|
|
* The mount contract every Live chrome adapter (DOM, Svelte, ...) satisfies.
|
|
* Published alongside the surfaces on __IMPECCABLE_LIVE_CHROME_CORE__.
|
|
*/
|
|
export const LIVE_CHROME_MOUNT_CONTRACT = Object.freeze(['root', 'transport', 'state', 'actions']);
|
|
|
|
export const LIVE_UI_SURFACES = Object.freeze([
|
|
{
|
|
key: 'global-bottom-bar',
|
|
ids: [
|
|
id('global-bar'), id('global-bar-brand'), id('pick-toggle'), id('insert-toggle'),
|
|
id('detect-toggle'), id('detect-badge'), id('design-toggle'), id('page-chat'),
|
|
id('page-chat-input'), id('page-chat-voice'), id('page-chat-send'),
|
|
],
|
|
},
|
|
{ key: 'pending-copy-edit-dock', ids: [id('pending-dock')] },
|
|
{
|
|
key: 'element-selection-chrome',
|
|
ids: [
|
|
id('highlight'), id('tooltip'), id('bar'), id('selection-pill'), id('input'),
|
|
id('configure-voice'), id('configure-bar-tooltip'),
|
|
],
|
|
},
|
|
{ key: 'action-picker', ids: [id('picker')] },
|
|
{ key: 'edit-chrome', ids: [id('edit-badge')] },
|
|
{ key: 'generating-row', ids: [id('bar'), id('shader')] },
|
|
{ key: 'variant-cycling-row', ids: [id('bar'), id('params-panel')] },
|
|
{ key: 'variant-params-panel', ids: [id('params-panel')] },
|
|
{ key: 'saving-confirmed-rows', ids: [id('bar')] },
|
|
{
|
|
key: 'insert-mode-chrome',
|
|
ids: [
|
|
id('insert-line'), id('insert-placeholder'), id('placeholder-resize'), id('insert-input'),
|
|
id('insert-voice'), id('insert-create'), id('insert-create-tooltip'),
|
|
],
|
|
},
|
|
{ key: 'annotation-chrome', ids: [id('annot'), id('annot-svg'), id('annot-pins'), id('annot-clear')] },
|
|
{ key: 'design-system-panel', ids: [id('design-host')] },
|
|
{ key: 'toasts-and-errors', ids: [id('toast'), id('mount-error')] },
|
|
{ key: 'css-isolation-boundary', ids: [id('root')] },
|
|
].map((surface) => Object.freeze({ ...surface, ids: Object.freeze(surface.ids) })));
|
|
|
|
/** Every id any surface owns, de-duplicated, in surface order. */
|
|
export const LIVE_UI_COMPONENT_IDS = Object.freeze([
|
|
...new Set(LIVE_UI_SURFACES.flatMap((surface) => surface.ids)),
|
|
]);
|