@synopackageland/ui 0.9.5 → 0.9.6

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,33 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.6 (2026-10-14)
4
+
5
+ Fixes from the 0.10.3 acceptance run, plus `InputGroup`, `CellText openLabel` and `Space wrap`. **Behavior change:** a floating `Dialog` keeps a 12px margin from the browser viewport and the DSM taskbar, so it can be up to 24px shorter; narrow label columns shrink to 40% of the row.
6
+ 修正 0.10.3 驗收發現的問題,並新增 `InputGroup`、`CellText openLabel` 與 `Space wrap`。**行為變更:** 浮動 `Dialog` 與瀏覽器視窗及 DSM 工作列保持 12px 間距,因此最多矮 24px;窄的標籤欄縮為列寬的 40%。
7
+
8
+ - A sticky `FormActions` only sticks while the scroll area has room for it below the form's top. In a full-page app whose form starts near the bottom of the page, the bar was pinned over the form's first fields and cut off; it now stays in the flow until there is room.
9
+ - 黏性 `FormActions` 只在捲動區於表單頂端下方有足夠空間時才黏在底部。全頁 App 中表單從頁面底部附近開始時,按鈕列原本被固定在表單前幾個欄位上而被截斷;現在空間不足時留在原位。
10
+ - A floating `Dialog` keeps the same 12px margin above (below the DSM taskbar) and below. A dialog as tall as the room touched the taskbar at the top and the viewport edge at the bottom.
11
+ - 浮動 `Dialog` 上方(DSM 工作列下)與下方保持相同的 12px 間距。先前與可用空間等高的對話框,上緣貼著工作列、下緣貼著視窗邊緣。
12
+ - In a narrow card, the label column of `KeyValueRow`, `SettingsRow` and `FormItem` (horizontal) shrinks to at most 40% of the row (`--ui-label-column`), and labels and `KeyValueRow` values break between words, not inside one (`凌晨2:39` stays together).
13
+ - 窄卡片中,`KeyValueRow`、`SettingsRow` 與 `FormItem`(水平)的標籤欄最多佔列寬 40%(`--ui-label-column`),標籤與 `KeyValueRow` 的值在詞與詞之間換行,不在詞中斷開(「凌晨2:39」不拆開)。
14
+ - `Card` footers line up at the bottom of a `CardGrid` row: the body grows to fill a card made taller by its neighbours.
15
+ - `CardGrid` 同一列的 `Card` 底部列對齊在底端:卡片被鄰居撐高時,內容區會填滿多出的高度。
16
+ - `FormItem`s nested in a `SettingsSection` (or any wrapper) inside a `Form` keep the form's field gap; before, only the form's direct children got it and nested fields touched. The automatic gap follows `--ui-field-gap`: 6px in a DSM window (8px vertical), 10px on a full page.
17
+ - `Form` 內巢狀在 `SettingsSection`(或其他包裝)中的 `FormItem` 也套用表單欄位間距;先前只有表單的直接子元素有間距,巢狀欄位彼此相貼。自動間距改用 `--ui-field-gap`:DSM 視窗 6px(垂直 8px),全頁 10px。
18
+ - A two-line `CellText` has a 2px gap between its lines, and `DataTable` cells have 6px vertical padding, so stacked cells no longer touch the row lines.
19
+ - 兩行的 `CellText` 行間有 2px 間距,`DataTable` 儲存格上下各 6px 內距,堆疊的儲存格不再貼著列線。
20
+ - A line break in a `Dialog` or `MessageBox` description stays a line break.
21
+ - `Dialog` 與 `MessageBox` 描述中的換行會保留。
22
+ - `Space` has `wrap`: a row of tags or buttons flows onto more lines with the same gap.
23
+ - `Space` 新增 `wrap`:一排標籤或按鈕空間不足時以相同間距換行。
24
+ - `CellText` has `openLabel`: the main text becomes a link-styled button that emits `open` (for example to open a file in File Station), keeps the ellipsis and shows the label as its tooltip; `openDisabled` disables it.
25
+ - `CellText` 新增 `openLabel`:主文字變成連結樣式的按鈕並發出 `open`(例如在 File Station 開啟檔案),保留省略號並以該標籤作為提示;`openDisabled` 可停用。
26
+ - New `InputGroup` puts a field and the buttons acting on it on one line with an 8px gap; the field takes the room left.
27
+ - 新增 `InputGroup`:欄位與作用於它的按鈕排在同一行,間距 8px,欄位佔剩餘空間。
28
+ - The JSON catalog and `syno-pkg-land-ui describe` cover `CellText`, `CellStatus`, `ListItem` and `InputGroup`.
29
+ - JSON catalog 與 `syno-pkg-land-ui describe` 新增 `CellText`、`CellStatus`、`ListItem` 與 `InputGroup`。
30
+
3
31
  ## 0.9.5 (2026-10-14)
