@synopackageland/ui 0.25.12 → 0.25.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.25.13 (2026-11-13)
6
+
7
+ ### Lists
8
+
9
+ - **DetailList: sub-rows inside an expanded DataGrid row.** Each line has a leading cell (a `Tag`), a text with a secondary text and trailing actions; the leading cells share one column as wide as the widest, and the list starts under the Name column's text. `max` shows that many lines and a summary line counts the rest ("3 more"), with its own leading, text and trailing slots for a "Show all" action. Under 448px wide the parts stack. Exported with its `DetailListItem` type
10
+ - **The DataGrid expand slot gets `indent`.** The pixels from the row's start to the first data column's text (past the chevron and checkbox columns), also set as `--ui-grid-detail-indent` on the expand row; `DataGridExpandSlotProps` is now exported
11
+
12
+ ### Docs
13
+
14
+ - `expandable.type: 'cell'` draws no chevron column and ignores double click; a cell slot opens the row with its `toggleExpand` prop. The type comment and README now say so
15
+
5
16
  ## 0.25.12 (2026-11-12)
6
17
 
7
18
  ### Phone
package/README.md CHANGED
@@ -548,7 +548,7 @@ DSM-style application building blocks:
548
548
  - SettingsPage / Form / FormItem / FormGroup / FormNote / InfoBox / FormActions / Fieldset (DSM-native settings structure, see [docs/layout-rules.md](docs/layout-rules.md))
549
549
  - Callout (see [docs/callout.md](docs/callout.md) for when to use a Callout, a toast or an inline note) / EmptyState / StepList
550
550
  - ConnectionTopology
551
- - DataTable / DataGrid
551
+ - DataTable / DataGrid / DetailList (sub-rows inside an expanded DataGrid row)
552
552
  - TreeView
553
553
  - FilePicker
554
554
  - AppRoot (DSM-embedded app root)
@@ -903,6 +903,20 @@ for one column.
903
903
  - **Selection.** The header box selects every selectable row of its scope: the current page (`select-all-scope="page"`, the default) or every row the filter leaves, across pages (`"all"`). It is checked when all of them are selected, mixed (`aria-checked="mixed"`, a dash) when some are, and a click when all are clears them; keys outside the scope (another page, rows the filter hides) are kept. `row-selectable(row)` returning `false` disables a row's box, and the header box skips that row and keeps its state. `row-select-disabled-reason(row)` says why: the box is wrapped in a Tab stop with that text as its accessible name and as a `Tooltip`, so the reason is visible on hover and keyboard focus, not only in a native `title`. With no selectable row the header box is disabled.
904
904
  - **Footer bar.** `footer` shows the DSM bar with the item count; `refreshable` adds the refresh button (`@refresh`, `refreshing` spins it). Without `footer` it appears when there is more than one page, a page-size choice that matters, or a `#footer` slot.
905
905
  - **Localisation.** Every built-in string goes through `labels`: `empty`, `noMatch`, `items(count)`, `filtered(count, total)`, `page(page, count)`, `previous`, `next`, `pageSize`, `refresh`, `selectAll`, `selectRow(key, row)`, `resizeColumn(label)`, `columns`, `resetColumns`, `hiddenByWidth`. `emptyText` still works.
906
+ - **Expanded rows.** `:expandable="{ type: 'row' }"` adds a chevron column (double click toggles too) and renders the `#expand` slot under an open row; bind `v-model:expanded-keys` or call the exposed `expandRow` / `collapseRow` / `expandAllRows`. `type: 'cell'` draws no chevron column and ignores double click: a `#cell-<key>` slot opens the row itself with its `toggleExpand` and `expanded` props, so give that control an `aria-expanded`. The slot gets `indent`, the pixels to the first data column's text, also set as `--ui-grid-detail-indent` on the expand row.
907
+ - **Detail rows.** For sub-rows in that slot (the copies of a file, the members of a group) use `DetailList`: it starts under the Name column's text, puts each line's `#leading` (a `Tag`) in a column as wide as the widest, then the item's `text` and `secondary` (or the default slot), then `#trailing` actions (an `IconButton` with a `label`, or a `variant="text"` Button). `max` shows that many lines and a summary line counts the rest ("3 more", or `summary` / `#summary`); `#summary-leading` and `#summary-trailing` fill that line, for example a "Show all 20 copies" button that opens a `Sheet`. A `#summary` slot keeps the line even when nothing is hidden. Under 448px the lead, text and actions stack.
908
+
909
+ ```vue
910
+ <DataGrid :columns="columns" :rows="files" selectable :expandable="{ type: 'row' }">
911
+ <template #expand="{ row }">
912
+ <DetailList :items="row.copies" :max="5" :label="`Copies of ${row.name}`">
913
+ <template #leading="{ item }"><Tag :label="item.role" :appearance="item.role === 'Keep' ? 'success' : 'warning'" /></template>
914
+ <template #trailing="{ item }"><Button variant="text" @click="toggle(item)">Keep</Button></template>
915
+ <template #summary-trailing><Button variant="text" @click="showAll(row)">Show all {{ row.copies.length }} copies</Button></template>
916
+ </DetailList>
917
+ </template>
918
+ </DataGrid>
919
+ ```
906
920
  - **Loading.** `loading` masks the table with a centred indicator; `loading-text` adds a message.
