@synopackageland/ui 0.19.11 → 0.20.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
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.20.1 (2026-11-04)
4
+
5
+ - List pages stay white when a detail pane opens beside a `DataGrid`: the pane keeps its 1px border with no card shadow, and the selected row shows DSM's light blue.
6
+ - `Callout` spans its container, is one form row high with the icon, text, action button and close button centred, and drops the top gradient band.
7
+ - A closed `Callout` is remembered in browser storage (keyed by App and `dismissKey`, or by page, tone and text) and leaves no empty row; it shows again when its text or state changes. A `danger` callout is hidden for the page load only.
8
+ - Closed callouts are listed under the page's single info button, each with a button to show it again.
9
+
10
+ ## 0.20.0 (2026-11-04)
11
+
12
+ - `PageContent height="fill"` gives its height to a `SectionTabs fill` or a `SettingsPage` however deeply the App wraps it: every element between the page body and that component becomes a flex column that takes the room its siblings leave, so an App needs no CSS of its own to pass the height through its page wrappers. A hidden wrapper (`v-show`, `hidden`) stays hidden.
13
+ - In such a page, a `SectionTabs fill` tab that is not a `SettingsPage` scrolls under the fixed strip instead of running past the page's bottom; a `SettingsPage` tab still scrolls only its own body over its footer.
14
+ - [Layout rules](docs/layout-rules.md) describe the current page layout: no page title under a sidebar that names the page, the page's buttons in a bar above it, and only the content scrolling. A migration section lists the CSS an App can drop.
15
+ - Fix long `Select` and `Combobox` lists showing no scrollbar, so a list that scrolls no longer looked cut off. Reka hides the native bar inside its list viewports; the DSM scrollbar is drawn there again, in light and dark, while `ScrollArea` keeps hiding its own bar.
16
+
3
17
  ## 0.19.11 (2026-11-03)
4
18
 
5
19
  - `Progress` draws its track as a faint tint of its own tone (`--ui-primary-soft`, `--ui-success-soft`, `--ui-warning-soft`, `--ui-danger-soft`) instead of the grey border colour, so a bar never sits on a grey track.
package/README.md CHANGED
@@ -167,7 +167,7 @@ portal (Dialog, Sheet, Toast, Popover, Select, DropdownMenu, ContextMenu,
167
167
  Tooltip) into itself, not `document.body`, where the scoped tokens
168
168
  and reset would not reach them. Each `AppRoot` teleports into its own element;
169
169
  theme and density tokens on sibling roots reach their own portals. By default
170
- (`modal-scope="app"`, since 0.6.0) each root owns its Dialog/Sheet and popup
170
+ (`modal-scope="app"`) each root owns its Dialog/Sheet and popup
171
171
  layers and never mutates `document.body`, so give it a bounded size such as
172
172
  `style="height: 100%"`. A full-page web or Portal app that wants document-wide
173
173
  modality passes `modal-scope="document"` (see below).
@@ -388,7 +388,7 @@ Without a listener the existing logo/name markup stays unchanged. The `brand`
388
388
  slot replaces the default brand and owns its own interaction; it is never
389
389
  wrapped in a button. A DSM window's title bar remains managed by DSM.
390
390
 
391
- `navigation="top"` (0.13.1+) lays the `sidebar` slot out as one bar above the
391
+ `navigation="top"` lays the `sidebar` slot out as one bar above the
392
392
  page instead of a left column: the brand, then the `AppSidebar` items in a row
393
393
  (a row with children opens them in a menu; the bar scrolls sideways when the
394
394
  items run out of room), then `sidebar-footer`. It applies in the DSM-window
@@ -407,7 +407,7 @@ forward it before an app can choose it through that shell.
407
407
  For standalone content that owns its layout, use `<PageContent surface="none" height="fill">`.
408
408
  It removes the page's horizontal gutters and adds no surface in web, DSM-window
409
409
  or phone layouts. The default `surface="auto"` remains unchanged; `flat` keeps
410
- the dashboard canvas. In 0.12.4+, `auto` already has no outer page card in web
410
+ the dashboard canvas. `auto` has no outer page card in web
411
411
  mode. Child components keep their own styling and spacing. The JSON `Page`
412
412
  component accepts the same `surface="none"` option. SDK `AppShell` is a separate
413
413
  package: if it creates `PageContent` internally, it must expose/forward this
