@synopackageland/ui 0.20.19 → 0.21.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/CHANGELOG.md +31 -0
- package/dist/components/app/app-layout/AppLayout.vue.d.ts +20 -0
- package/dist/components/app/app-layout/PhoneFab.vue.d.ts +18 -0
- package/dist/components/app/app-layout/hideOnScroll.d.ts +37 -0
- package/dist/components/app/app-layout/iconActionTitles.d.ts +9 -0
- package/dist/components/app/app-layout/pageTitle.d.ts +76 -6
- package/dist/components/app/app-toolbar/AppToolbar.vue.d.ts +8 -7
- package/dist/components/app/aside-panel/AsidePanel.vue.d.ts +1 -1
- package/dist/components/app/page-content/PageContent.vue.d.ts +6 -0
- package/dist/components/app/page-fab/PageFab.vue.d.ts +12 -0
- package/dist/components/app/page-header/PageHeader.vue.d.ts +17 -4
- package/dist/components/app/section-tabs/SectionTabs.vue.d.ts +4 -3
- package/dist/components/app/settings-page/SettingsPage.vue.d.ts +16 -1
- package/dist/components/primitives/motion/PushTransition.vue.d.ts +4 -0
- package/dist/grid.js +9 -0
- package/dist/i18n/text.d.ts +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +13417 -12959
- package/dist/json-preview/preview.js +11100 -10639
- package/dist/lib/motion.d.ts +1 -1
- package/dist/reka-runtime.json +1 -1
- package/dist/theme.css +1 -1
- package/dist/themes/dsm7-embedded-theme.css +1 -1
- package/dist/themes/dsm7-embedded.css +1 -1
- package/dist/themes/dsm7.css +1 -1
- package/docs/adaptive-layout.md +10 -0
- package/docs/button-policy.md +3 -1
- package/docs/mobile-native.md +118 -5
- package/docs/release-checks.md +1 -1
- package/package.json +92 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.21.0 (2026-11-07)
|
|
6
|
+
|
|
7
|
+
Native phone shell. A *touch phone* is an `AppLayout` 640px or narrower under a coarse pointer (`data-ui-phone`). A narrow DSM window driven by a mouse, tablets and desktop are unchanged. No App change is required; every new behaviour has an opt-out (docs/mobile-native.md, "Native phone shell").
|
|
8
|
+
|
|
9
|
+
- **Page actions become a FAB.** On a touch phone the page's actions (PageHeader `#actions`, a pushed page's `#header-actions`, AppToolbar `#actions`) render in a floating action button at the bottom right instead of the bar. One action: the 56px FAB is that action and runs it. Two or more: the FAB opens a speed dial of labelled pills over a scrim, with focus trapped in it; Escape, Back, the scrim or the FAB close it and focus returns to the FAB; a pick runs the action and closes it; reduced motion shows it at once. A page whose primary action is in a footer bar (a `SettingsPage` footer, a sticky `FormActions`) keeps its actions in the bar. Page content gets `--ui-fab-room` of bottom padding
|
|
10
|
+
- **Opt-out / override:** `phone-actions="fab" | "bar" | "inline"` on `AppLayout` (all pages) and on `PageHeader`, `AppToolbar` and `PushTransition` (one page). `bar` is the 0.20.20 behaviour
|
|
11
|
+
- **New `PageFab`:** `<PageFab><Button variant="primary">…</Button></PageFab>` in the page's actions picks the FAB explicitly; the page's other actions go to the bar. Elsewhere it renders in place
|
|
12
|
+
- **Hide on scroll, on by default.** Scrolling a page down (16px) slides the bar, the tab bar, the FAB and a clean settings footer out; any scroll up (4px), the top of the page and a scroll that stops at its end bring them back. They never hide while the speed dial, the drawer, a sheet or a dialog is open or a text field has focus. They move in `--ui-motion-bars` (200ms, 0 with reduced motion). The root carries `data-ui-bars-hidden="all|bottom"`
|
|
13
|
+
- **Opt-out:** `<AppLayout :hide-on-scroll="false">` (the App) or `<PageContent :hide-on-scroll="false">` (one page). Both keep the settings footer as well
|
|
14
|
+
- **Settings footer hides only when clean.** A `SettingsPage` footer slides away with the bars only while its form is clean, never while it is dirty, invalid or saving. New props `dirty`, `invalid` and `saving`; left out, it reads them from the page: clean while the footer's primary button is disabled, invalid while a field has `aria-invalid="true"`, saving while a footer button is loading. The footer does not collapse at rest
|
|
15
|
+
- **Footer hints on their own line.** On a touch phone, a hint or status beside the buttons of any footer bar (`data-ui-footer-bar`: SettingsPage, Dialog, Sheet, BottomSheet, Card, Panel, Wizard, AppActionBar, and a FormActions in one) takes a full-width line above them instead of a narrow column of one or two words per line. Wrap bare text in an element
|
|
16
|
+
- **One compact bar.** A root page with no menu button leads the bar with the App icon (`brand-icon`), title start-aligned; no brand row. On a touch phone at most two trailing icons show in the bar; more page actions stay in the page's row, and `headerActions` go to "…" once page actions are in the bar. `AppTabBar` labels are 12px
|
|
17
|
+
- **SectionTabs: the underline strip on a touch phone.** `phone="auto"` with four or fewer sections (not `fill`) is now the scrolling underline strip under the bar instead of a full-width SegmentControl. `phone="segment"` keeps the SegmentControl; a mouse-driven narrow window keeps it too
|
|
18
|
+
- **Host insets.** `--ui-safe-top/-right/-bottom/-left` read `--ui-host-inset-*` first, then `env(safe-area-inset-*)`. A host shell that draws its own chrome around the App sets them so the bars and the FAB clear it. The Package Land mobile shell draws none and needs no setting
|
|
19
|
+
- New UI string "Page actions" (the speed dial's name), in all nine locales
|
|
20
|
+
- `check:phone-layout` covers a list page with one action (FAB), three (speed dial), `phone-actions="bar"`, hide-on-scroll off, and settings pages with a clean footer, a dirty footer and a footer hint, at 390x844, 360x800 and 390x664 with touch, in a DSM window and on desktop, in English and Traditional Chinese. It also checks the FAB's size, place and colour, hiding and showing on scroll, the dial's focus trap, Escape and scrim, and reduced motion. `check:mobile` gains the FAB, the open speed dial, hidden bars and a footer hint
|
|
21
|
+
|
|
22
|
+
## 0.20.20 (2026-11-07)
|
|
23
|
+
|
|
24
|
+
Phone layout (AppLayout 640px or narrower). No App change is required; `PageHeader` `back` is new and optional.
|
|
25
|
+
|
|
26
|
+
- **One header row in a settings drill-down.** A section pushed from a `SectionTabs` list (`PushTransition` with a `title` inside an `AppLayout`) takes the phone bar over while it is shown: Back, the section's title and its `header-actions`, in one row. The page title row and the pushed page's own 48px back header are no longer drawn under it. The list view keeps the page title. Back, the browser's Back and the edge swipe still pop the section
|
|
27
|
+
- **Page actions join the title row.** The `#actions` of the `PageHeader` whose title is in the bar, a pushed page's `#header-actions` and the `#actions` of an `AppToolbar` in AppLayout's `toolbar` slot render in the phone bar after the title (`[data-ui-mobile-page-actions]`), before `headerActions`. They no longer get a bar of their own (the SDK AppShell's Refresh bar is gone on phones). A Button with an icon is drawn as its 44px icon, with its label as its accessible name and tooltip. A text-only Button stays text, in the primary colour. A primary or danger Button keeps its fill. An `AppToolbar` with nothing else takes no row. If the actions do not fit beside the title (the title would be under 80px, or the row would overflow), they stay in the page's own row. Wider layouts are unchanged
|
|
28
|
+
- **One header row on a detail page: `PageHeader` `back`.** `<PageHeader title="Meeting record" back @back="…">` marks a sub-page. On a phone the bar leads with Back, shows this page's title (whatever AppLayout's `title` says) and holds its actions; Back emits `back` and the App pops its own route. Wider, the header leads its title with a Back button. Use it instead of a hand-drawn Back row above the page
|
|
29
|
+
- **No stacked dividers above the footer.** A collapsed `SettingsSection` (and a fixed one with an empty body) draws no rule under its title. Collapsed sections in a row form one list, with a rule between rows and none after the last, so the footer's rule is the only one under them. Desktop too. `SettingsSection` carries `data-state="open|closed"`
|
|
30
|
+
- **One divider in the SettingsPage footer (and other footer bars).** A `FormActions` in a footer that draws its own rule no longer adds its own sticky border, padding and background. This covers the SettingsPage footer (the page's own Reset / Apply and an App's `footer` slot) and the Dialog, Sheet, BottomSheet, Card, Panel, Wizard and AppActionBar footers, which now carry `data-ui-footer-bar`. On a phone the SettingsPage footer drew two rules
|
|
31
|
+
- **Buttons one size smaller on a phone.** Under a coarse pointer in the phone layout, a `Button` and a `SplitButton` are drawn md 36px, sm 28px and lg 44px (`--ui-button-md/-sm/-lg`), one size below the 44px field beside them. Their tap box stays 44px through the shared box (`data-ui-hit`); the SplitButton's two halves now join it too, and its label, not the button, cuts its overflow. An `IconButton` keeps its 36/44px. A mouse-driven narrow window and wider layouts are unchanged
|
|
32
|
+
- **Whole-page scroll on a phone.** At any height (390x664 portrait included), a page with a `SettingsPage` or a `SectionTabs fill` scrolls as one, in the area under the bar. Before, it squeezed the settings body into an inner scroller about 310–540px tall whose scrollbar iOS hides, so the sections below the first one looked gone. Every element between the area and the settings, an App shell's fill wrappers included, takes its content's height. The bar stays, the section strip and a sticky `PageHeader` stick under it, and Reset / Apply stick at the bottom (a short page keeps them at the screen's bottom). The root carries `data-ui-layout-scroll="page"`. Short landscape screens keep their short mode; desktop and DSM windows wider than 640px keep the settings body's own scroller
|
|
33
|
+
- **Disclosure rows on the content edge.** On a touch phone, a collapsible `SettingsSection` header and an `Accordion` trigger start their title on the content edge, where the rule and the content below start, and put the chevron at the row's end (down when closed, up when open) instead of a leading chevron that put the title 24px in. A mouse-driven window keeps the leading chevron. A SegmentControl and the SectionTabs segments already sit on the content edges; a wider one in an App comes from App markup
|
|
34
|
+
- New browser check `check:phone-layout` (in the full gate): the settings list, a pushed section, a long settings page and a detail page at 390x844, 360x800 and 390x664 with touch, in a 390px DSM window and on a 1280px desktop, in English and Traditional Chinese. It checks for one header row, the page's actions in the bar, no stacked rules, footer buttons drawn smaller with a 44px tap box, disclosures on the content edges and a single page scroller on a phone
|
|
35
|
+
|
|
5
36
|
## 0.20.19 (2026-11-06)
|
|
6
37
|
|
|
7
38
|
- 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
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PhoneActionsPlacement } from './pageTitle';
|
|
1
2
|
import { DropdownMenuEntry } from '../../primitives/dropdown-menu/DropdownMenu.vue';
|
|
2
3
|
import { AppAsideState, AppNavigation, WideLayout } from '../../../lib/adaptiveLayout';
|
|
3
4
|
type __VLS_Props = {
|
|
@@ -37,6 +38,23 @@ type __VLS_Props = {
|
|
|
37
38
|
* label); the rest open from "…". A pick emits `headerAction` with the key.
|
|
38
39
|
*/
|
|
39
40
|
headerActions?: DropdownMenuEntry[];
|
|
41
|
+
/**
|
|
42
|
+
* Where a page's own actions (PageHeader `#actions`, a pushed page's
|
|
43
|
+
* `#header-actions`, an AppToolbar's `#actions` above the page) go on a
|
|
44
|
+
* phone: `fab` (default) a floating action button, which runs a single
|
|
45
|
+
* action or opens a speed dial of them; `bar` icons in the phone bar;
|
|
46
|
+
* `inline` the page's own header row. A page's `phone-actions` overrides
|
|
47
|
+
* it. A page with a sticky footer (a SettingsPage footer, a sticky
|
|
48
|
+
* FormActions) keeps them in the bar, and a narrow window used with a
|
|
49
|
+
* mouse treats `fab` as `bar`.
|
|
50
|
+
*/
|
|
51
|
+
phoneActions?: PhoneActionsPlacement;
|
|
52
|
+
/**
|
|
53
|
+
* On a phone, scrolling the page down slides the phone bar, the tab bar
|
|
54
|
+
* and the FAB out of view, and any scroll up brings them back. `false`
|
|
55
|
+
* keeps them; a page opts out alone with PageContent `hide-on-scroll="false"`.
|
|
56
|
+
*/
|
|
57
|
+
hideOnScroll?: boolean;
|
|
40
58
|
};
|
|
41
59
|
type __VLS_Slots = {
|
|
42
60
|
sidebar?: () => unknown;
|
|
@@ -86,6 +104,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {}, {
|
|
|
86
104
|
}>, {
|
|
87
105
|
title: string;
|
|
88
106
|
height: "auto" | "fill";
|
|
107
|
+
phoneActions: PhoneActionsPlacement;
|
|
89
108
|
minHeight: string;
|
|
90
109
|
back: boolean;
|
|
91
110
|
sidebarWidth: string;
|
|
@@ -96,6 +115,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_PublicProps, {}, {
|
|
|
96
115
|
brandIcon: string;
|
|
97
116
|
navigation: AppNavigation;
|
|
98
117
|
headerActions: DropdownMenuEntry[];
|
|
118
|
+
hideOnScroll: boolean;
|
|
99
119
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
100
120
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
101
121
|
declare const _default: typeof __VLS_export;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/** Slid out of view (the page scrolled down, or the keyboard is open). */
|
|
3
|
+
hidden?: boolean;
|
|
4
|
+
};
|
|
5
|
+
type __VLS_ModelProps = {
|
|
6
|
+
'open'?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type __VLS_PublicProps = __VLS_Props & __VLS_ModelProps;
|
|
9
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_PublicProps, {
|
|
10
|
+
actions: import('vue').Ref<HTMLElement | null, HTMLElement | null>;
|
|
11
|
+
count: import('vue').Ref<number, number>;
|
|
12
|
+
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
13
|
+
"update:open": (value: boolean) => any;
|
|
14
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
15
|
+
"onUpdate:open"?: ((value: boolean) => any) | undefined;
|
|
16
|
+
}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
17
|
+
declare const _default: typeof __VLS_export;
|
|
18
|
+
export default _default;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { InjectionKey, Ref, WatchSource } from 'vue';
|
|
2
|
+
/** Scrolling down this far in one go hides the bars (a small threshold against jitter). */
|
|
3
|
+
export declare const HIDE_AFTER_PX = 16;
|
|
4
|
+
/** Scrolling up this far brings them back: any real scroll up, not a sub-pixel wobble. */
|
|
5
|
+
export declare const SHOW_AFTER_PX = 4;
|
|
6
|
+
/**
|
|
7
|
+
* Which bars a scroll hides: `all` (the phone bar, the tab bar and the FAB)
|
|
8
|
+
* when the page scrolls in an area under the bar, `bottom` (the tab bar and
|
|
9
|
+
* the FAB) when the document scrolls, which already carries the bar away.
|
|
10
|
+
*/
|
|
11
|
+
export type BarsHidden = false | 'all' | 'bottom';
|
|
12
|
+
export interface HideOnScrollOptions {
|
|
13
|
+
/** The layout's content column: scrolls in it (or of the document) count. */
|
|
14
|
+
column: Readonly<Ref<HTMLElement | null>>;
|
|
15
|
+
/** The phone bar, to tell whether the scroller carries it. */
|
|
16
|
+
bar: () => HTMLElement | null;
|
|
17
|
+
/** On only for a phone with the feature on (no page opted out). */
|
|
18
|
+
enabled: () => boolean;
|
|
19
|
+
/** Never hide while this holds (the speed dial or the navigation drawer is open). */
|
|
20
|
+
blocked: () => boolean;
|
|
21
|
+
/** The room the bars take: a page that scrolls less than this keeps them, or hiding them would end its scroll. */
|
|
22
|
+
room: () => number;
|
|
23
|
+
/** How long hiding or showing moves the layout; scrolls in that time are its own, not the user's. */
|
|
24
|
+
settleMs: () => number;
|
|
25
|
+
/** Each change shows the bars again (a new page). */
|
|
26
|
+
reset: WatchSource[];
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Hide-on-scroll for the phone shell: scrolling the page down slides the bars
|
|
30
|
+
* out, any scroll up brings them back at once, and so do the top of the page
|
|
31
|
+
* and a scroll that ends at its bottom. It never hides while a sheet, dialog,
|
|
32
|
+
* the speed dial or the drawer is open, or while a text field has focus, and
|
|
33
|
+
* focus moving into the bars shows them.
|
|
34
|
+
*/
|
|
35
|
+
export declare function useHideOnScroll(options: HideOnScrollOptions): Ref<BarsHidden>;
|
|
36
|
+
/** A page's opt-out from hide-on-scroll (PageContent `hide-on-scroll="false"`): counts while it is mounted. */
|
|
37
|
+
export declare const APP_KEEP_BARS_KEY: InjectionKey<() => () => void>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* A page's actions in the phone bar draw a labelled Button as its icon alone
|
|
4
|
+
* (adaptive.css): its text stays its accessible name, and this gives it the
|
|
5
|
+
* same text as a tooltip, as the bar's own icon actions have. The title goes
|
|
6
|
+
* again when the button leaves the bar (a wider layout puts it back in its
|
|
7
|
+
* header), and a title the App set is kept.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useIconActionTitles(container: Readonly<Ref<HTMLElement | null>>): void;
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import { ComputedRef, InjectionKey, Ref } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Where a page's own actions go on a phone (an App 640px or narrower with a
|
|
4
|
+
* coarse pointer): `fab`, a floating action button at the bottom right (one
|
|
5
|
+
* action runs at once, two or more open a speed dial); `bar`, icons in the
|
|
6
|
+
* phone bar after the title; `inline`, the page's own header row. A narrow
|
|
7
|
+
* window used with a mouse treats `fab` as `bar`.
|
|
8
|
+
*/
|
|
9
|
+
export type PhoneActionsPlacement = 'fab' | 'bar' | 'inline';
|
|
2
10
|
interface PageTitleEntry {
|
|
3
11
|
title: () => string;
|
|
12
|
+
/**
|
|
13
|
+
* A sub-page's Back (a detail page's PageHeader `back`, a pushed page). On a
|
|
14
|
+
* phone the bar then leads with Back and shows this title, whatever
|
|
15
|
+
* AppLayout's own `title` says: the page and its way back are one row.
|
|
16
|
+
*/
|
|
17
|
+
back?: () => void;
|
|
4
18
|
}
|
|
5
19
|
/**
|
|
6
20
|
* The bar's page title (the phone bar, or the bar of a short screen). A
|
|
7
21
|
* PageHeader in the layout's content registers its title; the last one
|
|
8
|
-
*
|
|
9
|
-
* prop is set.
|
|
22
|
+
* registered is the page's, and the bar shows it unless AppLayout's own `title`
|
|
23
|
+
* prop is set. A sub-page (an entry with `back`) takes the phone bar over.
|
|
10
24
|
*/
|
|
11
25
|
export interface AppPageTitleHost {
|
|
12
26
|
/** The content column: a PageHeader outside it (in a dialog or sheet) keeps its own title. */
|
|
@@ -14,13 +28,69 @@ export interface AppPageTitleHost {
|
|
|
14
28
|
entries: Ref<readonly PageTitleEntry[]>;
|
|
15
29
|
/** Whether the bar shows this entry's title, so its PageHeader keeps the heading for screen readers only. */
|
|
16
30
|
shows: (entry: PageTitleEntry) => boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The phone bar's place for the page's own actions (PageHeader `#actions`,
|
|
33
|
+
* a pushed page's `#header-actions`, an AppToolbar's `#actions` above the
|
|
34
|
+
* page); null where there is no phone bar. They render there, after the
|
|
35
|
+
* title and before the bar's `headerActions`, instead of in a row of their own.
|
|
36
|
+
*/
|
|
37
|
+
actions: Readonly<Ref<HTMLElement | null>>;
|
|
38
|
+
/** Counts what renders into `actions`, so the bar knows the title is not alone. Returns the release. */
|
|
39
|
+
useActions: () => () => void;
|
|
40
|
+
/** The phone's floating action button, where page actions go with the `fab` placement; null where there is none. */
|
|
41
|
+
fab?: Readonly<Ref<HTMLElement | null>>;
|
|
42
|
+
/** The placement a page's actions take, given the page's own choice (its `phone-actions`). */
|
|
43
|
+
placement?: (requested: PhoneActionsPlacement | undefined) => PhoneActionsPlacement;
|
|
44
|
+
/**
|
|
45
|
+
* A footer bar that sticks at the bottom of the page (a SettingsPage
|
|
46
|
+
* footer, a sticky FormActions) claims the bottom: the page's primary
|
|
47
|
+
* action is there, so the page's actions take the bar, not a FAB.
|
|
48
|
+
*/
|
|
49
|
+
useFooterBar?: () => () => void;
|
|
50
|
+
/** A PageFab holds the FAB: the page's other actions with the `fab` placement take the bar instead. */
|
|
51
|
+
useExplicitFab?: () => () => void;
|
|
17
52
|
}
|
|
18
53
|
export declare const APP_PAGE_TITLE_KEY: InjectionKey<AppPageTitleHost>;
|
|
19
|
-
/**
|
|
20
|
-
|
|
54
|
+
/**
|
|
55
|
+
* `active` says whether the bar shows a page title of this text (it is the
|
|
56
|
+
* page's last PageHeader); `phone` whether the phone bar is up, where a
|
|
57
|
+
* sub-page's title always shows.
|
|
58
|
+
*/
|
|
59
|
+
export declare function createPageTitleHost(main: Readonly<Ref<HTMLElement | null>>, active: (title: string) => boolean, options?: {
|
|
60
|
+
phone?: () => boolean;
|
|
61
|
+
actions?: Readonly<Ref<HTMLElement | null>>;
|
|
62
|
+
actionUsers?: Ref<number>;
|
|
63
|
+
fab?: Readonly<Ref<HTMLElement | null>>;
|
|
64
|
+
placement?: (requested: PhoneActionsPlacement | undefined) => PhoneActionsPlacement;
|
|
65
|
+
footerBars?: Ref<number>;
|
|
66
|
+
explicitFabs?: Ref<number>;
|
|
67
|
+
}): AppPageTitleHost;
|
|
21
68
|
/**
|
|
22
69
|
* Hands a PageHeader's title to the layout's bar. Returns whether the bar shows
|
|
23
|
-
* it, so the header can keep its own heading for screen readers only.
|
|
70
|
+
* it, so the header can keep its own heading for screen readers only. With
|
|
71
|
+
* `back` the page is a sub-page: on a phone the bar leads with Back and calls
|
|
72
|
+
* it. With `when`, the title is handed over only while it holds (a pushed page
|
|
73
|
+
* while it is shown).
|
|
74
|
+
*/
|
|
75
|
+
export declare function usePageTitle(element: Readonly<Ref<HTMLElement | null>>, title: () => string, options?: {
|
|
76
|
+
back?: () => (() => void) | undefined;
|
|
77
|
+
when?: () => boolean;
|
|
78
|
+
}): ComputedRef<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Where a component's actions render on a phone: the phone bar or the FAB
|
|
81
|
+
* (`target`), or null for its own row. Counts them while they are in the bar.
|
|
82
|
+
* `wanted` says whether the component would move them out of its row (its
|
|
83
|
+
* title is in the bar, or it is the bar above the page); `placement` is the
|
|
84
|
+
* component's own `phone-actions`, which overrides the layout's.
|
|
85
|
+
*/
|
|
86
|
+
export declare function usePageActionsInBar(wanted: () => boolean, placement?: () => PhoneActionsPlacement | undefined): {
|
|
87
|
+
target: ComputedRef<HTMLElement | null>;
|
|
88
|
+
placement: ComputedRef<PhoneActionsPlacement>;
|
|
89
|
+
};
|
|
90
|
+
/**
|
|
91
|
+
* Claims the bottom of the layout's page for a footer bar while `active`
|
|
92
|
+
* holds and `element` is in the layout's content column (a footer in a dialog
|
|
93
|
+
* or sheet does not count).
|
|
24
94
|
*/
|
|
25
|
-
export declare function
|
|
95
|
+
export declare function useFooterBarClaim(element: Readonly<Ref<HTMLElement | null>>, active: () => boolean): void;
|
|
26
96
|
export {};
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
import { PhoneActionsPlacement } from '../app-layout/pageTitle';
|
|
1
2
|
type __VLS_Props = {
|
|
2
3
|
height?: string;
|
|
4
|
+
/** Where `#actions` go on a phone when this is the bar above the page: `fab`, `bar` or `inline` (this row). Defaults to AppLayout's `phone-actions`. */
|
|
5
|
+
phoneActions?: PhoneActionsPlacement;
|
|
3
6
|
};
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
leading?: (
|
|
7
|
-
|
|
8
|
-
default?: (props: typeof __VLS_8) => any;
|
|
9
|
-
} & {
|
|
10
|
-
actions?: (props: typeof __VLS_10) => any;
|
|
7
|
+
type __VLS_Slots = {
|
|
8
|
+
default?: () => unknown;
|
|
9
|
+
leading?: () => unknown;
|
|
10
|
+
actions?: () => unknown;
|
|
11
11
|
};
|
|
12
12
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
13
13
|
height: string;
|
|
14
|
+
phoneActions: PhoneActionsPlacement;
|
|
14
15
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
16
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
16
17
|
declare const _default: typeof __VLS_export;
|
|
@@ -53,11 +53,11 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
53
53
|
mode: import('vue').ComputedRef<Mode>;
|
|
54
54
|
}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
55
55
|
initialFocus: "field" | "panel" | "none";
|
|
56
|
+
fab: boolean;
|
|
56
57
|
icon: Component;
|
|
57
58
|
shortcut: string;
|
|
58
59
|
expandable: boolean;
|
|
59
60
|
unread: boolean;
|
|
60
|
-
fab: boolean;
|
|
61
61
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
62
62
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
63
63
|
declare const _default: typeof __VLS_export;
|
|
@@ -12,6 +12,11 @@ type __VLS_Props = {
|
|
|
12
12
|
* holding one) takes the height left and scrolls itself.
|
|
13
13
|
*/
|
|
14
14
|
height?: 'auto' | 'fill';
|
|
15
|
+
/**
|
|
16
|
+
* `false` keeps a phone's bars in place while this page shows, when
|
|
17
|
+
* AppLayout hides them on scroll (its `hide-on-scroll`, on by default).
|
|
18
|
+
*/
|
|
19
|
+
hideOnScroll?: boolean;
|
|
15
20
|
};
|
|
16
21
|
declare var __VLS_1: {};
|
|
17
22
|
type __VLS_Slots = {} & {
|
|
@@ -21,6 +26,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
21
26
|
height: "auto" | "fill";
|
|
22
27
|
width: "fill" | "readable" | (string & {});
|
|
23
28
|
surface: "auto" | "flat" | "card" | "none";
|
|
29
|
+
hideOnScroll: boolean;
|
|
24
30
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
25
31
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
26
32
|
declare const _default: typeof __VLS_export;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
type __VLS_Slots = {
|
|
2
|
+
default?: () => unknown;
|
|
3
|
+
};
|
|
4
|
+
declare const __VLS_base: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
5
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
6
|
+
declare const _default: typeof __VLS_export;
|
|
7
|
+
export default _default;
|
|
8
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
9
|
+
new (): {
|
|
10
|
+
$slots: S;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -1,16 +1,29 @@
|
|
|
1
|
+
import { PhoneActionsPlacement } from '../app-layout/pageTitle';
|
|
1
2
|
type __VLS_Props = {
|
|
2
3
|
title: string;
|
|
3
4
|
description?: string;
|
|
4
5
|
sticky?: boolean;
|
|
6
|
+
/** A sub-page's header: Back before the title, emitting `back`. On a phone, the bar's Back. */
|
|
7
|
+
back?: boolean;
|
|
8
|
+
/** Where `#actions` go on a phone: `fab`, `bar` or `inline` (this header's row). Defaults to AppLayout's `phone-actions`. */
|
|
9
|
+
phoneActions?: PhoneActionsPlacement;
|
|
5
10
|
};
|
|
6
|
-
declare var
|
|
11
|
+
declare var __VLS_19: {}, __VLS_27: {}, __VLS_29: {};
|
|
7
12
|
type __VLS_Slots = {} & {
|
|
8
|
-
meta?: (props: typeof
|
|
13
|
+
meta?: (props: typeof __VLS_19) => any;
|
|
9
14
|
} & {
|
|
10
|
-
actions?: (props: typeof
|
|
15
|
+
actions?: (props: typeof __VLS_27) => any;
|
|
16
|
+
} & {
|
|
17
|
+
actions?: (props: typeof __VLS_29) => any;
|
|
11
18
|
};
|
|
12
|
-
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
19
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
20
|
+
back: () => any;
|
|
21
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
22
|
+
onBack?: (() => any) | undefined;
|
|
23
|
+
}>, {
|
|
13
24
|
sticky: boolean;
|
|
25
|
+
phoneActions: PhoneActionsPlacement;
|
|
26
|
+
back: boolean;
|
|
14
27
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
15
28
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
16
29
|
declare const _default: typeof __VLS_export;
|
|
@@ -8,9 +8,10 @@ export type SectionTab = {
|
|
|
8
8
|
/**
|
|
9
9
|
* How the sections show on a phone (an App 640px wide or less):
|
|
10
10
|
* `list` a grouped list that pushes each section as a page, `segment` a
|
|
11
|
-
* full-width SegmentControl, `strip` the scrolling strip
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* full-width SegmentControl, `strip` the scrolling underline strip. `auto`: a
|
|
12
|
+
* list for five or more sections or a `fill` settings page, else the strip on
|
|
13
|
+
* a touch phone (a SegmentControl before 0.21.0; ask for `segment` to keep
|
|
14
|
+
* it) and a SegmentControl in a narrow window used with a mouse.
|
|
14
15
|
*/
|
|
15
16
|
export type SectionTabsPhoneLayout = 'auto' | 'list' | 'segment' | 'strip';
|
|
16
17
|
type __VLS_Props = {
|
|
@@ -1,10 +1,25 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
/**
|
|
3
|
+
* The form has changes not yet applied. With `false` the footer may slide
|
|
4
|
+
* away with the phone's bars on a scroll down; with `true` it stays. Left
|
|
5
|
+
* out, the footer reads it: the form is clean while the footer's primary
|
|
6
|
+
* button (every button, when none is primary) is disabled.
|
|
7
|
+
*/
|
|
8
|
+
dirty?: boolean;
|
|
9
|
+
/** A field has an error: the footer stays. A field with `aria-invalid="true"` counts too. */
|
|
10
|
+
invalid?: boolean;
|
|
11
|
+
/** Apply is running: the footer stays. A footer button in its loading state counts too. */
|
|
12
|
+
saving?: boolean;
|
|
13
|
+
};
|
|
1
14
|
declare var __VLS_1: {}, __VLS_9: {};
|
|
2
15
|
type __VLS_Slots = {} & {
|
|
3
16
|
default?: (props: typeof __VLS_1) => any;
|
|
4
17
|
} & {
|
|
5
18
|
footer?: (props: typeof __VLS_9) => any;
|
|
6
19
|
};
|
|
7
|
-
declare const __VLS_base: import('vue').DefineComponent<
|
|
20
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
21
|
+
dirty: boolean;
|
|
22
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
8
23
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
9
24
|
declare const _default: typeof __VLS_export;
|
|
10
25
|
export default _default;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PhoneActionsPlacement } from '../../app/app-layout/pageTitle';
|
|
1
2
|
type __VLS_Props = {
|
|
2
3
|
/** Whether the page is pushed. */
|
|
3
4
|
show: boolean;
|
|
@@ -11,6 +12,8 @@ type __VLS_Props = {
|
|
|
11
12
|
keepMounted?: boolean;
|
|
12
13
|
/** The page's element. */
|
|
13
14
|
as?: string;
|
|
15
|
+
/** Where `#header-actions` go on a phone while the layout's bar shows this page: `fab`, `bar` or `inline` (a row atop the page). Defaults to AppLayout's `phone-actions`. */
|
|
16
|
+
phoneActions?: PhoneActionsPlacement;
|
|
14
17
|
};
|
|
15
18
|
type __VLS_Slots = {
|
|
16
19
|
default?: () => unknown;
|
|
@@ -27,6 +30,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
27
30
|
enabled: boolean;
|
|
28
31
|
under: HTMLElement | null;
|
|
29
32
|
keepMounted: boolean;
|
|
33
|
+
phoneActions: PhoneActionsPlacement;
|
|
30
34
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
31
35
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
32
36
|
declare const _default: typeof __VLS_export;
|
package/dist/grid.js
CHANGED
|
@@ -3942,6 +3942,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
3942
3942
|
"Free now {now}, free after {after}": "Free now {now}, free after {after}",
|
|
3943
3943
|
Sections: "Sections",
|
|
3944
3944
|
"Back to the previous page": "Back",
|
|
3945
|
+
"Page actions": "Page actions",
|
|
3945
3946
|
Slider: "Slider",
|
|
3946
3947
|
"Increase value": "Increase value",
|
|
3947
3948
|
"Decrease value": "Decrease value",
|
|
@@ -4203,6 +4204,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
4203
4204
|
"Free now {now}, free after {after}": "目前可用 {now},清理後可用 {after}",
|
|
4204
4205
|
Sections: "區段",
|
|
4205
4206
|
"Back to the previous page": "返回",
|
|
4207
|
+
"Page actions": "頁面動作",
|
|
4206
4208
|
Slider: "滑桿",
|
|
4207
4209
|
"Increase value": "增加數值",
|
|
4208
4210
|
"Decrease value": "減少數值",
|
|
@@ -4463,6 +4465,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
4463
4465
|
"Free now {now}, free after {after}": "当前可用 {now},清理后可用 {after}",
|
|
4464
4466
|
Sections: "区段",
|
|
4465
4467
|
"Back to the previous page": "返回",
|
|
4468
|
+
"Page actions": "页面操作",
|
|
4466
4469
|
Slider: "滑块",
|
|
4467
4470
|
"Increase value": "增加数值",
|
|
4468
4471
|
"Decrease value": "减少数值",
|
|
@@ -4723,6 +4726,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
4723
4726
|
"Free now {now}, free after {after}": "現在の空き {now}、解放後の空き {after}",
|
|
4724
4727
|
Sections: "セクション",
|
|
4725
4728
|
"Back to the previous page": "戻る",
|
|
4729
|
+
"Page actions": "ページの操作",
|
|
4726
4730
|
Slider: "スライダー",
|
|
4727
4731
|
"Increase value": "値を増やす",
|
|
4728
4732
|
"Decrease value": "値を減らす",
|
|
@@ -4983,6 +4987,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
4983
4987
|
"Free now {now}, free after {after}": "현재 여유 공간 {now}, 정리 후 여유 공간 {after}",
|
|
4984
4988
|
Sections: "섹션",
|
|
4985
4989
|
"Back to the previous page": "뒤로",
|
|
4990
|
+
"Page actions": "페이지 작업",
|
|
4986
4991
|
Slider: "슬라이더",
|
|
4987
4992
|
"Increase value": "값 증가",
|
|
4988
4993
|
"Decrease value": "값 감소",
|
|
@@ -5243,6 +5248,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
5243
5248
|
"Free now {now}, free after {after}": "Jetzt frei {now}, danach frei {after}",
|
|
5244
5249
|
Sections: "Abschnitte",
|
|
5245
5250
|
"Back to the previous page": "Zurück",
|
|
5251
|
+
"Page actions": "Seitenaktionen",
|
|
5246
5252
|
Slider: "Schieberegler",
|
|
5247
5253
|
"Increase value": "Wert erhöhen",
|
|
5248
5254
|
"Decrease value": "Wert verringern",
|
|
@@ -5503,6 +5509,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
5503
5509
|
"Free now {now}, free after {after}": "Libre maintenant {now}, libre ensuite {after}",
|
|
5504
5510
|
Sections: "Sections",
|
|
5505
5511
|
"Back to the previous page": "Retour",
|
|
5512
|
+
"Page actions": "Actions de la page",
|
|
5506
5513
|
Slider: "Curseur",
|
|
5507
5514
|
"Increase value": "Augmenter la valeur",
|
|
5508
5515
|
"Decrease value": "Diminuer la valeur",
|
|
@@ -5763,6 +5770,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
5763
5770
|
"Free now {now}, free after {after}": "Libre ahora {now}, libre después {after}",
|
|
5764
5771
|
Sections: "Secciones",
|
|
5765
5772
|
"Back to the previous page": "Atrás",
|
|
5773
|
+
"Page actions": "Acciones de la página",
|
|
5766
5774
|
Slider: "Control deslizante",
|
|
5767
5775
|
"Increase value": "Aumentar valor",
|
|
5768
5776
|
"Decrease value": "Disminuir valor",
|
|
@@ -6023,6 +6031,7 @@ const Xe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
|
|
|
6023
6031
|
"Free now {now}, free after {after}": "Libero ora {now}, libero dopo {after}",
|
|
6024
6032
|
Sections: "Sezioni",
|
|
6025
6033
|
"Back to the previous page": "Indietro",
|
|
6034
|
+
"Page actions": "Azioni della pagina",
|
|
6026
6035
|
Slider: "Cursore",
|
|
6027
6036
|
"Increase value": "Aumenta valore",
|
|
6028
6037
|
"Decrease value": "Diminuisci valore",
|
package/dist/i18n/text.d.ts
CHANGED
|
@@ -106,6 +106,7 @@ export declare const englishUiText: {
|
|
|
106
106
|
readonly "Free now {now}, free after {after}": "Free now {now}, free after {after}";
|
|
107
107
|
readonly Sections: "Sections";
|
|
108
108
|
readonly "Back to the previous page": "Back";
|
|
109
|
+
readonly "Page actions": "Page actions";
|
|
109
110
|
readonly Slider: "Slider";
|
|
110
111
|
readonly "Increase value": "Increase value";
|
|
111
112
|
readonly "Decrease value": "Decrease value";
|
package/dist/index.d.ts
CHANGED
|
@@ -260,6 +260,8 @@ export type { AppSidebarGroup, AppSidebarItem } from './components/app/app-sideb
|
|
|
260
260
|
export { default as AppToolbar } from './components/app/app-toolbar/AppToolbar.vue';
|
|
261
261
|
export { default as AppActionBar } from './components/app/app-action-bar/AppActionBar.vue';
|
|
262
262
|
export { default as PageHeader } from './components/app/page-header/PageHeader.vue';
|
|
263
|
+
export { default as PageFab } from './components/app/page-fab/PageFab.vue';
|
|
264
|
+
export type { PhoneActionsPlacement } from './components/app/app-layout/pageTitle';
|
|
263
265
|
export { default as PageToolbar } from './components/app/page-toolbar/PageToolbar.vue';
|
|
264
266
|
export { default as SplitPane } from './components/containers/split-pane/SplitPane.vue';
|
|
265
267
|
export { default as ListDetail } from './components/containers/list-detail/ListDetail.vue';
|