907
921
  - **Footer layout.** The footer has top and bottom divider lines and a separator
908
922
  before Refresh. In a flex column with a bounded height, the grid fills the
@@ -63,7 +63,11 @@ export type DataGridGroup = {
63
63
  compare?: (a: unknown, b: unknown) => number;
64
64
  };
65
65
  export type DataGridExpandable = {
66
- /** `row` toggles on double click as well; `cell` needs the chevron button only. */
66
+ /**
67
+ * `row` (default) adds a chevron column and toggles on double click as well.
68
+ * `cell` draws no chevron column and ignores double click: a cell slot
69
+ * toggles the row itself with its `toggleExpand` and `expanded` props.
70
+ */
67
71
  type?: 'row' | 'cell';
68
72
  /** Slot name of the expanded content; defaults to `expand`. */
69
73
  slot?: string;
@@ -129,6 +133,12 @@ export type DataGridSelectionSlotProps = {
129
133
  export type DataGridExpandSlotProps = {
130
134
  row: Record<string, unknown>;
131
135
  index: number;
136
+ /**
137
+ * Pixels from the row's start to the text of the first data column (the
138
+ * Name column). The expand row also sets it as `--ui-grid-detail-indent`,
139
+ * which `DetailList` follows.
140
+ */
141
+ indent: number;
132
142
  };
133
143
  export type { DataGridLabels } from './labels';
134
144
  export type { ResolvedDataGridLabels } from './labels';
@@ -0,0 +1,54 @@
1
+ import { DetailListItem } from './types';
2
+ declare const __VLS_export: <T extends DetailListItem>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
3
+ props: import('vue').PublicProps & __VLS_PrettifyLocal<{
4
+ items: T[];
5
+ /** Show at most this many lines; the rest are counted on the summary line. */
6
+ max?: number;
7
+ /** Text of the summary line; defaults to "{count} more" when lines are hidden. */
8
+ summary?: string;
9
+ /** Accessible name of the list, e.g. "Copies of ubuntu.iso". */
10
+ label?: string;
11
+ /** Width of the leading column, e.g. `120px`; defaults to the widest leading cell. */
12
+ leadingWidth?: string;
13
+ }> & (typeof globalThis extends {
14
+ __VLS_PROPS_FALLBACK: infer P;
15
+ } ? P : {});
16
+ expose: (exposed: {}) => void;
17
+ attrs: any;
18
+ slots: {
19
+ leading?: (props: {
20
+ item: T;
21
+ index: number;
22
+ }) => unknown;
23
+ default?: (props: {
24
+ item: T;
25
+ index: number;
26
+ }) => unknown;
27
+ trailing?: (props: {
28
+ item: T;
29
+ index: number;
30
+ }) => unknown;
31
+ 'summary-leading'?: (props: {
32
+ hidden: T[];
33
+ count: number;
34
+ }) => unknown;
35
+ summary?: (props: {
36
+ hidden: T[];
37
+ count: number;
38
+ }) => unknown;
39
+ 'summary-trailing'?: (props: {
40
+ hidden: T[];
41
+ count: number;
42
+ }) => unknown;
43
+ };
44
+ emit: {};
45
+ }>) => import('vue').VNode & {
46
+ __ctx?: NonNullable<Awaited<typeof __VLS_setup>>;
47
+ };
48
+ declare const _default: typeof __VLS_export;
49
+ export default _default;
50
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
51
+ [K in keyof T]: T[K];
52
+ } : {
53
+ [K in keyof T as K]: T[K];
54
+ }) & {};
@@ -0,0 +1,8 @@
1
+ /** One line of a DetailList; `key` must be unique in the list. */
2
+ export type DetailListItem = {
3
+ key: string | number;
4
+ /** Main text, e.g. a path; a default slot replaces it. */
5
+ text?: string;
6
+ /** Quieter text after the main text, e.g. a date. */
7
+ secondary?: string;
8
+ };
package/dist/grid.js CHANGED
@@ -4084,6 +4084,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4084
4084
  "Show password": "Show password",
4085
4085
  "Hide password": "Hide password",
4086
4086
  "Learn more": "Learn more",
4087
+ "{count} more": "{count} more",
4087
4088
  "Show less": "Show less",
4088
4089
  "Note:": "Note:",
4089
4090
  "Copy path": "Copy path",
@@ -4348,6 +4349,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4348
4349
  "Show password": "顯示密碼",
4349
4350
  "Hide password": "隱藏密碼",
4350
4351
  "Learn more": "了解更多",
4352
+ "{count} more": "還有 {count} 項",
4351
4353
  "Show less": "收合",
4352
4354
  "Note:": "附註:",
4353
4355
  "Copy path": "複製路徑",
@@ -4611,6 +4613,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4611
4613
  "Show password": "显示密码",
4612
4614
  "Hide password": "隐藏密码",
4613
4615
  "Learn more": "了解更多",
4616
+ "{count} more": "还有 {count} 项",
4614
4617
  "Show less": "收起",