@@ -437,6 +437,12 @@ under its sticky header, with the pager always in view. Pages that are not
437
437
  `fill` in the same layout scroll as before. In the SDK's `AppShell`, the same
438
438
  is a page's `fill: true`.
439
439
 
440
+ A settings page fills the same way: `PageContent height="fill"` gives the
441
+ height to a `SectionTabs fill` or a `SettingsPage` through the App's own
442
+ wrapper elements, with no CSS of their own. The tab strip and the footer stay,
443
+ only the sections scroll, and a tab that is not a `SettingsPage` scrolls under
444
+ the strip. The SDK's `AppShell` fills such a page by itself.
445
+
440
446
  ```vue
441
447
  <AppLayout height="fill" min-height="0">
442
448
  <template #sidebar>…</template>
@@ -492,7 +498,7 @@ tones (`--ui-success`, …).
492
498
 
493
499
  **Theme hooks.** The `data-ui-*` and `data-*` attributes and the layout tokens
494
500
  listed in [docs/theme-hooks.md](docs/theme-hooks.md) are public API with
495
- stability rules (0.13.1+): `--ui-icon-size`, `--ui-heading-weight`,
501
+ stability rules: `--ui-icon-size`, `--ui-heading-weight`,
496
502
  `--ui-card-padding`, the top bar's `--ui-top-nav-*` and the phone bar's
497
503
  `--ui-mobile-bar-*`, `Button`'s `data-variant`, the layout regions
498
504
  (`data-ui-layout-sidebar`, `data-ui-layout-main`, `data-ui-mobile-navigation`,
@@ -964,8 +970,8 @@ Use the pnpm version specified in `package.json`.
964
970
  ```bash
965
971
  pnpm story # component workbench
966
972
  pnpm dev # rebuild dist when library source changes
967
- pnpm check # production build, then lint, typecheck and tests in parallel, then the package audit
968
- pnpm check:fast # as check, but only the tests the changes since origin/master reach (vitest --changed)
973
+ npm run gates # basic build, lint, typecheck, unit tests, notices and package audit
974
+ npm run gates:full # optional browser/workbench/registry integrations, only when requested
969
975
  pnpm story:build # build the component workbench
970
976
  pnpm check:host # after pnpm build: DSM host simulation screenshots (Chrome)
971
977
  pnpm check:date-picker # after pnpm build: app-local calendars, Dialog Escape and full-bleed pages (ego-browser)
@@ -973,8 +979,9 @@ pnpm check:switch # after pnpm build: Switch knob geometry and click toggling (C
973
979
  pnpm check:topology # after pnpm build: ConnectionTopology motion, keyboard and narrow layout (Chrome)
