@synopackageland/ui 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/LICENSE +21 -0
  2. package/LICENSES/THIRD_PARTY.md +1866 -0
  3. package/README.md +440 -0
  4. package/dist/components/app/app-action-bar/AppActionBar.vue.d.ts +15 -0
  5. package/dist/components/app/app-layout/AppLayout.vue.d.ts +26 -0
  6. package/dist/components/app/app-root/AppRoot.vue.d.ts +20 -0
  7. package/dist/components/app/app-sidebar/AppSidebar.vue.d.ts +34 -0
  8. package/dist/components/app/app-toolbar/AppToolbar.vue.d.ts +22 -0
  9. package/dist/components/app/page-header/PageHeader.vue.d.ts +17 -0
  10. package/dist/components/app/section-tabs/SectionTabs.vue.d.ts +16 -0
  11. package/dist/components/composite/callout/Callout.vue.d.ts +19 -0
  12. package/dist/components/composite/data-grid/DataGrid.vue.d.ts +126 -0
  13. package/dist/components/composite/data-grid/columnWidths.d.ts +6 -0
  14. package/dist/components/composite/data-grid/labels.d.ts +12 -0
  15. package/dist/components/composite/data-table/DataTable.vue.d.ts +34 -0
  16. package/dist/components/composite/empty-state/EmptyState.vue.d.ts +19 -0
  17. package/dist/components/composite/file-picker/FilePicker.vue.d.ts +49 -0
  18. package/dist/components/composite/search-field/SearchField.vue.d.ts +19 -0
  19. package/dist/components/composite/settings-row/SettingsRow.vue.d.ts +22 -0
  20. package/dist/components/composite/settings-section/SettingsSection.vue.d.ts +21 -0
  21. package/dist/components/composite/tree-view/TreeView.vue.d.ts +44 -0
  22. package/dist/components/primitives/accordion/Accordion.vue.d.ts +28 -0
  23. package/dist/components/primitives/badge/Badge.vue.d.ts +18 -0
  24. package/dist/components/primitives/button/Button.vue.d.ts +28 -0
  25. package/dist/components/primitives/button/IconButton.vue.d.ts +25 -0
  26. package/dist/components/primitives/checkbox/Checkbox.vue.d.ts +16 -0
  27. package/dist/components/primitives/context-menu/ContextMenu.vue.d.ts +26 -0
  28. package/dist/components/primitives/context-menu/ContextMenuItems.vue.d.ts +13 -0
  29. package/dist/components/primitives/context-menu/types.d.ts +13 -0
  30. package/dist/components/primitives/date-picker/DatePicker.vue.d.ts +25 -0
  31. package/dist/components/primitives/dialog/Dialog.vue.d.ts +44 -0
  32. package/dist/components/primitives/dropdown-menu/DropdownMenu.vue.d.ts +36 -0
  33. package/dist/components/primitives/input/Input.vue.d.ts +21 -0
  34. package/dist/components/primitives/input/Textarea.vue.d.ts +19 -0
  35. package/dist/components/primitives/loading/LoadingArea.vue.d.ts +8 -0
  36. package/dist/components/primitives/loading/LoadingIndicator.vue.d.ts +10 -0
  37. package/dist/components/primitives/loading/LoadingMask.vue.d.ts +20 -0
  38. package/dist/components/primitives/popover/Popover.vue.d.ts +24 -0
  39. package/dist/components/primitives/progress/Progress.vue.d.ts +11 -0
  40. package/dist/components/primitives/radio-group/RadioGroup.vue.d.ts +22 -0
  41. package/dist/components/primitives/select/Select.vue.d.ts +21 -0
  42. package/dist/components/primitives/separator/Separator.vue.d.ts +8 -0
  43. package/dist/components/primitives/sheet/Sheet.vue.d.ts +47 -0
  44. package/dist/components/primitives/skeleton/Skeleton.vue.d.ts +12 -0
  45. package/dist/components/primitives/spinner/Spinner.vue.d.ts +10 -0
  46. package/dist/components/primitives/split-button/SplitButton.vue.d.ts +30 -0
  47. package/dist/components/primitives/surface/Surface.vue.d.ts +22 -0
  48. package/dist/components/primitives/switch/Switch.vue.d.ts +15 -0
  49. package/dist/components/primitives/tabs/Tabs.vue.d.ts +28 -0
  50. package/dist/components/primitives/toast/ToastProvider.vue.d.ts +21 -0
  51. package/dist/components/primitives/toast/toast.d.ts +25 -0
  52. package/dist/components/primitives/tooltip/Tooltip.vue.d.ts +21 -0
  53. package/dist/index.d.ts +59 -0
  54. package/dist/index.js +15795 -0
  55. package/dist/lib/appRoot.d.ts +2 -0
  56. package/dist/lib/cn.d.ts +2 -0
  57. package/dist/lib/localModal.d.ts +44 -0
  58. package/dist/reka-runtime.json +23 -0
  59. package/dist/theme.css +1 -0
  60. package/dist/themes/dsm7-embedded-reset.css +1 -0
  61. package/dist/themes/dsm7-embedded-theme.css +1 -0
  62. package/dist/themes/dsm7-embedded.css +1 -0
  63. package/dist/themes/dsm7.css +1 -0
  64. package/docs/app-local-modal.md +120 -0
  65. package/package.json +51 -0