4615
4618
  "Note:": "注意:",
4616
4619
  "Copy path": "复制路径",
@@ -4874,6 +4877,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
4874
4877
  "Show password": "パスワードを表示",
4875
4878
  "Hide password": "パスワードを隠す",
4876
4879
  "Learn more": "詳細",
4880
+ "{count} more": "ほか {count} 件",
4877
4881
  "Show less": "閉じる",
4878
4882
  "Note:": "注:",
4879
4883
  "Copy path": "パスをコピー",
@@ -5137,6 +5141,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5137
5141
  "Show password": "비밀번호 표시",
5138
5142
  "Hide password": "비밀번호 숨기기",
5139
5143
  "Learn more": "자세히 알아보기",
5144
+ "{count} more": "{count}개 더",
5140
5145
  "Show less": "간단히 보기",
5141
5146
  "Note:": "참고:",
5142
5147
  "Copy path": "경로 복사",
@@ -5400,6 +5405,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5400
5405
  "Show password": "Passwort anzeigen",
5401
5406
  "Hide password": "Passwort verbergen",
5402
5407
  "Learn more": "Mehr erfahren",
5408
+ "{count} more": "{count} weitere",
5403
5409
  "Show less": "Weniger anzeigen",
5404
5410
  "Note:": "Hinweis:",
5405
5411
  "Copy path": "Pfad kopieren",
@@ -5663,6 +5669,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5663
5669
  "Show password": "Afficher le mot de passe",
5664
5670
  "Hide password": "Masquer le mot de passe",
5665
5671
  "Learn more": "En savoir plus",
5672
+ "{count} more": "{count} de plus",
5666
5673
  "Show less": "Afficher moins",
5667
5674
  "Note:": "Remarque :",
5668
5675
  "Copy path": "Copier le chemin",
@@ -5926,6 +5933,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
5926
5933
  "Show password": "Mostrar contraseña",
5927
5934
  "Hide password": "Ocultar contraseña",
5928
5935
  "Learn more": "Más información",
5936
+ "{count} more": "{count} más",
5929
5937
  "Show less": "Mostrar menos",
5930
5938
  "Note:": "Nota:",
5931
5939
  "Copy path": "Copiar ruta",
@@ -6189,6 +6197,7 @@ const qe = (e, t) => e.x >= t.x && e.x < t.x + t.width && e.y >= t.y && e.y < t.
6189
6197
  "Show password": "Mostra password",
6190
6198
  "Hide password": "Nascondi password",
6191
6199
  "Learn more": "Scopri di più",
6200
+ "{count} more": "Altri {count}",
6192
6201
  "Show less": "Mostra meno",
6193
6202
  "Note:": "Nota:",
6194
6203
  "Copy path": "Copia percorso",
@@ -238,6 +238,7 @@ export declare const englishUiText: {
238
238
  readonly "Show password": "Show password";
239
239
  readonly "Hide password": "Hide password";
240
240
  readonly "Learn more": "Learn more";
241
+ readonly "{count} more": "{count} more";
241
242
  readonly "Show less": "Show less";
242
243
  readonly "Note:": "Note:";
243
244
  readonly "Copy path": "Copy path";
package/dist/index.d.ts CHANGED
@@ -176,7 +176,7 @@ export { isPicture, isUnsupportedPicture } from './lib/files';
176
176
  export type { FileItem, FileState } from './lib/files';
177
177
  export type { DataTableColumn } from './components/composite/data-table/DataTable.vue';
178
178
  export { default as DataGrid } from './components/composite/data-grid/DataGrid.vue';
179
- export type { DataGridColumn, DataGridColumnWidths, DataGridLabels, ResolvedDataGridLabels, DataGridSort, DataGridGroup, DataGridExpandable, DataGridDraggable, DataGridReorder, DataGridCellUpdate, DataGridAdapter, DataGridCellSlotProps } from './components/composite/data-grid/DataGrid.vue';
179
+ export type { DataGridColumn, DataGridColumnWidths, DataGridLabels, ResolvedDataGridLabels, DataGridSort, DataGridGroup, DataGridExpandable, DataGridDraggable, DataGridReorder, DataGridCellUpdate, DataGridAdapter, DataGridCellSlotProps, DataGridExpandSlotProps } from './components/composite/data-grid/DataGrid.vue';
180
180
  export type { TableColumnType, TableColumnAlign } from './components/composite/data-grid/columnType';
181
181
  export { loadGridState, saveGridState, type DataGridViewState } from './components/composite/data-grid/viewState';
182
182
  export { default as TreeView } from './components/composite/tree-view/TreeView.vue';
@@ -319,3 +319,5 @@ export { filePickerText } from './i18n/filePicker';
319
319
  export type { FilePickerText } from './i18n/filePicker';
320
320
  export { default as Link } from './components/primitives/link/Link.vue';
321
321
  export { default as KeyValueRow } from './components/composite/key-value-row/KeyValueRow.vue';
322
+ export { default as DetailList } from './components/composite/detail-list/DetailList.vue';
323
+ export type { DetailListItem } from './components/composite/detail-list/types';