isotone 1.1.2 → 1.2.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.
Files changed (54) hide show
  1. package/AGENTS.md +84 -6
  2. package/CHANGELOG.md +46 -0
  3. package/README.md +64 -14
  4. package/dist/{IterationPanel-phJRYtUO.d.ts → IterationPanel-Bq77d5NT.d.ts} +3 -1
  5. package/dist/{chunk-FKEKBZ3E.js → chunk-2FY2JNPG.js} +95 -9
  6. package/dist/chunk-2FY2JNPG.js.map +1 -0
  7. package/dist/chunk-BDTB3DFR.js +100 -0
  8. package/dist/chunk-BDTB3DFR.js.map +1 -0
  9. package/dist/{chunk-PUXQGUMQ.js → chunk-BTJHQXF7.js} +104 -5
  10. package/dist/chunk-BTJHQXF7.js.map +1 -0
  11. package/dist/chunk-JCTWHR7U.js +13 -0
  12. package/dist/chunk-JCTWHR7U.js.map +1 -0
  13. package/dist/{chunk-I7CZUPDO.js → chunk-KRS57POF.js} +17 -33
  14. package/dist/chunk-KRS57POF.js.map +1 -0
  15. package/dist/chunk-L6O4HYGP.js +1150 -0
  16. package/dist/chunk-L6O4HYGP.js.map +1 -0
  17. package/dist/chunk-MX4RQJFV.js +9 -0
  18. package/dist/chunk-MX4RQJFV.js.map +1 -0
  19. package/dist/chunk-YPDV3PX4.js +142 -0
  20. package/dist/chunk-YPDV3PX4.js.map +1 -0
  21. package/dist/cli.js +1079 -148
  22. package/dist/cli.js.map +1 -1
  23. package/dist/core.d.ts +135 -10
  24. package/dist/core.js +12 -3
  25. package/dist/index.d.ts +13 -28
  26. package/dist/index.js +618 -281
  27. package/dist/index.js.map +1 -1
  28. package/dist/isotone.global.js +98 -42
  29. package/dist/serve.d.ts +5 -3
  30. package/dist/serve.js +60 -23
  31. package/dist/serve.js.map +1 -1
  32. package/dist/server.d.ts +7 -0
  33. package/dist/server.js +24 -11
  34. package/dist/server.js.map +1 -1
  35. package/dist/vite-plugin.d.ts +4 -3
  36. package/dist/vite-plugin.js +48 -128
  37. package/dist/vite-plugin.js.map +1 -1
  38. package/docs/blast.md +164 -0
  39. package/docs/integrations.md +75 -15
  40. package/docs/migration.md +19 -0
  41. package/docs/updates.md +110 -4
  42. package/docs/variants.md +102 -9
  43. package/package.json +2 -1
  44. package/dist/chunk-A4DX2V4C.js +0 -7
  45. package/dist/chunk-A4DX2V4C.js.map +0 -1
  46. package/dist/chunk-FKEKBZ3E.js.map +0 -1
  47. package/dist/chunk-I7CZUPDO.js.map +0 -1
  48. package/dist/chunk-PUXQGUMQ.js.map +0 -1
  49. package/dist/chunk-RQ2YI5KS.js +0 -24
  50. package/dist/chunk-RQ2YI5KS.js.map +0 -1
  51. package/dist/chunk-TGAU3WTF.js +0 -549
  52. package/dist/chunk-TGAU3WTF.js.map +0 -1
  53. package/dist/chunk-X6V2AKJL.js +0 -375
  54. package/dist/chunk-X6V2AKJL.js.map +0 -1
package/dist/core.d.ts CHANGED
@@ -1,3 +1,32 @@
1
+ /** Read-only snapshot from the local development server. */
2
+ interface UpdateInfo {
3
+ currentVersion: string;
4
+ latestVersion: string | null;
5
+ status: 'checking' | 'available' | 'current' | 'ahead' | 'unavailable' | 'disabled';
6
+ upgrade: {
7
+ manager: 'npm' | 'pnpm' | 'yarn';
8
+ command: string;
9
+ cwd: string;
10
+ } | null;
11
+ message?: string;
12
+ }
13
+ /**
14
+ * The user's request to upgrade Isotone, carried by one feedback note. The
15
+ * local server builds it from its own update check; the browser only asks for
16
+ * it, so the versions and command never come from page content.
17
+ */
18
+ interface UpdateRequest {
19
+ from: string;
20
+ to: string;
21
+ /** The exact command `check-update` suggests, pinned to `to`. */
22
+ command: string;
23
+ /** The directory to run it in: the manifest that declares Isotone. */
24
+ cwd: string;
25
+ manager: 'npm' | 'pnpm' | 'yarn';
26
+ /** The release's changelog, to summarize for the user afterwards. */
27
+ changelog?: string;
28
+ }
29
+
1
30
  /**
2
31
  * isotone — variants: the framework-free model.
3
32
  *
@@ -44,7 +73,12 @@ interface SelectVariantAxis {
44
73
  /** The primary option; what a host renders when nothing is selected. */
