@synopackageland/ui 0.20.17 → 0.20.19

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,19 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.20.19 (2026-11-06)
6
+
7
+ - The phone navigation drawer returns focus to its opener inside the shell (the menu button or a More tab) after Escape, Close, a navigation pick, Back or a swipe. If a touch tap left focus on the host page outside the shell, it falls back to the menu button instead of returning focus to the host. It waits until the drawer has left and the background is no longer inert
8
+ - Dialog, Sheet, BottomSheet, RecordPanel and notifications remember focus only inside their AppRoot (including its floating dialog host). A touch-opened overlay ignores the host page's focused element and returns to the pressed control inside the app; existing closeAutoFocus overrides still take precedence
9
+
10
+ ## 0.20.18 (2026-11-06)
11
+
12
+ - `Callout` takes `dismissScope`. `persistent` (the default) keeps today's behaviour: a closed callout stays closed after a reload until what it says changes. `occurrence` is for a notice about a passing state (reconnecting, an error, a stalled capture) that the App shows with `v-if` while the state lasts: closing hides this appearance only, nothing is stored, and the dismissal is forgotten when the Callout unmounts, so the next time the state starts the notice shows again. `dismissalKey` and `forgetDismissal` are exported: `forgetDismissal(dismissalKey('reconnecting'))` shows the callout with that `dismissKey` again (docs/callout.md, "Closing")
13
+ - `useToast({ optional: true })` returns a controller that shows nothing when there is no `ToastProvider` (in a unit test or a preview) instead of throwing; its calls return -1 and `update` returns false. `useToast()` without options still throws, and its message names the option. `toastControllerKey` is exported, so a test can provide its own controller (docs/callout.md)
14
+ - On a touch screen, the remove button of a tag in `MultipleSelect` and `SuperboxSelect` gets the shared 44px tap box (`data-ui-hit`) instead of its 16px drawn size, and nothing scrolls sideways. So that no box covers another control, the tags in the field keep the tap gap (`--ui-tap-gap`, 8px) side by side and a box's height between wrapped rows, and the tags keep room at their end so the last box on a row never covers the clear and open buttons. The hidden read-only input after the tags takes no taps; a tap on the field opens it as before. Mouse layouts are unchanged
15
+ - On a touch screen, a `SettingsPage` in a page with gutters keeps the whole 44px tap box of a control on its content's edge. Its body is a scroller of its own and began at the gutter, so a Switch under its label on a phone (a pushed settings section) kept only 32px of its width. On touch the body now reaches over the gutter, as its footer does, and keeps it as padding: the content stays where it was. `check:mobile` now passes in full
16
+ - A test now covers a full-width dismissible Callout at the top of an `overflow-y: auto` column with no `PageContent` (an App's record page) at 390px: nothing scrolls sideways since 0.20.17, and the close button keeps its 44px tap box inside the callout
17
+
5
18
  ## 0.20.17 (2026-11-06)
6
19
 
7
20
  - On a touch screen, a control at the end edge of its own component no longer makes an App's page scroll sideways. A dismissible `Callout` stretched to full width in an App's own vertical scroller (not inside a `PageContent`) had its close button's 44px tap box reach 2px past the scroller (12px for an inline Callout) at 390px, so the scroller was wider than its view and a sideways drag moved the page. The shared tap box (hit-area.css) now takes `--ui-hit-end-room`, the room between a control and its component's end edge: the box stops at that edge and grows towards the control's start side instead, still 44px, and nothing is drawn differently. The Callout close button, a `Tag`'s remove button, the `SearchField` clear button, the password reveal button, the `PathDisplay` copy button and the `Notification` close button set it. A Tag's remove button drops its own extra 32px tap box, which the shared 44px box already covered. `FileThumbs` and `RichTextEditor` image thumbnails stop the tap box of the last item and its remove button at the row's end edge (the last `FileThumbs` item's box is 34px wide instead of 42px, its remove badge's 30px), and removable `FileThumbs` keep 6px at the end so the remove badge no longer sticks out of the row; the `InputSteppers` presets button's tap box stops at the field's edge and keeps its 32px by reaching further towards the text. Dialog, Drawer (`Sheet`), Toast, RecordPanel and AsidePanel close buttons already fit inside their headers and are unchanged (docs/mobile-native.md, "Hit area")
package/dist/cli.js CHANGED
File without changes
@@ -1,3 +1,4 @@
1
+ import { CalloutDismissScope } from './calloutDismissal';
1
2
  type __VLS_Props = {
2
3
  tone?: 'info' | 'success' | 'warning' | 'danger';
3
4
  /**
@@ -20,6 +21,15 @@ type __VLS_Props = {
20
21
  * its dismissal is stored. Without it the id is drawn from the page path, the tone and the text.
21
22
  */
22
23
  dismissKey?: string;
24
+ /**
25
+ * `persistent` (default): closing is remembered after a reload too.
26
+ * `occurrence`: for a notice about a passing state (reconnecting, an error,
27
+ * a stalled capture) that the App shows with `v-if` while the state lasts.
28
+ * Closing hides this appearance only: nothing is stored, and the
29
+ * dismissal is forgotten when the Callout unmounts, so the next time the
30
+ * state starts it shows again.
31
+ */
32
+ dismissScope?: CalloutDismissScope;
23
33
  closeLabel?: string;
24
34
  /** A machine code (e.g. `login_wait_timeout`), shown after the message in a quieter style. */
25
35
  code?: string;
@@ -61,6 +71,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {}, {
61
71
  variant: "soft" | "inline" | "hint";
62
72
  tone: "info" | "success" | "warning" | "danger";
63
73
  dismissible: boolean;
74
+ dismissScope: CalloutDismissScope;
64
75
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
65
76
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
66
77
  declare const _default: typeof __VLS_export;
@@ -3,10 +3,25 @@ import { Component } from 'vue';
3
3
  export declare function hashText(text: string): string;
4
4
  /** The App a dismissal belongs to: the DSM package, else the page's host and directory. */
5
5
  export declare function appScope(): string;
6
- /** The storage key of a callout: the App's id for it, or one drawn from the page, the tone and the text. */
7
- export declare function dismissalKey(dismissKey: string | undefined, tone: string, text: string): string;
6
+ /**
7
+ * How long a closed Callout stays closed. `persistent` (default): after a
8
+ * reload too, until what it says changes (a `danger` callout for this page
9
+ * load). `occurrence`: this appearance only. The dismissal is kept in memory
10
+ * and forgotten when the Callout unmounts, so when the App shows it again
11
+ * for the next occurrence of its condition (a `v-if` on "reconnecting"), it
12
+ * is open again.
13
+ */
14
+ export type CalloutDismissScope = 'persistent' | 'occurrence';
15
+ /**
16
+ * The key a callout's dismissal is stored under: the App's `dismissKey` for it,
17
+ * or one drawn from the page, the tone and the text. With a `dismissKey` the
18
+ * tone and the text are not needed: `forgetDismissal(dismissalKey('reconnecting'))`
19
+ * shows a closed callout again.
20
+ */
21
+ export declare function dismissalKey(dismissKey: string | undefined, tone?: string, text?: string): string;
8
22
  export declare function isDismissed(key: string, signature: string): boolean;
9
23
  export declare function rememberDismissal(key: string, signature: string, persist: boolean): void;
24
+ /** Forgets a callout's dismissal (a key from `dismissalKey`): it shows again, on this page and after a reload. */
10
25
  export declare function forgetDismissal(key: string): void;
11
26
  /** A closed callout that is still on the page, as the info button lists it. */
12
27
  export interface HiddenCallout {
@@ -42,4 +42,14 @@ export type ToastController = {
42
42
  pending: (title: string, description?: string) => number;
43
43
  };
44
44
  export declare const toastControllerKey: InjectionKey<ToastController>;
45
- export declare function useToast(): ToastController;
45
+ export type UseToastOptions = {
46
+ /**
47
+ * Without a `<ToastProvider>` ancestor, return a controller that shows
48
+ * nothing instead of throwing: for a component that also mounts in unit
49
+ * tests and previews without the App shell. Its calls return -1 (`update`
50
+ * returns false).
51
+ */
52
+ optional?: boolean;
53
+ };
54
+ /** The App's toasts. Throws without a `<ToastProvider>` ancestor, unless `optional` is set. */
55
+ export declare function useToast(options?: UseToastOptions): ToastController;
@@ -0,0 +1,4 @@
1
+ import { InjectionKey, Ref } from 'vue';
2
+ export declare const APP_FOCUS_ROOT_KEY: InjectionKey<Ref<HTMLElement | null>>;
3
+ /** Remember only this app's controls, including its viewport portal. */
4
+ export declare function useFocusOwner(): (element: HTMLElement) => boolean;
@@ -6,7 +6,8 @@ export declare const OPENER_FOCUS_FRAMES = 120;
6
6
  * an element that had focus when the content mounted, so a bottom sheet, and
7
7
  * a dialog opened by a click that did not focus its button (Safari, touch),
8
8
  * left focus on <body> when Escape or the Close button shut it. The opener is
9
- * the focused element when `open` turns true, else the control just pressed.
9
+ * the focused element inside the app when `open` turns true, else the control
10
+ * just pressed inside the app, else the supplied fallback trigger.
10
11
  *
11
12
  * The returned handler, called from the content's `closeAutoFocus` after the
12
13
  * consumer's own listener, runs when the overlay starts to close: its content
@@ -21,4 +22,7 @@ export declare const OPENER_FOCUS_FRAMES = 120;
21
22
  * document. A consumer that prevents the default
22
23
  * keeps full control.
23
24
  */
24
- export declare function useOpenerFocus(open: () => boolean): (event: Event) => void;
25
+ export declare function useOpenerFocus(open: () => boolean, options?: {
26
+ contains?: (element: HTMLElement) => boolean;
27
+ fallback?: () => HTMLElement | null;
28
+ }): (event: Event) => void;
package/dist/index.d.ts CHANGED
@@ -57,8 +57,8 @@ export { default as DatePicker } from './components/primitives/date-picker/DateP
57
57
  export type { DateFormat, DateTimeParts, TimeFormat } from './components/primitives/date-picker/dateTime';
58
58
  export { DATE_FORMATS, TIME_FORMATS, composeDateTime, formatDateText, formatTimeText, hourOptions, minuteOptions, parseDateText, parseDateTime, } from './components/primitives/date-picker/dateTime';
59
59
  export { default as ToastProvider } from './components/primitives/toast/ToastProvider.vue';
60
- export { useToast } from './components/primitives/toast/toast';
61
- export type { ToastController, ToastMessage, ToastOptions, ToastTone } from './components/primitives/toast/toast';
60
+ export { toastControllerKey, useToast } from './components/primitives/toast/toast';
61
+ export type { ToastController, ToastMessage, ToastOptions, ToastTone, UseToastOptions } from './components/primitives/toast/toast';
62
62
  export { default as StatusSlot } from './feedback/StatusSlot.vue';
63
63
  export { useShowAfter } from './feedback/showAfter';
64
64
  export type { ShowAfterOptions } from './feedback/showAfter';
@@ -129,6 +129,8 @@ export { default as SettingsSection } from './components/composite/settings-sect
129
129
  export { default as Footbar } from './components/composite/footbar/Footbar.vue';
130
130
  export type { FootbarButton, FootbarButtonRegion, FootbarButtonSize, FootbarButtonVariant, } from './components/composite/footbar/types';
131
131
  export { default as Callout } from './components/composite/callout/Callout.vue';
132
+ export { dismissalKey, forgetDismissal } from './components/composite/callout/calloutDismissal';
133
+ export type { CalloutDismissScope } from './components/composite/callout/calloutDismissal';
132
134
  export { default as StepList } from './components/composite/step-list/StepList.vue';
133
135
  export type { StepListItem, StepStatus } from './components/composite/step-list/types';
134
136
  export { default as ConnectionTopology } from './components/composite/connection-topology/ConnectionTopology.vue';