4
32
 
5
33
  Settings rows, buttons, callouts and status colours are restyled; dialogs, menus and lists stay inside the DSM window and below its taskbar. **Behavior change:** a `Button` or `IconButton` whose click handler returns a promise is busy and disabled until it settles and drops a second click. The rest is additive.
package/README.md CHANGED
@@ -505,13 +505,18 @@ Use the pnpm version specified in `package.json`.
505
505
  ```bash
506
506
  pnpm story # component workbench
507
507
  pnpm dev # rebuild dist when library source changes
508
- pnpm check # lint, typecheck, tests, and production build
508
+ pnpm check # production build, then lint, typecheck and tests in parallel, then the package audit
509
+ pnpm check:fast # as check, but only the tests the changes since origin/master reach (vitest --changed)
509
510
  pnpm story:build # build the component workbench
510
511
  pnpm check:host # after pnpm build: DSM host simulation screenshots (Chrome)
511
512
  pnpm check:switch # after pnpm build: Switch knob geometry and click toggling (Chrome)
512
513
  pnpm check:topology # after pnpm build: ConnectionTopology motion, keyboard and narrow layout (Chrome)
513
514
  ```
514
515
 
516
+ Use `pnpm check:fast` while developing (`SYNOPKGLAND_GATE_BASE` sets the base),
517
+ and `pnpm check` once before a release: the full run is the release gate.
518
+ `check` prints one line per passing task and a failing task's whole log.
519
+
515
520
  `pnpm check:host` serves `tests/dsm-host` and screenshots each overlay scene in
516
521
  English and Traditional Chinese with headless Chrome (set `CHROME` to its path
517
522
  if it is not in `/Applications`), with and without `host-simulation.css`, a
