@synopackageland/ui 0.5.8 → 0.6.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.
- package/LICENSES/THIRD_PARTY.md +450 -0
- package/README.md +18 -10
- package/dist/cli.js +296 -0
- package/dist/components/app/app-layout/AppLayout.vue.d.ts +12 -5
- package/dist/components/app/page-content/PageContent.vue.d.ts +3 -0
- package/dist/components/app/responsive-view/ResponsiveView.vue.d.ts +24 -0
- package/dist/components/composite/data-table/DataTable.vue.d.ts +9 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4280 -4105
- package/dist/json/SynoJsonRenderer.vue.d.ts +21 -0
- package/dist/json/catalog.d.ts +910 -0
- package/dist/json/describe.d.ts +31 -0
- package/dist/json/registry.d.ts +13953 -0
- package/dist/json/schema.d.ts +9 -0
- package/dist/json/validate.d.ts +63 -0
- package/dist/json-ai-prompt.md +184 -0
- package/dist/json-catalog.schema.json +2723 -0
- package/dist/json-preview/preview.js +21657 -0
- package/dist/json.d.ts +10 -0
- package/dist/json.js +1117 -0
- package/dist/lib/adaptiveLayout.d.ts +9 -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/adaptive-layout.md +143 -0
- package/docs/app-local-modal.md +4 -3
- package/docs/component-defaults-0.5.7.md +90 -0
- package/docs/json-ui.md +154 -0
- package/package.json +15 -3
package/docs/json-ui.md
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Declarative DSM UI (`@synopackageland/ui/json`)
|
|
2
|
+
|
|
3
|
+
The JSON entry point is a curated AI/declarative surface over the normal Vue
|
|
4
|
+
SDK. It is intentionally smaller than the full component library. Ordinary
|
|
5
|
+
application structure, settings, forms, dialogs, resource tables and state
|
|
6
|
+
bindings can stay declarative; domain-specific views and business logic remain
|
|
7
|
+
normal Vue/TypeScript extensions.
|
|
8
|
+
|
|
9
|
+
It also supports responsive `AppShell` and `ResponsiveView` alternatives:
|
|
10
|
+
one JSON spec renders as a DSM window or a phone view, and as a wide Portal
|
|
11
|
+
page when its `AppShell` sets `wideLayout: "web"`.
|
|
12
|
+
See [adaptive-layout.md](adaptive-layout.md).
|
|
13
|
+
|
|
14
|
+
## Boundary
|
|
15
|
+
|
|
16
|
+
Use JSON for repeated application interaction patterns:
|
|
17
|
+
|
|
18
|
+
- DSM app shell, sidebar, toolbar, page header and tabs
|
|
19
|
+
- settings/forms and ordinary validation/state binding
|
|
20
|
+
- dialogs, callouts, empty/loading states and progress
|
|
21
|
+
- simple resource collections/tables
|
|
22
|
+
- action dispatch into host-owned backend functions
|
|
23
|
+
|
|
24
|
+
Keep these in application code and expose them as extension components/actions:
|
|
25
|
+
|
|
26
|
+
- domain-specific visualizations (treemap, topology, terminal, media canvas)
|
|
27
|
+
- rich table rows/cells with domain actions
|
|
28
|
+
- filesystem/NAS pickers or native DSM bridges
|
|
29
|
+
- polling, retries, transactions, authorization and other business workflows
|
|
30
|
+
|
|
31
|
+
This gives the declarative layer an escape hatch instead of expanding the DSL
|
|
32
|
+
until it becomes another programming language.
|
|
33
|
+
|
|
34
|
+
## Basic renderer
|
|
35
|
+
|
|
36
|
+
```vue
|
|
37
|
+
<script setup lang="ts">
|
|
38
|
+
import { SynoJsonRenderer } from '@synopackageland/ui/json'
|
|
39
|
+
import type { Spec } from '@synopackageland/ui/json'
|
|
40
|
+
|
|
41
|
+
const spec: Spec = {
|
|
42
|
+
root: 'root',
|
|
43
|
+
state: { enabled: true },
|
|
44
|
+
elements: {
|
|
45
|
+
root: { type: 'AppRoot', props: { modalScope: 'app' }, children: ['shell'] },
|
|
46
|
+
shell: { type: 'AppShell', props: { minHeight: '0' }, children: ['page'] },
|
|
47
|
+
page: { type: 'Page', props: { width: 'readable' }, children: ['settings'] },
|
|
48
|
+
settings: { type: 'SettingsSection', props: { title: 'General', collapsible: false }, children: ['enabled'] },
|
|
49
|
+
enabled: { type: 'SettingsField', props: { label: 'Enabled' }, children: ['switch'] },
|
|
50
|
+
switch: { type: 'Switch', props: { checked: { $bindState: '/enabled' } }, children: [] },
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
</script>
|
|
54
|
+
|
|
55
|
+
<template><SynoJsonRenderer :spec="spec" /></template>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Real applications: extend, do not fork
|
|
59
|
+
|
|
60
|
+
An application normally declares its backend actions and only the special
|
|
61
|
+
renderers it needs. Spread the SDK definitions/renderers into the app catalog:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
import { h } from 'vue'
|
|
65
|
+
import {
|
|
66
|
+
defineCatalog,
|
|
67
|
+
defineRegistry,
|
|
68
|
+
jsonRenderVueSchema,
|
|
69
|
+
synoJsonComponentDefinitions,
|
|
70
|
+
synoJsonRenderers,
|
|
71
|
+
z,
|
|
72
|
+
} from '@synopackageland/ui/json'
|
|
73
|
+
import DownloadTaskTable from './DownloadTaskTable.vue'
|
|
74
|
+
|
|
75
|
+
export const catalog = defineCatalog(jsonRenderVueSchema, {
|
|
76
|
+
components: {
|
|
77
|
+
...synoJsonComponentDefinitions,
|
|
78
|
+
DownloadTaskTable: {
|
|
79
|
+
props: z.object({ rows: z.array(z.unknown()) }),
|
|
80
|
+
description: 'Gopeed download rows with progress and per-row actions.',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
actions: {
|
|
84
|
+
refreshDownloads: { description: 'Reload download tasks.' },
|
|
85
|
+
createDownload: {
|
|
86
|
+
params: z.object({ url: z.string(), folder: z.string(), filename: z.string().optional() }),
|
|
87
|
+
description: 'Create a download through the package backend.',
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
})
|
|
91
|
+
|
|
92
|
+
export const { registry } = defineRegistry(catalog, {
|
|
93
|
+
components: {
|
|
94
|
+
...synoJsonRenderers,
|
|
95
|
+
DownloadTaskTable: ({ props }) => h(DownloadTaskTable, { rows: props.rows }),
|
|
96
|
+
},
|
|
97
|
+
actions: {
|
|
98
|
+
refreshDownloads: async () => { /* call existing app/store code */ },
|
|
99
|
+
createDownload: async (params) => { /* call existing app/store code */ },
|
|
100
|
+
},
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The same boundary works for Syno Reclaim: its app shell/settings/dialogs can be
|
|
105
|
+
declarative while `Treemap`, `ReclaimGrid`, `ProgressRing` and the scan/cleanup
|
|
106
|
+
state machines stay application-owned extensions.
|
|
107
|
+
|
|
108
|
+
## AI tools
|
|
109
|
+
|
|
110
|
+
The package ships a `syno-ui` command (`npx @synopackageland/ui <command>`, or
|
|
111
|
+
`npx syno-ui` once installed) and the same functions from the JSON entry:
|
|
112
|
+
|
|
113
|
+
| Command | Purpose | Function |
|
|
114
|
+
| --- | --- | --- |
|
|
115
|
+
| `catalog [--json]` | Components, required props, slots, events | `listSynoJsonComponents()` |
|
|
116
|
+
| `describe <Component> [--json]` | Prop JSON Schemas and a minimal valid element | `describeSynoJsonComponent()` |
|
|
117
|
+
| `schema` | Spec JSON Schema (draft 2020-12) generated from the catalog | `synoJsonSchema()` |
|
|
118
|
+
| `prompt` | System prompt: catalog, rules and the self-check workflow | `synoJsonAiPrompt()` |
|
|
119
|
+
| `validate <file...>` | Every problem at once, with JSON Pointer `path` and a `hint` | `validateSynoJsonSpec()` |
|
|
120
|
+
| `render <file>` | Validate, screenshot 390/640/960/1350 px, report overflow by spec key | (Chrome, Node 22+) |
|
|
121
|
+
|
|
122
|
+
`validate` checks the spec shape, unknown components/props/slots/events (with
|
|
123
|
+
"did you mean"), required props, literal types and enum values, child
|
|
124
|
+
references and cycles, state pointers, `$item` outside `repeat`, actions,
|
|
125
|
+
`$computed` functions and i18n keys. Tell it what the host provides:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
syno-ui validate ui.json --json --actions save,refresh --functions formatBytes \
|
|
129
|
+
--state host-state.json --messages messages/en.json
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Exit codes: `0` valid, `1` spec errors (or warnings with `--strict`, or layout
|
|
133
|
+
issues from `render`), `2` usage, unreadable files or browser failure.
|
|
134
|
+
|
|
135
|
+
Localized text uses `{"$computed": "t", "args": {"key": "settings.title"}}`.
|
|
136
|
+
Register `t` through the renderer's `functions` prop; `--messages` checks every
|
|
137
|
+
key and warns about literal user-facing text.
|
|
138
|
+
|
|
139
|
+
### Workflow for an AI
|
|
140
|
+
|
|
141
|
+
1. Read `syno-ui prompt` once, then `syno-ui catalog` and `syno-ui describe` for
|
|
142
|
+
the components you plan to use.
|
|
143
|
+
2. Write `{ "root", "elements", "state" }`, seeding every state path you bind.
|
|
144
|
+
3. Run `syno-ui validate ui.json --json` with the host's actions, functions,
|
|
145
|
+
state and messages. Fix each error at its `path` using its `hint`; repeat.
|
|
146
|
+
4. Run `syno-ui render ui.json --out shots`, look at the screenshots, and fix
|
|
147
|
+
every element named in an `outside_viewport` or `clipped_content` issue.
|
|
148
|
+
5. Hand over the spec only when `validate` and `render` both exit 0.
|
|
149
|
+
|
|
150
|
+
Builds also write `dist/json-catalog.schema.json` and `dist/json-ai-prompt.md`
|
|
151
|
+
(exported as `@synopackageland/ui/json-catalog.schema.json` and
|
|
152
|
+
`@synopackageland/ui/json-ai-prompt.md`) for constrained-generation pipelines.
|
|
153
|
+
Give the model the prompt plus the application's own actions and extension
|
|
154
|
+
components, not the Vue source tree.
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.6.0",
|
|
3
3
|
"description": "Shared Vue 3 UI component library with a DSM 7 inspired application theme",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
@@ -11,7 +11,10 @@
|
|
|
11
11
|
"LICENSE",
|
|
12
12
|
"LICENSES",
|
|
13
13
|
"README.md",
|
|
14
|
-
"docs/
|
|
14
|
+
"docs/adaptive-layout.md",
|
|
15
|
+
"docs/app-local-modal.md",
|
|
16
|
+
"docs/component-defaults-0.5.7.md",
|
|
17
|
+
"docs/json-ui.md"
|
|
15
18
|
],
|
|
16
19
|
"main": "./dist/index.js",
|
|
17
20
|
"module": "./dist/index.js",
|
|
@@ -21,6 +24,12 @@
|
|
|
21
24
|
"types": "./dist/index.d.ts",
|
|
22
25
|
"import": "./dist/index.js"
|
|
23
26
|
},
|
|
27
|
+
"./json": {
|
|
28
|
+
"types": "./dist/json.d.ts",
|
|
29
|
+
"import": "./dist/json.js"
|
|
30
|
+
},
|
|
31
|
+
"./json-catalog.schema.json": "./dist/json-catalog.schema.json",
|
|
32
|
+
"./json-ai-prompt.md": "./dist/json-ai-prompt.md",
|
|
24
33
|
"./theme.css": "./dist/theme.css",
|
|
25
34
|
"./themes/dsm7.css": "./dist/themes/dsm7.css",
|
|
26
35
|
"./themes/dsm7-embedded.css": "./dist/themes/dsm7-embedded.css",
|
|
@@ -32,7 +41,10 @@
|
|
|
32
41
|
},
|
|
33
42
|
"dependencies": {
|
|
34
43
|
"@internationalized/date": "3.12.4",
|
|
35
|
-
"@
|
|
44
|
+
"@json-render/core": "0.21.0",
|
|
45
|
+
"@json-render/vue": "0.21.0",
|
|
46
|
+
"@lucide/vue": "1.48.0",
|
|
47
|
+
"zod": "^4.6.5"
|
|
36
48
|
},
|
|
37
49
|
"engines": {
|
|
38
50
|
"node": ">=20"
|