974
980
  ```
975
981
 
976
- Use `pnpm check:fast` while developing (`SYNOPKGLAND_GATE_BASE` sets the base),
977
- and `pnpm check` once before a release: the full run is the release gate.
982
+ Use `npm run gates` for development and release. Extended checks require an
983
+ explicit `npm run gates:full`; full is optional. `pnpm check` and `check:fast`
984
+ are basic aliases. See [release checks](docs/release-checks.md).
978
985
  `check` prints one line per passing task and a failing task's whole log.
979
986
 
980
987
  With `SYNOPKGLAND_DOCKER_SSH=<ssh host>`, `pnpm check`, `check:fast` and
@@ -1044,12 +1051,11 @@ See the [documentation](https://www.varvis.me/docs/) for usage.
1044
1051
 
1045
1052
  ### CI and tag releases
1046
1053
 
1047
- GitHub Actions runs on Ubuntu for pushes to `master` and `ci/**`, pull requests,
1048
- and manual dispatch. Both workflows share `.github/actions/verify`: a frozen
1049
- pnpm install from npmjs, `pnpm check` (build, lint, typecheck, unit tests and the
1050
- package-content audit), `notices:check`, responsive/host/switch/layout/motion
1051
- browser checks, and the Histoire workbench build. pnpm and Playwright Chromium
1052
- are cached. Browser screenshots and measurements are retained for seven days.
1054
+ Automatic CI runs basic checks. The disabled CI/release workflow templates
1055
+ share `.github/actions/verify`: frozen dependency installation and
1056
+ `npm run gates` (build, lint, typecheck, unit tests, notices and package audit).
1057
+ Browser integrations, workbench builds and registry consumer smoke require
1058
+ `npm run gates:full` only when explicitly requested.
1053
1059
 
1054
1060
  To release the package:
1055
1061
 
@@ -1066,8 +1072,8 @@ To release the package:
1066
1072
  ```
1067
1073
 
1068
1074
  The release workflow checks the exact tag/version, default-branch ancestry,
1069
- nonempty changelog section and npm version availability. It runs the same full
1070
- CI gates, stages the package into an empty directory, packs it, and audits
1075
+ nonempty changelog section and npm version availability. It runs the same basic
1076
+ checks, stages the package into an empty directory, packs it, and audits
1071
1077
  the actual tarball (every exported dist file, MIT license, notices, bundled Reka,
1072
1078
  package name and no `publishConfig`). A separate job rechecks the artifact and
1073
1079
  registry before publishing with `NPM_TOKEN`, then creates a GitHub Release from
@@ -1077,7 +1083,7 @@ If npm publication succeeds but GitHub Release creation fails, create the Releas
1077
1083
  from the changelog separately; rerunning publishing intentionally refuses the
1078
1084
  already published version.
1079
1085
 
1080
- On branches and PRs, the release workflow performs the full pipeline through
1086
+ On branches and PRs, the release workflow performs basic validation through
1081
1087
  `npm publish <tgz> --dry-run --access public --ignore-scripts`, without npm
1082
1088
  credentials or creating a GitHub Release. An existing npm version is allowed only
1083
1089
  in dry-run mode and is reported explicitly; npm 11 also rejects duplicate versions
@@ -1121,7 +1127,7 @@ Linux motion 使用 `MOTION_BROWSER=playwright`,本機預設 ego-browser 保
1121
1127
  本機只送工作樹並等待;未設時照舊在本機跑。`check:local-browser` 仍在本機用 ego-browser。
1122
1128
 
1123
1129
 
1124
- ## Form controls and compact settings (0.5.7)
1130
+ ## Form controls and compact settings
1125
1131
 
1126
1132
  `Form` and standalone `FormItem` default to `direction="auto"`. They use the
1127
1133
  container's width, including a DSM package window, and stack labels below 520px.
@@ -1204,7 +1210,7 @@ DatePicker's calendar inherits Provider locale unless its own Intl `locale` is
1204
1210
  supplied. Caller-owned option labels, content, URLs, rules' custom messages and
1205
1211
  business terminology stay caller-owned. Validation fallbacks use the locale at
1206
1212
  validation time; imperative message-box default titles use the locale at opening.
1207
- See [the complete default-text and container audit](docs/component-defaults-0.5.7.md).
1213
+ See [the complete default-text and container audit](docs/component-defaults.md).
1208
1214
 
1209
1215
  `KeyValueRow` renders a `dl` with `dt`/`dd`; its default slot accepts rich values,
1210
1216
  including Link. The `Wizard` step list shows the registered steps and does not
@@ -1,13 +1,13 @@
1
1
  type __VLS_Props = {
2
2
  height?: string;
3
3
  };
4
- declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
4
+ declare var __VLS_1: {}, __VLS_8: {}, __VLS_10: {};
5
5
  type __VLS_Slots = {} & {
6
6
  leading?: (props: typeof __VLS_1) => any;
7
7
  } & {
8
- default?: (props: typeof __VLS_3) => any;
8
+ default?: (props: typeof __VLS_8) => any;
9
9
  } & {
10
- actions?: (props: typeof __VLS_5) => any;
10
+ actions?: (props: typeof __VLS_10) => any;
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;
@@ -4,7 +4,7 @@ type __VLS_Props = {
4
4
  * `--ui-page-readable-width`; any other value is a CSS maximum width.
5
5
  */
6
6
  width?: 'fill' | 'readable' | (string & {});
7
- /** card uses the white content area; flat uses the page grey; auto is white unless the page holds a card, then grey like flat. none adds no surface or horizontal gutters, for content that owns its layout at every width. */
7
+ /** card uses the white content area; flat uses the page grey; auto is white unless the page holds a card, then grey like flat; a list page (a DataGrid on the page, outside any card) stays white when a pane opens beside it. none adds no surface or horizontal gutters, for content that owns its layout at every width. */
8
8
  surface?: 'auto' | 'flat' | 'card' | 'none';