@@ -6,7 +6,7 @@ type __VLS_Props = {
6
6
  rules?: FormRules;
7
7
  /** `'horizontal'` puts the label beside the control, `'vertical'` above it. */
8
8
  direction?: FormDirection;
9
- /** Gap between items; `'auto'` uses `dense` (horizontal) or `regular` (vertical). */
9
+ /** Gap between items, nested ones included; `'auto'` uses `--ui-field-gap` (horizontal) or 2px more (vertical). */
10
10
  spacing?: FormSpacing;
11
11
  /** Maximum width of every control: `'xs'`–`'lg'`, `'full'` or a CSS length. A FormItem can override it. */
12
12
  fieldWidth?: FieldWidth;
@@ -2,7 +2,7 @@ type __VLS_Props = {
2
2
  align?: 'start' | 'end';
3
3
  /** Indents the actions past a horizontal form's label column, so they line up with the fields. */
4
4
  labelWidth?: string;
5
- /** Indents the actions past the shared label column (`--ui-label-width`). */
5
+ /** Indents the actions past the shared label column (`--ui-label-column`). */
6
6
  inset?: boolean;
7
7
  /** Keeps the actions in view at the bottom of a long scrolling form, over a divider. */
8
8
  sticky?: boolean;
@@ -6,15 +6,25 @@ type __VLS_Props = {
6
6
  layout?: 'stacked' | 'inline';
7
7
  /** A leading icon, e.g. a file type. */
8
8
  icon?: Component;
9
+ /** Makes the main text a button that emits `open`; the label is its tooltip, e.g. "Open in File Station". */
10
+ openLabel?: string;
11
+ openDisabled?: boolean;
9
12
  };
10
- declare var __VLS_6: {}, __VLS_8: {};
13
+ declare var __VLS_6: {}, __VLS_8: {}, __VLS_10: {};
11
14
  type __VLS_Slots = {} & {
12
15
  default?: (props: typeof __VLS_6) => any;
13
16
  } & {
14
- secondary?: (props: typeof __VLS_8) => any;
17
+ default?: (props: typeof __VLS_8) => any;
18
+ } & {
19
+ secondary?: (props: typeof __VLS_10) => any;
15
20
  };
16
- declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
21
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
22
+ open: () => any;
23
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
24
+ onOpen?: (() => any) | undefined;
25
+ }>, {
17
26
  layout: "stacked" | "inline";
27
+ openDisabled: boolean;
18
28
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
29
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
30
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,13 @@
1
+ declare var __VLS_1: {};
2
+ type __VLS_Slots = {} & {
3
+ default?: (props: typeof __VLS_1) => any;
4
+ };
5
+ 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>;
6
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
7
+ declare const _default: typeof __VLS_export;
8
+ export default _default;
9
+ type __VLS_WithSlots<T, S> = T & {
10
+ new (): {
11
+ $slots: S;
12
+ };
13
+ };
@@ -1,5 +1,5 @@
1
1
  import { SpaceAlign, SpaceDirection, SpaceJustify } from './space';
2
- /** Lays children out in one line with a shared gap and alignment. */
2
+ /** Lays children out in one line (or, with `wrap`, several) with a shared gap and alignment. */
3
3
  type __VLS_Props = {
4
4
  alignItems?: SpaceAlign;
5
5
  /** @deprecated Use `alignItems`; kept so existing templates keep working. */
@@ -8,6 +8,8 @@ type __VLS_Props = {
8
8
  direction?: SpaceDirection;
9
9
  /** A spacing name (`regular`) or a pixel number. */
10
10
  spacing?: 'none' | 'dense' | 'compact' | 'regular' | 'relaxed' | number;
11
+ /** Lets the items wrap onto more lines, with the same gap between lines. */
12
+ wrap?: boolean;
11
13
  };
12
14
  declare var __VLS_1: {};
13
15
  type __VLS_Slots = {} & {
@@ -16,6 +18,7 @@ type __VLS_Slots = {} & {
16
18
  declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
17
19
  direction: SpaceDirection;
18
20
  spacing: "none" | "dense" | "compact" | "regular" | "relaxed" | number;
21
+ wrap: boolean;
19
22
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
20
23
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
21
24
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,8 @@
1
+ import { Ref } from 'vue';
2
+ /**
3
+ * Whether a bottom-sticky element fits between the top of its parent and the
4
+ * bottom of its scrolling area. A sticky box never rises above its parent, so
5
+ * while the parent starts closer to that edge than the box is tall, sticking
6
+ * would hold the box past the edge, cut off; it waits at the parent's end.
7
+ */
8
+ export declare function useStickyRoom(element: Ref<HTMLElement | null>, enabled: () => boolean): Ref<boolean, boolean>;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export { default as Button } from './components/primitives/button/Button.vue';
2
2
  export { default as IconButton } from './components/primitives/button/IconButton.vue';
3
3
  export { default as Input } from './components/primitives/input/Input.vue';
4
4
  export { default as Textarea } from './components/primitives/input/Textarea.vue';
5
+ export { default as InputGroup } from './components/primitives/input-group/InputGroup.vue';
5
6
  export { default as InputSteppers } from './components/primitives/input-steppers/InputSteppers.vue';
6
7
  export type { InputSteppersMenuItem } from './components/primitives/input-steppers/InputSteppers.vue';
7
8
  export { default as Slider } from './components/primitives/slider/Slider.vue';