@wildwinter/app-shell 0.35.1 → 0.37.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/dist/index.d.cts CHANGED
@@ -150,6 +150,11 @@ interface PaneSideConfig {
150
150
  label?: string;
151
151
  /** Shortcut hint appended to the tooltip, e.g. "Cmd+1". */
152
152
  shortcutHint?: string;
153
+ /** false = the pane is not offered at all: no toggle, togglePane ignored,
154
+ * forced closed whatever the remembered state says. For a slot a host has
155
+ * retired but keeps mounted (Storyletter's inspector) - the shell used to
156
+ * offer a chevron that opened a paneful of nothing. Default true. */
157
+ offered?: boolean;
153
158
  }
154
159
  interface PaneShellState {
155
160
  open: Record<PaneSide, boolean>;
@@ -780,6 +785,25 @@ interface StaleBarOptions {
780
785
  }
781
786
  declare function staleBar(opts: StaleBarOptions): HTMLElement;
782
787
 
788
+ /** What the remark is about. `info` is the plain case; `ok` says a thing you
789
+ * asked for happened; `error` says it did not. */
790
+ type ToastKind = "info" | "ok" | "error";
791
+ interface ToastOptions {
792
+ /** How long it stays, in ms, before the exit plays. Defaults to 4000, or
793
+ * 7000 for an error. */
794
+ duration?: number;
795
+ }
796
+ /**
797
+ * Show a toast. Replaces any toast already showing.
798
+ *
799
+ * `message` is shown as written; a newline breaks the line ("Bundle
800
+ * published\n<path>"), and a long unbroken token such as a path wraps inside
801
+ * the card rather than spilling past it.
802
+ */
803
+ declare function toast(message: string, kind?: ToastKind, opts?: ToastOptions): void;
804
+ /** Dismiss the current toast now, if any. Plays the exit. */
805
+ declare function dismissToast(): void;
806
+
783
807
  interface StepperItem {
784
808
  /**
785
809
  * One word for what kind of thing this is: "error", "comment", "resolved".
@@ -876,4 +900,4 @@ declare function historyNav(onBack: () => void, onForward: () => void): {
876
900
  set(canBack: boolean, canForward: boolean): void;
877
901
  };
878
902
 
879
- export { type AboutOptions, type AnchoredPanel, type AnchoredPanelOptions, type Child, type Comment, type CommentMessage, type CommentsOptions, type ConfirmOptions, type DocLine, type DupGuard, type ElProps, type GameIdEditorOptions, type IconName, type IconSvgName, type Identity, type IdentityOptions, type JobProgressOptions, type JobProgressView, type NavHistory, type NavHistoryOptions, type Notes, type NotesEditorOptions, PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, type PaneShell, type PaneShellOptions, type PaneShellState, type PaneSide, type PaneSideConfig, type PinButton, type PinButtonOptions, type PropertyRefOptions, RESERVED_PROPERTY_NAMES, type SaveController, type SaveControllerOptions, type SaveIndicator, type SaveStatus, type SettingsDialog, type SettingsDialogOptions, type SettingsSection, type SettingsSectionHandle, type ShardVc, type StaleBarOptions, type StepperBarOptions, type StepperItem, type StepperTone, type TipRect, type TooltipOptions, type VcMap, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, vcBadgeFor };
903
+ export { type AboutOptions, type AnchoredPanel, type AnchoredPanelOptions, type Child, type Comment, type CommentMessage, type CommentsOptions, type ConfirmOptions, type DocLine, type DupGuard, type ElProps, type GameIdEditorOptions, type IconName, type IconSvgName, type Identity, type IdentityOptions, type JobProgressOptions, type JobProgressView, type NavHistory, type NavHistoryOptions, type Notes, type NotesEditorOptions, PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, type PaneShell, type PaneShellOptions, type PaneShellState, type PaneSide, type PaneSideConfig, type PinButton, type PinButtonOptions, type PropertyRefOptions, RESERVED_PROPERTY_NAMES, type SaveController, type SaveControllerOptions, type SaveIndicator, type SaveStatus, type SettingsDialog, type SettingsDialogOptions, type SettingsSection, type SettingsSectionHandle, type ShardVc, type StaleBarOptions, type StepperBarOptions, type StepperItem, type StepperTone, type TipRect, type ToastKind, type ToastOptions, type TooltipOptions, type VcMap, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dismissToast, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, toast, vcBadgeFor };
package/dist/index.d.ts CHANGED
@@ -150,6 +150,11 @@ interface PaneSideConfig {
150
150
  label?: string;
151
151
  /** Shortcut hint appended to the tooltip, e.g. "Cmd+1". */
152
152
  shortcutHint?: string;
153
+ /** false = the pane is not offered at all: no toggle, togglePane ignored,
154
+ * forced closed whatever the remembered state says. For a slot a host has
155
+ * retired but keeps mounted (Storyletter's inspector) - the shell used to
156
+ * offer a chevron that opened a paneful of nothing. Default true. */
157
+ offered?: boolean;
153
158
  }
154
159
  interface PaneShellState {
155
160
  open: Record<PaneSide, boolean>;
@@ -780,6 +785,25 @@ interface StaleBarOptions {
780
785
  }
781
786
  declare function staleBar(opts: StaleBarOptions): HTMLElement;
782
787
 
788
+ /** What the remark is about. `info` is the plain case; `ok` says a thing you
789
+ * asked for happened; `error` says it did not. */
790
+ type ToastKind = "info" | "ok" | "error";
791
+ interface ToastOptions {
792
+ /** How long it stays, in ms, before the exit plays. Defaults to 4000, or
793
+ * 7000 for an error. */
794
+ duration?: number;
795
+ }
796
+ /**
797
+ * Show a toast. Replaces any toast already showing.
798
+ *
799
+ * `message` is shown as written; a newline breaks the line ("Bundle
800
+ * published\n<path>"), and a long unbroken token such as a path wraps inside
801
+ * the card rather than spilling past it.
802
+ */
803
+ declare function toast(message: string, kind?: ToastKind, opts?: ToastOptions): void;
804
+ /** Dismiss the current toast now, if any. Plays the exit. */
805
+ declare function dismissToast(): void;
806
+
783
807
  interface StepperItem {
784
808
  /**
785
809
  * One word for what kind of thing this is: "error", "comment", "resolved".
@@ -876,4 +900,4 @@ declare function historyNav(onBack: () => void, onForward: () => void): {
876
900
  set(canBack: boolean, canForward: boolean): void;
877
901
  };
878
902
 
879
- export { type AboutOptions, type AnchoredPanel, type AnchoredPanelOptions, type Child, type Comment, type CommentMessage, type CommentsOptions, type ConfirmOptions, type DocLine, type DupGuard, type ElProps, type GameIdEditorOptions, type IconName, type IconSvgName, type Identity, type IdentityOptions, type JobProgressOptions, type JobProgressView, type NavHistory, type NavHistoryOptions, type Notes, type NotesEditorOptions, PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, type PaneShell, type PaneShellOptions, type PaneShellState, type PaneSide, type PaneSideConfig, type PinButton, type PinButtonOptions, type PropertyRefOptions, RESERVED_PROPERTY_NAMES, type SaveController, type SaveControllerOptions, type SaveIndicator, type SaveStatus, type SettingsDialog, type SettingsDialogOptions, type SettingsSection, type SettingsSectionHandle, type ShardVc, type StaleBarOptions, type StepperBarOptions, type StepperItem, type StepperTone, type TipRect, type TooltipOptions, type VcMap, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, vcBadgeFor };
903
+ export { type AboutOptions, type AnchoredPanel, type AnchoredPanelOptions, type Child, type Comment, type CommentMessage, type CommentsOptions, type ConfirmOptions, type DocLine, type DupGuard, type ElProps, type GameIdEditorOptions, type IconName, type IconSvgName, type Identity, type IdentityOptions, type JobProgressOptions, type JobProgressView, type NavHistory, type NavHistoryOptions, type Notes, type NotesEditorOptions, PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, type PaneShell, type PaneShellOptions, type PaneShellState, type PaneSide, type PaneSideConfig, type PinButton, type PinButtonOptions, type PropertyRefOptions, RESERVED_PROPERTY_NAMES, type SaveController, type SaveControllerOptions, type SaveIndicator, type SaveStatus, type SettingsDialog, type SettingsDialogOptions, type SettingsSection, type SettingsSectionHandle, type ShardVc, type StaleBarOptions, type StepperBarOptions, type StepperItem, type StepperTone, type TipRect, type ToastKind, type ToastOptions, type TooltipOptions, type VcMap, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dismissToast, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, toast, vcBadgeFor };
package/dist/index.js CHANGED
@@ -152,23 +152,23 @@ function initTooltips(opts = {}) {
152
152
 
153
153
  // src/dom.ts
154
154
  function el(tag, classNameOrProps, ...children) {
155
- const node = document.createElement(tag);
155
+ const node2 = document.createElement(tag);
156
156
  const props = typeof classNameOrProps === "string" ? { className: classNameOrProps } : classNameOrProps ?? {};
157
- if (props.className) node.className = props.className;
158
- if (props.text !== void 0 && props.text !== null) node.textContent = props.text;
159
- if (props.title !== void 0) node.title = props.title;
157
+ if (props.className) node2.className = props.className;
158
+ if (props.text !== void 0 && props.text !== null) node2.textContent = props.text;
159
+ if (props.title !== void 0) node2.title = props.title;
160
160
  if (props.tip !== void 0) {
161
- node.dataset["tip"] = props.tip;
162
- node.setAttribute("aria-label", props.tip);
161
+ node2.dataset["tip"] = props.tip;
162
+ node2.setAttribute("aria-label", props.tip);
163
163
  ensureTooltipHost();
164
164
  }
165
- if (props.onClick) node.addEventListener("click", props.onClick);
165
+ if (props.onClick) node2.addEventListener("click", props.onClick);
166
166
  for (const child of children) {
167
167
  if (child === null || child === void 0) continue;
168
- node.append(child);
168
+ node2.append(child);
169
169
  }
170
170
  checkTooltipHost();
171
- return node;
171
+ return node2;
172
172
  }
173
173
  function iconBtn(glyph, title, onClick, disabled = false, danger = false) {
174
174
  const b = el("button", `shell-icon${danger ? " danger" : ""}`);
@@ -200,7 +200,7 @@ function tagChips(holder, onChange) {
200
200
  const wrap = el("div", "shell-tags");
201
201
  const input = el("input", "shell-tag-input");
202
202
  input.type = "text";
203
- input.placeholder = "add value";
203
+ input.placeholder = "Add value";
204
204
  input.spellcheck = false;
205
205
  const makeChip = (v) => {
206
206
  const chip = el("span", "shell-tag", v);
@@ -336,7 +336,11 @@ var openVar = { nav: "--nav-open-w", inspector: "--insp-open-w" };
336
336
  var collapseClass = { nav: "no-nav", inspector: "no-inspector" };
337
337
  function mountPaneShell(host, opts) {
338
338
  const cfg = { nav: opts.nav, inspector: opts.inspector };
339
- const open = { nav: opts.initial?.open?.nav ?? true, inspector: opts.initial?.open?.inspector ?? true };
339
+ const offered = (side) => cfg[side].offered !== false;
340
+ const open = {
341
+ nav: offered("nav") && (opts.initial?.open?.nav ?? true),
342
+ inspector: offered("inspector") && (opts.initial?.open?.inspector ?? true)
343
+ };
340
344
  const width = { ...opts.initial?.width ?? {} };
341
345
  const el2 = (tag, cls) => {
342
346
  const n = document.createElement(tag);
@@ -366,6 +370,8 @@ function mountPaneShell(host, opts) {
366
370
  const root = el2("div", "pane-shell");
367
371
  root.append(topbar, panes);
368
372
  host.append(root);
373
+ if (!offered("nav")) navToggle.remove();
374
+ if (!offered("inspector")) inspToggle.remove();
369
375
  function applyToggleGlyph(side, button) {
370
376
  const isOpen = open[side];
371
377
  button.textContent = side === "nav" ? isOpen ? "\u2039" : "\u203A" : isOpen ? "\u203A" : "\u2039";
@@ -382,8 +388,8 @@ function mountPaneShell(host, opts) {
382
388
  panes.style.setProperty(openVar.inspector, width.inspector !== void 0 ? `${width.inspector}px` : cfg.inspector.defaultWidth);
383
389
  applyToggleGlyph("nav", navToggle);
384
390
  applyToggleGlyph("inspector", inspToggle);
385
- navResizer.style.display = cfg.nav.resizable === false ? "none" : "";
386
- inspResizer.style.display = cfg.inspector.resizable === false ? "none" : "";
391
+ navResizer.style.display = cfg.nav.resizable === false || !offered("nav") ? "none" : "";
392
+ inspResizer.style.display = cfg.inspector.resizable === false || !offered("inspector") ? "none" : "";
387
393
  }
388
394
  const snapshot = () => ({ open: { ...open }, width: { ...width } });
389
395
  const persist = () => opts.onChange?.(snapshot());
@@ -394,7 +400,7 @@ function mountPaneShell(host, opts) {
394
400
  persist();
395
401
  }
396
402
  function togglePane(side) {
397
- setPaneOpen(side, !open[side]);
403
+ if (offered(side)) setPaneOpen(side, !open[side]);
398
404
  }
399
405
  function resetWidths() {
400
406
  delete width.nav;
@@ -658,14 +664,14 @@ function closeWithExit(element, done) {
658
664
  if (fired) return;
659
665
  fired = true;
660
666
  element.removeEventListener("animationend", onEnd);
661
- clearTimeout(timer2);
667
+ clearTimeout(timer3);
662
668
  done();
663
669
  };
664
670
  const onEnd = (e) => {
665
671
  if (e.target === element) finish();
666
672
  };
667
673
  element.addEventListener("animationend", onEnd);
668
- const timer2 = setTimeout(finish, seconds * 1e3 + 120);
674
+ const timer3 = setTimeout(finish, seconds * 1e3 + 120);
669
675
  }
670
676
 
671
677
  // src/confirm.ts
@@ -1505,7 +1511,7 @@ function createSaveController(opts) {
1505
1511
  let auto = true;
1506
1512
  let dirty = false;
1507
1513
  let dirtySince = 0;
1508
- let timer2;
1514
+ let timer3;
1509
1515
  let inFlight;
1510
1516
  const setStatus = (next) => {
1511
1517
  if (next === status) return;
@@ -1513,17 +1519,17 @@ function createSaveController(opts) {
1513
1519
  opts.onStatus?.(status);
1514
1520
  };
1515
1521
  const clearTimer = () => {
1516
- if (timer2 === void 0) return;
1517
- clearTimeout(timer2);
1518
- timer2 = void 0;
1522
+ if (timer3 === void 0) return;
1523
+ clearTimeout(timer3);
1524
+ timer3 = void 0;
1519
1525
  };
1520
1526
  const arm = () => {
1521
1527
  clearTimer();
1522
1528
  if (!auto) return;
1523
1529
  const deadline = dirtySince + maxWaitMs;
1524
1530
  const wait = Math.max(0, Math.min(delayMs, deadline - Date.now()));
1525
- timer2 = setTimeout(() => {
1526
- timer2 = void 0;
1531
+ timer3 = setTimeout(() => {
1532
+ timer3 = void 0;
1527
1533
  void run();
1528
1534
  }, wait);
1529
1535
  };
@@ -1597,13 +1603,13 @@ var WORDS = {
1597
1603
  unsaved: "Unsaved"
1598
1604
  };
1599
1605
  function saveIndicator(initial = "saved") {
1600
- const node = el("span");
1606
+ const node2 = el("span");
1601
1607
  const set = (status) => {
1602
- node.className = `savestat ${status}`;
1603
- node.textContent = WORDS[status];
1608
+ node2.className = `savestat ${status}`;
1609
+ node2.textContent = WORDS[status];
1604
1610
  };
1605
1611
  set(initial);
1606
- return { el: node, set };
1612
+ return { el: node2, set };
1607
1613
  }
1608
1614
 
1609
1615
  // src/stale.ts
@@ -1624,6 +1630,43 @@ function staleBar(opts) {
1624
1630
  );
1625
1631
  }
1626
1632
 
1633
+ // src/toast.ts
1634
+ var DURATION = { info: 4e3, ok: 4e3, error: 7e3 };
1635
+ var node;
1636
+ var timer2 = 0;
1637
+ var seq = 0;
1638
+ function mount() {
1639
+ if (node && node.isConnected) return node;
1640
+ node = el("div", { className: "shell-toast" });
1641
+ node.setAttribute("role", "status");
1642
+ node.setAttribute("aria-live", "polite");
1643
+ node.hidden = true;
1644
+ document.body.append(node);
1645
+ return node;
1646
+ }
1647
+ function toast(message, kind = "info", opts = {}) {
1648
+ const t = mount();
1649
+ const id = ++seq;
1650
+ t.textContent = message;
1651
+ t.className = `shell-toast ${kind}`;
1652
+ t.hidden = false;
1653
+ window.clearTimeout(timer2);
1654
+ timer2 = window.setTimeout(() => {
1655
+ closeWithExit(t, () => {
1656
+ if (seq === id) t.hidden = true;
1657
+ });
1658
+ }, opts.duration ?? DURATION[kind]);
1659
+ }
1660
+ function dismissToast() {
1661
+ if (!node || node.hidden) return;
1662
+ window.clearTimeout(timer2);
1663
+ const id = seq;
1664
+ const t = node;
1665
+ closeWithExit(t, () => {
1666
+ if (seq === id) t.hidden = true;
1667
+ });
1668
+ }
1669
+
1627
1670
  // src/stepper.ts
1628
1671
  function renderStepperBar(host, opts) {
1629
1672
  const { items } = opts;
@@ -1746,6 +1789,6 @@ function historyNav(onBack, onForward) {
1746
1789
  };
1747
1790
  }
1748
1791
 
1749
- export { PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, RESERVED_PROPERTY_NAMES, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, vcBadgeFor };
1792
+ export { PALETTE, PALETTE_SIZE, PROPERTY_NAME_HINT, RESERVED_PROPERTY_NAMES, askIdentity, bindPropertyName, bindPropertyRef, closeAnchoredPanel, closeWithExit, colourFor, colourIndex, confirmDialog, createNavHistory, createSaveController, dismissToast, dupGuard, el, expandableRow, firstIllegalPropertyName, focusNewRow, foldVc, gameIdify, hideTip, historyNav, icon, iconBtn, iconSvg, initTooltips, isCaseOnlyPropertyName, isValidGameId, isValidPropertyName, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, propertyNameProblem, propertyNameify, propertyRefProblem, renderStepperBar, revalidatePropertyRefs, saveIndicator, showAbout, staleBar, tagChips, tipAt, tipBold, toast, vcBadgeFor };
1750
1793
  //# sourceMappingURL=index.js.map
1751
1794
  //# sourceMappingURL=index.js.map