@synopackageland/ui 0.23.9 → 0.25.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,59 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.25.1 (2026-11-09)
6
+
7
+ Wizard additions: a result step with an outcome, a progress step for work the app watches, guard redirects that drop a stale reply, and a centred WizardDialog on a phone. Also touch press feedback on a phone. Existing `done` steps and guards behave as before; see the migration notes for an App with exhaustive types, a guard that moved the wizard itself, or phone screenshots of a WizardDialog.
8
+
9
+ ### Wizard
10
+
11
+ - **`type="result"`** with `result-tone` (`success`, `warning`, `danger`, `neutral`; default `neutral`): a closing step that shows the outcome's mark and colour, read as "Succeeded", "Warning", "Failed" or "Done", with no ring and no burst. Finish is the one blue action; there is no Back or Cancel. The guide marks a warning or a failure in its colour (`data-state="warning"`/`"error"`) and reads it so, never as completed. A result step ignores `next-step-key` (a development warning says so). `done` is unchanged
12
+ - **`type="progress"`** with `progress` (`{ mode: 'indeterminate', label, status? }` or `{ mode: 'determinate', label, value, max, valueLabel?, status? }`): the existing `Progress` bar on its tinted track and a polite status line. No Next or Back unless `show-next`/`show-back` is `true`. `stop-label` adds a secondary button that emits `stop`; `stop-disabled` disables it. The wizard runs no work, polls nothing and has no timeout
13
+ - **Guard redirects.** A guard receives `{ from, direction, signal }` and may return `{ goTo: 'key' }` to move to another registered step (a `v-if` step it just mounted too) through the usual events and focus. An unknown or the same key keeps the step and emits the new `navigation-error` (`unknown-step`, `same-step`); a guard that throws or rejects keeps the step and emits `guard-rejected` (it used to reject the press's promise). Guards without arguments returning `false` or nothing still fit
14
+ - **Pending moves are dropped** when the wizard leaves the step, is reset to another step, closes (`WizardDialog`, not while "Keep editing" is asked) or unmounts: the guard's `signal` aborts, the spinner stops at once, and a late reply moves nothing and emits nothing. `Wizard` exposes `cancelPending()`
15
+ - New types: `WizardGuard`, `WizardGuardContext`, `WizardGuardResult`, `WizardNavigationError`, `WizardProgress`, `WizardResultTone`; `WizardStepType` adds `progress` and `result`
16
+ - **`WizardDialog` is a centred modal on a phone** (`presentation="modal"`, the new default), with the phone's 24px dialog corner and dim scrim; `presentation="adaptive"` keeps the bottom sheet. Its "Discard changes?" question is always centred. On a phone it is as tall as its step, up to its height inside the safe area, and only a longer step scrolls in the body under a fixed header and footer. `Dialog` takes the same `presentation` prop (default `adaptive`, so other dialogs are unchanged); a `modal` one on a phone treats `height` as a cap
17
+ - **The wizard's name lines up with the step title.** A `WizardDialog`'s header now takes the wizard's own margin (24px, 16px when narrow), so the name no longer starts 8px right of the title in a small window or on a phone
18
+ - docs/wizard.md: Result, Progress and Guards sections, and recipes for backend branches, two equal choices with one confirm, handing over between wizards, watching work, opening another DSM app, and what is not provided. Choice cards: 2–4 is a guide, not a limit (also README and layout rules)
19
+
20
+ ### Touch phone
21
+
22
+ - **Press feedback.** On a touch phone a Button or an IconButton takes the `--ui-state-pressed` layer over its own active colour and settles to `scale(0.98)` in 100ms (`cubic-bezier(0.24, 1, 0.4, 1)`). A ghost and a link button take no second layer; a list row, a tab and a menu item keep the layer alone; disabled controls take nothing. Reduced motion and `data-ui-motion="off"` keep the layer without the scale. A transform only, so nothing moves around the control. A DSM window, a desktop page and a touch tablet are unchanged
23
+
24
+ ### Migration notes
25
+
26
+ - An exhaustive `switch` or `Record<WizardStepType, …>` needs `progress` and `result`
27
+ - A guard that set `active-step-key` itself and then returned nothing used to move on as the step said too; the change of step now drops the move. Return `{ goTo }` instead
28
+ - A guard that throws no longer rejects the main action's promise; listen to `navigation-error`
29
+ - Phone screenshots of a `WizardDialog` need new baselines, or set `presentation="adaptive"`
30
+
31
+ ## 0.25.0 (2026-11-09)
32
+
33
+ A softer, less boxy look everywhere. On a touch phone: a pale page with white frameless cards, round corners (cards 20px, fields 12px, sheets and dialogs 24px, buttons and segmented controls capsules), a 16px gutter and card inset, 15px text on a 22px line, inset grouped lists, a floating pill tab bar and an ink segmented control. In a DSM window and on a full page: rounder corners by role, one solid focus ring, a white mist (window) or blue-grey (full page) behind a modal, dialog rules only where the body scrolls, a tighter card header, underlined tabs on a full page and a neutral hover layer. The phone takes the focus ring and the hover layer too, and keeps its own corners, spacing, tabs and scrim. No API change and no App change is required; an App with pixel snapshots needs new baselines.
34
+
35
+ ### Touch phone
36
+
37
+ - New `src/theme/phone.css` (in every theme), all inside `@media (pointer: coarse)` and scoped to the phone presentation. docs/mobile-native.md, "Phone look", lists every value before and after
38
+ - Phone tokens: `--ui-font-size` 15 (was 14), `-sm` 13 (12), `-lg` 17 (15), `-title` 17 (16), `--ui-line-height` 22 (20), `--ui-page-padding-x` 16 (12), `--ui-section-gap` 16 (12), `--ui-card-padding` 16 (12), `--ui-radius-md` 12 (4) and `-lg` 14 (6), which the 0.23.9 roles follow (control, container and popover 12; panel and nav 14), `-dialog`/`-window`/`-sheet` 24 (8/8/12); new `--ui-radius-card` 20, `--ui-phone-ink`, `--ui-phone-separator`, `--ui-tab-bar-float` 8
39
+ - Contrast (WCAG AA): phone muted text is 80% grey (4.8:1 on the page; it was 2:1) and 62% in dark (5.7:1); a primary button's fill is the accent's step 10 (4.6:1 with its white label; step 9 was 4.0:1)
40
+ - Tap boxes stay 44px; hide on scroll, the commit footer, the FAB and the end space are unchanged (the FAB, a toast and the page end follow the floating tab bar's 8px gap)
41
+ - Every phone page is on the mist, not only a page of cards (a list, a live and a record page too; a data-grid page and `surface="none"` keep their own). A sticky row and a heading painted with `--ui-app-web-surface` follow the page's colour
42
+ - A list of ListItems on the page (`role="list"`, `ul` or `ol` holding only ListItems, outside a card, sheet or dialog) is an inset grouped list: a white group with the card's corner, rows inset 16px, straight hairlines from the text's edge, and the heading right above it on the rows' text. ListItem separators are straight everywhere (a rounded row bent its top border)
43
+ - Segmented control on a phone: 6px sides and the selected label keeps its weight; up to three segments stay equal columns but one whose label is wider than its share grows to it (the others share the rest), so a label is not cut; four keep equal columns that ellipsize ("Transcript 45" in a three-way control at 390)
44
+ - `check:phone-layout` fails when a label in a segmented control of up to three truncates; the record fixture's view control is a three-way one with a count
45
+ - `tests/css/hit-slop-component-edge.test.ts` expects the phone's 16px gutter
46
+
47
+ ### DSM window and full page
48
+
49
+ - **Corners by role** ([theme hooks](docs/theme-hooks.md#corner-radius)). DSM window: `inner` 4px (was 3), `control` 6 (4), `container` 8 (4), `popover` 8 (4), `panel` 8 (5), `nav` 6 (5), `window` 10 (3), `dialog` 10 (6). Full page: `inner` 6 (3), `control` 8 (4), `container` 10 (4), `popover` 10 (4), `panel` 12 (6), `nav` 8 (6), `window` 14 (8), `dialog` 14 (8). A menu row stays concentric with its menu. New `--ui-radius-callout` (window 10, web and mobile 12) for a Callout and a Toast; `--ui-callout-radius` still wins. The mobile presentation keeps its roles on the steps, so a touch phone's steps (below) round them. The steps `--ui-radius-sm/md/lg` keep 3/4/5px. The rule "no corner more than 2px rounder than a card" is retired; the theme hooks list the pre-0.25 values for an App that wants them back
50
+ - **One solid focus ring.** `--ui-focus-ring` is the accent itself (was 45% of it); `--ui-shadow-focus` is a 2px surface gap and a 2px ring (was 1px and 2px). New `--ui-shadow-focus-inset` (a row, a cell, a tab) and `--ui-shadow-focus-field` (a field: its border turns primary with a 3px `--ui-focus-halo` halo). The 61 rings written out in components and theme CSS now use these tokens (`tests/css/focus-ring.test.ts`)
51
+ - **Scrim.** A DSM window mists the page in white at 55% behind a modal (was black 40% with a 1px blur; the blur is gone everywhere). A full page dims in `--ui-overlay-page`, a blue-grey at 32%. The mobile presentation keeps black 40% (`--ui-overlay-dim`); dark is unchanged
52
+ - **Dialog rules.** The header rule shows only once the body has scrolled under it, and the footer rule only while more lies below; a `flush` body keeps both. `useScrollEdges` now follows a scroller that renders after mount
53
+ - **Card.** Under a header the body starts at the header's own 12px below the title (was 12 + 16px), so the title reads with its content. A card without a header is unchanged
54
+ - **Tabs on a full page.** A 2px accent underline under the selected tab (sliding like the notch); unselected tabs are 500, and each tab reserves its bold width (`data-ui-tab-label`) so the row does not shift. A DSM window and the mobile presentation keep DSM's notch and bold labels
55
+ - **State layer.** New `--ui-state-hover` (6% of the text colour) and `--ui-state-pressed` (8%). A ghost `Button` and `IconButton` and the rows of `DropdownMenu` and `ContextMenu` use them instead of the pale-blue hover and the accent highlight. Lists, tables and `Select` lists keep DSM's pale-blue row hover. `--ui-pressed` is now a deprecated alias of `--ui-state-pressed`
56
+ - **Popups** drop 6px from their trigger and settle from 96% (were 4px and 97%)
57
+
5
58
  ## 0.23.9 (2026-11-08)
6
59
 
7
60
  Semantic corner radius tokens, with no visual change. Each role resolves to the step it replaces, so every corner keeps its size in a DSM window, on the web and on a phone.
package/README.md CHANGED
@@ -530,7 +530,7 @@ Primitives:
530
530
 
531
531
  - Button (`danger-outline` for a destructive choice beside the main action) / IconButton / CopyButton
532
532
  - Input / Textarea
533
- - Checkbox / CheckboxGroup / RadioGroup / Switch — use RadioGroup for 2–4 mutually exclusive settings; Checkbox for independent options; Switch for immediate on/off. Reserve primary-filled, capsule-shaped SegmentControl for toolbar views ([choice policy](docs/layout-rules.md)); a `SegmentItem` takes a `count`, and a row of more views than fit scrolls sideways.
533
+ - Checkbox / CheckboxGroup / RadioGroup / Switch — use RadioGroup for mutually exclusive settings (choice cards suit 2–4 options with an icon and a line each; that is a guide, not a limit, and more short options read better as a vertical list); Checkbox for independent options; Switch for immediate on/off. Reserve primary-filled, capsule-shaped SegmentControl for toolbar views ([choice policy](docs/layout-rules.md)); a `SegmentItem` takes a `count`, and a row of more views than fit scrolls sideways.
534
534
  - Select
535
535
  - Badge (`dot` leads any tone with the dot) / StatusDot / Separator / Spinner / LoadingMask / LoadingArea / Progress / SizeBar / Skeleton / Surface
536
536
  - SplitButton
package/dist/cli.js CHANGED
File without changes
@@ -1,4 +1,4 @@
1
- import { WizardFooterConfig, WizardStepChange, WizardStepper } from './types';
1
+ import { WizardFooterConfig, WizardNavigationError, WizardStepChange, WizardStepper } from './types';
2
2
  type __VLS_Props = {
3
3
  /** Initial / external reset key. Internal navigation keeps working when the caller does not bind it back. */
4
4
  activeStepKey?: string;
@@ -25,11 +25,13 @@ type __VLS_Props = {
25
25
  railMinWidth?: number;
26
26
  progressText?: (current: number, total: number) => string;
27
27
  };
28
+ /** Drops the pending move, if any: its guard's signal aborts and its reply is ignored. */
29
+ declare function cancelPending(): void;
28
30
  declare function toNextStep(): Promise<void>;
29
31
  declare function toPreviousStep(): Promise<void>;
30
32
  declare function finish(): Promise<void>;
31
33
  declare function cancel(): void;
32
- declare var __VLS_6: {}, __VLS_14: {
34
+ declare var __VLS_16: {}, __VLS_24: {
33
35
  nextStep: typeof toNextStep;
34
36
  previousStep: typeof toPreviousStep;
35
37
  finish: typeof finish;
@@ -40,9 +42,9 @@ declare var __VLS_6: {}, __VLS_14: {
40
42
  stepKey: string;
41
43
  };
42
44
  type __VLS_Slots = {} & {
43
- default?: (props: typeof __VLS_6) => any;
45
+ default?: (props: typeof __VLS_16) => any;
44
46
  } & {
45
- footer?: (props: typeof __VLS_14) => any;
47
+ footer?: (props: typeof __VLS_24) => any;
46
48
  };
47
49
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
48
50
  activeStepKey: import('vue').ComputedRef<string>;
@@ -55,18 +57,21 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
55
57
  toPreviousStep: typeof toPreviousStep;
56
58
  finish: typeof finish;
57
59
  cancel: typeof cancel;
60
+ cancelPending: typeof cancelPending;
58
61
  }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
59
62
  cancel: () => any;
60
63
  finished: () => any;
61
64
  "update:activeStepKey": (key: string) => any;
62
65
  "next-step": (change: WizardStepChange) => any;
63
66
  "previous-step": (change: WizardStepChange) => any;
67
+ "navigation-error": (error: WizardNavigationError) => any;
64
68
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
65
69
  onCancel?: (() => any) | undefined;
66
70
  onFinished?: (() => any) | undefined;
67
71
  "onUpdate:activeStepKey"?: ((key: string) => any) | undefined;
68
72
  "onNext-step"?: ((change: WizardStepChange) => any) | undefined;
69
73
  "onPrevious-step"?: ((change: WizardStepChange) => any) | undefined;
74
+ "onNavigation-error"?: ((error: WizardNavigationError) => any) | undefined;
70
75
  }>, {
71
76
  footer: WizardFooterConfig;
72
77
  fit: boolean;
@@ -15,12 +15,14 @@ type __VLS_Props = {
15
15
  closeOnFinish?: boolean;
16
16
  /** `true` asks "Keep editing / Discard" before the close button, Escape or Cancel closes the wizard; `false` closes at once. Finish never asks. */
17
17
  confirmClose?: boolean;
18
+ /** `modal` (default) is a centred window everywhere, a phone included; `adaptive` is a bottom sheet on a phone. */
19
+ presentation?: 'modal' | 'adaptive';
18
20
  };
19
- declare var __VLS_9: {}, __VLS_20: {};
21
+ declare var __VLS_9: {}, __VLS_22: {};
20
22
  type __VLS_Slots = {} & {
21
23
  trigger?: (props: typeof __VLS_9) => any;
22
24
  } & {
23
- default?: (props: typeof __VLS_20) => any;
25
+ default?: (props: typeof __VLS_22) => any;
24
26
  };
25
27
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
26
28
  cancel: () => any;
@@ -35,6 +37,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
35
37
  defaultOpen: boolean;
36
38
  showClose: boolean;
37
39
  confirmClose: boolean;
40
+ presentation: "modal" | "adaptive";
38
41
  closeOnFinish: boolean;
39
42
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
40
43
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -1,4 +1,4 @@
1
- import { WizardStepProps } from './types';
1
+ import { WizardResultTone, WizardStepProps } from './types';
2
2
  type __VLS_Slots = {
3
3
  default?: () => unknown;
4
4
  /** A picture or a diagram at the top of the step, in place of the icon tile. */
@@ -8,7 +8,11 @@ type __VLS_Slots = {
8
8
  };
9
9
  declare const __VLS_base: import('vue').DefineComponent<WizardStepProps, {
10
10
  active: import('vue').ComputedRef<boolean>;
11
- }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<WizardStepProps> & Readonly<{}>, {
11
+ }, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
12
+ stop: () => any;
13
+ }, string, import('vue').PublicProps, Readonly<WizardStepProps> & Readonly<{
14
+ onStop?: (() => any) | undefined;
15
+ }>, {
12
16
  footer: boolean;
13
17
  type: import('./types').WizardStepType;
14
18
  lazy: boolean;
@@ -16,6 +20,8 @@ declare const __VLS_base: import('vue').DefineComponent<WizardStepProps, {
16
20
  nextDisabled: boolean;
17
21
  showNext: boolean;
18
22
  showBack: boolean;
23
+ resultTone: WizardResultTone;
24
+ stopDisabled: boolean;
19
25
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
20
26
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
27
  declare const _default: typeof __VLS_export;
@@ -1,9 +1,38 @@
1
1
  import { Component } from 'vue';
2
2
  /**
3
3
  * `'welcome'` is the entry step and only offers the forward action; `'done'`
4
- * is the closing step: a success hero, no Back or Cancel, and Finish.
4
+ * is the closing step of a flow that succeeded: a success hero, no Back or
5
+ * Cancel, and Finish. `'result'` is a closing step whose outcome the app sets
6
+ * with `resultTone` (success, warning, danger or neutral): no Back or Cancel,
7
+ * Finish, and no celebration. `'progress'` shows work the app runs and
8
+ * watches: a progress bar and a status line, with no Next or Back unless the
9
+ * step asks for them.
5
10
  */
6
- export type WizardStepType = 'normal' | 'welcome' | 'done';
11
+ export type WizardStepType = 'normal' | 'welcome' | 'done' | 'progress' | 'result';
12
+ /**
13
+ * The outcome a `type="result"` step reports. It sets the step's mark, its
14
+ * colour and what assistive technology reads; `neutral` (the default) claims
15
+ * neither success nor failure.
16
+ */
17
+ export type WizardResultTone = 'success' | 'warning' | 'danger' | 'neutral';
18
+ /**
19
+ * What a `type="progress"` step shows. `indeterminate` while the total is not
20
+ * known; `determinate` with a count. `status` is one line read politely by
21
+ * assistive technology when it changes. The wizard only draws it: the app runs
22
+ * and watches the work and moves the wizard on when the work ends.
23
+ */
24
+ export type WizardProgress = {
25
+ mode: 'indeterminate';
26
+ label: string;
27
+ status?: string;
28
+ } | {
29
+ mode: 'determinate';
30
+ label: string;
31
+ value: number;
32
+ max: number;
33
+ valueLabel?: string;
34
+ status?: string;
35
+ };
7
36
  /**
8
37
  * How the wizard shows its progress: a segmented bar beside the step title in
9
38
  * the header (`'auto'`, `'bar'`), a rail listing the steps beside the step
@@ -11,8 +40,39 @@ export type WizardStepType = 'normal' | 'welcome' | 'done';
11
40
  * "Step n of total" line (`'none'`). `'header'` is the bar, kept for 0.16.
12
41
  */
13
42
  export type WizardStepper = 'auto' | 'bar' | 'rail' | 'header' | 'none';
14
- /** A guard may return `false` (or resolve `false`) to block the step change. */
15
43
  export type MaybePromise<T> = T | Promise<T>;
44
+ /**
45
+ * What a step guard returns: `false` keeps the step, nothing moves on as
46
+ * the step says, and `{ goTo }` moves to that registered step instead, for
47
+ * this move only.
48
+ */
49
+ export type WizardGuardResult = void | false | {
50
+ goTo: string;
51
+ };
52
+ /**
53
+ * What a step guard receives. `signal` aborts when the move no longer
54
+ * matters: the wizard left the step, was reset to another one, closed or
55
+ * unmounted. A reply that comes after that is ignored.
56
+ */
57
+ export type WizardGuardContext = {
58
+ from: string;
59
+ direction: 'next' | 'previous';
60
+ signal: AbortSignal;
61
+ };
62
+ /** A step guard. A guard written without arguments, returning `false` or nothing, still fits. */
63
+ export type WizardGuard = (context: WizardGuardContext) => MaybePromise<WizardGuardResult>;
64
+ /**
65
+ * Why a move did not happen: the guard's `goTo` named a step that is not
66
+ * registered (`unknown-step`) or the step itself (`same-step`), or the guard
67
+ * threw or rejected (`guard-rejected`). The wizard stays on the step; the app
68
+ * shows its own message.
69
+ */
70
+ export type WizardNavigationError = {
71
+ from: string;
72
+ direction: 'next' | 'previous';
73
+ code: 'unknown-step' | 'same-step' | 'guard-rejected';
74
+ target?: string;
75
+ };
16
76
  export type WizardStepProps = {
17
77
  /** Unique key the wizard uses to identify this step. */
18
78
  stepKey: string;
@@ -25,15 +85,15 @@ export type WizardStepProps = {
25
85
  description?: string;
26
86
  /** An icon shown in a tile beside the description; the `#hero` slot replaces it with a picture or a diagram. */
27
87
  icon?: Component;
28
- /** Omitted on the final step: the forward button then becomes Apply. */
88
+ /** Omitted on the final step: the forward button then becomes Apply. A `result` step ignores it. */
29
89
  nextStepKey?: string | (() => string);
30
90
  /** Omitted falls back to the step registered just before this one. */
31
91
  previousStepKey?: string | (() => string);
32
- /** Async guard run before moving forward. `false` blocks the change. */
33
- preEnterNextStep?: () => MaybePromise<false | void>;
34
- /** Async guard run before moving back. `false` blocks the change. */
35
- preEnterPreviousStep?: () => MaybePromise<false | void>;
36
- /** Runs when the final Apply action succeeds. */
92
+ /** Guard run before moving forward: `false` keeps the step, `{ goTo }` moves to another step. */
93
+ preEnterNextStep?: WizardGuard;
94
+ /** Guard run before moving back: `false` keeps the step, `{ goTo }` moves to another step. */
95
+ preEnterPreviousStep?: WizardGuard;
96
+ /** Runs when the final Apply or Finish action is taken. */
37
97
  finished?: () => MaybePromise<void>;
38
98
  /** `false` hides the shared footer while this step is active. */
39
99
  footer?: boolean;
@@ -41,12 +101,20 @@ export type WizardStepProps = {
41
101
  nextLabel?: string;
42
102
  /** Disables the forward button, for a step that is not complete yet. */
43
103
  nextDisabled?: boolean;
44
- /** `false` hides the forward button, for a step that moves on by itself or through its own choices. */
104
+ /** `false` hides the forward button, for a step that moves on by itself or through its own choices. A `progress` step hides it unless this is `true`. */
45
105
  showNext?: boolean;
46
- /** `false` hides Back on this step. */
106
+ /** `false` hides Back on this step. A `progress` step hides it unless this is `true`. */
47
107
  showBack?: boolean;
48
- /** Renders the content only while the step is shown, instead of keeping it mounted for its form state. */
108
+ /** Renders the content only while the step is shown, instead of keeping it mounted for its form state. It does not start or stop any work of the app's. */
49
109
  lazy?: boolean;
110
+ /** A `progress` step's bar and status line; without it the step shows an indeterminate bar named by its headline. */
111
+ progress?: WizardProgress;
112
+ /** A `result` step's outcome; `neutral` when omitted. */
113
+ resultTone?: WizardResultTone;
114
+ /** A `progress` step's stop button label (such as "Stop watching" or "Cancel task"); the step emits `stop` when it is pressed. Without it there is no button. */
115
+ stopLabel?: string;
116
+ /** Disables the stop button, while the app waits for the backend to confirm it. */
117
+ stopDisabled?: boolean;
50
118
  };
51
119
  export type WizardFooterConfig = boolean | {
52
120
  startLabel?: string;
@@ -8,6 +8,8 @@ export type WizardStepRegistration = {
8
8
  slots: Slots;
9
9
  /** The step's element, which orders a step mounted later (a `v-if`) among the others. */
10
10
  element: () => HTMLElement | null | undefined;
11
+ /** Emits the step's `stop` (a `progress` step's stop button in the footer). */
12
+ stop: () => void;
11
13
  };
12
14
  /** Which way the wizard last moved, for the step's entrance. */
13
15
  export type WizardDirection = 'forward' | 'back' | undefined;
@@ -29,6 +29,8 @@ type __VLS_Props = {
29
29
  closeOnOutside?: boolean;
30
30
  /** The mask over the app behind: `dim` (default), `light` (a faint tint, as DSM leaves the window behind a wizard) or `none`. It blocks presses in each case. */
31
31
  scrim?: 'dim' | 'light' | 'none';
32
+ /** `adaptive` (default) is a bottom sheet on a phone and a centred window elsewhere; `modal` stays a centred window on a phone too, as a DSM wizard does. A `modal` phone dialog takes the phone's dim scrim instead of `light`. */
33
+ presentation?: 'adaptive' | 'modal';
32
34
  };
33
35
  declare var __VLS_15: {}, __VLS_18: {}, __VLS_20: {}, __VLS_23: {}, __VLS_38: {}, __VLS_86: {}, __VLS_99: {}, __VLS_107: {};
34
36
  type __VLS_Slots = {} & {
@@ -70,6 +72,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
70
72
  closeOnOutside: boolean;
71
73
  scrim: "dim" | "light" | "none";
72
74
  headerDivider: boolean;
75
+ presentation: "adaptive" | "modal";
73
76
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
74
77
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
75
78
  declare const _default: typeof __VLS_export;
@@ -3,7 +3,8 @@ export type ScrollEdgesAxis = 'x' | 'y' | 'both';
3
3
  /** Whether a scroller has more content before (`start`, `top`) or after
4
4
  * (`end`, `bottom`) what it shows. `axis` picks the horizontal pair (`x`, the
5
5
  * default), the vertical pair (`y`) or both. Follows scrolling and size
6
- * changes of the scroller and of its content. */
6
+ * changes of the scroller and of its content, and a scroller that renders
7
+ * after mount (a dialog's body) or is replaced. */
7
8
  export declare function useScrollEdges(viewport: Readonly<ShallowRef<HTMLElement | null>>, axis?: () => ScrollEdgesAxis): {
8
9
  start: import('vue').Ref<boolean, boolean>;
9
10
  end: import('vue').Ref<boolean, boolean>;
package/dist/grid.js CHANGED
@@ -3961,6 +3961,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
3961
3961
  Connecting: "Connecting",
3962
3962
  "Needs attention": "Needs attention",
3963
3963
  Failed: "Failed",
3964
+ Succeeded: "Succeeded",
3964
3965
  "Not set up": "Not set up",
3965
3966
  Unknown: "Unknown",
3966
3967
  "No connections": "No connections",
@@ -4223,6 +4224,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4223
4224
  Connecting: "連線中",
4224
4225
  "Needs attention": "需要處理",
4225
4226
  Failed: "失敗",
4227
+ Succeeded: "成功",
4226
4228
  "Not set up": "未設定",
4227
4229
  Unknown: "未知",
4228
4230
  "No connections": "尚無連線",
@@ -4484,6 +4486,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4484
4486
  Connecting: "连接中",
4485
4487
  "Needs attention": "需要处理",
4486
4488
  Failed: "失败",
4489
+ Succeeded: "成功",
4487
4490
  "Not set up": "未设置",
4488
4491
  Unknown: "未知",
4489
4492
  "No connections": "暂无连接",
@@ -4745,6 +4748,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4745
4748
  Connecting: "接続中",
4746
4749
  "Needs attention": "対応が必要",
4747
4750
  Failed: "失敗",
4751
+ Succeeded: "成功",
4748
4752
  "Not set up": "未設定",
4749
4753
  Unknown: "不明",
4750
4754
  "No connections": "接続はありません",
@@ -5006,6 +5010,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5006
5010
  Connecting: "연결 중",
5007
5011
  "Needs attention": "확인 필요",
5008
5012
  Failed: "실패",
5013
+ Succeeded: "성공",
5009
5014
  "Not set up": "설정 안 됨",
5010
5015
  Unknown: "알 수 없음",
5011
5016
  "No connections": "연결 없음",
@@ -5267,6 +5272,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5267
5272
  Connecting: "Verbindung wird hergestellt",
5268
5273
  "Needs attention": "Aktion erforderlich",
5269
5274
  Failed: "Fehlgeschlagen",
5275
+ Succeeded: "Erfolgreich",
5270
5276
  "Not set up": "Nicht eingerichtet",
5271
5277
  Unknown: "Unbekannt",
5272
5278
  "No connections": "Keine Verbindungen",
@@ -5528,6 +5534,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5528
5534
  Connecting: "Connexion en cours",
5529
5535
  "Needs attention": "Action requise",
5530
5536
  Failed: "Échec",
5537
+ Succeeded: "Réussi",
5531
5538
  "Not set up": "Non configuré",
5532
5539
  Unknown: "Inconnu",
5533
5540
  "No connections": "Aucune connexion",
@@ -5789,6 +5796,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5789
5796
  Connecting: "Conectando",
5790
5797
  "Needs attention": "Requiere atención",
5791
5798
  Failed: "Fallido",
5799
+ Succeeded: "Correcto",
5792
5800
  "Not set up": "Sin configurar",
5793
5801
  Unknown: "Desconocido",
5794
5802
  "No connections": "Sin conexiones",
@@ -6050,6 +6058,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
6050
6058
  Connecting: "Connessione in corso",
6051
6059
  "Needs attention": "Richiede attenzione",
6052
6060
  Failed: "Non riuscito",
6061
+ Succeeded: "Riuscito",
6053
6062
  "Not set up": "Non configurato",
6054
6063
  Unknown: "Sconosciuto",
6055
6064
  "No connections": "Nessuna connessione",
@@ -123,6 +123,7 @@ export declare const englishUiText: {
123
123
  readonly Connecting: "Connecting";
124
124
  readonly "Needs attention": "Needs attention";
125
125
  readonly Failed: "Failed";
126
+ readonly Succeeded: "Succeeded";
126
127
  readonly "Not set up": "Not set up";
127
128
  readonly Unknown: "Unknown";
128
129
  readonly "No connections": "No connections";
package/dist/index.d.ts CHANGED
@@ -233,7 +233,7 @@ export { messageBoxKey } from './components/composite/message-box/types';
233
233
  export { default as Wizard } from './components/composite/wizard/Wizard.vue';
234
234
  export { default as WizardStep } from './components/composite/wizard/WizardStep.vue';
235
235
  export { default as WizardDialog } from './components/composite/wizard/WizardDialog.vue';
236
- export type { WizardFooterConfig, WizardStepChange, WizardStepProps, WizardStepType, WizardStepper } from './components/composite/wizard/types';
236
+ export type { WizardFooterConfig, WizardGuard, WizardGuardContext, WizardGuardResult, WizardNavigationError, WizardProgress, WizardResultTone, WizardStepChange, WizardStepProps, WizardStepType, WizardStepper } from './components/composite/wizard/types';
237
237
  export { default as AboutDialog } from './components/composite/about-dialog/AboutDialog.vue';
238
238
  export type { AboutCheckState, AboutVersionInfo } from './components/composite/about-dialog/types';
239
239
  export { default as AppRoot } from './components/app/app-root/AppRoot.vue';