45
74
  defaultOption: string;
46
75
  showWhen?: VariantAxisCondition;
47
- /** Panel grouping: a hairline separates consecutive different sections. */
76
+ /**
77
+ * The part of the page the selector belongs to, shown as a section header in
78
+ * the panel. Usually written as a label prefix instead (`"Header > Logo size"`);
79
+ * see {@link axisSection}. When set, it wins over the prefix, and `''` keeps the
80
+ * selector out of every section with its label shown as written.
81
+ */
48
82
  section?: string;
49
83
  }
50
84
  interface RangeVariantAxis {
@@ -86,6 +120,42 @@ interface VariantAction {
86
120
  action: 'remove-option' | 'remove-axis' | 'keep-default';
87
121
  optionId?: string;
88
122
  }
123
+ /** How a section and its selector are joined for display: `Header › Logo size`. */
124
+ declare const SECTION_SEPARATOR = " \u203A ";
125
+ interface SectionedLabel {
126
+ /** The section's display name, or `null` for a selector without one. */
127
+ section: string | null;
128
+ /** What the panel prints under the section header. */
129
+ label: string;
130
+ /** Section and label together, for assistive technology, notes and the CLI. */
131
+ fullLabel: string;
132
+ }
133
+ /**
134
+ * Split a selector label into its section and its own name. `"Header > Logo size"`
135
+ * is the Logo size selector in the Header section. The first separator wins, so
136
+ * `"Header > Nav > Gap"` is `Nav > Gap` in Header. An explicit `section` overrides
137
+ * the prefix: the label then shows as written, less a prefix that repeats the
138
+ * section, and `''` means no section at all.
139
+ */
140
+ declare function splitSectionLabel(label: string, section?: string): SectionedLabel;
141
+ declare function axisSection(axis: Pick<VariantAxis, 'label' | 'section'>): SectionedLabel;
142
+ interface VariantSection<T extends VariantAxis = VariantAxis> {
143
+ /** Display name, from the section's first selector; `null` for selectors without one. */
144
+ name: string | null;
145
+ /** Case-insensitive identity: `"Header"` and `"header"` are one section. */
146
+ key: string;
147
+ axes: (SectionedLabel & {
148
+ axis: T;
149
+ })[];
150
+ }
151
+ /**
152
+ * Group axes for the panel. Selectors without a section come first, without a
153
+ * header; sections follow in the order their first selector appears, and every
154
+ * selector keeps its relative order. A dependent axis (`showWhen`) without its
155
+ * own section joins its parent's, so it never jumps away from the control that
156
+ * reveals it. Linear in the number of axes.
157
+ */
158
+ declare function sectionAxes<T extends VariantAxis>(axes: T[]): VariantSection<T>[];
89
159
  /** The primary value of an axis, as the selection string. */
90
160
  declare function axisDefault(axis: VariantAxis): string;
91
161
  /** True when `value` is legal for the axis. */
@@ -190,6 +260,9 @@ interface OverlayVariant {
190
260
  group?: string;
191
261
  /** What the panel calls the group's selector. Any member may carry it. */
192
262
  groupLabel?: string;
263
+ /** The panel section the group's selector sits in, like an axis `section`.
264
+ * Any member may carry it; a `groupLabel` prefix (`"Header > Logo"`) also works. */
265
+ section?: string;
193
266
  createdAt: string;
194
267
  /**
195
268
  * Repo-relative source path → what the override was derived from. `base`
@@ -212,7 +285,7 @@ interface OverlayVariantStatus extends OverlayVariant {
212
285
  missing: string[];
213
286
  }
214
287
  /**
215
- * A knob: a range or colour axis the host declares in `.isotone/knobs.json`
288
+ * A knob: a range, colour or select axis the host declares in `.isotone/knobs.json`
216
289
  * next to its overlay variants. The panel renders it as a slider (or a colour
217
290
  * pick) on the routes it names, and the value reaches the page as a CSS
218
291
  * custom property on `<html>`, `--knob-<id>`, with the axis unit appended
@@ -220,8 +293,12 @@ interface OverlayVariantStatus extends OverlayVariant {
220
293
  * committed default: `var(--knob-fade-from, 0%)`. "Save as defaults" files
221
294
  * the moved knobs in the same `[set-defaults]` note as the variant picks, so
222
295
  * the agent writes the numbers into the source and the knob file.
296
+ *
297
+ * A select knob's value is its option id, which CSS cannot branch on through a
298
+ * custom property, so it also lands as `data-knob-<id>` on `<html>`. Code that
299
+ * draws for itself listens for {@link KNOBS_EVENT} on the document.
223
300
  */
224
- type KnobAxis = (RangeVariantAxis | ColorVariantAxis) & {
301
+ type KnobAxis = (RangeVariantAxis | ColorVariantAxis | SelectVariantAxis) & {
225
302
  /** Route pattern(s) the knob belongs on, like a variant's `route`; absent means every route. */
226
303
  route?: string | string[];
227
304
  };
@@ -235,7 +312,11 @@ interface OverlayVariantsList {
235
312
  }
236
313
  /** The custom property a knob writes: `--knob-<id>`. */
237
314
  declare function knobVar(id: string): string;
238
- /** The property's value: a range carries its unit, a colour is its hex. */
315
+ /** Fired on `<html>`, bubbling, when a knob's value changes. `detail` is
316
+ * `{ id, value }` with the same value the custom property holds, or `null`
317
+ * when the knob went back to its default. */
318
+ declare const KNOBS_EVENT = "isotone:knob";
319
+ /** The property's value: a range carries its unit, a colour is its hex, a select is the option id. */
239
320
  declare function knobCssValue(axis: KnobAxis, value: string): string;
240
321
  /** The knobs that belong on `route`. */
241
322
  declare function knobsFor(knobs: KnobAxis[] | undefined, route: string): KnobAxis[];
@@ -245,6 +326,10 @@ declare function applyKnobValues(knobs: KnobAxis[], values: VariantSelections, r
245
326
  setProperty(name: string, value: string): void;
246
327
  removeProperty(name: string): void;
247
328
  };
329
+ setAttribute?(name: string, value: string): void;
330
+ removeAttribute?(name: string): void;
331
+ getAttribute?(name: string): string | null;
332
+ dispatchEvent?(event: Event): boolean;
248
333
  }): void;
249
334
  /** The knobs that sit off their default, with the value the panel showed. */
250
335
  declare function knobDelta(knobs: KnobAxis[], values: VariantSelections): {
@@ -344,8 +429,25 @@ interface IterationElement {
344
429
  tag: string;
345
430
  /** Trimmed text-content snippet (may be empty for visual elements). */
346
431
  text: string;
347
- /** Best-effort CSS path for locating the element in code. */
432
+ /** CSS path to the element. A pin made in a browser matches only this element. */
348
433
  selector: string;
434
+ /** Identifying attributes: role, name, aria-label, data-*, class and so on. */
435
+ attributes?: Record<string, string>;
436
+ /** React components around the element, outermost first. */
437
+ component?: string[];
438
+ /** `file:line` of the JSX, where the host's React still records it. */
439
+ source?: string;
440
+ /** Labelled or headed ancestors, outermost first. */
441
+ within?: string[];
442
+ /** The closest ancestor's text, for an element with none of its own. */
443
+ near?: string;
444
+ /** Where it sat on the page when pinned, in CSS pixels from the document's corner. */
445
+ rect?: {
446
+ x: number;
447
+ y: number;
448
+ w: number;
449
+ h: number;
450
+ };
349
451
  }
350
452
  /** A durable reference to a selector or one of its options, not a DOM path. */
351
453
  interface VariantReference {
@@ -365,6 +467,23 @@ interface NoteContext {
365
467
  variantAction?: VariantRemoval;
366
468
  elements?: IterationElement[];
367
469
  variant?: VariantReference | null;
470
+ /** The user's request to upgrade Isotone, built by the local server from
471
+ * its own update check. At most one is open at a time. */
472
+ update?: UpdateRequest;
473
+ /** The agent's question or remark about the note, written with
474
+ * `isotone --reply <id> "<text>"`. Only the CLI writes it; the panel shows it
475
+ * under the note, and the reviewer answers by editing the note. */
476
+ reply?: NoteReply;
477
+ }
478
+ interface NoteReply {
479
+ text: string;
480
+ at: string;
481
+ /** A fingerprint of the note as it was when the agent asked. Until the
482
+ * reviewer edits the note, Blast does not hand it out again. */
483
+ about?: string;
484
+ /** Set when the note has changed since the agent asked: the reviewer's
485
+ * edit answered the question, so it is no longer pending. */
486
+ answered?: boolean;
368
487
  }
369
488
  /** A note written in the panel, read and answered by the coding agent. */
370
489
  interface IterationNote extends NoteContext {
@@ -399,12 +518,18 @@ interface NodeLike {
399
518
  textContent?: string | null;
400
519
  /** One-based child position, when the adapter can provide it cheaply. */
401
520
  indexInParent?: number;
521
+ /** Whether a selector finds this node and nothing else. Without one, the
522
+ * path stops at an id or the depth cap, unchecked. */
523
+ isOnlyMatch?(selector: string): boolean;
524
+ /** What else identifies the node, beyond its path. */
525
+ context?(): Partial<IterationElement>;
402
526
  }
403
527
  /**
404
- * Best-effort descriptor of a picked element for locating it in code. Walks
405
- * up the tree collecting `#id` (preferred) or `tag:nth-child(n)` segments up
406
- * to a shallow depth, stopping at `BODY` or the depth cap. Kept framework-free
407
- * so it is unit-testable.
528
+ * Descriptor of a picked element for locating it in code. Walks up the tree
529
+ * collecting `#id` (preferred) or `tag:nth-child(n)` segments. The panel finds
530
+ * pins again with `querySelector`, which takes the first match, so with a real
531
+ * DOM the walk goes on past `maxDepth` until the path matches this element
532
+ * alone. Kept framework-free so it is unit-testable.
408
533
  */
409
534
  declare function describeIterationElement(el: NodeLike, maxDepth?: number): IterationElement;
410
535
  declare function elementAsNode(el: Element): NodeLike;
@@ -451,4 +576,4 @@ declare function createIterationStore(cfg?: IterationStoreConfig): {
451
576
  readonly hasUnsyncedNotes: boolean;
452
577
  };
453
578
 
454
- export { type ColorSwatch, type ColorVariantAxis, type IterationElement, type IterationNote, type IterationStoreConfig, KNOBS_STORAGE_KEY, type KnobAxis, type LiveVariantSelection, type NodeLike, type NoteContext, OVERLAY_DEFAULT_OPTION, OVERLAY_GROUP_ID, type OverlayGroup, type OverlayVariant, type OverlayVariantStatus, type OverlayVariantsList, type RangeVariantAxis, type RouteGateOptions, type SaveLocation, type SelectVariantAxis, VARIANTS_ENDPOINT, type VariantAction, type VariantAxis, type VariantAxisCondition, type VariantOption, type VariantReference, type VariantRemoval, type VariantSelections, type VariantsSource, applyKnobValues, axisDefault, createIterationStore, createOverlayVariantsSource, createVariantsSource, defaultSelections, describeIterationElement, elementAsNode, formatRangeValue, isAxisVisible, isDirty, isRouteVisible, isValidSelection, knobCssValue, knobDelta, knobVar, knobsFor, overlayAxes, overlayGroups, parseVariantParam, serializeVariantParam, variantAppliesTo, visibleAxes };
579
+ export { type ColorSwatch, type ColorVariantAxis, type IterationElement, type IterationNote, type IterationStoreConfig, KNOBS_EVENT, KNOBS_STORAGE_KEY, type KnobAxis, type LiveVariantSelection, type NodeLike, type NoteContext, type NoteReply, OVERLAY_DEFAULT_OPTION, OVERLAY_GROUP_ID, type OverlayGroup, type OverlayVariant, type OverlayVariantStatus, type OverlayVariantsList, type RangeVariantAxis, type RouteGateOptions, SECTION_SEPARATOR, type SaveLocation, type SectionedLabel, type SelectVariantAxis, type UpdateInfo, type UpdateRequest, VARIANTS_ENDPOINT, type VariantAction, type VariantAxis, type VariantAxisCondition, type VariantOption, type VariantReference, type VariantRemoval, type VariantSection, type VariantSelections, type VariantsSource, applyKnobValues, axisDefault, axisSection, createIterationStore, createOverlayVariantsSource, createVariantsSource, defaultSelections, describeIterationElement, elementAsNode, formatRangeValue, isAxisVisible, isDirty, isRouteVisible, isValidSelection, knobCssValue, knobDelta, knobVar, knobsFor, overlayAxes, overlayGroups, parseVariantParam, sectionAxes, serializeVariantParam, splitSectionLabel, variantAppliesTo, visibleAxes };
package/dist/core.js CHANGED
@@ -3,14 +3,17 @@ import {
3
3
  describeIterationElement,
4
4
  elementAsNode,
5
5
  isRouteVisible
6
- } from "./chunk-FKEKBZ3E.js";
6
+ } from "./chunk-2FY2JNPG.js";
7
7
  import {
8
+ KNOBS_EVENT,
8
9
  KNOBS_STORAGE_KEY,
9
10
  OVERLAY_DEFAULT_OPTION,
10
11
  OVERLAY_GROUP_ID,
12
+ SECTION_SEPARATOR,
11
13
  VARIANTS_ENDPOINT,
12
14
  applyKnobValues,
13
15
  axisDefault,
16
+ axisSection,
14
17
  createOverlayVariantsSource,
15
18
  createVariantsSource,
16
19
  defaultSelections,
@@ -25,18 +28,22 @@ import {
25
28
  overlayAxes,
26
29
  overlayGroups,
27
30
  parseVariantParam,
31
+ sectionAxes,
28
32
  serializeVariantParam,
33
+ splitSectionLabel,
29
34
  variantAppliesTo,
30
35
  visibleAxes
31
- } from "./chunk-PUXQGUMQ.js";
32
- import "./chunk-A4DX2V4C.js";
36
+ } from "./chunk-BTJHQXF7.js";
33
37
  export {
38
+ KNOBS_EVENT,
34
39
  KNOBS_STORAGE_KEY,
35
40
  OVERLAY_DEFAULT_OPTION,
36
41
  OVERLAY_GROUP_ID,
42
+ SECTION_SEPARATOR,
37
43
  VARIANTS_ENDPOINT,
38
44
  applyKnobValues,
39
45
  axisDefault,
46
+ axisSection,
40
47
  createIterationStore,
41
48
  createOverlayVariantsSource,
42
49
  createVariantsSource,
@@ -55,7 +62,9 @@ export {
55
62
  overlayAxes,
56
63
  overlayGroups,
57
64
  parseVariantParam,
65
+ sectionAxes,
58
66
  serializeVariantParam,
67
+ splitSectionLabel,
59
68
  variantAppliesTo,
60
69
  visibleAxes
61
70
  };
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { I as IterationShortcut } from './IterationPanel-phJRYtUO.js';
2
- export { a as IterationPanel, b as IterationPanelProps } from './IterationPanel-phJRYtUO.js';
1
+ import { I as IterationShortcut } from './IterationPanel-Bq77d5NT.js';
2
+ export { a as IterationPanel, b as IterationPanelProps } from './IterationPanel-Bq77d5NT.js';
3
3
  import { VariantsSource, RouteGateOptions, VariantReference, VariantAction } from './core.js';
4
- export { ColorSwatch, ColorVariantAxis, IterationElement, IterationNote, IterationStoreConfig, KNOBS_STORAGE_KEY, KnobAxis, NodeLike, NoteContext, OVERLAY_DEFAULT_OPTION, OVERLAY_GROUP_ID, OverlayGroup, OverlayVariant, OverlayVariantStatus, OverlayVariantsList, RangeVariantAxis, SelectVariantAxis, VARIANTS_ENDPOINT, VariantAxis, VariantAxisCondition, VariantOption, VariantRemoval, VariantSelections, applyKnobValues, axisDefault, createOverlayVariantsSource, createVariantsSource, defaultSelections, describeIterationElement, elementAsNode, formatRangeValue, isAxisVisible, isDirty, isRouteVisible, isValidSelection, knobCssValue, knobDelta, knobVar, knobsFor, overlayAxes, overlayGroups, parseVariantParam, serializeVariantParam, visibleAxes } from './core.js';
4
+ export { ColorSwatch, ColorVariantAxis, IterationElement, IterationNote, IterationStoreConfig, KNOBS_STORAGE_KEY, KnobAxis, NodeLike, NoteContext, NoteReply, OVERLAY_DEFAULT_OPTION, OVERLAY_GROUP_ID, OverlayGroup, OverlayVariant, OverlayVariantStatus, OverlayVariantsList, RangeVariantAxis, SECTION_SEPARATOR, SectionedLabel, SelectVariantAxis, UpdateRequest, VARIANTS_ENDPOINT, VariantAxis, VariantAxisCondition, VariantOption, VariantRemoval, VariantSection, VariantSelections, applyKnobValues, axisDefault, axisSection, createOverlayVariantsSource, createVariantsSource, defaultSelections, describeIterationElement, elementAsNode, formatRangeValue, isAxisVisible, isDirty, isRouteVisible, isValidSelection, knobCssValue, knobDelta, knobVar, knobsFor, overlayAxes, overlayGroups, parseVariantParam, sectionAxes, serializeVariantParam, splitSectionLabel, visibleAxes } from './core.js';
5
5
  import { I as IterationTheme } from './theme-BWv_ZNhC.js';
6
6
  import * as react from 'react';
7
7
 
@@ -19,9 +19,14 @@ interface MountIterationOptions {
19
19
  /**
20
20
  * Variants for the panel. A `VariantsSource` is rendered as-is; `'overlay'`
21
21
  * builds the overlay adapter against the Vite plugin's same-origin
22
- * endpoint. With neither this nor `endpoint`, nothing mounts.
22
+ * endpoint. `'knobs'` is the same adapter for a server that has knobs but no
23
+ * file variants (`isotone serve`), and its empty list says so. With neither
24
+ * this nor `endpoint`, nothing mounts.
23
25
  */
24
- variants?: VariantsSource | 'overlay';
26
+ variants?: VariantsSource | 'overlay' | 'knobs';
27
+ /** Where `'overlay'` reads variants and knobs. Defaults to the Vite plugin's
28
+ * same-origin endpoint; `isotone serve` passes its own absolute URL. */
29
+ variantsEndpoint?: string;
25
30
  /** Which tab a tabbed panel opens on until the reviewer picks one. */
26
31
  defaultTab?: 'variants' | 'notes';
27
32
  /** Optional localStorage namespace for multi-app origins. */
@@ -34,31 +39,9 @@ interface MountIterationOptions {
34
39
  * IterationPanelProps.getPayload. */
35
40
  getPayload?: () => unknown;
36
41
  }
37
- /**
38
- * Self-mount the Iteration panel into a shadow root on `document.body`,
39
- * outside any app tree, tracking `window.location.pathname` so it needs no
40
- * router integration.
41
- *
42
- * The shadow root is what makes this safe to drop into an app nobody vetted:
43
- * the host's resets, its `button` and `textarea` rules, its stacking and its
44
- * global handlers stop at the boundary, so the panel looks the same in every
45
- * app. Inherited properties and custom properties still cross, which is
46
- * deliberate — the panel reads `--font-sans` and `--foreground` from the host
47
- * so it matches the surrounding theme.
48
- *
49
- * The host element carries `data-isotone`, and that is load-bearing:
50
- * `document.elementFromPoint` retargets to the host for anything inside a
51
- * shadow root, so the element picker's self-exclusion matches on it.
52
- *
53
- * The host is created at runtime by `mountIteration` (never part of any HTML
54
- * React hydrates) and is watched by a MutationObserver: if a whole-document
55
- * render — a React Router hydration failure made worse by an extension, for
56
- * instance — replaces `<body>` and drops the host, it is re-appended to the
57
- * new body, shadow root and all, instead of a fresh mount losing panel state.
58
- */
59
42
  declare function mountIteration(opts: MountIterationOptions): () => void;
60
43
 
61
- declare function VariantsView({ source, showTitle, active, onFeedback, onClose, onSaved, onManage, pendingActions, }: {
44
+ declare function VariantsView({ source, showTitle, active, onFeedback, onClose, onSaved, onManage, pendingActions, emptyText, }: {
62
45
  source: VariantsSource;
63
46
  showTitle?: boolean;
64
47
  active?: boolean;
@@ -67,6 +50,8 @@ declare function VariantsView({ source, showTitle, active, onFeedback, onClose,
67
50
  onSaved?: () => void;
68
51
  onManage?: (action: VariantAction, reference: VariantReference) => Promise<void>;
69
52
  pendingActions?: VariantAction[];
53
+ /** What the list says when this page has no selectors. */
54
+ emptyText?: string;
70
55
  }): react.JSX.Element;
71
56
 
72
57
  declare const PANEL_CSS: string;