@synopackageland/ui 0.8.1 → 0.9.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 +236 -0
- package/README.md +16 -14
- package/dist/components/app/app-root/AppRoot.vue.d.ts +12 -1
- package/dist/components/composite/data-grid/DataGrid.vue.d.ts +6 -1
- package/dist/components/composite/tree-view/TreeView.vue.d.ts +3 -0
- package/dist/components/containers/expandable-item/ExpandableItem.vue.d.ts +1 -1
- package/dist/components/feedback/notification/Notification.vue.d.ts +1 -1
- package/dist/components/primitives/breadcrumb/BreadcrumbCrumb.vue.d.ts +5 -1
- package/dist/components/primitives/dialog/Dialog.vue.d.ts +7 -3
- package/dist/components/primitives/dialog/FloatingLayer.vue.d.ts +18 -0
- package/dist/components/primitives/icon/FileTypeIcon.vue.d.ts +17 -0
- package/dist/components/primitives/icon/fileType.d.ts +3 -0
- package/dist/composables/floatingHost.d.ts +21 -0
- package/dist/composables/floatingPlacement.d.ts +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7886 -7636
- package/dist/json/catalog.d.ts +2 -2
- package/dist/json/registry.d.ts +30 -30
- package/dist/json-preview/preview.js +5213 -5028
- package/dist/lib/floatingDialog.d.ts +22 -0
- package/dist/lib/localModal.d.ts +5 -0
- 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/app-local-modal.md +42 -0
- package/package.json +4 -7
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.9.1 (2026-10-12)
|
|
4
|
+
|
|
5
|
+
Two behavior changes: a Dialog without `width` is 520px wide inside `AppRoot`, and Breadcrumb's last level no longer emits `click-item`.
|
|
6
|
+
兩項行為變化:`AppRoot` 內未指定 `width` 的 Dialog 寬 520px;Breadcrumb 最後一段不再發出 `click-item`。
|
|
7
|
+
|
|
8
|
+
- **Behavior change.** Fix: Dialog's `width` applies again inside `AppRoot`. Since app-local modality, `max-width: calc(100% - 24px) !important` overrode it, so 480px or 800px dialogs stretched to almost the window width. A panel now narrows only when the app (or viewport) is narrower than `width`. Dialogs without `width` now take the 520px default instead of the window width; pass a larger `width` where a wide panel is wanted.
|
|
9
|
+
- **行為變化。** 修正:`AppRoot` 內 Dialog 的 `width` 重新生效。自 app-local modal 起,`max-width: calc(100% - 24px) !important` 蓋掉它,480px/800px 的 Dialog 都被撐到接近視窗寬;現在只在 app(或 viewport)比 `width` 窄時才夾到可用寬度。未指定 `width` 的 Dialog 改用預設 520px,不再是視窗寬;需要寬面板請傳較大的 `width`。
|
|
10
|
+
- Dialog takes `height` and `min-height`, so one row of content no longer leaves a flat panel. Both are capped to the available height, the body fills the panel and the footer stays at the bottom.
|
|
11
|
+
- Dialog 新增 `height` 與 `min-height`,內容只有一列時不再變成扁平面板;兩者都夾到可用高度,內容區撐滿、footer 固定在底部。
|
|
12
|
+
- `AppRoot` takes `dialog-bounds="viewport"` (app mode, default `app`): as in DSM, the mask covers only the owning window, while the Dialog panel can be dragged by its title bar (or moved with the arrow keys on its title) anywhere inside the browser viewport. It stacks with its window, hides with it, follows its moves, and becomes a bottom sheet below 600px or with a coarse pointer. Pressing it emits `activate` so the DSM host can bring the window forward. See `docs/app-local-modal.md`.
|
|
13
|
+
- `AppRoot` 新增 `dialog-bounds="viewport"`(app 模式,預設 `app`):與 DSM 原生一致,遮罩只蓋擁有它的視窗,Dialog 本體可用標題列拖移(或聚焦標題後用方向鍵)到瀏覽器 viewport 內任何位置;它隨視窗疊放與隱藏、跟著視窗移動,600px 以下或粗指標時改為底部 sheet。按下面板會發出 `activate`,讓 DSM host 把視窗帶到前面。詳見 `docs/app-local-modal.md`。
|
|
14
|
+
- **Behavior change:** Breadcrumb's current (last) level is plain text with `aria-current="page"`, no longer a button that emits `click-item`. With an action menu it stays the menu trigger.
|
|
15
|
+
- **行為變化:** Breadcrumb 的目前(最後)一段改為帶 `aria-current="page"` 的文字,不再是會發出 `click-item` 的按鈕;有 action menu 時仍是選單觸發鈕。
|
|
16
|
+
- TreeView takes `selection-style="background"`: a selected row only gets the selected background, and its icon and text keep their colors, as in DSM File Station. The default `accent` is unchanged.
|
|
17
|
+
- TreeView 新增 `selection-style="background"`:選中列只換背景,圖示與文字維持原色(DSM File Station 樣式);預設 `accent` 不變。
|
|
18
|
+
- DataGrid takes `single-select`: no checkbox column, a click selects one row, the rows are in the tab order (the selected row, else the first), the arrow keys move the selection and Enter emits `rowActivate`.
|
|
19
|
+
- DataGrid 新增 `single-select`:無勾選框欄,點列單選;列可用鍵盤聚焦(選中列,否則第一列),方向鍵移動選取,Enter 觸發 `rowActivate`。
|
|
20
|
+
- `FileTypeIcon` draws a folder (`kind="folder"`, `open`) or a file whose extension picks the icon (image, video, audio, archive, text, code, else a plain file). Its colours are the theme tokens `--ui-file-folder` (DSM 7 File Station yellow) and `--ui-file-icon`, so a theme recolours every file list; `fileTypeIcon(name)` returns the icon alone.
|
|
21
|
+
- 新增 `FileTypeIcon`:畫資料夾(`kind="folder"`、`open`)或依副檔名選圖示的檔案(圖片、影片、音訊、壓縮檔、文字、程式碼,其餘為一般檔案)。顏色來自主題 token `--ui-file-folder`(DSM 7 File Station 黃色)與 `--ui-file-icon`,主題可一次改掉所有檔案列表的顏色;`fileTypeIcon(name)` 只回傳圖示元件。
|
|
22
|
+
|
|
23
|
+
## 0.9.0 (2026-10-11)
|
|
24
|
+
|
|
25
|
+
- **Breaking change:** the package is published only as `@synopackageland/ui` on npmjs. `@synology-eg/syno-pkg-land-ui` and its internal registry release are gone; replace the package name in `package.json` and every import (`@synology-eg/syno-pkg-land-ui/theme.css` becomes `@synopackageland/ui/theme.css`, and so on). The repository moved to https://github.com/synopackageland/syno-pkg-land-ui. The `syno-pkg-land-ui` CLI and CSS names are unchanged.
|
|
26
|
+
- **破壞性變更:** 套件只以 `@synopackageland/ui` 發佈到 npmjs。`@synology-eg/syno-pkg-land-ui` 與內部 registry 發版已移除;請在 `package.json` 與所有 import 換成新名稱(例如 `@synology-eg/syno-pkg-land-ui/theme.css` 改為 `@synopackageland/ui/theme.css`)。原始碼 repo 移至 https://github.com/synopackageland/syno-pkg-land-ui。`syno-pkg-land-ui` CLI 與 CSS 名稱不變。
|
|
27
|
+
- Fix: the npm package ships `CHANGELOG.md` again, so installed consumers can read release notes offline (npm 11 no longer packs it implicitly). `pnpm check:package` now fails when the package lacks it.
|
|
28
|
+
- 修正:npm 包重新附上 `CHANGELOG.md`,安裝後可離線閱讀版本紀錄(npm 11 不再自動打包)。套件缺少它時,`pnpm check:package` 會失敗。
|
|
29
|
+
|
|
30
|
+
## 0.8.1 (2026-10-10)
|
|
31
|
+
|
|
32
|
+
- Fix: FilePicker sizes follow DSM — a 1024 base with `B`/`KB`/`MB`/`GB`/`TB` labels and at most one decimal (`16 * 1024 ** 3` shows `16 GB`, previously `16.0 GB`; sizes of 1 TB and more no longer show as thousands of GB). The rule is exported as `formatFileSize(bytes)` for application text that repeats a limit.
|
|
33
|
+
- 修正:FilePicker 的大小顯示改依 DSM —— 1024 進位、標籤 `B`/`KB`/`MB`/`GB`/`TB`、最多一位小數(`16 * 1024 ** 3` 顯示 `16 GB`,原為 `16.0 GB`;1 TB 以上不再顯示成數千 GB)。同一規則匯出為 `formatFileSize(bytes)`,供應用程式重述上限的文字使用。
|
|
34
|
+
- Fix: `SectionTabs` no longer shows a vertical scrollbar. Its 30px tabs overflowed the strip's bottom border by 1px (10px when a narrow strip also showed a horizontal scrollbar). The baseline is now painted inside the strip, and a narrow strip scrolls sideways without a visible scrollbar. `Tabs` now does the same instead of letting its tabs spill out of the strip unreachable. `pnpm check:tabs` checks both at 320–1280px in every theme.
|
|
35
|
+
- 修正:`SectionTabs` 不再出現垂直捲軸。原本 30px 的分頁超出 strip 底線 1px(窄 strip 同時出現橫向捲軸時為 10px)。底線改畫在 strip 內,窄 strip 改為無可見捲軸的橫向捲動。`Tabs` 同樣改為橫向捲動,不再讓分頁溢出 strip 而無法到達。`pnpm check:tabs` 在 320–1280px、各 theme 下檢查兩者。
|
|
36
|
+
|
|
37
|
+
## 0.8.0 (2026-10-08)
|
|
38
|
+
|
|
39
|
+
- **Breaking change:** rename the `syno-ui` CSS class and data attributes to `syno-pkg-land-ui`, without aliases. The themes style only the new names, and components render only the new attributes. Update consumer stylesheets, DOM queries and test selectors:
|
|
40
|
+
|
|
41
|
+
| 0.7.x | 0.8.0 |
|
|
42
|
+
| --- | --- |
|
|
43
|
+
| `.syno-ui-root` | `.syno-pkg-land-ui-root` |
|
|
44
|
+
| `[data-syno-ui]` | `[data-syno-pkg-land-ui]` |
|
|
45
|
+
| `[data-syno-ui-select-trigger]` | `[data-syno-pkg-land-ui-select-trigger]` |
|
|
46
|
+
| `[data-syno-ui-select-search]` | `[data-syno-pkg-land-ui-select-search]` |
|
|
47
|
+
| `[data-syno-ui-select-clear]` | `[data-syno-pkg-land-ui-select-clear]` |
|
|
48
|
+
| `[data-syno-ui-select-create-hint]` | `[data-syno-pkg-land-ui-select-create-hint]` |
|
|
49
|
+
| `[data-syno-ui-select-tag]` | `[data-syno-pkg-land-ui-select-tag]` |
|
|
50
|
+
| `[data-syno-ui-select-tag-remove]` | `[data-syno-pkg-land-ui-select-tag-remove]` |
|
|
51
|
+
|
|
52
|
+
The embedded theme still scopes every rule to the app root (`[data-ui-app]`, unchanged). A literal replacement of `syno-ui` with `syno-pkg-land-ui` covers every row.
|
|
53
|
+
- **破壞性變更(breaking change):** `syno-ui` 開頭的 CSS class 與 data attribute 改名為 `syno-pkg-land-ui`,不保留別名。theme 只樣式化新名稱,元件只輸出新屬性。consumer 的 stylesheet、DOM 查詢與測試 selector 要依上表更新(把 `syno-ui` 逐字換成 `syno-pkg-land-ui` 即可涵蓋全部)。embedded theme 仍把所有規則 scope 在 app root(`[data-ui-app]`,未改名)。
|
|
54
|
+
|
|
55
|
+
## 0.7.0 (2026-10-08)
|
|
56
|
+
|
|
57
|
+
- **Breaking change:** rename the CLI bin from `syno-ui` to `syno-pkg-land-ui`, without an alias. The npm package remains `@synopackageland/ui`. Update scripts to `npx --no syno-pkg-land-ui <command>` after installing, or `npx -y -p @synopackageland/ui@0.7.0 syno-pkg-land-ui <command>` without a local install. Help, validation hints, generated AI prompts, diagnostic prefixes and release smoke use the new name. The default screenshot directory is now `syno-pkg-land-ui-render`; pass `--out` to choose a fixed directory.
|
|
58
|
+
- **破壞性變更(breaking change):** CLI bin 從 `syno-ui` 改名為 `syno-pkg-land-ui`,不保留別名。npm 套件名仍為 `@synopackageland/ui`。已安裝時改用 `npx --no syno-pkg-land-ui <command>`;未安裝時用 `npx -y -p @synopackageland/ui@0.7.0 syno-pkg-land-ui <command>`。help、驗證提示、產生的 AI prompt、診斷前綴與發版 smoke 同步改名。預設截圖目錄改為 `syno-pkg-land-ui-render`;可用 `--out` 固定目錄。
|
|
59
|
+
- Fix `--help` to print usage on stdout and exit 0, allowing packed-release smoke to succeed. Preserve existing CSS classes and data attributes for consumer compatibility; only injection Symbol descriptions change, retaining their exported keys and identity semantics.
|
|
60
|
+
- 修正 `--help`:將 usage 輸出到 stdout 並回傳 0,讓 tarball 發版 smoke 可成功執行。為相容 consumer,保留既有 CSS class 與 data attribute;僅改 injection Symbol 的描述文字,保留匯出 key 與身分比對語義。
|
|
61
|
+
|
|
62
|
+
## 0.6.1 (2026-10-08)
|
|
63
|
+
|
|
64
|
+
- Fix: the public package now declares its `syno-ui` bin, so `npx @synopackageland/ui <command>` works. 0.6.0 shipped `dist/cli.js` without the `bin` field. Release staging keeps `bin` and refuses a missing, empty or non-Node bin target; the tarball audit requires every bin target in `dist/` with a `#!/usr/bin/env node` line; and the release job installs the packed tarball in a fresh project and runs `syno-ui --help` and `syno-ui catalog` before publishing.
|
|
65
|
+
- 修正:public 套件補上 `syno-ui` bin,`npx @synopackageland/ui <command>` 可以執行(0.6.0 有 `dist/cli.js` 但缺 `bin` 欄位)。發版 staging 保留 `bin`,bin 目標不存在、空檔或不是 Node script 就拒絕;tarball audit 要求每個 bin 目標在 `dist/` 且以 `#!/usr/bin/env node` 開頭;發版前會把打包好的 tarball 裝進全新專案並執行 `syno-ui --help` 與 `syno-ui catalog`。
|
|
66
|
+
- Fix: `syno-ui render` and the browser checks launch Chrome with `--disable-partial-raster`. Partial raster could redraw an anti-aliased edge one colour level differently, so identical pages sometimes screenshotted differently; this made `check:host` fail intermittently on CI.
|
|
67
|
+
- 修正:`syno-ui render` 與瀏覽器檢查啟動 Chrome 時加上 `--disable-partial-raster`。partial raster 重繪反鋸齒邊緣時可能差一個色階,相同頁面截圖偶爾不一致,造成 CI 上 `check:host` 偶發失敗。
|
|
68
|
+
|
|
69
|
+
## 0.6.0 (2026-10-08)
|
|
70
|
+
|
|
71
|
+
- **Breaking default change:** `AppRoot` now defaults to `modal-scope="app"`. Dialog/Sheet and popup layers block only that app's background and never mutate `document.body`, so an open dialog no longer locks the DSM desktop or hides other apps. App mode needs a bounded root size (`<AppRoot style="height: 100%">`). Full-page web/Portal apps that want document-wide modality pass `modal-scope="document"`; nesting AppRoots now requires `modal-scope="document"` on both. `pnpm check:host` adds an outbound check: with the embedded theme and an open dialog, DSM elements keep every computed style, their own `@keyframes`, document fonts and html/body inline styles.
|
|
72
|
+
- **預設行為變更(breaking):** `AppRoot` 預設改為 `modal-scope="app"`。Dialog/Sheet 與 popup 只擋該 app 的背景,不再改 `document.body`,開著的 dialog 不會鎖住 DSM 桌面或隱藏其他 app。app 模式需要有界的 root 尺寸(`<AppRoot style="height: 100%">`)。需要整頁 modal 的 web/Portal 頁面請傳 `modal-scope="document"`;巢狀 AppRoot 兩層都要設 `modal-scope="document"`。`pnpm check:host` 新增反向檢查:載入 embedded theme 並開 dialog 後,DSM 元素的 computed style、自身 `@keyframes`、文件字型與 html/body inline style 都不變。
|
|
73
|
+
- Adaptive DSM layout: `AppLayout` switches by its own width between `mobile` (≤600px; slide-out navigation, phone bottom sheets, narrow-table cards), `window` and, only with `wide-layout="web"`, the wide `web` Portal layout. Maximized DSM windows stay in `window` mode. See `docs/adaptive-layout.md`. The phone drawer no longer slides out on first mount, and its keyboard handling stays inside its own app.
|
|
74
|
+
- 自適應 DSM 版面:`AppLayout` 依自身寬度切換 `mobile`(≤600px;滑出導覽、手機 bottom sheet、窄表格卡片)、`window`,以及需 `wide-layout="web"` 才啟用的寬版 `web` Portal 版面。最大化的 DSM 視窗維持 `window`。手機 drawer 首次 mount 不再滑出,鍵盤處理限於自己的 app。
|
|
75
|
+
- New `./json` entry: `SynoJsonRenderer` renders validated JSON UI specs (json-render 0.21) from a component catalog; `AppShell` accepts `wideLayout`. `validateSynoJsonSpec` reports errors with JSON pointer paths and fix hints, including `$computed` functions and `t()` message keys. The catalog-generated JSON Schema and AI prompt are exported as `./json-catalog.schema.json` and `./json-ai-prompt.md`.
|
|
76
|
+
- 新增 `./json` entry:`SynoJsonRenderer` 依 catalog 渲染驗證過的 JSON UI spec;`validateSynoJsonSpec` 以 JSON pointer 路徑與修正提示回報錯誤。由 catalog 生成的 JSON Schema 與 AI prompt 以 `./json-catalog.schema.json`、`./json-ai-prompt.md` 匯出。
|
|
77
|
+
- New `syno-ui` CLI (`npx @synopackageland/ui <command>`): `catalog`, `describe`, `schema`, `prompt`, `validate` (`--json`, `--strict`; exit 1 for spec errors, 2 for unreadable inputs) and `render`, which validates, screenshots 390/640/960/1350px in a local Chrome and names overflowing or clipped spec elements. See the AI tools section of `docs/json-ui.md`.
|
|
78
|
+
- 新增 `syno-ui` CLI:`catalog`、`describe`、`schema`、`prompt`、`validate` 與 `render`(用本機 Chrome 截 390/640/960/1350px 並指出 overflow/被裁切的 spec 元素)。
|
|
79
|
+
- Fix: the embedded theme's Tailwind `spin`/`pulse` keyframes are renamed `ui-spin`/`ui-pulse`, so they cannot replace DSM or other apps' animations of the same name (since 0.5.8); the build rejects unprefixed keyframes. The package now ships the documents the README links to. DataTable's empty mobile view is outside its ARIA list; Portal page surfaces are separated from the toolbar.
|
|
80
|
+
- 修正:embedded theme 的 `spin`/`pulse` keyframes 改名為 `ui-spin`/`ui-pulse`,不再蓋掉 DSM 或其他 app 同名動畫,build 會擋未加前綴的 keyframes。套件附上 README 連結的文件。DataTable 行動版空狀態移出 ARIA list;Portal page surface 與 toolbar 分開。
|
|
81
|
+
|
|
82
|
+
## 0.5.8 (2026-10-07)
|
|
83
|
+
|
|
84
|
+
- Fix embedded Tabs/Select controls reverting to the browser font while their parents use the theme font. The host reset now preserves inherited control fonts; host acceptance checks computed font stacks as well as exact screenshot equality. Update Switch browser acceptance for ids forwarded to the actual control.
|
|
85
|
+
- 修正 embedded Tabs/Select 被 host reset 改回瀏覽器字型,改為繼承 app 字型;host gate 同時驗證 computed font stack 與圖像完全一致。Switch 瀏覽器驗收更新為實際 control 上的 id。
|
|
86
|
+
- Add Ubuntu GitHub Actions CI and a public npm tag release pipeline, sharing frozen npmjs installs, library/package/notices checks, responsive/host/switch/layout/motion acceptance and workbench builds. Pin actions by commit and cache pnpm/Chromium.
|
|
87
|
+
- Gate public releases on exact stable tag/version, default-branch ancestry, npm version availability and the actual packed dist/exports/license/metadata. Branches, PRs and manual dispatch rehearse with `npm publish --dry-run`; only pushed version tags can publish and create a changelog-backed GitHub Release. Preserve the internal release path and default ego motion runner; add a Playwright motion backend for Linux.
|
|
88
|
+
- 新增 Ubuntu CI 與 public npm tag 發版流程,共用 npmjs 鎖定安裝、完整 library/package/notices、responsive/host/switch/layout/motion 與 workbench 檢查;action 釘 SHA 並快取 pnpm/Chromium。
|
|
89
|
+
- 正式發版驗證穩定版 tag/版本、預設分支歷史、npm 未存在及實際 tarball 的 dist/exports/授權/metadata。分支、PR、手動執行以 dry-run 演練;只有推 tag 可發 npm 並建立 changelog Release。保留內部發版與 ego motion,新增 Linux Playwright motion。
|
|
90
|
+
|
|
91
|
+
## 0.5.7 (2026-10-07)
|
|
92
|
+
|
|
93
|
+
- Fix inherited `FormItem direction="auto"` inside narrow containers: the Form now preserves the requested direction in its context, and every item resolves auto using its own width. A 96px FieldCell stays vertical even in a wide Form. Explicit Form/FormItem directions remain supported. Remove the downstream `direction="vertical"` workaround when the intent is auto.
|
|
94
|
+
- **Default change:** SettingsRow stacks its label above its control below 520px of its own width; wider rows retain two columns. Container-responsive Form, FormItem, RepeatRow, FieldCell, CardGrid and overflow layouts use local geometry. Row/Grid/Space responsive breakpoint objects retain their documented viewport semantics.
|
|
95
|
+
- **Default change:** built-in component text now follows reactive `ConfigProvider locale` across en, zh-TW, zh-CN, ja, ko, de, fr, es and it. This includes Link external/download annotations, select/search placeholders, dialog/panel/wizard actions, loading/empty states, tree/grid/pagination controls, notifications/toast announcements, date/color/schedule pickers and typography hints. Existing explicit text/label props and partial text objects win, including empty strings. DatePicker's calendar locale now inherits Provider locale unless explicitly supplied. Validation fallback messages use the locale at validation time; controller-generated message-box titles use the locale when opened. See `docs/component-defaults-0.5.7.md` for the audited inventory.
|
|
96
|
+
- Remove downstream Link `external-label`/`download-label` translations when they only duplicate these defaults. Keep application link text and custom terminology translated by the application.
|
|
97
|
+
- Document FilePicker's existing `type` → `size` → `duplicate` → `count` rejection precedence, single-file replacement/removal, empty selection and application read/parse errors; no new rejection reason or replacement behavior.
|
|
98
|
+
- Verify KeyValueRow's existing wrapping with a 256-character unbroken version string in a 320px nested container: it wraps without overflow in all responsive gate modes. Downstream `.connect-value` wrapping can be removed for this tested composition.
|
|
99
|
+
- Extend `pnpm check:responsive` with inherited-auto 96px FieldCells, nested 320px Form/SettingsRow/CardGrid and long-value measurements at 640/960/1280/1920 in layered/embedded/embedded-host modes.
|
|
100
|
+
|
|
101
|
+
## 0.5.6 (2026-10-07)
|
|
102
|
+
|
|
103
|
+
- Form controls automatically bind the enclosing `FormItem` control id, description, help/error, required and invalid ARIA state. Explicit ids update the label target; custom descriptions merge with the field's descriptions. Input changes, selection commits, disabled state and blur report to field validation. Composite popup inputs cannot reuse the field id; sibling controls have one primary control and retain unique ids when it is removed.
|
|
104
|
+
- `Select`, the combobox family, `Checkbox`, `Switch`, numeric/date/color controls, `SearchField`, `CopyCutField`, `FilePicker` and `ScheduleTable` forward identity, ARIA, data attributes and control listeners to their actual control; layout class/style stay on wrappers. `SegmentItem` and `SplitButton` forward attrs to their action button. Overlay attrs target the popup surface (Tooltip attrs target its trigger), and custom dialog/popover/menu ids retain trigger `aria-controls` links. `Progress` attrs target its progressbar.
|
|
105
|
+
- **Default change:** `Form` and standalone `FormItem` use `direction="auto"`: below 520px of available container width, labels stack above controls; wider containers retain the horizontal 180px label column. Pass `direction="horizontal"` for the old fixed layout, or `direction="vertical"` for an always-stacked form. A FormItem can override its enclosing form. Zero-width/SSR containers initially retain the horizontal layout.
|
|
106
|
+
- `Input` and `Select` protect readable minimum widths (96/128px, capped by the available width); Select labels truncate while the arrow cannot shrink. Keep adjacent controls in wrapping `FieldCell`/`RepeatRow` compositions.
|
|
107
|
+
- `RepeatRow` reserves a separate remove column and aligns removal with the first control's center, including labelled cells and wrapped rows; new `removeDisabled` prop. **Default change:** the remove button stays on the first line rather than following the last wrapped cell. Row fields now live in an inner wrapping element; update direct-child CSS selectors to `[data-repeat-fields] > …`.
|
|
108
|
+
- `FilePicker variant="compact"` renders a normal button and optional file list. All text, limits, removal and rejection messages accept `text` overrides with named `{name}`, `{size}`, `{count}` placeholders. Built-in locales: en, zh-TW, zh-CN, ja, ko, de, fr, es, it; `ConfigProvider locale` supplies a reactive default and an explicit FilePicker locale wins. The existing dropzone is retained, with a single native keyboard action instead of nested button roles. Disabled drop/selection/removal paths refuse changes.
|
|
109
|
+
- New `Link`: native href/download behavior, external/download icons, safe new-tab rel, visible keyboard focus, disabled activation, and overridable accessibility labels. New `KeyValueRow`: compact read-only description-list rows with value/label slots.
|
|
110
|
+
- `Wizard showSteps` adds an optional noninteractive step guide using registered step headings; navigation still goes through the existing guards. `footer.startLabel` and `progressText(current,total)` make the remaining default text replaceable; footer actions wrap.
|
|
111
|
+
- Scoped preflight normalizes heading/paragraph/list/button/form/table defaults after the DSM host reset and before library utilities. Both themes use the same base rules; the reset-only entry remains host reset only. **Default change:** raw app headings, paragraphs and lists no longer retain browser margins/bullets, and raw buttons no longer retain browser borders/backgrounds. Add explicit app typography/spacing classes or semantic `Typo*` components where those defaults were intentional.
|
|
112
|
+
- **Default change:** `EmptyState` minimum height is 112px with 20px vertical padding (previously 192px / 40px). Pass `class="min-h-48 py-10"` to restore the previous space.
|
|
113
|
+
- Remaining internal strings in DatePicker, InputSteppers, ColorPicker, AboutDialog, ToastProvider, ScheduleTable, TypoHeader, AppSidebar, SectionTabs and AdvancePanelGrid are now configurable. ScheduleTable supports disabled state and translated day labels. Forced-colors mode uses an outline for keyboard focus because shadows can disappear; no dark theme is claimed.
|
|
114
|
+
- TreeView disabled nodes cannot expand through their toggle, initiate a drag, accept a drop, or reorder through Alt+Arrow keyboard actions.
|
|
115
|
+
- Build gates: `pnpm check` builds before typecheck/tests; MotionPreview uses the package self-reference with source types so a clean checkout does not require pre-existing dist for typecheck. Release staging verifies every exported JS/type/CSS file exists and is nonempty before writing the destination.
|
|
116
|
+
- The “SDK / 0.5.6 fixes” story covers the new and fixed compositions. `pnpm check:responsive` captures 36 images (dashboard/form/defects × 640/960/1280/1920 × layered/embedded/embedded-host) and records geometry in `measurements.json`. README includes a jsdom Select keyboard helper and migration examples.
|
|
117
|
+
|
|
118
|
+
## 0.5.5 (2026-10-06)
|
|
119
|
+
|
|
120
|
+
Page layout that adapts to the window (DSM Control Panel / Package Center behaviour: the content area fills the window, cards add columns as it grows, form fields keep a fixed sensible width). Everything below is additive except the two defaults marked **default change**.
|
|
121
|
+
|
|
122
|
+
- `PageContent` (new): wraps `PageHeader`, `SectionTabs` and the page body so they share one left and right edge. `width="fill"` (default) uses the whole content area; `width="readable"` caps it at `--ui-page-readable-width` (880px); any CSS length is a custom cap. The header actions always end at the same edge as the content.
|
|
123
|
+
- `CardGrid` (new): `repeat(auto-fit, minmax(min(100%, minItemWidth), 1fr))`, equal-height cards. Props: `minItemWidth` (`280px`), `gap`, `fit` (`'stretch'` grows the cards to use the whole row; `'fill'` keeps empty tracks, so a lone card stays at column width).
|
|
124
|
+
- Form fields: `Form`, `FormItem` and `SettingsRow` take `fieldWidth` (`'xs'` 96px, `'sm'` 160px, `'md'` 320px, `'lg'` 480px, `'full'`, or a CSS length). **Default change:** controls stop at `'md'` instead of stretching to the container; pass `field-width="full"` for the old behaviour (a textarea, a table, a `RepeatRows` block).
|
|
125
|
+
- **Default change:** a horizontal `FormItem` has a 12px gap between its label column and the control.
|
|
126
|
+
- `Card` `footerAlign` (`'start'` default, `'end'`, `'between'`); the footer is a wrapping flex row. New `FormActions` (`align`, `labelWidth`) does the same for a button row outside a card.
|
|
127
|
+
- `RepeatRows` / `RepeatRow` / `FieldCell` (new): editable repeated rows. `FieldCell width` sizes each field to its content (`'xs'` for a port, `'sm'` for a protocol); cells wrap on narrow widths; `RepeatRow` ends in a delete button (`removeLabel`, emits `remove`); `RepeatRows` ends in the add button (`addLabel`, `addDisabled`, emits `add`). The component does not own the data.
|
|
128
|
+
- `EmptyState` already centres in its container, so inside `PageContent` it centres in the content area.
|
|
129
|
+
- `pnpm check:responsive` screenshots a dashboard and a settings form at 640/960/1280/1920px in the layered, embedded and embedded + host themes and asserts no horizontal overflow, header/content edge alignment, column counts, field caps and footer alignment. The compositions live in the "DSM 7 / Page layout" story.
|
|
130
|
+
|
|
131
|
+
### Usage
|
|
132
|
+
|
|
133
|
+
```vue
|
|
134
|
+
<!-- dashboard -->
|
|
135
|
+
<PageContent>
|
|
136
|
+
<PageHeader title="Overview"><template #actions><Button>Recheck</Button></template></PageHeader>
|
|
137
|
+
<CardGrid><Card v-for="p in providers" :key="p.name" :title="p.name">…<Button variant="primary">Set up</Button></Card></CardGrid>
|
|
138
|
+
</PageContent>
|
|
139
|
+
|
|
140
|
+
<!-- settings form -->
|
|
141
|
+
<PageContent width="readable">
|
|
142
|
+
<PageHeader title="Cloudflare" />
|
|
143
|
+
<SectionTabs v-model="tab" :items="tabs" />
|
|
144
|
+
<Card title="Connection">
|
|
145
|
+
<Form><FormItem label="Domain"><Input v-model="domain" /></FormItem></Form>
|
|
146
|
+
<Callout tone="warning">…</Callout><Checkbox v-model="agreed" label="I understand" />
|
|
147
|
+
<template #footer><FormActions><Button variant="primary" :disabled="!agreed">Apply</Button><Button variant="ghost">Cancel</Button></FormActions></template>
|
|
148
|
+
</Card>
|
|
149
|
+
</PageContent>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## 0.5.4 (2026-10-06)
|
|
153
|
+
|
|
154
|
+
- DSM-embedded fix: `host-reset.css` reverts bare elements to browser defaults, and the library relied on a Tailwind preflight that the embedded theme does not ship. `Card`, `EmptyState`, `PageHeader` and `WizardStep` headings now set `margin: 0` (a Card header was 64px tall because of the default `h3` margin), and the `SettingsSection`, `Card` and `ExpandableItem` toggle buttons reset their border, background and padding; the dashed header rules of `SettingsSection` and `Fieldset` draw only the bottom edge (a collapsible section showed a grey bordered button instead of the blue DSM title row). No API change.
|
|
155
|
+
|
|
156
|
+
## 0.5.3 (2026-10-06)
|
|
157
|
+
|
|
158
|
+
- Match the supplied Control Panel reference: blue selected tab labels, bold 14px main labels / 13px section labels, and a raised notch in the divider instead of a blue underline. The marker keeps its 120ms movement and panels keep their 160ms fade.
|
|
159
|
+
- DataGrid footer now draws both horizontal borders, with a divider before the refresh control. The grid fills available space in a flex container so its footer can rest at the bottom while rows scroll independently; `flex-none` opts out.
|
|
160
|
+
- Hide the reorder handle and its extra column when row dragging is disabled or omitted. Enabled dragging and pivot-column handles remain supported.
|
|
161
|
+
|
|
162
|
+
## 0.5.2 (2026-10-06)
|
|
163
|
+
|
|
164
|
+
- Tabs and SectionTabs share a sliding underline (120ms), measured again when labels or layout change. Tabs content fades in over 160ms without delaying selection or keyboard focus.
|
|
165
|
+
- SectionTabs optionally renders named `panel-${value}` slots with the same fade. Existing navigation-only usage is supported; caller attributes still reach the nav.
|
|
166
|
+
- Spinner uses a full rotating SVG ring with a smoothly growing/shrinking arc. Dash animation loops at one full circumference, removing the clipped half-ring and angle reset.
|
|
167
|
+
- These animations respect `prefers-reduced-motion` in standalone and DSM-embedded themes.
|
|
168
|
+
|
|
169
|
+
## 0.4.2 (2026-10-05)
|
|
170
|
+
|
|
171
|
+
### Switch (visual fix, backward compatible)
|
|
172
|
+
|
|
173
|
+
- The switch track is a `<button>`, and its browser padding (1px 6px) was never reset in the DSM-embedded theme: the knob started 6px from the track edge and the checked knob overflowed the right edge by 4px. The track now has `padding: 0`, so the knob rests 1px from the track edge in both states. No API change; consumers need no code change, only the bump.
|
|
174
|
+
- The switch toggles on click in the library (component tests plus a real-browser click in the standalone and embedded themes, with and without host CSS). `pnpm check:switch` covers the geometry and the click.
|
|
175
|
+
|
|
176
|
+
## 0.4.1 (2026-10-03)
|
|
177
|
+
|
|
178
|
+
### Controls (visual change, backward compatible)
|
|
179
|
+
|
|
180
|
+
- The theme gains one shared control chrome: `--ui-control-bg` / `-hover` / `-active`, `--ui-control-border` / `-active`, `--ui-control-divider` / `-on-accent`, `--ui-control-track`, `--ui-shadow-control-active`, `--ui-radius-control` (4px) and `--ui-motion-ease`. The resting surface, the hover border and the disabled label alpha follow the DSM 7 measurements; the resting frame, the hover and pressed tones, the divider, the press depth and the control radius are derived from them (DSM leaves the resting frame transparent and uses a 3px radius).
|
|
181
|
+
- `Button`, `IconButton` and `SplitButton` share those tokens: a resting 1px frame, a deeper hover surface and frame, a real pressed state (darker surface, stronger frame, 1px inset depth) and a focus state that sharpens the frame as well as showing the ring. Primary and danger keep their colour on press instead of showing a lighter halo, and their resting frame is one step darker than the fill.
|
|
182
|
+
- A disabled grey or ghost button now keeps its surface and dims only the label; a loading button keeps full strength and shows a visible ring, white on the accent fills (`--ui-spin-color`). `IconButton` gains the matching hover, pressed and focus states, and ghost/secondary dim the glyph instead of the whole box.
|
|
183
|
+
- `SplitButton` is one control again: both halves hover and press together, and a real 1px divider replaces the doubled border (it no longer turns grey on the blue variant).
|
|
184
|
+
- `Input`, `Textarea`, `Select`, `SearchField`, `Checkbox`, `RadioGroup` and `Switch` share the control radius, easing and focus-ring tokens; `--ui-focus-ring` is slightly stronger (0.30 → 0.35).
|
|
185
|
+
|
|
186
|
+
**Behaviour changes to check when upgrading:** controls read `--ui-radius-control`, so an override of `--ui-radius-sm` or `--ui-radius-md` no longer reshapes them. A disabled grey button no longer fades its surface, and a loading button is no longer dimmed.
|
|
187
|
+
|
|
188
|
+
## 0.4.0 (2026-10-03)
|
|
189
|
+
|
|
190
|
+
- Bundle a hash-verified patch of Reka 2.10.5: final modal cleanup restores host body styles and priorities. Consumers need no Reka dependency or patch. Vue remains an external peer.
|
|
191
|
+
- Add opt-in `AppRoot modal-scope="app"` for local Dialog/Sheet and popup layer, focus, scroll and ARIA ownership. Default document modality is preserved.
|
|
192
|
+
- Forward cancellable Dialog/Sheet Escape, outside interaction and autofocus events.
|
|
193
|
+
- Reject nested app-local AppRoots and simultaneous app/document overlays. Add packed-consumer Chromium acceptance and dist runtime/license audits.
|
|
194
|
+
|
|
195
|
+
## 0.3.1 (2026-10-02)
|
|
196
|
+
|
|
197
|
+
### Cursor
|
|
198
|
+
|
|
199
|
+
- Every clickable control now shows the hand cursor: buttons (including icon buttons and both halves of a split button), links, tabs, section tabs, sidebar items, menu, dropdown and select items, checkbox / radio / switch controls and their labels, sortable grid headers, clickable rows, close buttons and upload drop zones. Disabled, read-only and busy controls keep the default cursor; text inputs keep the text cursor. The rules live in the theme (`theme.css` and every `themes/*` export).
|
|
200
|
+
|
|
201
|
+
## 0.3.0 (2026-10-01)
|
|
202
|
+
|
|
203
|
+
### Theme: native DSM 7 look (visual change, minor bump)
|
|
204
|
+
|
|
205
|
+
Tokens were re-measured against DSM 7.4 (`docs/dsm-native-metrics.md`). Apps that use the tokens get the new look without code changes; apps that hard-code sizes may need a pass.
|
|
206
|
+
|
|
207
|
+
- Font: `Verdana, Arial, …` (CJK fallbacks) at **13px** (was system sans 14px); text `#414b55`, secondary and muted text are 60% / 40% alpha of it.
|
|
208
|
+
- Accent `#057feb` (hover `#0075db`, active `#0062b8`), success `#009e05`, warning `#f58414`, danger `#e64040`.
|
|
209
|
+
- Selected / hover tints `rgb(5 127 235 / 10% | 4%)`; borders `#c6d4e0` at 70% / 40%.
|
|
210
|
+
- Radii 3px (navigation 5px); controls 24 / 28 / 34px (were 28 / 34 / 40); navigation row 42px; page padding 16px; sidebar 215px.
|
|
211
|
+
- Bare buttons in `AppSidebar`, `SectionTabs`, `SearchField` and ghost `IconButton` now set `border-0 bg-transparent` themselves (needed so the embedded and layered themes render alike).
|
|
212
|
+
- `Button` secondary is the flat grey DSM button; `AppSidebar`, `SectionTabs` (30px strip, bold 12px labels, blue underline), menus, `SearchField` follow DSM.
|
|
213
|
+
- New tokens: `--ui-font-size-lg`, `--ui-shadow-card`, `--ui-grid-header-height`, `--ui-grid-row-height`, `--ui-grid-footer-height`. Density modes now scale the grid row height too.
|
|
214
|
+
|
|
215
|
+
### Loading
|
|
216
|
+
|
|
217
|
+
- `Spinner` is the DSM ring; `size` is now the box size (default 24, was an 18px icon).
|
|
218
|
+
- New `LoadingMask` (centred message over busy content), `LoadingArea` (centred in its container) and `LoadingIndicator`.
|
|
219
|
+
- `Button loading` uses the ring.
|
|
220
|
+
|
|
221
|
+
### DataGrid
|
|
222
|
+
|
|
223
|
+
- Unbound `sort` now sorts internally (before, the grid did nothing unless bound); `default-sort` sets the start state; bound `sort` stays controlled.
|
|
224
|
+
- Keyboard sort (Enter/Space), `aria-sort`.
|
|
225
|
+
- Column resize with drag and arrow keys, `minWidth`, `v-model:column-widths`, `@column-resize`, `resizable`.
|
|
226
|
+
- Footer bar (`footer`, item count, `refreshable`/`refreshing`/`@refresh`), `select-on-row-click`, `max-height`, column dividers, `loading-text`.
|
|
227
|
+
- `labels` prop for every built-in string (unblocks localised pagination); `emptyText` still works.
|
|
228
|
+
- Types `DataGridColumnWidths`, `DataGridLabels`.
|
|
229
|
+
|
|
230
|
+
**Behaviour changes to check when upgrading:** `stickyHeader` now defaults to `true`; `loading` shows a mask instead of skeleton rows (`loadingRows` is ignored and deprecated); `width`/`minWidth` accept numbers; the footer counter text moved after the page controls; the grid has a trailing filler column once all widths are known.
|
|
231
|
+
|
|
232
|
+
### Toolbar
|
|
233
|
+
|
|
234
|
+
- `AppSidebar`: idle items are transparent (only the selected item is filled); optional `searchable` field and `collapsible` section headers (both off by default).
|
|
235
|
+
- `SplitButton` caret is a solid triangle.
|
|
236
|
+
- New `SplitButton`; `SearchField` gets `variant="filter"`.
|
package/README.md
CHANGED
|
@@ -253,6 +253,12 @@ const open = ref(false)
|
|
|
253
253
|
</template>
|
|
254
254
|
```
|
|
255
255
|
|
|
256
|
+
`width` (default `520px`) is the panel's maximum width. `height` or
|
|
257
|
+
`min-height` (for example `min-height="420px"`) keeps a panel with little
|
|
258
|
+
content from collapsing. In a DSM window, `<AppRoot dialog-bounds="viewport">`
|
|
259
|
+
lets dialogs be dragged out of the window, within the browser viewport. See
|
|
260
|
+
[docs/app-local-modal.md](docs/app-local-modal.md#floating-dialogs-in-a-dsm-window).
|
|
261
|
+
|
|
256
262
|
### Toast notifications
|
|
257
263
|
|
|
258
264
|
Wrap your page with `ToastProvider` in `App.vue`:
|
|
@@ -474,23 +480,20 @@ pnpm add @synopackageland/ui
|
|
|
474
480
|
|
|
475
481
|
## Releases
|
|
476
482
|
|
|
477
|
-
The
|
|
478
|
-
|
|
479
|
-
Public repository and issue tracker links will be added once those are selected.
|
|
483
|
+
The package is published to npmjs as `@synopackageland/ui` only.
|
|
484
|
+
The source repository is https://github.com/synopackageland/syno-pkg-land-ui.
|
|
480
485
|
See the [documentation](https://www.varvis.me/docs/) for usage.
|
|
481
486
|
|
|
482
487
|
### CI and tag releases
|
|
483
488
|
|
|
484
489
|
GitHub Actions runs on Ubuntu for pushes to `master` and `ci/**`, pull requests,
|
|
485
490
|
and manual dispatch. Both workflows share `.github/actions/verify`: a frozen
|
|
486
|
-
pnpm install from npmjs, `pnpm check` (build, lint, typecheck, unit tests and
|
|
487
|
-
package-content
|
|
491
|
+
pnpm install from npmjs, `pnpm check` (build, lint, typecheck, unit tests and the
|
|
492
|
+
package-content audit), `notices:check`, responsive/host/switch/layout/motion
|
|
488
493
|
browser checks, and the Histoire workbench build. pnpm and Playwright Chromium
|
|
489
494
|
are cached. Browser screenshots and measurements are retained for seven days.
|
|
490
|
-
The internal target audit inspects metadata offline; it never contacts an
|
|
491
|
-
internal registry. The existing `pnpm release` internal workflow remains available.
|
|
492
495
|
|
|
493
|
-
To release the
|
|
496
|
+
To release the package:
|
|
494
497
|
|
|
495
498
|
1. Update `package.json` to a new stable `X.Y.Z` version and add the matching
|
|
496
499
|
`## X.Y.Z (date)` section to `CHANGELOG.md`. Keep `pnpm-lock.yaml` current.
|
|
@@ -506,9 +509,9 @@ To release the public package:
|
|
|
506
509
|
|
|
507
510
|
The release workflow checks the exact tag/version, default-branch ancestry,
|
|
508
511
|
nonempty changelog section and npm version availability. It runs the same full
|
|
509
|
-
CI gates, stages
|
|
512
|
+
CI gates, stages the package into an empty directory, packs it, and audits
|
|
510
513
|
the actual tarball (every exported dist file, MIT license, notices, bundled Reka,
|
|
511
|
-
|
|
514
|
+
package name and no `publishConfig`). A separate job rechecks the artifact and
|
|
512
515
|
registry before publishing with `NPM_TOKEN`, then creates a GitHub Release from
|
|
513
516
|
that version's changelog using `GITHUB_TOKEN`. Publishing uses `--access public
|
|
514
517
|
--ignore-scripts`, without provenance. Only the publish job has `contents: write`.
|
|
@@ -538,13 +541,12 @@ GitHub-hosted job; the host gate also exercises the default-modal isolation fixt
|
|
|
538
541
|
Ubuntu CI 在 `master`、`ci/**` push、PR 與手動執行時,從 npmjs 安裝鎖定依賴,
|
|
539
542
|
共用完整 build/lint/typecheck/test/package audit/notices 與
|
|
540
543
|
responsive/host/switch/layout/motion、Histoire build 檢查。
|
|
541
|
-
快取 pnpm 與 Chromium
|
|
542
|
-
不連內部 registry;既有 `pnpm release` 保留。
|
|
544
|
+
快取 pnpm 與 Chromium;瀏覽器證據保留七天。
|
|
543
545
|
|
|
544
546
|
發版時先更新 `package.json` 版號與 CHANGELOG 對應段落,通過 CI 後合併至
|
|
545
547
|
`master`,再推送合併 commit 的 `vX.Y.Z` tag(指令如上)。Workflow 驗證 tag、
|
|
546
|
-
預設分支歷史與 npm 版本未存在,完成同一組檢查後 stage
|
|
547
|
-
實際 tgz,確保 dist、所有 exports、MIT
|
|
548
|
+
預設分支歷史與 npm 版本未存在,完成同一組檢查後 stage、pack 並稽核
|
|
549
|
+
實際 tgz,確保 dist、所有 exports、MIT/第三方授權與套件 metadata 齊全。
|
|
548
550
|
獨立 publish job 重新驗證,再以 `NPM_TOKEN` 發 npm,成功後以 changelog 建立
|
|
549
551
|
GitHub Release;不使用 provenance。npm 已成功但 GitHub Release 失敗時,另行
|
|
550
552
|
建立 Release;重跑會拒絕已存在的 npm 版本。
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
type __VLS_Props = {
|
|
2
2
|
modalScope?: 'document' | 'app';
|
|
3
|
+
/**
|
|
4
|
+
* `viewport` lets app-local dialogs leave the app window, as DSM's own
|
|
5
|
+
* dialogs do: the mask still covers only this root, the panel can be dragged
|
|
6
|
+
* anywhere in the viewport. Set it only inside a DSM window.
|
|
7
|
+
*/
|
|
8
|
+
dialogBounds?: 'app' | 'viewport';
|
|
3
9
|
};
|
|
4
10
|
declare var __VLS_7: {}, __VLS_9: {};
|
|
5
11
|
type __VLS_Slots = {} & {
|
|
@@ -7,8 +13,13 @@ type __VLS_Slots = {} & {
|
|
|
7
13
|
} & {
|
|
8
14
|
default?: (props: typeof __VLS_9) => any;
|
|
9
15
|
};
|
|
10
|
-
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
16
|
+
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
17
|
+
activate: () => any;
|
|
18
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
19
|
+
onActivate?: (() => any) | undefined;
|
|
20
|
+
}>, {
|
|
11
21
|
modalScope: "document" | "app";
|
|
22
|
+
dialogBounds: "app" | "viewport";
|
|
12
23
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
13
24
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
14
25
|
declare const _default: typeof __VLS_export;
|
|
@@ -103,6 +103,8 @@ type __VLS_Props = {
|
|
|
103
103
|
selectable?: boolean;
|
|
104
104
|
/** With `selectable`: a row click selects that row; Ctrl/Cmd-click toggles it. */
|
|
105
105
|
selectOnRowClick?: boolean;
|
|
106
|
+
/** One selected row at a time, picked by clicking the row; no checkbox column. */
|
|
107
|
+
singleSelect?: boolean;
|
|
106
108
|
page?: number;
|
|
107
109
|
pageSize?: number;
|
|
108
110
|
totalRows?: number;
|
|
@@ -172,6 +174,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
172
174
|
}) => any;
|
|
173
175
|
rowClick: (row: Record<string, unknown>) => any;
|
|
174
176
|
rowDblclick: (row: Record<string, unknown>) => any;
|
|
177
|
+
rowActivate: (row: Record<string, unknown>) => any;
|
|
175
178
|
rowExpand: (key: string) => any;
|
|
176
179
|
rowCollapse: (key: string) => any;
|
|
177
180
|
groupToggle: (groupKey: string, expanded: boolean) => any;
|
|
@@ -201,6 +204,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
201
204
|
}) => any) | undefined;
|
|
202
205
|
onRowClick?: ((row: Record<string, unknown>) => any) | undefined;
|
|
203
206
|
onRowDblclick?: ((row: Record<string, unknown>) => any) | undefined;
|
|
207
|
+
onRowActivate?: ((row: Record<string, unknown>) => any) | undefined;
|
|
204
208
|
onRowExpand?: ((key: string) => any) | undefined;
|
|
205
209
|
onRowCollapse?: ((key: string) => any) | undefined;
|
|
206
210
|
onGroupToggle?: ((groupKey: string, expanded: boolean) => any) | undefined;
|
|
@@ -222,6 +226,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
222
226
|
loading: boolean;
|
|
223
227
|
group: DataGridGroup | null;
|
|
224
228
|
loadingText: string;
|
|
229
|
+
draggable: boolean | DataGridDraggable;
|
|
225
230
|
page: number;
|
|
226
231
|
pageSize: number;
|
|
227
232
|
rowKey: string;
|
|
@@ -229,6 +234,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
229
234
|
selectedKeys: string[];
|
|
230
235
|
selectable: boolean;
|
|
231
236
|
selectOnRowClick: boolean;
|
|
237
|
+
singleSelect: boolean;
|
|
232
238
|
localSort: boolean;
|
|
233
239
|
localPagination: boolean;
|
|
234
240
|
loadingRows: number;
|
|
@@ -239,7 +245,6 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
239
245
|
expandable: DataGridExpandable | null;
|
|
240
246
|
expandedKeys: string[];
|
|
241
247
|
defaultExpandedKeys: string[];
|
|
242
|
-
draggable: boolean | DataGridDraggable;
|
|
243
248
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
244
249
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
245
250
|
declare const _default: typeof __VLS_export;
|
|
@@ -16,6 +16,8 @@ type __VLS_Props = {
|
|
|
16
16
|
loadChildren?: (node: TreeNode) => Promise<TreeNode[] | undefined>;
|
|
17
17
|
/** Localise the expand/collapse control. */
|
|
18
18
|
expandLabel?: (node: TreeNode, expanded: boolean) => string;
|
|
19
|
+
/** `accent` also colors the selected icon and text; `background` only shades the row, as DSM File Station does. */
|
|
20
|
+
selectionStyle?: 'accent' | 'background';
|
|
19
21
|
};
|
|
20
22
|
declare function nodeById(id: string): TreeNode | undefined;
|
|
21
23
|
declare function getCheckedNodes(includeHalf?: boolean): TreeNode[];
|
|
@@ -84,6 +86,7 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {
|
|
|
84
86
|
checkable: boolean;
|
|
85
87
|
defaultCheckedKeys: string[];
|
|
86
88
|
loadChildren: (node: TreeNode) => Promise<TreeNode[] | undefined>;
|
|
89
|
+
selectionStyle: "accent" | "background";
|
|
87
90
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
88
91
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
89
92
|
declare const _default: typeof __VLS_export;
|
|
@@ -64,9 +64,9 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
64
64
|
"onDrag-over"?: ((event: DragEvent) => any) | undefined;
|
|
65
65
|
"onDrag-end"?: ((event: DragEvent) => any) | undefined;
|
|
66
66
|
}>, {
|
|
67
|
+
draggable: boolean;
|
|
67
68
|
selectable: boolean;
|
|
68
69
|
expandable: boolean;
|
|
69
|
-
draggable: boolean;
|
|
70
70
|
expanded: boolean;
|
|
71
71
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
72
72
|
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
@@ -34,8 +34,8 @@ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {},
|
|
|
34
34
|
open: boolean;
|
|
35
35
|
tone: NotificationTone;
|
|
36
36
|
content: string | false;
|
|
37
|
-
duration: number | false;
|
|
38
37
|
cancel: NotificationAction;
|
|
38
|
+
duration: number | false;
|
|
39
39
|
confirm: NotificationAction;
|
|
40
40
|
paused: boolean;
|
|
41
41
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
@@ -5,7 +5,11 @@ type __VLS_Props = {
|
|
|
5
5
|
/** The level owns the action menu, so it shows a dropdown chevron. */
|
|
6
6
|
hasMenu?: boolean;
|
|
7
7
|
};
|
|
8
|
-
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
8
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
9
|
+
click: (event: MouseEvent) => any;
|
|
10
|
+
}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
|
|
11
|
+
onClick?: ((event: MouseEvent) => any) | undefined;
|
|
12
|
+
}>, {
|
|
9
13
|
current: boolean;
|
|
10
14
|
hasMenu: boolean;
|
|
11
15
|
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
@@ -4,17 +4,21 @@ type __VLS_Props = {
|
|
|
4
4
|
title?: string;
|
|
5
5
|
description?: string;
|
|
6
6
|
width?: string;
|
|
7
|
+
/** A fixed panel height, capped to the available height. */
|
|
8
|
+
height?: string;
|
|
9
|
+
/** Keeps the panel from shrinking with short content, capped to the available height. */
|
|
10
|
+
minHeight?: string;
|
|
7
11
|
closeLabel?: string;
|
|
8
12
|
/** Hides the header close affordance for fixed-flow dialogs that own their dismiss path. */
|
|
9
13
|
showClose?: boolean;
|
|
10
14
|
};
|
|
11
|
-
declare var __VLS_14: {},
|
|
15
|
+
declare var __VLS_14: {}, __VLS_71: {}, __VLS_73: {};
|
|
12
16
|
type __VLS_Slots = {} & {
|
|
13
17
|
trigger?: (props: typeof __VLS_14) => any;
|
|
14
18
|
} & {
|
|
15
|
-
default?: (props: typeof
|
|
19
|
+
default?: (props: typeof __VLS_71) => any;
|
|
16
20
|
} & {
|
|
17
|
-
footer?: (props: typeof
|
|
21
|
+
footer?: (props: typeof __VLS_73) => any;
|
|
18
22
|
};
|
|
19
23
|
declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
20
24
|
escapeKeyDown: (event: KeyboardEvent) => any;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
type __VLS_Props = {
|
|
2
|
+
host: HTMLElement | null;
|
|
3
|
+
};
|
|
4
|
+
declare var __VLS_14: {}, __VLS_16: {};
|
|
5
|
+
type __VLS_Slots = {} & {
|
|
6
|
+
default?: (props: typeof __VLS_14) => any;
|
|
7
|
+
} & {
|
|
8
|
+
default?: (props: typeof __VLS_16) => any;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_base: 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>;
|
|
11
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
12
|
+
declare const _default: typeof __VLS_export;
|
|
13
|
+
export default _default;
|
|
14
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
15
|
+
new (): {
|
|
16
|
+
$slots: S;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { IconSize } from './icon';
|
|
2
|
+
type __VLS_Props = {
|
|
3
|
+
kind?: 'folder' | 'file';
|
|
4
|
+
/** A file's name; its extension picks the icon. */
|
|
5
|
+
name?: string;
|
|
6
|
+
/** Draws an open folder. */
|
|
7
|
+
open?: boolean;
|
|
8
|
+
size?: IconSize;
|
|
9
|
+
};
|
|
10
|
+
declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
|
|
11
|
+
size: IconSize;
|
|
12
|
+
name: string;
|
|
13
|
+
open: boolean;
|
|
14
|
+
kind: "folder" | "file";
|
|
15
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
16
|
+
declare const _default: typeof __VLS_export;
|
|
17
|
+
export default _default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Ref, ShallowRef } from 'vue';
|
|
2
|
+
import { Box, Size } from '../lib/floatingDialog';
|
|
3
|
+
export declare const FLOATING_HOST_KEY = "@synopkgland/floating-host";
|
|
4
|
+
export declare const FLOATING_HOST_ATTRIBUTE = "data-ui-floating";
|
|
5
|
+
export type FloatingHost = {
|
|
6
|
+
element: ShallowRef<HTMLElement | null>;
|
|
7
|
+
/** The app root's box, or null while its window is hidden. */
|
|
8
|
+
owner: ShallowRef<Box | null>;
|
|
9
|
+
viewport: ShallowRef<Size>;
|
|
10
|
+
/** False on a narrow viewport or with a coarse pointer: panels become viewport sheets. */
|
|
11
|
+
draggable: Ref<boolean>;
|
|
12
|
+
};
|
|
13
|
+
export declare function injectFloatingHost(): FloatingHost | null;
|
|
14
|
+
/**
|
|
15
|
+
* A viewport-sized layer for dialogs that may leave the app window, as DSM's
|
|
16
|
+
* own dialogs do. It sits right after the window that owns the app, at that
|
|
17
|
+
* window's z-index, so other DSM windows still stack over both, and it hides
|
|
18
|
+
* with the window. It carries the app root attribute, so the scoped theme
|
|
19
|
+
* styles it, and it lets presses through except on panels.
|
|
20
|
+
*/
|
|
21
|
+
export declare function useFloatingHost(root: Ref<HTMLElement | null>, enabled: boolean, activate: () => void): FloatingHost | null;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Ref } from 'vue';
|
|
2
|
+
import { Point } from '../lib/floatingDialog';
|
|
3
|
+
import { FloatingHost } from './floatingHost';
|
|
4
|
+
/**
|
|
5
|
+
* Places a floating dialog panel: centered over its app window when it opens,
|
|
6
|
+
* then moved by its title bar (pointer) or title (arrow keys), always kept
|
|
7
|
+
* inside the viewport and moved along with the app window.
|
|
8
|
+
*/
|
|
9
|
+
export declare function useFloatingPlacement(handle: Ref<HTMLElement | null>, host: FloatingHost | null): {
|
|
10
|
+
position: import('vue').ShallowRef<Point | null, Point | null>;
|
|
11
|
+
draggable: import('vue').ComputedRef<boolean>;
|
|
12
|
+
onPointerdown: (event: PointerEvent) => void;
|
|
13
|
+
onKeydown: (event: KeyboardEvent) => void;
|
|
14
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -48,6 +48,8 @@ export type { TabItem } from './components/primitives/tabs/Tabs.vue';
|
|
|
48
48
|
export { default as Accordion } from './components/primitives/accordion/Accordion.vue';
|
|
49
49
|
export type { AccordionEntry } from './components/primitives/accordion/Accordion.vue';
|
|
50
50
|
export { default as Icon } from './components/primitives/icon/Icon.vue';
|
|
51
|
+
export { default as FileTypeIcon } from './components/primitives/icon/FileTypeIcon.vue';
|
|
52
|
+
export { fileTypeIcon } from './components/primitives/icon/fileType';
|
|
51
53
|
export { useIconButton } from './components/primitives/icon/useIconButton';
|
|
52
54
|
export type { IconButtonOptions } from './components/primitives/icon/useIconButton';
|
|
53
55
|
export { clearIconRegistry, getRegisteredIcon, registerIcons } from './components/primitives/icon/iconRegistry';
|