@jskit-ai/ui-generator 0.1.13 → 0.1.15
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/README.md +147 -123
- package/package.descriptor.mjs +182 -82
- package/package.json +2 -2
- package/src/server/buildTemplateContext.js +31 -136
- package/src/server/subcommands/addSubpages.js +73 -0
- package/src/server/subcommands/element.js +30 -15
- package/src/server/subcommands/outlet.js +26 -126
- package/src/server/subcommands/page.js +142 -0
- package/src/server/subcommands/pageSupport.js +552 -0
- package/src/server/subcommands/support.js +145 -1
- package/test/addSubpagesSubcommand.test.js +321 -0
- package/test/buildTemplateContext.test.js +426 -65
- package/test/elementSubcommand.test.js +79 -6
- package/test/outletSubcommand.test.js +92 -29
- package/test/packageDescriptor.test.js +10 -0
- package/test/pageSubcommand.test.js +352 -0
- package/src/server/subcommands/container.js +0 -644
- package/templates/src/pages/admin/ui-generator/Page.vue +0 -6
- package/test/containerSubcommand.test.js +0 -307
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jskit-ai/ui-generator
|
|
2
2
|
|
|
3
|
-
Generate
|
|
3
|
+
Generate app-local UI pages, page links, placed elements, and routed subpage hosts for JSKIT apps.
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
@@ -10,181 +10,205 @@ List available placement targets in the current app:
|
|
|
10
10
|
npx jskit list placements
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Create a normal page at an explicit file:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
npx jskit generate @jskit-ai/ui-generator page
|
|
16
|
+
npx jskit generate @jskit-ai/ui-generator page \
|
|
17
|
+
admin/reports-dashboard/index.vue \
|
|
18
|
+
--name "Reports Dashboard"
|
|
17
19
|
```
|
|
18
20
|
|
|
19
|
-
|
|
21
|
+
Create a file-route page:
|
|
20
22
|
|
|
21
23
|
```bash
|
|
22
|
-
npx jskit generate @jskit-ai/ui-generator page
|
|
24
|
+
npx jskit generate @jskit-ai/ui-generator page \
|
|
25
|
+
admin/contacts/[contactId].vue \
|
|
26
|
+
--name "Contact"
|
|
23
27
|
```
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
Upgrade an existing page into a routed subpage host:
|
|
26
30
|
|
|
27
31
|
```bash
|
|
28
|
-
npx jskit generate @jskit-ai/ui-generator
|
|
32
|
+
npx jskit generate @jskit-ai/ui-generator add-subpages \
|
|
33
|
+
admin/contacts/[contactId].vue \
|
|
34
|
+
--title "Contact" \
|
|
35
|
+
--subtitle "Manage contact modules."
|
|
29
36
|
```
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
Create a reusable placed element:
|
|
32
39
|
|
|
33
40
|
```bash
|
|
34
|
-
npx jskit generate @jskit-ai/ui-generator element
|
|
41
|
+
npx jskit generate @jskit-ai/ui-generator placed-element \
|
|
42
|
+
--name "Alerts Widget" \
|
|
43
|
+
--surface admin
|
|
35
44
|
```
|
|
36
45
|
|
|
37
|
-
|
|
46
|
+
Inject a plain generic outlet into an existing Vue file:
|
|
38
47
|
|
|
39
48
|
```bash
|
|
40
|
-
npx jskit generate @jskit-ai/ui-generator
|
|
49
|
+
npx jskit generate @jskit-ai/ui-generator outlet \
|
|
50
|
+
src/components/ContactSummaryCard.vue \
|
|
51
|
+
--target contact-view:summary-actions
|
|
41
52
|
```
|
|
42
53
|
|
|
43
|
-
|
|
54
|
+
## Commands
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
- `page <target-file>`: create a route page at that exact file relative to `src/pages/` and add a link placement entry for it.
|
|
57
|
+
- `add-subpages <target-file>`: upgrade an existing page relative to `src/pages/` into the standard `SectionContainerShell + ShellOutlet + RouterView` host shape.
|
|
58
|
+
- `placed-element`: create a reusable component and register a placement for it.
|
|
59
|
+
- `outlet <target-file>`: inject a plain `ShellOutlet` into an existing Vue SFC.
|
|
48
60
|
|
|
49
|
-
|
|
61
|
+
For `placed-element`, the default placement target is `shell-layout:top-right`.
|
|
62
|
+
Use `--placement host:position` to override it.
|
|
50
63
|
|
|
51
|
-
|
|
52
|
-
npx jskit generate @jskit-ai/ui-generator container --name "Contact" --surface admin --directory-prefix contacts --route-path "[contactId]"
|
|
53
|
-
```
|
|
64
|
+
## The Mental Model
|
|
54
65
|
|
|
55
|
-
|
|
66
|
+
`page` and `add-subpages` operate on explicit page files relative to `src/pages/`. `outlet` still targets an explicit Vue file path relative to the app root.
|
|
56
67
|
|
|
57
|
-
|
|
58
|
-
npx jskit generate @jskit-ai/ui-generator container --name "Practice" --surface admin --placement shell-layout:primary-menu
|
|
59
|
-
```
|
|
68
|
+
That means:
|
|
60
69
|
|
|
61
|
-
|
|
70
|
+
- `catalog/index.vue` is obviously an index-route page
|
|
71
|
+
- `catalog.vue` is obviously a file-route page
|
|
72
|
+
- there is no extra route-shape flag to remember
|
|
73
|
+
- the owning surface is derived from where the file lives
|
|
62
74
|
|
|
63
|
-
|
|
64
|
-
npx jskit generate @jskit-ai/ui-generator outlet --file src/pages/w/[workspaceSlug]/admin/contacts/[contactId]/index.vue --host contact-view
|
|
65
|
-
```
|
|
75
|
+
This is the reference model for JSKIT page-producing generators.
|
|
66
76
|
|
|
67
|
-
|
|
77
|
+
- `@jskit-ai/ui-generator page <target-file>` works from an explicit page file relative to `src/pages/`.
|
|
78
|
+
- `@jskit-ai/crud-ui-generator crud <target-root>` works from an explicit route root relative to `src/pages/`.
|
|
79
|
+
- `@jskit-ai/assistant page <target-file>` and `settings-page <target-file>` work from explicit page files relative to `src/pages/`.
|
|
68
80
|
|
|
69
|
-
|
|
70
|
-
npx jskit generate @jskit-ai/ui-generator help
|
|
71
|
-
npx jskit generate @jskit-ai/ui-generator outlet help
|
|
72
|
-
npx jskit generate @jskit-ai/ui-generator outlet
|
|
73
|
-
```
|
|
81
|
+
## Page Links
|
|
74
82
|
|
|
75
|
-
|
|
83
|
+
`page` creates a page file and appends a link placement block for it.
|
|
84
|
+
|
|
85
|
+
These options control that generated page link:
|
|
86
|
+
|
|
87
|
+
- `--link-placement`: where the page link renders
|
|
88
|
+
- `--link-component-token`: how the page link is rendered
|
|
89
|
+
- `--link-to`: explicit `props.to` override for the page link
|
|
90
|
+
|
|
91
|
+
This is intentionally separate from `placed-element`, which still uses `--placement` because it places arbitrary UI, not a page link.
|
|
92
|
+
|
|
93
|
+
## Routed Subpages
|
|
94
|
+
|
|
95
|
+
`add-subpages` is the only routed-subpages command.
|
|
96
|
+
|
|
97
|
+
It upgrades an existing page so the page itself owns:
|
|
98
|
+
|
|
99
|
+
- `SectionContainerShell`
|
|
100
|
+
- `ShellOutlet host="..." position="sub-pages"`
|
|
101
|
+
- `RouterView`
|
|
102
|
+
|
|
103
|
+
`--target` controls that outlet target:
|
|
104
|
+
|
|
105
|
+
- if omitted, the target is derived from the page path
|
|
106
|
+
- `--target contact-view` means `contact-view:sub-pages`
|
|
107
|
+
- `--target contact-view:secondary-tabs` uses an explicit custom position
|
|
108
|
+
|
|
109
|
+
Derived target examples:
|
|
76
110
|
|
|
77
|
-
- `
|
|
78
|
-
- `
|
|
79
|
-
- `
|
|
80
|
-
- `
|
|
111
|
+
- `src/pages/admin/catalog/index.vue` -> `catalog:sub-pages`
|
|
112
|
+
- `src/pages/admin/catalog.vue` -> `catalog:sub-pages`
|
|
113
|
+
- `src/pages/admin/contacts/[contactId].vue` -> `contacts-contact-id:sub-pages`
|
|
114
|
+
- `src/pages/admin/catalog/products/index.vue` -> `catalog-products:sub-pages`
|
|
81
115
|
|
|
82
|
-
|
|
116
|
+
If the page already contains a `RouterView`, `add-subpages` fails instead of trying to update an existing routed host.
|
|
83
117
|
|
|
84
|
-
|
|
85
|
-
- `--placement-to` to set explicit `props.to` in the generated placement block.
|
|
86
|
-
- if `--placement-to` is omitted and `--directory-prefix` includes a `(nestedChildren)` route group, `props.to` is auto-set to `./<page-slug>`.
|
|
118
|
+
It also ensures the shared support scaffold exists:
|
|
87
119
|
|
|
88
|
-
|
|
120
|
+
- `src/components/SectionContainerShell.vue`
|
|
121
|
+
- `src/components/TabLinkItem.vue`
|
|
122
|
+
- `packages/main/src/client/providers/MainClientProvider.js` registration for `local.main.ui.tab-link-item`
|
|
89
123
|
|
|
90
|
-
|
|
91
|
-
- `src/components/SectionContainerShell.vue` (shared container shell with responsive tab row)
|
|
92
|
-
- `src/components/TabLinkItem.vue` (tab link item token component)
|
|
93
|
-
- `packages/main/src/client/providers/MainClientProvider.js` registration for `local.main.ui.tab-link-item`
|
|
94
|
-
- `<route>.vue` as a thin wrapper around `SectionContainerShell` + `<RouterView />`, with route meta outlet declaration at `meta.jskit.placements.outlets`
|
|
95
|
-
- no shell menu placement is added unless `--placement` is explicitly provided
|
|
96
|
-
- Child pages for a `container` go directly under the container route path, not under `(nestedChildren)`.
|
|
97
|
-
- Example container route: `src/pages/admin/practice.vue`
|
|
98
|
-
- Example child page path: `src/pages/admin/practice/notes/index.vue`
|
|
99
|
-
- Example URL: `/admin/practice/notes`
|
|
100
|
-
- Use `(nestedChildren)` for the `page + outlet` pattern when the parent page is an existing `index.vue` route that should render child routes inside its own `RouterView`.
|
|
124
|
+
## Child Route Placement Rule
|
|
101
125
|
|
|
102
|
-
|
|
126
|
+
Child routes attach differently depending on the parent page file shape.
|
|
127
|
+
|
|
128
|
+
If the parent is a file route:
|
|
129
|
+
|
|
130
|
+
- parent: `src/pages/admin/catalog.vue`
|
|
131
|
+
- child pages go under: `src/pages/admin/catalog/...`
|
|
132
|
+
- example child page: `src/pages/admin/catalog/products/index.vue`
|
|
133
|
+
|
|
134
|
+
If the parent is an index route:
|
|
135
|
+
|
|
136
|
+
- parent: `src/pages/admin/catalog/index.vue`
|
|
137
|
+
- child pages go under: `src/pages/admin/catalog/index/...`
|
|
138
|
+
- example child page: `src/pages/admin/catalog/index/products/index.vue`
|
|
139
|
+
|
|
140
|
+
That `index/...` folder shape is the native file-based routing rule for nesting children under an `index.vue` page.
|
|
141
|
+
|
|
142
|
+
## Example: File Route Parent
|
|
143
|
+
|
|
144
|
+
Create the parent page:
|
|
103
145
|
|
|
104
146
|
```bash
|
|
105
147
|
npx jskit generate @jskit-ai/ui-generator page \
|
|
106
|
-
|
|
107
|
-
--
|
|
108
|
-
--directory-prefix "practice" \
|
|
109
|
-
--placement practice:sub-pages \
|
|
110
|
-
--placement-component-token local.main.ui.tab-link-item
|
|
148
|
+
admin/contacts/[contactId].vue \
|
|
149
|
+
--name "Contact"
|
|
111
150
|
```
|
|
112
151
|
|
|
113
|
-
|
|
114
|
-
- `--container <route-slug>`
|
|
115
|
-
- `--route-path <resource-slug>`
|
|
116
|
-
- optional `--placement` override (default becomes `<container>:sub-pages` for list pages)
|
|
152
|
+
Upgrade it to host subpages:
|
|
117
153
|
|
|
118
|
-
|
|
154
|
+
```bash
|
|
155
|
+
npx jskit generate @jskit-ai/ui-generator add-subpages \
|
|
156
|
+
admin/contacts/[contactId].vue \
|
|
157
|
+
--title "Contact" \
|
|
158
|
+
--subtitle "Manage contact modules."
|
|
159
|
+
```
|
|
119
160
|
|
|
120
|
-
|
|
121
|
-
- `import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";`
|
|
122
|
-
- `<ShellOutlet host="<host>" position="<position>" />` in template
|
|
123
|
-
- optional `<RouterView />` (when `--mode routed`, only if one does not already exist in the file)
|
|
124
|
-
- `--mode` supports:
|
|
125
|
-
- `routed` (default): insert `RouterView` if missing
|
|
126
|
-
- `outlet-only`: insert only `ShellOutlet`
|
|
161
|
+
Generate a child page link inside that host:
|
|
127
162
|
|
|
128
|
-
|
|
163
|
+
```bash
|
|
164
|
+
npx jskit generate @jskit-ai/ui-generator page \
|
|
165
|
+
admin/contacts/[contactId]/notes/index.vue \
|
|
166
|
+
--name "Notes"
|
|
167
|
+
```
|
|
129
168
|
|
|
130
|
-
|
|
169
|
+
## Example: Index Route Parent
|
|
131
170
|
|
|
132
|
-
|
|
171
|
+
Create the parent page:
|
|
133
172
|
|
|
134
173
|
```bash
|
|
135
|
-
npx jskit generate ui-generator
|
|
136
|
-
|
|
137
|
-
--
|
|
138
|
-
--position sub-pages \
|
|
139
|
-
--mode routed
|
|
174
|
+
npx jskit generate @jskit-ai/ui-generator page \
|
|
175
|
+
admin/catalog/index.vue \
|
|
176
|
+
--name "Catalog"
|
|
140
177
|
```
|
|
141
178
|
|
|
142
|
-
|
|
179
|
+
Upgrade it to host subpages:
|
|
180
|
+
|
|
181
|
+
```bash
|
|
182
|
+
npx jskit generate @jskit-ai/ui-generator add-subpages \
|
|
183
|
+
admin/catalog/index.vue \
|
|
184
|
+
--title "Catalog"
|
|
185
|
+
```
|
|
143
186
|
|
|
144
|
-
|
|
145
|
-
- `--host`: outlet host namespace (used later by placements).
|
|
146
|
-
- `--position`: outlet position key under that host.
|
|
147
|
-
- `--mode routed`: ensures `<RouterView />` exists so nested pages render inline.
|
|
187
|
+
Because the parent page is `index.vue`, nested child pages live under the matching `index/` folder.
|
|
148
188
|
|
|
149
|
-
|
|
189
|
+
Generate a child page link inside that host:
|
|
150
190
|
|
|
151
191
|
```bash
|
|
152
|
-
npx jskit generate
|
|
153
|
-
|
|
154
|
-
--
|
|
155
|
-
--operations list,view,new,edit \
|
|
156
|
-
--resource-file packages/pets/src/shared/petResource.js \
|
|
157
|
-
--directory-prefix "contacts/[contactId]/(nestedChildren)" \
|
|
158
|
-
--placement contact-view:sub-pages \
|
|
159
|
-
--placement-component-token local.main.ui.tab-link-item \
|
|
160
|
-
--placement-to ./pets \
|
|
161
|
-
--id-param petId
|
|
192
|
+
npx jskit generate @jskit-ai/ui-generator page \
|
|
193
|
+
admin/catalog/index/products/index.vue \
|
|
194
|
+
--name "Products"
|
|
162
195
|
```
|
|
163
196
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
## Placement Notes
|
|
184
|
-
|
|
185
|
-
- `--placement` expects `host:position`.
|
|
186
|
-
- Targets come from:
|
|
187
|
-
- app-declared `<ShellOutlet host="..." position="..." />` in `src/**/*.vue`
|
|
188
|
-
- app route meta `meta.jskit.placements.outlets` declarations in `src/**/*.vue`
|
|
189
|
-
- installed package metadata `metadata.ui.placements.outlets`
|
|
190
|
-
- If `--placement` is omitted, the app default outlet is used.
|
|
197
|
+
When `page` finds the nearest parent page upgraded with `add-subpages`, it reuses that parent’s real outlet target, defaults the link renderer to `local.main.ui.tab-link-item`, and derives `to` from the child route automatically.
|
|
198
|
+
|
|
199
|
+
## Generic Outlet Injection
|
|
200
|
+
|
|
201
|
+
`outlet` is intentionally small.
|
|
202
|
+
|
|
203
|
+
It only adds:
|
|
204
|
+
|
|
205
|
+
- `import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";`
|
|
206
|
+
- `<ShellOutlet host="..." position="..." />`
|
|
207
|
+
|
|
208
|
+
It does not:
|
|
209
|
+
|
|
210
|
+
- add `RouterView`
|
|
211
|
+
- add `SectionContainerShell`
|
|
212
|
+
- add routed subpage scaffolding
|
|
213
|
+
|
|
214
|
+
Use `add-subpages` when the goal is routed child pages inside a page.
|