package/README.md ADDED
@@ -0,0 +1,440 @@
1
+ # @synopackageland/ui
2
+
3
+ Vue 3 component library with a DSM 7-inspired theme for application interiors.
4
+ Import the components you need into your Vue application.
5
+
6
+ ## Installation
7
+
8
+ Synology Package Land UI provides Vue components for Synology package applications,
9
+ including an embedded theme and AppRoot for shared DSM desktop windows.
10
+ See the [public documentation](https://www.varvis.me/docs/).
11
+
12
+ ```bash
13
+ npm install @synopackageland/ui --registry https://registry.npmjs.org
14
+ ```
15
+
16
+ Vue **3.5 or later within Vue 3** is required by the package. Building from
17
+ source requires Node.js **20+** and pnpm **10.33.2**.
18
+
19
+ ## Quick start
20
+
21
+ ### 1. Import the stylesheet once
22
+
23
+ In your application's entry point (`src/main.ts`):
24
+
25
+ ```ts
26
+ import { createApp } from 'vue'
27
+ import App from './App.vue'
28
+ import '@synopackageland/ui/theme.css'
29
+
30
+ createApp(App).mount('#app')
31
+ ```
32
+
33
+ The stylesheet includes the DSM 7 theme and compiled component utilities. You do
34
+ not need to install or configure Tailwind to use these components. The package
35
+ also exports `themes/dsm7.css` with the same content; import only one of them.
36
+ For an app inside a DSM window, see [Using inside a DSM window](#using-inside-a-dsm-window).
37
+
38
+ ### 2. Import and use components
39
+
40
+ Example `App.vue`:
41
+
42
+ ```vue
43
+ <script setup lang="ts">
44
+ import { ref } from 'vue'
45
+ import { Button, Input, Select } from '@synopackageland/ui'
46
+ import type { SelectOption } from '@synopackageland/ui'
47
+
48
+ const name = ref('')
49
+ const access = ref('read')
50
+ const message = ref('')
51
+ const options: SelectOption[] = [
52
+ { label: 'Read only', value: 'read' },
53
+ { label: 'Read / write', value: 'write' },
54
+ ]
55
+
56
+ function save() {
57
+ message.value = `Saved ${name.value} with ${access.value} access`
58
+ }
59
+ </script>
60
+
61
+ <template>
62
+ <form class="settings-form" @submit.prevent="save">
63
+ <label for="name">Name</label>
64
+ <Input id="name" v-model="name" placeholder="Enter a name" />
65
+ <Select v-model="access" :options="options" aria-label="Access level" />
66
+ <Button type="submit" variant="primary" :disabled="!name.trim()">
67
+ Save
68
+ </Button>
69
+ <p role="status">{{ message }}</p>
70
+ </form>
71
+ </template>
72
+
73
+ <style scoped>
74
+ .settings-form {
75
+ display: grid;
76
+ gap: 12px;
77
+ max-width: 360px;
78
+ padding: 24px;
79
+ }
80
+ </style>
81
+ ```
82
+
83
+ Components imported in `<script setup>` are available directly in the template.
84
+ No `app.use()` plugin registration is required. JavaScript consumers can omit
85
+ `lang="ts"`, the type import, and the `: SelectOption[]` annotation.
86
+
87
+ ## Using inside a DSM window
88
+
89
+ A DSM package window is not a page of its own: every window shares the DSM
90
+ desktop's document and its stylesheets. Two things break `theme.css` there:
91
+
92
+ - DSM's stylesheets are not in cascade layers, and an unlayered rule beats every
93
+ layered one whatever its specificity. `theme.css` is layered (Tailwind 4), so
94
+ DSM's element resets such as `div,p,td{margin:0;padding:0}` win over the
95
+ library's utilities.
96
+ - `theme.css` puts its tokens on `:root`, where they would restyle the desktop
97
+ and collide with other apps that use another version of this library.
98
+
99
+ Use the embedded theme and the `AppRoot` component instead:
100
+
101
+ ```ts
102
+ // the DSM entry of your app, instead of theme.css
103
+ import '@synopackageland/ui/themes/dsm7-embedded.css'
104
+ ```
105
+
106
+ ```vue
107
+ <script setup lang="ts">
108
+ import { AppRoot, ToastProvider } from '@synopackageland/ui'
109
+ </script>
110
+
111
+ <template>
112
+ <AppRoot style="height: 100%">
113
+ <ToastProvider>
114
+ <!-- your app -->
115
+ </ToastProvider>
116
+ </AppRoot>
117
+ </template>
118
+ ```
119
+
120
+ `themes/dsm7-embedded.css`:
121
+
122
+ - has no `@layer`, so library classes beat DSM's element rules;
123
+ - scopes every token and rule to the app root, the element with the
124
+ `data-ui-app` attribute (`APP_ROOT_ATTRIBUTE` / `APP_ROOT_SELECTOR` are
125
+ exported), so nothing outside it changes;
126
+ - starts with a host reset that reverts, inside the app root, what DSM's
127
+ element-only rules set (margins, paddings, borders, outline, position,
128
+ display, fonts, colors, list style, `appearance`, …), including the
129
+ `body button:lang(…)` font rules;
130
+ - makes the app root the containing block of fixed overlays, so dialogs,
131
+ sheets and toasts stay inside the window.
132
+
133
+ `AppRoot` renders `<div data-ui-app data-syno-ui>` and routes every overlay
134
+ portal (Dialog, Sheet, Toast, Popover, Select, DropdownMenu, ContextMenu,
135
+ Tooltip) into itself, not `document.body`, where the scoped tokens
136
+ and reset would not reach them. Each `AppRoot` teleports into its own element;
137
+ theme and density tokens on sibling roots reach their own portals. Modal state
138
+ is shared across the document by default. Use `modal-scope="app"` for independent
139
+ Dialog/Sheet and popup layers (see below). `AppRoot` disables
140
+ reka-ui's scrollbar compensation, but this does not prevent other body mutations.
141
+
142
+ Give each independently mounted Vue application a unique ID prefix **before
143
+ mounting**, so generated dialog titles/descriptions and other ARIA references
144
+ cannot resolve to another app's elements:
145
+
146
+ ```ts
147
+ const app = createApp(App)
148
+ app.config.idPrefix = 'my-package' // unique across apps in this document
149
+ app.mount('#my-package-root')
150
+ ```
151
+
152
+ Without `AppRoot`, put `data-ui-app` on your mount element and wrap the app in
153
+ reka-ui's `<ConfigProvider :teleport-to="rootElement" :scroll-body="false">`.
154
+ Inside `AppRoot`, a nested `ConfigProvider` (for `dir` or `locale`) must pass
155
+ the same `teleport-to`, and your own `<Teleport>`s must target an element inside
156
+ the root.
157
+
158
+ Theme overrides go on your own app root, after the library stylesheet. Use a
159
+ package-specific selector, so an override does not also match other apps:
160
+
161
+ ```css
162
+ [data-ui-app][data-package='my-package'] {
163
+ --ui-primary: #0086e5;
164
+ }
165
+ ```
166
+
167
+ Set `data-package="my-package"` on that app's `<AppRoot>`.
168
+
169
+ Keep your app's own CSS out of cascade layers too, for the same reason.
170
+
171
+ If your app has its own base rules for bare elements, such as a button reset
172
+ or heading margins, load the embedded theme as its two parts, with your rules
173
+ between them:
174
+
175
+ ```ts
176
+ import '@synopackageland/ui/themes/dsm7-embedded-reset.css'
177
+ import './base.css' // e.g. [data-ui-app] :where(button) { border: 0 solid; }
178
+ import '@synopackageland/ui/themes/dsm7-embedded-theme.css'
179
+ ```
180
+
181
+ Your rules and the library classes have the same specificity as the reset, so
182
+ order decides: after the reset, your rules are not reverted; before the theme,
183
+ they do not override library classes. Loaded one after the other, the two parts
184
+ render as `dsm7-embedded.css`. The reset reverts `font-family` on form controls
185
+ with a doubled root attribute, `[data-ui-app][data-ui-app] :where(button, input,
186
+ select, textarea)`, to beat DSM's `body button:lang(…)` rules; a font rule of
187
+ yours for them needs the same selector.
188
+
189
+ Known limits:
190
+
191
+ - Tailwind sizes are in `rem`, which follows the desktop's `html` font size.
192
+ - DSM rules more specific than one class (`.x-panel div`, `#id p`) are not
193
+ reverted; the reset covers element-only rules.
194
+ - Default Dialog/Sheet modality remains document-wide: it locks body scrolling
195
+ and pointer events, disables earlier panels and hides other apps.
196
+ - The bundled patched Reka restores host body style values/priorities after the
197
+ final lock release, including padding-right/margin-right. Consumers need no
198
+ Reka installation or package-manager patch.
199
+ - With `<AppRoot modal-scope="app" style="height: 100%">`, Dialog/Sheet and popup
200
+ layers instead block only that app's background. Other apps/host remain usable;
201
+ local dialogs omit aria-modal and permit deliberate focus switching. Provide
202
+ a bounded root size and an accessible host window switch. Select scope at mount
203
+ time. Nested app-local AppRoots and simultaneous app/document overlays are unsupported
204
+ and produce explicit errors. Multiple SDK/Reka runtime copies do not coordinate.
205
+ - Independently mounted Vue apps without unique `app.config.idPrefix` values
206
+ generate colliding IDs. `AppRoot` does not assign those prefixes automatically.
207
+ - Keyframe names (`ui-*`, `spin`, `pulse`) and Tailwind's `@property`
208
+ registrations are global, as in `theme.css`.
209
+
210
+ Body cleanup is now a normal regression test. The unprefixed ID collision
211
+ remains an expected failure, reproducible with `UI_ISOLATION_STRICT=1`.
212
+ See [App-local modal](docs/app-local-modal.md) for the implemented contract,
213
+ patch delivery and browser support limits. Vue stays an external peer; the
214
+ patched Reka implementation is bundled and tree-shakeable.
215
+
216
+ Run `pnpm check:local-browser [output-dir] [existing-ego-space-id]` for a clean
217
+ packed-consumer Chromium acceptance run (requires ego-browser).
218
+
219
+ ## Common component patterns
220
+
221
+ ### Dialog
222
+
223
+ Use `v-model:open` to control visibility. The default slot contains the body;
224
+ `trigger` and `footer` provide the opening button and action area.
225
+
226
+ ```vue
227
+ <script setup lang="ts">
228
+ import { ref } from 'vue'
229
+ import { Button, Dialog } from '@synopackageland/ui'
230
+
231
+ const open = ref(false)
232
+ </script>
233
+
234
+ <template>
235
+ <Dialog v-model:open="open" title="Settings" description="Review your settings.">
236
+ <template #trigger>
237
+ <Button>Open settings</Button>
238
+ </template>
239
+ <p>Your settings content goes here.</p>
240
+ <template #footer>
241
+ <Button variant="primary" @click="open = false">Done</Button>
242
+ </template>
243
+ </Dialog>
244
+ </template>
245
+ ```
246
+
247
+ ### Toast notifications
248
+
249
+ Wrap your page with `ToastProvider` in `App.vue`:
250
+
251
+ ```vue
252
+ <script setup lang="ts">
253
+ import { ToastProvider } from '@synopackageland/ui'
254
+ import SettingsPage from './SettingsPage.vue'
255
+ </script>
256
+
257
+ <template>
258
+ <ToastProvider>
259
+ <SettingsPage />
260
+ </ToastProvider>
261
+ </template>
262
+ ```
263
+
264
+ Then call `useToast()` inside a descendant, such as `SettingsPage.vue`:
265
+
266
+ ```vue
267
+ <script setup lang="ts">
268
+ import { Button, useToast } from '@synopackageland/ui'
269
+
270
+ const toast = useToast()
271
+ </script>
272
+
273
+ <template>
274
+ <Button @click="toast.success('Settings applied')">Show notification</Button>
275
+ </template>
276
+ ```
277
+
278
+ `useToast()` requires a provider ancestor; calling it in the same component that
279
+ renders the provider does not satisfy that requirement.
280
+
281
+ ### Application layout
282
+
283
+ ```vue
284
+ <script setup lang="ts">
285
+ import { AppLayout, Button, PageHeader } from '@synopackageland/ui'
286
+ </script>
287
+
288
+ <template>
289
+ <AppLayout min-height="100vh">
290
+ <PageHeader title="Package settings" description="Manage your application.">
291
+ <template #actions>
292
+ <Button variant="primary">Save</Button>
293
+ </template>
294
+ </PageHeader>
295
+ <section style="padding: 24px">Your page content goes here.</section>
296
+ </AppLayout>
297
+ </template>
298
+ ```
299
+
300
+ `AppLayout` also accepts `sidebar`, `toolbar`, and `footer` slots.
301
+
302
+ ## Theme override
303
+
304
+ Components use semantic CSS tokens. Import your override stylesheet after the library stylesheet to customize branding:
305
+
306
+ ```css
307
+ :root {
308
+ --ui-primary: #0086e5;
309
+ --ui-primary-hover: #0077cf;
310
+ --ui-radius-md: 6px;
311
+ --ui-page-padding-x: 24px;
312
+ --ui-section-gap: 16px;
313
+ }
314
+ ```
315
+
316
+ Density can be switched per application subtree:
317
+
318
+ ```html
319
+ <main data-ui-density="compact">
320
+ <!-- controls, navigation rows, toolbar and page spacing become denser -->
321
+ </main>
322
+ ```
323
+
324
+ ## Current component set
325
+
326
+ Primitives:
327
+
328
+ - Button / IconButton
329
+ - Input / Textarea
330
+ - Checkbox / RadioGroup / Switch
331
+ - Select
332
+ - Badge / Separator / Spinner / LoadingMask / LoadingArea / Progress / Skeleton / Surface
333
+ - SplitButton
334
+ - Tooltip / Popover / DropdownMenu / ContextMenu / Dialog
335
+ - Sheet / Drawer
336
+ - DatePicker
337
+ - ToastProvider + `useToast()`
338
+ - Tabs / Accordion
339
+
340
+ DSM-style application building blocks:
341
+
342
+ - SearchField
343
+ - SettingsRow / SettingsSection
344
+ - Callout / EmptyState
345
+ - DataTable / DataGrid
346
+ - TreeView
347
+ - FilePicker
348
+ - AppRoot (DSM-embedded app root)
349
+ - AppLayout / AppSidebar / AppToolbar / AppActionBar
350
+ - PageHeader / SectionTabs
351
+
352
+ `FilePicker` owns file selection/validation/drop-zone UI only; applications remain responsible for upload transport.
353
+
354
+ ### DataGrid
355
+
356
+ ```vue
357
+ <DataGrid
358
+ :columns="[{ key: 'name', label: 'Name', sortable: true, width: 170, minWidth: 80 }]"
359
+ :rows="rows"
360
+ :default-sort="{ key: 'name', direction: 'asc' }"
361
+ v-model:column-widths="savedWidths"
362
+ footer
363
+ refreshable
364
+ :labels="{ items: n => `${n} 個項目`, refresh: '重新整理', empty: '沒有資料' }"
365
+ @refresh="reload"
366
+ />
367
+ ```
368
+
369
+ - **Sort.** Click a sortable header, or focus it and press Enter/Space (`aria-sort` is set). Cycle: ascending, descending, off. Leave `sort` unbound and the grid sorts itself (start with `default-sort`); bind `v-model:sort` to control it; with `:local-sort="false"` it only emits.
370
+ - **Column resize.** Drag the right edge of a header, or focus the edge and press the left/right arrows (10px). Widths are px, never below the column's `minWidth` (default 40). Persist them with `v-model:column-widths` (or `@column-resize`); pass them back to restore. `resizable` is on by default; turn it off per grid or per column.
371
+ - **Layout.** Sticky header (default), column dividers, hover and selected row colours, `max-height` to scroll inside the grid. `selectable` adds checkboxes; with `select-on-row-click` a row click selects the row and Ctrl/Cmd-click toggles it.
372
+ - **Footer bar.** `footer` shows the DSM bar with the item count; `refreshable` adds the refresh button (`@refresh`, `refreshing` spins it). Without `footer` it appears only when there is more than one page or a `#footer` slot.
373
+ - **Localisation.** Every built-in string goes through `labels`: `empty`, `items(count)`, `page(page, count)`, `previous`, `next`, `refresh`, `selectAll`, `selectRow(key)`, `resizeColumn(label)`. `emptyText` still works.
374
+ - **Loading.** `loading` masks the table with a centred indicator; `loading-text` adds a message.
375
+ - Virtual scrolling is not provided; page long lists (`page-size`).
376
+
377
+ ### Loading
378
+
379
+ `Spinner` is the DSM ring (`size` is the box in px, default 24). `LoadingMask` wraps content and covers it with a white 60% mask and a centred message box while `loading`; `LoadingArea` fills its container (give the parent a height) and centres the indicator, for whole-page or whole-panel waits. `Button loading` shows the 16px ring inline. Do not place a bare `Spinner` in a block container and expect it to be centred: use `LoadingArea`.
380
+
381
+ ### Toolbar
382
+
383
+ `SplitButton` (button + menu arrow) and `SearchField variant="filter"` (the DSM funnel filter box) join `Button`, whose default look is the flat grey DSM toolbar button.
384
+
385
+ `DatePicker` uses an ISO `YYYY-MM-DD` string as its `v-model` so consumers do not need to expose the underlying date library in application state.
386
+
387
+ ## Library development
388
+
389
+ This section is for changing the component library itself. Applications consuming
390
+ the published npm package do not need these steps.
391
+
392
+ ```bash
393
+ pnpm install
394
+ pnpm build
395
+ ```
396
+
397
+ Use the pnpm version specified in `package.json`.
398
+
399
+ ```bash
400
+ pnpm story # component workbench
401
+ pnpm dev # rebuild dist when library source changes
402
+ pnpm check # lint, typecheck, tests, and production build
403
+ pnpm story:build # build the component workbench
404
+ pnpm check:host # after pnpm build: DSM host simulation screenshots (Chrome)
405
+ ```
406
+
407
+ `pnpm check:host` serves `tests/dsm-host` and screenshots each overlay scene in
408
+ English and Traditional Chinese with headless Chrome (set `CHROME` to its path
409
+ if it is not in `/Applications`), with and without `host-simulation.css`, a
410
+ stylesheet written for these tests that reproduces DSM's known element rules.
411
+ The images must be identical, and must match `theme.css` on a plain page. They
412
+ are left in `.dsm-host-shots/`.
413
+
414
+ In the workbench, open `DSM 7 / App Interior` and `DSM 7 / Advanced Components`
415
+ for reference compositions. See [SPEC.md](./SPEC.md) for architecture and
416
+ contribution rules, and [src/index.ts](./src/index.ts) for public exports.
417
+
418
+ ### Try local changes in another application
419
+
420
+ Build this library first, then run the following in the consuming project,
421
+ replacing the path with your local checkout:
422
+
423
+ ```bash
424
+ pnpm add link:/absolute/path/to/syno-pkg-land-ui
425
+ ```
426
+
427
+ Keep `pnpm dev` running in the library checkout to rebuild `dist` as you edit.
428
+ Use the same package imports and stylesheet import shown above. To return to the
429
+ published package, replace the local link with the package:
430
+
431
+ ```bash
432
+ pnpm add @synopackageland/ui
433
+ ```
434
+
435
+ ## Releases
436
+
437
+ The public npm package is `@synopackageland/ui`. Both release targets are built
438
+ from the same source and share runtime files, exports, MIT license and notices.
439
+ Public repository and issue tracker links will be added once those are selected.
440
+ See the [documentation](https://www.varvis.me/docs/) for usage.
@@ -0,0 +1,15 @@
1
+ declare var __VLS_1: {}, __VLS_3: {};
2
+ type __VLS_Slots = {} & {
3
+ leading?: (props: typeof __VLS_1) => any;
4
+ } & {
5
+ default?: (props: typeof __VLS_3) => any;
6
+ };
7
+ 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>;
8
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
9
+ declare const _default: typeof __VLS_export;
10
+ export default _default;
11
+ type __VLS_WithSlots<T, S> = T & {
12
+ new (): {
13
+ $slots: S;
14
+ };
15
+ };
@@ -0,0 +1,26 @@
1
+ type __VLS_Props = {
2
+ sidebarWidth?: string;
3
+ minHeight?: string;
4
+ };
5
+ declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {}, __VLS_7: {};
6
+ type __VLS_Slots = {} & {
7
+ sidebar?: (props: typeof __VLS_1) => any;
8
+ } & {
9
+ toolbar?: (props: typeof __VLS_3) => any;
10
+ } & {
11
+ default?: (props: typeof __VLS_5) => any;
12
+ } & {
13
+ footer?: (props: typeof __VLS_7) => any;
14
+ };
15
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
16
+ sidebarWidth: string;
17
+ minHeight: string;
18
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
19
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
20
+ declare const _default: typeof __VLS_export;
21
+ export default _default;
22
+ type __VLS_WithSlots<T, S> = T & {
23
+ new (): {
24
+ $slots: S;
25
+ };
26
+ };
@@ -0,0 +1,20 @@
1
+ type __VLS_Props = {
2
+ modalScope?: 'document' | 'app';
3
+ };
4
+ declare var __VLS_7: {}, __VLS_9: {};
5
+ type __VLS_Slots = {} & {
6
+ default?: (props: typeof __VLS_7) => any;
7
+ } & {
8
+ default?: (props: typeof __VLS_9) => 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<{}>, {
11
+ modalScope: "document" | "app";
12
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
13
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
16
+ type __VLS_WithSlots<T, S> = T & {
17
+ new (): {
18
+ $slots: S;
19
+ };
20
+ };
@@ -0,0 +1,34 @@
1
+ import { Component } from 'vue';
2
+ export type AppSidebarItem = {
3
+ key: string;
4
+ label: string;
5
+ icon?: Component;
6
+ badge?: string | number;
7
+ disabled?: boolean;
8
+ };
9
+ export type AppSidebarGroup = {
10
+ label?: string;
11
+ items: AppSidebarItem[];
12
+ };
13
+ type __VLS_Props = {
14
+ modelValue?: string;
15
+ groups: AppSidebarGroup[];
16
+ /** Show the DSM search field above the list; it filters items by label. */
17
+ searchable?: boolean;
18
+ searchPlaceholder?: string;
19
+ /** Section headers get a chevron and fold their items. */
20
+ collapsible?: boolean;
21
+ };
22
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
23
+ select: (item: AppSidebarItem) => any;
24
+ "update:modelValue": (value: string) => any;
25
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
26
+ onSelect?: ((item: AppSidebarItem) => any) | undefined;
27
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
28
+ }>, {
29
+ collapsible: boolean;
30
+ searchable: boolean;
31
+ searchPlaceholder: string;
32
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
33
+ declare const _default: typeof __VLS_export;
34
+ export default _default;
@@ -0,0 +1,22 @@
1
+ type __VLS_Props = {
2
+ height?: string;
3
+ };
4
+ declare var __VLS_1: {}, __VLS_3: {}, __VLS_5: {};
5
+ type __VLS_Slots = {} & {
6
+ leading?: (props: typeof __VLS_1) => any;
7
+ } & {
8
+ default?: (props: typeof __VLS_3) => any;
9
+ } & {
10
+ actions?: (props: typeof __VLS_5) => any;
11
+ };
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
+ height: string;
14
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
15
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
16
+ declare const _default: typeof __VLS_export;
17
+ export default _default;
18
+ type __VLS_WithSlots<T, S> = T & {
19
+ new (): {
20
+ $slots: S;
21
+ };
22
+ };
@@ -0,0 +1,17 @@
1
+ type __VLS_Props = {
2
+ title: string;
3
+ description?: string;
4
+ };
5
+ declare var __VLS_1: {};
6
+ type __VLS_Slots = {} & {
7
+ actions?: (props: typeof __VLS_1) => any;
8
+ };
9
+ 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>;
10
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
11
+ declare const _default: typeof __VLS_export;
12
+ export default _default;
13
+ type __VLS_WithSlots<T, S> = T & {
14
+ new (): {
15
+ $slots: S;
16
+ };
17
+ };
@@ -0,0 +1,16 @@
1
+ export type SectionTab = {
2
+ value: string;
3
+ label: string;
4
+ disabled?: boolean;
5
+ };
6
+ type __VLS_Props = {
7
+ modelValue: string;
8
+ items: SectionTab[];
9
+ };
10
+ declare const __VLS_export: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
11
+ "update:modelValue": (value: string) => any;
12
+ }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
13
+ "onUpdate:modelValue"?: ((value: string) => any) | undefined;
14
+ }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
15
+ declare const _default: typeof __VLS_export;
16
+ export default _default;
@@ -0,0 +1,19 @@
1
+ type __VLS_Props = {
2
+ tone?: 'info' | 'success' | 'warning' | 'danger';
3
+ title?: string;
4
+ };
5
+ declare var __VLS_6: {};
6
+ type __VLS_Slots = {} & {
7
+ default?: (props: typeof __VLS_6) => any;
8
+ };
9
+ declare const __VLS_base: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
10
+ tone: "info" | "success" | "warning" | "danger";
11
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
12
+ declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
13
+ declare const _default: typeof __VLS_export;
14
+ export default _default;
15
+ type __VLS_WithSlots<T, S> = T & {
16
+ new (): {
17
+ $slots: S;
18
+ };
19
+ };