vue-dockable-desktop 1.7.2 → 1.8.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
@@ -11,6 +11,108 @@ correspondence lives, alongside the feature-by-feature map in [docs/PARITY.md](d
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [1.8.1] — 2026-10-05
15
+
16
+ **Parity: react-dockable-desktop 7.7.1.** Two desktops on one page no longer strip each other's
17
+ skin.
18
+
19
+ ### Fixed
20
+
21
+ - **Unmounting one desktop stripped `<html>` of the other's skin, animations opt-out and stacking
22
+ base** (`data-vdd-skin`, `vdd-no-animations`, `--vdd-z-base`), and each desktop overwrote the
23
+ other's while both were mounted. The most recently mounted desktop now decides these, and
24
+ unmounting it hands them back to the others instead of removing them. Teleported chrome (menus,
25
+ toasts, flyouts, modals) therefore follows the newest desktop's skin when two desktops use
26
+ different skins.
27
+
28
+ rdd 7.7.1 also fixed panel DOM, sizes and lifecycle handlers shared between workspaces. None of it
29
+ applied here: vdd's panel cache has been per desktop from the start.
30
+
31
+ ### Internal
32
+
33
+ Faster checks, the same checks. Nothing in the published package changes.
34
+
35
+ - **`npm run verify`** — types, lint and the test suite, about a minute: the check to run while
36
+ working. **`npm run gate:release`** — the coverage sweep, then every milestone gate M1–M17 in
37
+ one call: the check to run before a release.
38
+ - **`npm run gate -- M13 M15 M16`** runs several milestones on one standing gate (types, lint,
39
+ tests, build…) instead of repeating it for each. Each step's time is recorded in
40
+ `artifacts/M<n>/gate.json`.
41
+ - **The branding gates wait for the page to be still instead of sleeping.** A scene, the overlays
42
+ and each hover now wait until nothing is animating or changing, with the old sleep as the
43
+ ceiling; the wait after the pointer leaves a control stays fixed, since the timers it starts are
44
+ invisible to such a check. M16 checks its three corner scales on one page per scene, and no
45
+ longer runs the hover walk for corners, which never read it. M15 captures a scene twice only
46
+ for an unexpected difference. Rewriting both baselines with the new code gave byte-identical
47
+ fixtures.
48
+ - **The baselines key elements by library class, not position**, so a new wrapper element no
49
+ longer renames everything after it (this release's dialog row renamed a whole modal). Both
50
+ fixtures were regenerated once: every scene has the same entries with identical values, under
51
+ the new keys.
52
+ - **`gate:selftest` leaves the tree fresh**: it rebuilds `dist/` and re-runs the coverage sweep at
53
+ the end, so a following M13 never reads the report a seeded violation left behind.
54
+ - **Three stale milestone rules updated** ([0020](docs/decisions/0020-stale-milestone-rules.md)):
55
+ M2 still required `src/core/rtl.ts`, deleted at M13 as dead code; M5 looked for the window clamp
56
+ where it no longer lives; M6 expected the pre-1.1.2 side for an RTL tab drop. Each keeps its
57
+ intent and checks today's code, and the new M2 and M5 rules have seeded violations in the
58
+ selftest (100 rules).
59
+
60
+ | | before | after |
61
+ |---|---|---|
62
+ | every gate, M1–M17 | ≈26 min (17 standing gates) | ≈9 min (one) |
63
+ | M16 browser gate | 435 s | 137–145 s |
64
+ | M15 browser gate | 236 s | 173–183 s |
65
+ | while working | a gate run | `npm run verify`, ≈1 min |
66
+
67
+ ## [1.8.0] — 2026-10-05
68
+
69
+ **Parity: react-dockable-desktop 7.7.0.** Ready-made dialogs: the confirmation shows an icon,
70
+ a new alert dialog, and both as promises.
71
+
72
+ ### Added
73
+
74
+ - **`<VddConfirm>` shows an icon left of its message**: a question mark, coloured by
75
+ `alertType` (info, success, warning, danger) with the toast colour tokens. The new `icon` prop
76
+ replaces it with your own component; `icon: null` hides it.
77
+ - **`<VddAlert>`**: a message with a single OK button, for telling rather than asking. Its icon
78
+ follows `alertType`, with the same `icon` override. Props: `message`, `alertType`, `icon`,
79
+ `okLabel`, `onSettled`. Focus starts on OK and Enter presses it; Escape, the backdrop and the ×
80
+ acknowledge it too, unless the modal is `closable: false`. Button hook: `data-vdd-alert-ok`.
81
+ - **`useModals().confirm(options)` and `useModals().alert(options)`** open those dialogs (size
82
+ `small`) and return a promise: `confirm` resolves `true` for the confirm button and `false` for
83
+ cancel or any dismissal; `alert` resolves once it is closed. Option types: `ConfirmOptions`,
84
+ `AlertOptions`.
85
+ - **Message keys `confirmTitle`** ("Confirmation") **and `alertTitle`** ("Information"), the
86
+ helpers' default titles. A table typed `Record<MessageKey, string>` needs the two new keys.
87
+ - New classes: `vdd-dialog-content`, `vdd-dialog-icon`, `vdd-dialog-icon-{info|success|warning|danger}`.
88
+
89
+ rdd 7.7.0 also fixed an `RddConfirm` that never answered when dismissed, and one that overwrote
90
+ the modal's header icon. Neither applied here: `<VddConfirm>` already settled on unmount and
91
+ never set a header icon.
92
+
93
+ ### Upgrading
94
+
95
+ - A confirmation now draws a question mark beside its message. Pass `icon: null` to keep the
96
+ old look.
97
+ - The line under a confirmation's message is now the border of the new icon row,
98
+ `.vdd-dialog-content`, so it spans the icon too; it was `.vdd-confirmation-message`'s own
99
+ `border-bottom`. A stylesheet that restyled that border should target `.vdd-dialog-content`.
100
+
101
+ ### Tests
102
+
103
+ - `test/components/dialogs.test.ts`: settle-once for every exit of both dialogs (Escape,
104
+ backdrop, ×, `closeAllModals`, `close(id)`, the buttons); default, custom and hidden icons;
105
+ the header icon left alone; alert focus, label and `closable: false`; both promise helpers.
106
+ Each assertion was seen failing with its code removed.
107
+ - M10 checks that `<VddAlert>` settles on unmount and only once (with a selftest mutation). The
108
+ non-vacuity selftest now blanks `contributions.test.ts`: `useOverlays.ts` is reached by the new
109
+ dialog tests too, so blanking `useOverlays.test.ts` no longer leaves a module unexecuted.
110
+ - `test/core/stylesheet.test.ts`: every dialog-icon class has a rule coloured from a toast token,
111
+ and the separator is the icon row's border, not the message's (seen failing with each removed).
112
+ - The M15 colour baseline (`scripts/gates/browser/fixtures/m15-branding-baseline.json`, which M16
113
+ also reads) is regenerated on purpose: its scenes include a confirmation, whose message now sits
114
+ in the icon row. Nothing outside that modal changed.
115
+
14
116
  ## [1.7.2] — 2026-10-04
15
117
 
16
118
  **Parity: react-dockable-desktop 7.6.2.**
@@ -0,0 +1,19 @@
1
+ import type { Component } from 'vue';
2
+ import type { AlertType, Label } from '../types';
3
+ type __VLS_Props = {
4
+ message: Label;
5
+ /** Picks the built-in icon and its colour. */
6
+ alertType?: AlertType;
7
+ /** Omit it for the built-in icon of `alertType`, pass `null` for none, or pass a component. */
8
+ icon?: Component | null;
9
+ /** The button label. Defaults to the `ok` message. */
10
+ okLabel?: Label;
11
+ /** Called exactly once, whichever way the dialog closes. */
12
+ onSettled?: () => void;
13
+ };
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
15
+ icon: Component | null;
16
+ alertType: AlertType;
17
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
+ declare const _default: typeof __VLS_export;
19
+ export default _default;
@@ -1,3 +1,4 @@
1
+ import type { Component } from 'vue';
1
2
  import type { AlertType, Label } from '../types';
2
3
  type __VLS_Props = {
3
4
  message: Label;
@@ -10,8 +11,14 @@ type __VLS_Props = {
10
11
  onCancel?: () => void;
11
12
  /** Called exactly once, whichever way the dialog closes. `ok` says which. */
12
13
  onSettled?: (ok: boolean) => void;
14
+ /**
15
+ * The icon left of the message (1.8.0): omit it for the built-in question mark, pass `null`
16
+ * for none, or pass a component. Coloured by `alertType`.
17
+ */
18
+ icon?: Component | null;
13
19
  };
14
20
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
21
+ icon: Component | null;
15
22
  alertType: AlertType;
16
23
  yesNo: boolean;
17
24
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The icon slot left of a dialog's message (1.8.0). `icon` undefined draws the built-in icon —
3
+ * a question mark for a confirmation, the type's icon for an alert — `null` draws nothing, and a
4
+ * component is drawn in its place. Coloured by `vdd-dialog-icon-${type}`; the glyphs use
5
+ * currentColor, on the same grid as the toast icons.
6
+ */
7
+ import type { Component } from 'vue';
8
+ import type { AlertType } from '../types';
9
+ type __VLS_Props = {
10
+ icon: Component | null | undefined;
11
+ type: AlertType;
12
+ question?: boolean;
13
+ };
14
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -1,5 +1,28 @@
1
1
  import type { Component, ComputedRef } from 'vue';
2
2
  import type { ModalOptions, OverlayInstance, SidePanelOptions } from '../core/overlays';
3
+ import type { AlertType, Label } from '../types';
4
+ /** Options of `useModals().confirm()`. The title defaults to the `confirmTitle` message. */
5
+ export interface ConfirmOptions {
6
+ message: Label;
7
+ title?: Label;
8
+ alert?: string;
9
+ alertType?: AlertType;
10
+ icon?: Component | null;
11
+ /** Label the buttons "Yes"/"No" rather than "OK"/"Cancel". */
12
+ yesNo?: boolean;
13
+ /** @default 'small' */
14
+ size?: ModalOptions['size'];
15
+ }
16
+ /** Options of `useModals().alert()`. The title defaults to the `alertTitle` message. */
17
+ export interface AlertOptions {
18
+ message: Label;
19
+ title?: Label;
20
+ alertType?: AlertType;
21
+ icon?: Component | null;
22
+ okLabel?: Label;
23
+ /** @default 'small' */
24
+ size?: ModalOptions['size'];
25
+ }
3
26
  /**
4
27
  * The modal stack.
5
28
  *
@@ -25,6 +48,13 @@ export declare function useModals(): {
25
48
  force?: boolean;
26
49
  }) => Promise<void>;
27
50
  closeAll: () => void;
51
+ /**
52
+ * Open a `<VddConfirm>` (1.8.0). Resolves `true` for the confirm button, `false` for cancel and
53
+ * for any dismissal — Escape, the backdrop, the ×, or a close by code.
54
+ */
55
+ confirm: (options: ConfirmOptions) => Promise<boolean>;
56
+ /** Open a `<VddAlert>` (1.8.0). Resolves once it is closed, however. */
57
+ alert: (options: AlertOptions) => Promise<void>;
28
58
  };
29
59
  /**
30
60
  * The two side drawers.
@@ -0,0 +1,30 @@
1
+ /**
2
+ * What a desktop mirrors onto `<html>`: its skin, its animations opt-out and its stacking base.
3
+ *
4
+ * Chrome teleported to `document.body` (menus, toasts, flyouts, modals) can only inherit these from
5
+ * the document, so they are written there. The document is shared by every desktop on the page, which
6
+ * is why this module keeps state at module level, per document — and why it is a stack of owners
7
+ * rather than a plain write: with two desktops mounted, each used to overwrite the other, and
8
+ * unmounting either one removed the values for the one still on screen.
9
+ *
10
+ * Each field shows the most recently mounted owner that claims it. Releasing the last claim of a field
11
+ * removes it from `<html>`, as a single desktop always did. A field nobody claims is never touched, so
12
+ * a value the page set itself survives. rdd 7.7.1's `src/utils/documentMirror.ts` is the same rule.
13
+ */
14
+ export interface DocumentMirrorValues {
15
+ /** `data-vdd-skin`. An empty value claims "no skin attribute". */
16
+ skin?: string | null;
17
+ /** The `vdd-no-animations` class. */
18
+ noAnimations?: boolean;
19
+ /** `--vdd-z-base`. */
20
+ zBase?: number;
21
+ }
22
+ type Field = keyof DocumentMirrorValues;
23
+ /**
24
+ * Claims (or updates) `owner`'s values. A first claim puts the owner on top; an update keeps its
25
+ * place, so changing one desktop's skin never lets it jump over a desktop mounted after it.
26
+ */
27
+ export declare function claimDocumentMirror(owner: object, values: DocumentMirrorValues, doc?: Document): void;
28
+ /** Releases `owner`'s claim on `fields`; the owner leaves the stack once it claims nothing. */
29
+ export declare function releaseDocumentMirror(owner: object, fields?: readonly Field[], doc?: Document): void;
30
+ export {};
@@ -87,6 +87,14 @@ export declare const defaultMessages: {
87
87
  readonly id: "vdd.ok";
88
88
  readonly defaultMessage: "OK";
89
89
  };
90
+ readonly confirmTitle: {
91
+ readonly id: "vdd.confirmTitle";
92
+ readonly defaultMessage: "Confirmation";
93
+ };
94
+ readonly alertTitle: {
95
+ readonly id: "vdd.alertTitle";
96
+ readonly defaultMessage: "Information";
97
+ };
90
98
  readonly closeTooltip: {
91
99
  readonly id: "vdd.closeTooltip";
92
100
  readonly defaultMessage: "Close";