@jskit-ai/agent-docs 0.1.26 → 0.1.27
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/guide/agent/app-extras/assistant.md +7 -18
- package/guide/agent/app-extras/mobile-capacitor.md +374 -0
- package/guide/agent/app-extras/realtime.md +2 -1
- package/guide/agent/app-setup/a-more-interesting-shell.md +54 -47
- package/guide/agent/app-setup/authentication.md +10 -9
- package/guide/agent/app-setup/console.md +3 -3
- package/guide/agent/app-setup/multi-homing.md +22 -19
- package/guide/agent/app-setup/quickstart.md +11 -14
- package/guide/agent/app-setup/users.md +3 -3
- package/guide/agent/app-setup/working-with-the-jskit-cli.md +5 -4
- package/guide/agent/generators/ui-generators.md +29 -23
- package/guide/agent/index.md +3 -2
- package/package.json +1 -1
- package/patterns/page-scaffolding.md +3 -2
- package/patterns/placements.md +7 -1
- package/reference/autogen/KERNEL_MAP.md +16 -0
- package/reference/autogen/README.md +3 -0
- package/reference/autogen/packages/assistant.md +1 -0
- package/reference/autogen/packages/auth-web.md +20 -1
- package/reference/autogen/packages/crud-ui-generator.md +1 -0
- package/reference/autogen/packages/google-rewarded-core.md +222 -0
- package/reference/autogen/packages/google-rewarded-web.md +71 -0
- package/reference/autogen/packages/kernel.md +58 -6
- package/reference/autogen/packages/mobile-capacitor.md +76 -0
- package/reference/autogen/packages/shell-web.md +13 -0
- package/reference/autogen/packages/ui-generator.md +11 -0
- package/reference/autogen/packages/users-web.md +0 -1
- package/reference/autogen/packages/workspaces-web.md +0 -1
- package/reference/autogen/tooling/jskit-cli.md +98 -9
|
@@ -53,7 +53,7 @@ Open `http://localhost:5173/home/settings` in the browser to see that nested set
|
|
|
53
53
|
|
|
54
54
|
The most important new idea in `shell-web` is that the app now has _specific, named places_ where UI can be inserted later. JSKIT calls those places _placements_. In practice, this means later packages or generators do not have to rewrite the whole shell every time they want to add a menu entry, a widget, or a settings section.
|
|
55
55
|
|
|
56
|
-
Start by asking JSKIT what placement targets already exist:
|
|
56
|
+
Start by asking JSKIT what public placement targets already exist:
|
|
57
57
|
|
|
58
58
|
```bash
|
|
59
59
|
npx jskit list-placements
|
|
@@ -63,16 +63,25 @@ In a fresh `shell-web` app, the result looks like this:
|
|
|
63
63
|
|
|
64
64
|
```text
|
|
65
65
|
Available placements:
|
|
66
|
-
-
|
|
67
|
-
- shell-layout:primary-menu
|
|
68
|
-
- shell-layout:
|
|
69
|
-
- shell-layout:
|
|
70
|
-
-
|
|
66
|
+
- shell.primary-nav (default): Primary top-level navigation for the current surface.
|
|
67
|
+
- compact -> shell-layout:primary-menu
|
|
68
|
+
- medium -> shell-layout:primary-menu
|
|
69
|
+
- expanded -> shell-layout:primary-menu
|
|
70
|
+
- page.section-nav [owner:home-settings]: Navigation between child pages in the home settings section.
|
|
71
|
+
- compact -> home-settings:primary-menu
|
|
72
|
+
- medium -> home-settings:primary-menu
|
|
73
|
+
- expanded -> home-settings:primary-menu
|
|
71
74
|
```
|
|
72
75
|
|
|
73
|
-
This command lists
|
|
76
|
+
This command lists semantic placements, not the content inside them. Later, when you place things into the shell, this list stays stable unless the public placement topology changes.
|
|
74
77
|
|
|
75
|
-
|
|
78
|
+
The concrete outlets still exist, but they are implementation details. If you need to inspect them directly, use:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx jskit list-placements --concrete
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Those concrete target names come from real `ShellOutlet` elements in the app. See `src/components/ShellLayout.vue`:
|
|
76
85
|
|
|
77
86
|
```html
|
|
78
87
|
...
|
|
@@ -83,27 +92,20 @@ Those target names come from real `ShellOutlet` elements in the app. See `src/co
|
|
|
83
92
|
<ShellOutlet
|
|
84
93
|
target="shell-layout:primary-menu"
|
|
85
94
|
default
|
|
86
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
87
95
|
/>
|
|
88
96
|
...
|
|
89
|
-
<ShellOutlet
|
|
90
|
-
target="shell-layout:secondary-menu"
|
|
91
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
92
|
-
/>
|
|
97
|
+
<ShellOutlet target="shell-layout:secondary-menu" />
|
|
93
98
|
```
|
|
94
99
|
|
|
95
100
|
And the settings page introduces its own nested outlet in `src/pages/home/settings.vue`:
|
|
96
101
|
|
|
97
102
|
```html
|
|
98
|
-
<ShellOutlet
|
|
99
|
-
target="home-settings:primary-menu"
|
|
100
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
101
|
-
/>
|
|
103
|
+
<ShellOutlet target="home-settings:primary-menu" />
|
|
102
104
|
```
|
|
103
105
|
|
|
104
106
|
That nested example matters. It shows that the shell is not the only place that can host placements. A page inside the shell can define its own insertion point too. That is how JSKIT can later build menus inside sections such as settings without rewriting the whole shell.
|
|
105
107
|
|
|
106
|
-
Just as importantly, `shell-web` already uses that placement system itself. The starter app is not only exposing placement targets; it is also seeding real placement entries into them. The drawer gets `Home` and `Settings`, and the nested settings menu gets `General`. That is why the shell already feels real before you generate anything of your own.
|
|
108
|
+
Just as importantly, `shell-web` already uses that placement system itself. The starter app is not only exposing semantic placement targets; it is also seeding real placement entries into them. The drawer gets `Home` and `Settings`, and the nested settings menu gets `General`. That is why the shell already feels real before you generate anything of your own.
|
|
107
109
|
|
|
108
110
|
The shell also ships with a few app-owned component tokens that it can use as default link renderers. You can inspect those too:
|
|
109
111
|
|
|
@@ -133,7 +135,7 @@ To add a small UI element to the shell itself:
|
|
|
133
135
|
npx jskit generate ui-generator placed-element --name "Alerts Widget"
|
|
134
136
|
```
|
|
135
137
|
|
|
136
|
-
That command creates a Vue component under `src/components/` (in this case `src/components/AlertsWidgetElement.vue`), registers a new local token for it, and adds a placement entry targeting `shell
|
|
138
|
+
That command creates a Vue component under `src/components/` (in this case `src/components/AlertsWidgetElement.vue`), registers a new local token for it, and adds a placement entry targeting `shell.status`. After running it, refresh the home page in the browser. The shell now has a real app-owned widget living inside one of its named placement targets.
|
|
137
139
|
|
|
138
140
|
In this app, there is no need to pass `--surface`: since the app only has one enabled surface, JSKIT can infer it automatically.
|
|
139
141
|
|
|
@@ -141,13 +143,13 @@ In this app, there is no need to pass `--surface`: since the app only has one en
|
|
|
141
143
|
|
|
142
144
|
The settings host uses the same placement machinery, but the normal way to grow it is not by dropping a free-standing widget there. The more interesting case is adding a child page and letting JSKIT wire the menu entry for you.
|
|
143
145
|
|
|
144
|
-
The
|
|
146
|
+
The owner in the `list-placements` output helps you reason about where child pages belong. When you see:
|
|
145
147
|
|
|
146
148
|
```text
|
|
147
|
-
-
|
|
149
|
+
- page.section-nav [owner:home-settings]
|
|
148
150
|
```
|
|
149
151
|
|
|
150
|
-
you know that the
|
|
152
|
+
you know that the semantic placement is owned by the settings host page. So if you want a child page to appear in that menu, you should create it under that part of the route tree instead of treating the menu like a generic widget area. For example, `src/pages/home/settings/profile/index.vue` belongs to that settings section, so JSKIT can wire its preferred menu entry into `page.section-nav` with owner `home-settings` automatically.
|
|
151
153
|
|
|
152
154
|
Now use the settings host the way it is normally meant to be used: add a real child page under it.
|
|
153
155
|
|
|
@@ -155,7 +157,7 @@ Now use the settings host the way it is normally meant to be used: add a real ch
|
|
|
155
157
|
npx jskit generate ui-generator page home/settings/profile/index.vue --name "Profile"
|
|
156
158
|
```
|
|
157
159
|
|
|
158
|
-
This is a more interesting example than the widget case. JSKIT creates the page file, notices that `src/pages/home/settings.vue` owns the
|
|
160
|
+
This is a more interesting example than the widget case. JSKIT creates the page file, notices that `src/pages/home/settings.vue` owns the settings section navigation, and adds the preferred semantic menu entry there automatically. You do not have to write that placement entry by hand.
|
|
159
161
|
|
|
160
162
|
Open `/home/settings/profile` in the browser. The settings shell now shows a second real child page and a second real menu entry created by the same page-generation command. `General` was already there from `shell-web`; `Profile` is the first additional settings page you add yourself. This is the important part of the chapter: the exact same placement system works both at the top shell level and inside a page-owned nested outlet.
|
|
161
163
|
|
|
@@ -165,7 +167,7 @@ Now add a second sibling page:
|
|
|
165
167
|
npx jskit generate ui-generator page home/settings/notifications/index.vue --name "Notifications"
|
|
166
168
|
```
|
|
167
169
|
|
|
168
|
-
Open `/home/settings/notifications` in the browser. You now get a third settings menu entry without touching `settings.vue`, without writing a second menu component, and without hand-editing `src/placement.js`. JSKIT appends another placement entry targeting the same `
|
|
170
|
+
Open `/home/settings/notifications` in the browser. You now get a third settings menu entry without touching `settings.vue`, without writing a second menu component, and without hand-editing `src/placement.js`. JSKIT appends another placement entry targeting the same `page.section-nav` owner, so the links simply stack in the menu for free.
|
|
169
171
|
|
|
170
172
|
The order is also easy to reason about:
|
|
171
173
|
|
|
@@ -191,7 +193,7 @@ definePage({
|
|
|
191
193
|
});
|
|
192
194
|
```
|
|
193
195
|
|
|
194
|
-
This is why the `
|
|
196
|
+
This is why the `page.section-nav` owner from `list-placements` is such a useful clue: it tells you which page is acting as the host.
|
|
195
197
|
|
|
196
198
|
Even an `index.vue` page can have children. If you want an index page to stay visible while child routes render underneath it, put those children under an `index/` directory such as `src/pages/home/settings/profile/index/details.vue`.
|
|
197
199
|
|
|
@@ -209,8 +211,10 @@ In placement metadata, raw `mdi-*` strings are acceptable because the shell menu
|
|
|
209
211
|
```js
|
|
210
212
|
addPlacement({
|
|
211
213
|
id: "home.settings.profile.link",
|
|
212
|
-
target: "
|
|
213
|
-
|
|
214
|
+
target: "page.section-nav",
|
|
215
|
+
owner: "home-settings",
|
|
216
|
+
kind: "link",
|
|
217
|
+
surfaces: ["home"],
|
|
214
218
|
props: {
|
|
215
219
|
label: "Profile",
|
|
216
220
|
to: "./profile",
|
|
@@ -382,10 +386,10 @@ After the `shell-web` install plus the `placed-element` and `page` commands from
|
|
|
382
386
|
```js
|
|
383
387
|
addPlacement({
|
|
384
388
|
id: "shell-web.home.menu.home",
|
|
385
|
-
target: "shell
|
|
386
|
-
|
|
389
|
+
target: "shell.primary-nav",
|
|
390
|
+
kind: "link",
|
|
391
|
+
surfaces: ["home"],
|
|
387
392
|
order: 50,
|
|
388
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
389
393
|
props: {
|
|
390
394
|
label: "Home",
|
|
391
395
|
surface: "home",
|
|
@@ -397,10 +401,10 @@ addPlacement({
|
|
|
397
401
|
|
|
398
402
|
addPlacement({
|
|
399
403
|
id: "shell-web.home.menu.settings",
|
|
400
|
-
target: "shell
|
|
404
|
+
target: "shell.primary-nav",
|
|
405
|
+
kind: "link",
|
|
401
406
|
surfaces: ["home"],
|
|
402
407
|
order: 100,
|
|
403
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
404
408
|
props: {
|
|
405
409
|
label: "Settings",
|
|
406
410
|
surface: "home",
|
|
@@ -411,10 +415,11 @@ addPlacement({
|
|
|
411
415
|
|
|
412
416
|
addPlacement({
|
|
413
417
|
id: "shell-web.home.settings.general",
|
|
414
|
-
target: "
|
|
418
|
+
target: "page.section-nav",
|
|
419
|
+
owner: "home-settings",
|
|
420
|
+
kind: "link",
|
|
415
421
|
surfaces: ["home"],
|
|
416
422
|
order: 100,
|
|
417
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
418
423
|
props: {
|
|
419
424
|
label: "General",
|
|
420
425
|
surface: "home",
|
|
@@ -426,7 +431,8 @@ addPlacement({
|
|
|
426
431
|
|
|
427
432
|
addPlacement({
|
|
428
433
|
id: "ui-generator.element.alerts-widget",
|
|
429
|
-
target: "shell
|
|
434
|
+
target: "shell.status",
|
|
435
|
+
kind: "component",
|
|
430
436
|
surfaces: ["home"],
|
|
431
437
|
order: 155,
|
|
432
438
|
componentToken: "local.main.ui.element.alerts-widget"
|
|
@@ -434,10 +440,11 @@ addPlacement({
|
|
|
434
440
|
|
|
435
441
|
addPlacement({
|
|
436
442
|
id: "ui-generator.page.home.settings.profile.link",
|
|
437
|
-
target: "
|
|
443
|
+
target: "page.section-nav",
|
|
444
|
+
owner: "home-settings",
|
|
445
|
+
kind: "link",
|
|
438
446
|
surfaces: ["home"],
|
|
439
447
|
order: 155,
|
|
440
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
441
448
|
props: {
|
|
442
449
|
label: "Profile",
|
|
443
450
|
surface: "home",
|
|
@@ -449,10 +456,11 @@ addPlacement({
|
|
|
449
456
|
|
|
450
457
|
addPlacement({
|
|
451
458
|
id: "ui-generator.page.home.settings.notifications.link",
|
|
452
|
-
target: "
|
|
459
|
+
target: "page.section-nav",
|
|
460
|
+
owner: "home-settings",
|
|
461
|
+
kind: "link",
|
|
453
462
|
surfaces: ["home"],
|
|
454
463
|
order: 155,
|
|
455
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
456
464
|
props: {
|
|
457
465
|
label: "Notifications",
|
|
458
466
|
surface: "home",
|
|
@@ -465,13 +473,15 @@ addPlacement({
|
|
|
465
473
|
|
|
466
474
|
That snippet shows the full placement contract clearly:
|
|
467
475
|
|
|
468
|
-
- the target says
|
|
469
|
-
- the
|
|
476
|
+
- the target says which semantic placement should receive the entry
|
|
477
|
+
- the owner disambiguates page-owned semantic placements such as `page.section-nav`
|
|
478
|
+
- `kind: "link"` lets topology choose the concrete link renderer for the current layout
|
|
479
|
+
- component placements still provide their own `componentToken`
|
|
470
480
|
- `props.to` tells the generated menu link which child route to open
|
|
471
481
|
- `props.icon`, when you add one, belongs to menu metadata rather than direct Vuetify icon rendering
|
|
472
482
|
- the surface list says where it is active
|
|
473
483
|
- lower `order` values come first
|
|
474
|
-
- when multiple entries target the same
|
|
484
|
+
- when multiple entries target the same semantic placement with the same order, the shell keeps their source order
|
|
475
485
|
|
|
476
486
|
That is why the settings menu now shows `General` first, followed by `Profile` and `Notifications`: `General` is seeded by `shell-web` with a lower order, while the two generated pages share the same later order and keep their source order.
|
|
477
487
|
|
|
@@ -616,10 +626,7 @@ The important host file is still `src/pages/home/settings.vue`:
|
|
|
616
626
|
|
|
617
627
|
```vue
|
|
618
628
|
<v-list nav density="comfortable" rounded="lg" border>
|
|
619
|
-
<ShellOutlet
|
|
620
|
-
target="home-settings:primary-menu"
|
|
621
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
622
|
-
/>
|
|
629
|
+
<ShellOutlet target="home-settings:primary-menu" />
|
|
623
630
|
</v-list>
|
|
624
631
|
|
|
625
632
|
<RouterView />
|
|
@@ -631,7 +638,7 @@ The starter shell now uses a real child-page structure right away:
|
|
|
631
638
|
|
|
632
639
|
- `src/pages/home/settings/index.vue` is only a redirect into the first child page
|
|
633
640
|
- `src/pages/home/settings/general/index.vue` is the first real settings page
|
|
634
|
-
- `src/placement.js` already seeds a `General` link into `home-settings
|
|
641
|
+
- `src/placement.js` already seeds a `General` link into `page.section-nav` with owner `home-settings`
|
|
635
642
|
|
|
636
643
|
When you need that landing redirect yourself, use the same helper pattern:
|
|
637
644
|
|
|
@@ -319,10 +319,10 @@ The placement entry is just a normal shell link:
|
|
|
319
319
|
```js
|
|
320
320
|
addPlacement({
|
|
321
321
|
id: "ui-generator.page.home.reports.link",
|
|
322
|
-
target: "shell
|
|
322
|
+
target: "shell.primary-nav",
|
|
323
|
+
kind: "link",
|
|
323
324
|
surfaces: ["home"],
|
|
324
325
|
order: 155,
|
|
325
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
326
326
|
props: {
|
|
327
327
|
label: "Reports",
|
|
328
328
|
surface: "home",
|
|
@@ -390,10 +390,10 @@ To hide the `Reports` menu entry until the user is logged in, update the placeme
|
|
|
390
390
|
```js
|
|
391
391
|
addPlacement({
|
|
392
392
|
id: "ui-generator.page.home.reports.link",
|
|
393
|
-
target: "shell
|
|
393
|
+
target: "shell.primary-nav",
|
|
394
|
+
kind: "link",
|
|
394
395
|
surfaces: ["home"],
|
|
395
396
|
order: 155,
|
|
396
|
-
componentToken: "local.main.ui.surface-aware-menu-link-item",
|
|
397
397
|
props: {
|
|
398
398
|
label: "Reports",
|
|
399
399
|
surface: "home",
|
|
@@ -606,7 +606,8 @@ Authentication also becomes visible in the shell through `src/placement.js`:
|
|
|
606
606
|
```js
|
|
607
607
|
addPlacement({
|
|
608
608
|
id: "auth.profile.widget",
|
|
609
|
-
target: "shell
|
|
609
|
+
target: "shell.status",
|
|
610
|
+
kind: "component",
|
|
610
611
|
surfaces: ["*"],
|
|
611
612
|
order: 1000,
|
|
612
613
|
componentToken: "auth.web.profile.widget"
|
|
@@ -614,10 +615,10 @@ addPlacement({
|
|
|
614
615
|
|
|
615
616
|
addPlacement({
|
|
616
617
|
id: "auth.profile.menu.sign-in",
|
|
617
|
-
target: "auth
|
|
618
|
+
target: "auth.profile-menu",
|
|
619
|
+
kind: "link",
|
|
618
620
|
surfaces: ["*"],
|
|
619
621
|
order: 200,
|
|
620
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
621
622
|
props: {
|
|
622
623
|
label: "Sign in",
|
|
623
624
|
to: "/auth/login"
|
|
@@ -627,10 +628,10 @@ addPlacement({
|
|
|
627
628
|
|
|
628
629
|
addPlacement({
|
|
629
630
|
id: "auth.profile.menu.sign-out",
|
|
630
|
-
target: "auth
|
|
631
|
+
target: "auth.profile-menu",
|
|
632
|
+
kind: "link",
|
|
631
633
|
surfaces: ["*"],
|
|
632
634
|
order: 1000,
|
|
633
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
634
635
|
props: {
|
|
635
636
|
label: "Sign out",
|
|
636
637
|
to: "/auth/signout"
|
|
@@ -179,7 +179,7 @@ This follows the same route-owner pattern the guide has already shown on `home`
|
|
|
179
179
|
- `src/pages/console/settings.vue` is the nested settings shell
|
|
180
180
|
- `src/pages/console/settings/index.vue` is the initial developer-owned stub
|
|
181
181
|
|
|
182
|
-
That last file is intentionally empty, because later modules are expected to add real console settings sections
|
|
182
|
+
That last file is intentionally empty, because later modules are expected to add real console settings sections through `page.section-nav` with owner `console-settings`.
|
|
183
183
|
|
|
184
184
|
### `src/placement.js` wires the first console menu entry
|
|
185
185
|
|
|
@@ -188,10 +188,10 @@ The starter placement block is:
|
|
|
188
188
|
```js
|
|
189
189
|
addPlacement({
|
|
190
190
|
id: "console.web.menu.settings",
|
|
191
|
-
target: "shell
|
|
191
|
+
target: "shell.primary-nav",
|
|
192
|
+
kind: "link",
|
|
192
193
|
surfaces: ["console"],
|
|
193
194
|
order: 100,
|
|
194
|
-
componentToken: "local.main.ui.menu-link-item",
|
|
195
195
|
props: {
|
|
196
196
|
label: "Settings",
|
|
197
197
|
to: "/console/settings",
|
|
@@ -325,16 +325,13 @@ That command does two things:
|
|
|
325
325
|
- it creates `src/pages/w/[workspaceSlug]/admin/workspace/settings/billing/index.vue`
|
|
326
326
|
- it also appends the matching workspace settings menu entry into `src/placement.js`
|
|
327
327
|
|
|
328
|
-
The reason JSKIT can wire that link automatically is that the workspace settings shell already exposes a
|
|
328
|
+
The reason JSKIT can wire that link automatically is that the workspace settings shell already exposes a concrete outlet and topology maps it to semantic section navigation:
|
|
329
329
|
|
|
330
330
|
```vue
|
|
331
|
-
<ShellOutlet
|
|
332
|
-
target="admin-settings:primary-menu"
|
|
333
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
334
|
-
/>
|
|
331
|
+
<ShellOutlet target="admin-settings:primary-menu" />
|
|
335
332
|
```
|
|
336
333
|
|
|
337
|
-
|
|
334
|
+
The route host lets the generator infer `page.section-nav` with owner `admin-settings`. `src/placementTopology.js` then maps that semantic placement to `admin-settings:primary-menu` and supplies the link renderer for compact, medium, and expanded layouts. So a page generated under `w/[workspaceSlug]/admin/workspace/settings/...` automatically lands in the left-side workspace settings menu without you hand-writing the placement entry.
|
|
338
335
|
|
|
339
336
|
### Workspace pages are prepared for missing-workspace states
|
|
340
337
|
|
|
@@ -524,7 +521,8 @@ The workspace packages append a new block of placements:
|
|
|
524
521
|
```js
|
|
525
522
|
addPlacement({
|
|
526
523
|
id: "workspaces.profile.menu.surface-switch",
|
|
527
|
-
target: "auth
|
|
524
|
+
target: "auth.profile-menu",
|
|
525
|
+
kind: "component",
|
|
528
526
|
surfaces: ["*"],
|
|
529
527
|
order: 100,
|
|
530
528
|
componentToken: "workspaces.web.profile.menu.surface-switch-item",
|
|
@@ -533,7 +531,8 @@ addPlacement({
|
|
|
533
531
|
|
|
534
532
|
addPlacement({
|
|
535
533
|
id: "workspaces.workspace.selector",
|
|
536
|
-
target: "shell
|
|
534
|
+
target: "shell.identity",
|
|
535
|
+
kind: "component",
|
|
537
536
|
surfaces: ["*"],
|
|
538
537
|
order: 200,
|
|
539
538
|
componentToken: "workspaces.web.workspace.selector",
|
|
@@ -548,7 +547,8 @@ addPlacement({
|
|
|
548
547
|
|
|
549
548
|
addPlacement({
|
|
550
549
|
id: "workspaces.account.invites.cue",
|
|
551
|
-
target: "shell
|
|
550
|
+
target: "shell.status",
|
|
551
|
+
kind: "component",
|
|
552
552
|
surfaces: ["*"],
|
|
553
553
|
order: 850,
|
|
554
554
|
componentToken: "local.main.account.pending-invites.cue",
|
|
@@ -557,7 +557,8 @@ addPlacement({
|
|
|
557
557
|
|
|
558
558
|
addPlacement({
|
|
559
559
|
id: "workspaces.workspace.tools.widget",
|
|
560
|
-
target: "shell
|
|
560
|
+
target: "shell.status",
|
|
561
|
+
kind: "component",
|
|
561
562
|
surfaces: ["admin"],
|
|
562
563
|
order: 900,
|
|
563
564
|
componentToken: "workspaces.web.workspace.tools.widget"
|
|
@@ -565,7 +566,8 @@ addPlacement({
|
|
|
565
566
|
|
|
566
567
|
addPlacement({
|
|
567
568
|
id: "workspaces.workspace.menu.workspace-settings",
|
|
568
|
-
target: "admin-
|
|
569
|
+
target: "admin.tools-menu",
|
|
570
|
+
kind: "component",
|
|
569
571
|
surfaces: ["admin"],
|
|
570
572
|
order: 100,
|
|
571
573
|
componentToken: "workspaces.web.workspace-settings.menu-item"
|
|
@@ -573,7 +575,8 @@ addPlacement({
|
|
|
573
575
|
|
|
574
576
|
addPlacement({
|
|
575
577
|
id: "workspaces.workspace.menu.members",
|
|
576
|
-
target: "admin-
|
|
578
|
+
target: "admin.tools-menu",
|
|
579
|
+
kind: "component",
|
|
577
580
|
surfaces: ["admin"],
|
|
578
581
|
order: 200,
|
|
579
582
|
componentToken: "workspaces.web.workspace-members.menu-item"
|
|
@@ -588,7 +591,7 @@ That one block explains a lot of the new shell behavior.
|
|
|
588
591
|
- the admin surface gets workspace tools in the top-right area
|
|
589
592
|
- the admin workspace settings menu is now another nested placement host with both `Settings` and `Members`
|
|
590
593
|
|
|
591
|
-
If you want to add your own app-owned page into that top cog menu, first ask JSKIT which
|
|
594
|
+
If you want to add your own app-owned page into that top cog menu, first ask JSKIT which semantic placements exist:
|
|
592
595
|
|
|
593
596
|
```bash
|
|
594
597
|
npx jskit list-placements
|
|
@@ -597,25 +600,25 @@ npx jskit list-placements
|
|
|
597
600
|
In a workspace-enabled app, that list now includes:
|
|
598
601
|
|
|
599
602
|
```text
|
|
600
|
-
- admin-
|
|
603
|
+
- admin.tools-menu: Admin surface tools menu actions.
|
|
601
604
|
```
|
|
602
605
|
|
|
603
|
-
If you want
|
|
606
|
+
If you want the underlying outlet inventory, use `npx jskit list-placements --concrete`. If you want more package context, `npx jskit show @jskit-ai/workspaces-web --details` also shows the topology plus the default `Settings` and `Members` entries already targeting it.
|
|
604
607
|
|
|
605
|
-
Once you know the
|
|
608
|
+
Once you know the semantic placement id, generate the page like this:
|
|
606
609
|
|
|
607
610
|
```bash
|
|
608
611
|
npx jskit generate ui-generator page \
|
|
609
612
|
w/[workspaceSlug]/admin/catalogue/index.vue \
|
|
610
613
|
--name "Catalogue" \
|
|
611
|
-
--link-placement admin-
|
|
614
|
+
--link-placement admin.tools-menu
|
|
612
615
|
```
|
|
613
616
|
|
|
614
617
|
That command creates `src/pages/w/[workspaceSlug]/admin/catalogue/index.vue` and appends the matching link entry into `src/placement.js`.
|
|
615
618
|
|
|
616
|
-
`--link-placement` is necessary here because this route is just a normal `admin` page. It is **not** a child page under a local host like `w/[workspaceSlug]/admin/workspace/settings.vue`, so the generator has no nested settings
|
|
619
|
+
`--link-placement` is necessary here because this route is just a normal `admin` page. It is **not** a child page under a local host like `w/[workspaceSlug]/admin/workspace/settings.vue`, so the generator has no nested settings placement to infer automatically. If you omit `--link-placement`, the new page link falls back to the app's default `shell.primary-nav` placement instead of the cog menu.
|
|
617
620
|
|
|
618
|
-
You also do **not** need
|
|
621
|
+
You also do **not** need a renderer flag here. `admin.tools-menu` defines its link renderer in topology, so JSKIT resolves that when it renders the placement entry.
|
|
619
622
|
|
|
620
623
|
So the placement system from the shell chapter is still doing the same job as before. The app just has a richer routing and tenancy context now.
|
|
621
624
|
|
|
@@ -85,9 +85,7 @@ npx jskit generate assistant page \
|
|
|
85
85
|
npx jskit generate assistant settings-page \
|
|
86
86
|
console/settings/admin-assistant/index.vue \
|
|
87
87
|
--surface admin \
|
|
88
|
-
--name "Admin Assistant"
|
|
89
|
-
--link-placement console-settings:primary-menu \
|
|
90
|
-
--link-component-token local.main.ui.surface-aware-menu-link-item
|
|
88
|
+
--name "Admin Assistant"
|
|
91
89
|
|
|
92
90
|
npm install
|
|
93
91
|
npm run db:migrate
|
|
@@ -154,7 +152,7 @@ First list the available placement destinations:
|
|
|
154
152
|
npx jskit list-placements
|
|
155
153
|
```
|
|
156
154
|
|
|
157
|
-
In a workspace-enabled app, that output includes `admin-
|
|
155
|
+
In a workspace-enabled app, that output includes the semantic `admin.tools-menu` placement.
|
|
158
156
|
|
|
159
157
|
Then generate the page:
|
|
160
158
|
|
|
@@ -162,7 +160,7 @@ Then generate the page:
|
|
|
162
160
|
npx jskit generate ui-generator page \
|
|
163
161
|
w/[workspaceSlug]/admin/catalogue/index.vue \
|
|
164
162
|
--name "Catalogue" \
|
|
165
|
-
--link-placement admin-
|
|
163
|
+
--link-placement admin.tools-menu
|
|
166
164
|
```
|
|
167
165
|
|
|
168
166
|
`--link-placement` is necessary here because this is just a normal `admin` page. It is not a child page under a local route host that already owns a nested outlet.
|
|
@@ -183,13 +181,10 @@ Because this page is not under a more specific local host, JSKIT falls back to t
|
|
|
183
181
|
|
|
184
182
|
The workspace settings pages in Step 2 auto-linked into the settings menu for two reasons:
|
|
185
183
|
|
|
186
|
-
1. The parent host already exposes a
|
|
184
|
+
1. The parent host already exposes a concrete outlet:
|
|
187
185
|
|
|
188
186
|
```vue
|
|
189
|
-
<ShellOutlet
|
|
190
|
-
target="admin-settings:primary-menu"
|
|
191
|
-
default-link-component-token="local.main.ui.surface-aware-menu-link-item"
|
|
192
|
-
/>
|
|
187
|
+
<ShellOutlet target="admin-settings:primary-menu" />
|
|
193
188
|
```
|
|
194
189
|
|
|
195
190
|
2. Your generated pages live under that host route:
|
|
@@ -200,12 +195,14 @@ w/[workspaceSlug]/admin/workspace/settings/...
|
|
|
200
195
|
|
|
201
196
|
So JSKIT can infer both:
|
|
202
197
|
|
|
203
|
-
- the placement target: `
|
|
204
|
-
- the
|
|
198
|
+
- the semantic placement target: `page.section-nav`
|
|
199
|
+
- the placement owner: `admin-settings`
|
|
205
200
|
|
|
206
|
-
|
|
201
|
+
The renderer comes from `src/placementTopology.js`, where `page.section-nav` maps to the concrete `admin-settings:primary-menu` outlet for each layout class.
|
|
207
202
|
|
|
208
|
-
|
|
203
|
+
That is why the simple settings-page commands do not need `--link-placement`.
|
|
204
|
+
|
|
205
|
+
The admin cog example is different. `w/[workspaceSlug]/admin/catalogue/index.vue` is just a normal admin page, so there is no local nested host to infer. That is why you must pass `--link-placement admin.tools-menu` there.
|
|
209
206
|
|
|
210
207
|
If you want a little more context than the raw destination list, this is also useful:
|
|
211
208
|
|
|
@@ -180,10 +180,10 @@ The placement registry also becomes more interesting:
|
|
|
180
180
|
```js
|
|
181
181
|
addPlacement({
|
|
182
182
|
id: "users.profile.menu.settings",
|
|
183
|
-
target: "auth
|
|
183
|
+
target: "auth.profile-menu",
|
|
184
|
+
kind: "link",
|
|
184
185
|
surfaces: ["*"],
|
|
185
186
|
order: 500,
|
|
186
|
-
componentToken: "auth.web.profile.menu.link-item",
|
|
187
187
|
props: {
|
|
188
188
|
label: "Settings",
|
|
189
189
|
to: "/account"
|
|
@@ -239,7 +239,7 @@ src/components/account/settings/
|
|
|
239
239
|
|
|
240
240
|
Those three section components stay app-owned so you can reshape the actual UI freely.
|
|
241
241
|
|
|
242
|
-
The host itself now lives in `users-web` and resolves every account section through the `
|
|
242
|
+
The host itself now lives in `users-web` and resolves every account section through the semantic `settings.sections` placement with owner `account-settings`, including the default `profile`, `preferences`, and `notifications` entries.
|
|
243
243
|
|
|
244
244
|
So the screen follows the same rule as the rest of JSKIT UI: sections are added by placement rather than being hardcoded into an app-owned host component.
|
|
245
245
|
|
|
@@ -332,8 +332,8 @@ The placement sections are often the most useful part of `show --details`.
|
|
|
332
332
|
|
|
333
333
|
For `@jskit-ai/workspaces-web`, the detailed output shows placement contributions such as:
|
|
334
334
|
|
|
335
|
-
- the workspace selector in `shell
|
|
336
|
-
- the pending invites cue in `shell
|
|
335
|
+
- the workspace selector in `shell.identity`
|
|
336
|
+
- the pending invites cue in `shell.status`
|
|
337
337
|
- the workspace tools widget on the `admin` surface
|
|
338
338
|
- the `Members` and workspace settings menu entries
|
|
339
339
|
|
|
@@ -341,9 +341,10 @@ That lets you answer a very concrete question before installing anything:
|
|
|
341
341
|
|
|
342
342
|
- *what will change in the shell if I add this package?*
|
|
343
343
|
|
|
344
|
-
It also shows placement
|
|
344
|
+
It also shows semantic placement topology, such as:
|
|
345
345
|
|
|
346
|
-
- `admin-settings
|
|
346
|
+
- `page.section-nav` with owner `admin-settings`
|
|
347
|
+
- `admin.tools-menu`
|
|
347
348
|
|
|
348
349
|
which helps you understand where later app-owned pages or settings links can attach.
|
|
349
350
|
|