9
9
  /**
10
10
  * `'fill'` takes the container's height and does not scroll: the header,
@@ -3,11 +3,11 @@ type __VLS_Props = {
3
3
  description?: string;
4
4
  sticky?: boolean;
5
5
  };
6
- declare var __VLS_1: {}, __VLS_3: {};
6
+ declare var __VLS_6: {}, __VLS_8: {};
7
7
  type __VLS_Slots = {} & {
8
- meta?: (props: typeof __VLS_1) => any;
8
+ meta?: (props: typeof __VLS_6) => any;
9
9
  } & {
10
- actions?: (props: typeof __VLS_3) => any;
10
+ actions?: (props: typeof __VLS_8) => any;
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
  sticky: boolean;
@@ -8,17 +8,22 @@ type __VLS_Props = {
8
8
  variant?: 'soft' | 'inline' | 'hint';
9
9
  title?: string;
10
10
  /**
11
- * Shows a close button (default). Closing hides the callout until its
12
- * tone, title or text (or `dismissKey`) changes. Turn it off only for a
13
- * state that must stay in view, such as a blocking setup requirement.
11
+ * Shows a close button (default). Closing hides the callout, also after a
12
+ * reload, until its tone, title or text changes; a `danger` callout is
13
+ * hidden for this page load only. The page's info button lists it to show
14
+ * again. Turn it off only for a state that must stay in view, such as a
15
+ * blocking setup requirement.
14
16
  */
15
17
  dismissible?: boolean;
16
- /** What a dismissal is remembered by, instead of the tone and the rendered text. */
18
+ /**
19
+ * A stable id for the callout within the App (e.g. `'recycle-bin-dsm-hint'`), under which
20
+ * its dismissal is stored. Without it the id is drawn from the page path, the tone and the text.
21
+ */
17
22
  dismissKey?: string;
18
23
  closeLabel?: string;
19
24
  /** A machine code (e.g. `login_wait_timeout`), shown after the message in a quieter style. */
20
25
  code?: string;
21
- /** Span the container instead of stopping at `--ui-callout-max-width` (720px). */
26
+ /** @deprecated A Callout spans its container by default; `--ui-callout-max-width` caps it. */
22
27
  fill?: boolean;
23
28
  /** The toggle for the `details` slot. */
24
29
  moreLabel?: string;
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,37 @@
1
+ import { Component } from 'vue';
2
+ /** FNV-1a, 32 bits, as 8 hex digits: a short, stable name for a text. */
3
+ export declare function hashText(text: string): string;
4
+ /** The App a dismissal belongs to: the DSM package, else the page's host and directory. */
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;
8
+ export declare function isDismissed(key: string, signature: string): boolean;
9
+ export declare function rememberDismissal(key: string, signature: string, persist: boolean): void;
10
+ export declare function forgetDismissal(key: string): void;
11
+ /** A closed callout that is still on the page, as the info button lists it. */
12
+ export interface HiddenCallout {
13
+ tone: 'info' | 'success' | 'warning' | 'danger';
14
+ icon: Component;
15
+ label: string;
16
+ restore: () => void;
17
+ }
18
+ export declare const hiddenCallouts: import('vue').ShallowReactive<Map<number, HiddenCallout>>;
19
+ export declare function registerHiddenCallout(entry: HiddenCallout): () => void;
20
+ type Host = {
21
+ kind: 'info' | 'chrome';
22
+ id: symbol;
23
+ };
24
+ export declare function registerRecallHost(kind: Host['kind']): {
25
+ id: symbol;
26
+ unregister: () => void;
27
+ };
28
+ export declare const activeRecallHost: import('vue').ComputedRef<symbol | null>;
29
+ /**
30
+ * For a toolbar or a page header: whether it shows its own info button for the
31
+ * closed callouts (CalloutRecall). Only the first one mounted does, and only
32
+ * while no info button already there (a page's notes) lists them.
33
+ */
34
+ export declare function useCalloutRecallHost(): import('vue').ComputedRef<boolean>;
35
+ /** Tests only: forget this page load's dismissals, as a reload does. */
36
+ export declare function resetSessionDismissals(): void;
37
+ export {};
@@ -52,6 +52,8 @@ export declare const englishUiText: {
52
52
  readonly "Opens in a new tab": "Opens in a new tab";
53
53
  readonly Download: "Download";
54
54
  readonly Close: "Close";
55
+ readonly "Hidden notices": "Hidden notices";
56
+ readonly "Show again": "Show again";
55
57
  readonly Cancel: "Cancel";
56
58
  readonly Confirm: "Confirm";
57
59
  readonly OK: "OK";