@jskit-ai/agent-docs 0.1.274 → 0.1.276

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 (109) hide show
  1. package/guide/agent/app-extras/assistant-conversation.md +7 -1
  2. package/guide/agent/app-extras/assistant-voice.md +5 -1
  3. package/guide/agent/app-setup/database-layer.md +30 -0
  4. package/guide/agent/app-setup/material-3-migration.md +180 -0
  5. package/guide/agent/app-setup/upgrading-jskit.md +5 -0
  6. package/guide/agent/framework/material-3.md +316 -73
  7. package/guide/agent/framework/typed-features.md +207 -0
  8. package/guide/agent/framework/ui-operations.md +18 -35
  9. package/guide/agent/framework/ui-pass.md +155 -0
  10. package/guide/agent/index.md +3 -0
  11. package/package.json +1 -1
  12. package/patterns/feature-package/example/booking-engine/package.json +1 -1
  13. package/patterns/minimal-foundation/example/package.json +5 -4
  14. package/patterns/minimal-foundation/example/src/main.js +5 -11
  15. package/patterns/minimal-foundation/example/src/pages/home/index.vue +5 -18
  16. package/patterns/minimal-foundation/example/src/theme/index.js +9 -0
  17. package/patterns/minimal-foundation/example/src/views/NotFound.vue +5 -4
  18. package/patterns/shell-foundation/example/package.json +6 -6
  19. package/patterns/shell-foundation/example/packages/main/package.json +1 -1
  20. package/patterns/shell-foundation/example/src/main.js +5 -11
  21. package/patterns/shell-foundation/example/src/pages/home/index.vue +21 -57
  22. package/patterns/shell-foundation/example/src/pages/home/settings/general/index.vue +24 -19
  23. package/patterns/shell-foundation/example/src/pages/home/settings.vue +27 -84
  24. package/patterns/shell-foundation/example/src/theme/index.js +9 -0
  25. package/patterns/shell-foundation/example/src/views/NotFound.vue +9 -7
  26. package/reference/autogen/PATTERN_INDEX.md +37 -37
  27. package/reference/autogen/README.md +1 -0
  28. package/reference/autogen/packages/agent-docs.md +8 -4
  29. package/reference/autogen/packages/assistant-core.md +1 -0
  30. package/reference/autogen/packages/console-web.md +5 -0
  31. package/reference/autogen/packages/http-web.md +29 -2
  32. package/reference/autogen/packages/kernel.md +2 -1
  33. package/reference/autogen/packages/material-web.md +54 -0
  34. package/reference/autogen/packages/shell-web.md +121 -9
  35. package/reference/autogen/tooling/jskit-catalog.md +81 -0
  36. package/reference/autogen/tooling/testUtils.md +7 -0
  37. package/skills/jskit/SKILL.md +17 -6
  38. package/skills/jskit/references/heuristics/INDEX.md +3 -3
  39. package/skills/jskit/references/heuristics/row-policies.md +10 -0
  40. package/skills/jskit/references/heuristics/typed-features.md +12 -0
  41. package/skills/jskit/references/heuristics/ui-contract.md +10 -7
  42. package/skills/jskit/references/heuristics/ui-testing.md +14 -8
  43. package/skills/jskit/references/material-3.md +315 -72
  44. package/skills/jskit/references/pattern-index.md +37 -37
  45. package/skills/jskit/references/patterns/app/minimal-foundation/example/package.json +5 -4
  46. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/main.js +5 -11
  47. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/pages/home/index.vue +5 -18
  48. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/theme/index.js +9 -0
  49. package/skills/jskit/references/patterns/app/minimal-foundation/example/src/views/NotFound.vue +5 -4
  50. package/skills/jskit/references/patterns/app/shell-foundation/example/package.json +6 -6
  51. package/skills/jskit/references/patterns/app/shell-foundation/example/packages/main/package.json +1 -1
  52. package/skills/jskit/references/patterns/app/shell-foundation/example/src/main.js +5 -11
  53. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/index.vue +21 -57
  54. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/general/index.vue +24 -19
  55. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings.vue +27 -84
  56. package/skills/jskit/references/patterns/app/shell-foundation/example/src/theme/index.js +9 -0
  57. package/skills/jskit/references/patterns/app/shell-foundation/example/src/views/NotFound.vue +9 -7
  58. package/skills/jskit/references/patterns/assistant/assistant-surface/example/src/placement.js +1 -1
  59. package/skills/jskit/references/patterns/auth/accounts-hub/example/package.json +2 -2
  60. package/skills/jskit/references/patterns/auth/oidc-sign-in/example/package.json +2 -2
  61. package/skills/jskit/references/patterns/auth/supabase-auth/example/package.json +1 -1
  62. package/skills/jskit/references/patterns/connectors/calendar-cli/example/package.json +4 -4
  63. package/skills/jskit/references/patterns/console/console-surface/PATTERN.md +4 -2
  64. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/index.vue +10 -40
  65. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings/index.vue +3 -11
  66. package/skills/jskit/references/patterns/console/console-surface/example/src/pages/console/settings.vue +24 -72
  67. package/skills/jskit/references/patterns/console/console-surface/example/src/placement.js +28 -0
  68. package/skills/jskit/references/patterns/crud/crud-screen-set/PATTERN.md +13 -0
  69. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookEditPage.vue +2 -0
  70. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookFormFields.vue +0 -6
  71. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookListPage.vue +5 -2
  72. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookNewPage.vue +2 -0
  73. package/skills/jskit/references/patterns/crud/crud-screen-set/example/books/BookViewPage.vue +5 -9
  74. package/skills/jskit/references/patterns/crud/json-api-resource-package/example/packages/books/package.json +2 -2
  75. package/skills/jskit/references/patterns/database/mysql-application/example/package.json +1 -1
  76. package/skills/jskit/references/patterns/database/postgres-application/example/package.json +1 -1
  77. package/skills/jskit/references/patterns/realtime/realtime-application/example/package.json +2 -2
  78. package/skills/jskit/references/patterns/server/feature-package/example/booking-engine/package.json +1 -1
  79. package/skills/jskit/references/patterns/shell/application-shell/PATTERN.md +3 -1
  80. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/pages/home/index.vue +5 -18
  81. package/skills/jskit/references/patterns/shell/application-shell/example/expected-existing/src/views/NotFound.vue +14 -0
  82. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/index.vue +21 -57
  83. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/general/index.vue +24 -19
  84. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings.vue +27 -84
  85. package/skills/jskit/references/patterns/shell/application-shell/example/src/views/NotFound.vue +15 -0
  86. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/components/SyncStatusElement.vue +2 -2
  87. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/activity.vue +1 -1
  88. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports/overview.vue +1 -1
  89. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/pages/home/reports.vue +6 -3
  90. package/skills/jskit/references/patterns/ui/page-and-placement/example/src/placement.js +1 -1
  91. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsNotificationsSection.vue +2 -8
  92. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsPreferencesSection.vue +2 -8
  93. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsProfileSection.vue +5 -11
  94. package/skills/jskit/references/patterns/users/account-settings/example/src/components/account/settings/AccountSettingsSignInMethodsSection.vue +3 -9
  95. package/skills/jskit/references/patterns/users/account-settings/example/src/pages/account/index.vue +7 -0
  96. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users/package.json +2 -2
  97. package/skills/jskit/references/patterns/users/user-administration-server/example/packages/users-workspace/package.json +3 -3
  98. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/packages/main/src/client/components/AccountPendingInvitesCue.vue +1 -2
  99. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/components/WorkspaceNotFoundCard.vue +5 -6
  100. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings/index.vue +5 -12
  101. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/pages/admin/workspace/settings.vue +24 -72
  102. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/admin/index.vue +3 -4
  103. package/skills/jskit/references/patterns/workspaces/workspace-surfaces/example/src/surfaces/app/index.vue +3 -3
  104. package/skills/jskit/references/typed-features.md +207 -0
  105. package/skills/jskit/references/ui-operations.md +18 -35
  106. package/skills/jskit/references/ui-pass.md +150 -0
  107. package/patterns/shell-foundation/example/src/pages/home/settings/index.vue +0 -7
  108. package/skills/jskit/references/patterns/app/shell-foundation/example/src/pages/home/settings/index.vue +0 -7
  109. package/skills/jskit/references/patterns/shell/application-shell/example/src/pages/home/settings/index.vue +0 -7
@@ -2,6 +2,15 @@
2
2
  import { computed } from "vue";
3
3
  import { useShellLayoutState } from "@jskit-ai/shell-web/client/composables/useShellLayoutState";
4
4
 
5
+ definePage({
6
+ meta: {
7
+ jskit: {
8
+ title: "General",
9
+ parent: "/settings"
10
+ }
11
+ }
12
+ });
13
+
5
14
  const { drawerDefaultOpen, setDrawerDefaultOpen } = useShellLayoutState();
6
15
 
7
16
  const drawerDefaultOpenModel = computed({
@@ -15,23 +24,19 @@ const drawerDefaultOpenModel = computed({
15
24
  </script>
16
25
 
17
26
  <template>
18
- <section class="settings-general-screen d-flex flex-column ga-4">
19
- <p class="text-body-2 text-medium-emphasis mb-0">
20
- On wider screens, collapsed navigation remains available as a rail. Phone layouts close the drawer and keep primary navigation in the bottom bar.
21
- </p>
22
-
23
- <v-switch
24
- v-model="drawerDefaultOpenModel"
25
- color="primary"
26
- inset
27
- hide-details="auto"
28
- label="Start with expanded navigation on wider screens"
29
- />
30
- </section>
27
+ <v-card>
28
+ <v-list lines="three">
29
+ <v-list-item
30
+ title="Start with expanded navigation on wider screens"
31
+ subtitle="On wider screens, collapsed navigation remains available as a rail. Phone layouts close the drawer and keep primary navigation in the bottom bar."
32
+ >
33
+ <template #append>
34
+ <v-switch
35
+ v-model="drawerDefaultOpenModel"
36
+ aria-label="Start with expanded navigation on wider screens"
37
+ />
38
+ </template>
39
+ </v-list-item>
40
+ </v-list>
41
+ </v-card>
31
42
  </template>
32
-
33
- <style scoped>
34
- .settings-general-screen :deep(.v-switch) {
35
- min-height: 48px;
36
- }
37
- </style>
@@ -1,90 +1,33 @@
1
1
  <script setup>
2
+ import { computed } from "vue";
3
+ import { RouterView, useRoute } from "vue-router";
4
+ import ShellListDetail from "@jskit-ai/shell-web/client/components/ShellListDetail";
2
5
  import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";
3
- import { RouterView } from "vue-router";
4
- </script>
5
-
6
- <template>
7
- <section class="settings-shell d-flex flex-column ga-4">
8
- <v-sheet rounded="lg" border class="settings-shell__panel">
9
- <div class="settings-shell__body">
10
- <nav class="settings-shell__nav" aria-label="Home settings sections">
11
- <v-list nav density="compact" rounded="lg">
12
- <ShellOutlet target="home-settings:primary-menu" />
13
- </v-list>
14
- </nav>
15
-
16
- <main class="settings-shell__content">
17
- <RouterView />
18
- </main>
19
- </div>
20
- </v-sheet>
21
- </section>
22
- </template>
23
-
24
- <style scoped>
25
- .settings-shell {
26
- --settings-shell-panel-padding: 1rem;
27
- }
28
-
29
- .settings-shell__panel {
30
- overflow: hidden;
31
- }
32
-
33
- .settings-shell__body {
34
- display: grid;
35
- gap: 1rem;
36
- grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
37
- padding: var(--settings-shell-panel-padding);
38
- }
39
-
40
- .settings-shell__content {
41
- border-left: 1px solid rgba(var(--v-theme-on-surface), 0.18);
42
- min-width: 0;
43
- padding-left: 1rem;
44
- }
45
-
46
- .settings-shell__nav :deep(.v-list) {
47
- padding: 0.35rem;
48
- }
49
-
50
- .settings-shell__nav :deep(.v-list-item) {
51
- min-height: 48px;
52
- padding-inline: 0.6rem 0.7rem;
53
- }
54
6
 
55
- .settings-shell__nav :deep(.v-list-item__prepend) {
56
- margin-inline-end: 0;
57
- }
58
-
59
- .settings-shell__nav :deep(.v-list-item__spacer) {
60
- min-width: 0.5rem;
61
- width: 0.5rem;
62
- }
63
-
64
- .settings-shell__nav :deep(.v-list-item-title) {
65
- line-height: 1.2;
66
- }
67
-
68
- @media (max-width: 960px) {
69
- .settings-shell__body {
70
- grid-template-columns: 1fr;
71
- }
72
-
73
- .settings-shell__nav :deep(.v-list) {
74
- display: flex;
75
- gap: 0.25rem;
76
- overflow-x: auto;
77
- scrollbar-width: thin;
7
+ definePage({
8
+ meta: {
9
+ jskit: {
10
+ title: "Settings"
11
+ }
78
12
  }
13
+ });
79
14
 
80
- .settings-shell__nav :deep(.v-list-item) {
81
- flex: 0 0 auto;
82
- min-height: 48px;
83
- }
15
+ const route = useRoute();
16
+ // The section list shows beside the open section on wide windows, and on its own at /home/settings.
17
+ const detailOpen = computed(() => !/\/settings\/?$/u.test(route.path));
18
+ </script>
84
19
 
85
- .settings-shell__content {
86
- border-left: 0;
87
- padding-left: 0;
88
- }
89
- }
90
- </style>
20
+ <template>
21
+ <ShellListDetail :detail-open="detailOpen">
22
+ <template #list>
23
+ <nav aria-label="Home settings sections">
24
+ <v-list nav>
25
+ <ShellOutlet target="home-settings:primary-menu" />
26
+ </v-list>
27
+ </nav>
28
+ </template>
29
+ <template #detail>
30
+ <RouterView />
31
+ </template>
32
+ </ShellListDetail>
33
+ </template>
@@ -0,0 +1,9 @@
1
+ // The app's only theme facts. Material 3's light and dark colour schemes are generated from this one seed colour and
2
+ // follow the device's setting: change the seed to rebrand. A colour the app really owns goes in `colors` by camelCase
3
+ // name (it gets its own container roles, harmonized to the seed), and an icon of its own goes in `icons` as
4
+ // `{ name: "<24x24 SVG path>" }`, used as `$name`.
5
+ export const theme = {
6
+ seed: "#6750A4",
7
+ colors: {},
8
+ icons: {}
9
+ };
@@ -1,13 +1,15 @@
1
1
  <script setup>
2
- const title = "Not Found";
2
+ import ShellLayout from "@/components/ShellLayout.vue";
3
+
3
4
  const message = "The page you requested does not exist.";
4
5
  </script>
5
6
 
6
7
  <template>
7
- <v-container class="fill-height d-flex align-center justify-center">
8
- <v-card class="pa-6 text-center" max-width="560" rounded="lg">
9
- <v-card-title class="text-h4">{{ title }}</v-card-title>
10
- <v-card-text class="text-medium-emphasis">{{ message }}</v-card-text>
11
- </v-card>
12
- </v-container>
8
+ <!-- The shell's top app bar carries the title, and its navigation leads back into the app. -->
9
+ <ShellLayout title="Not Found" subtitle="">
10
+ <section class="d-flex flex-column align-center text-center on-surface-variant py-16">
11
+ <v-icon icon="$searchOff" size="48" />
12
+ <p class="text-body-large mt-4 mb-0">{{ message }}</p>
13
+ </section>
14
+ </ShellLayout>
13
15
  </template>
@@ -11,7 +11,7 @@ addPlacement({
11
11
  order: 140,
12
12
  props: {
13
13
  label: "Assistant",
14
- icon: "mdi-creation-outline",
14
+ icon: "$smartToy",
15
15
  surface: "admin",
16
16
  scopedSuffix: "/assistant",
17
17
  unscopedSuffix: "/assistant"
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@jskit-ai/database-runtime-mysql": "0.1.256",
6
- "@jskit-ai/oidc-issuer-core": "0.1.16"
5
+ "@jskit-ai/database-runtime-mysql": "0.1.257",
6
+ "@jskit-ai/oidc-issuer-core": "0.1.17"
7
7
  }
8
8
  }
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@jskit-ai/auth-provider-oidc-core": "0.2.14",
6
- "@jskit-ai/auth-web": "0.2.12"
5
+ "@jskit-ai/auth-provider-oidc-core": "0.2.15",
6
+ "@jskit-ai/auth-web": "0.2.13"
7
7
  }
8
8
  }
@@ -2,6 +2,6 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@jskit-ai/auth-provider-supabase-core": "0.2.11"
5
+ "@jskit-ai/auth-provider-supabase-core": "0.2.12"
6
6
  }
7
7
  }
@@ -7,10 +7,10 @@
7
7
  "db:migrate:status": "knex --knexfile ./knexfile.js migrate:list"
8
8
  },
9
9
  "dependencies": {
10
- "@jskit-ai/connectors-core": "0.2.10",
11
- "@jskit-ai/connector-google-calendar": "0.2.10",
12
- "@jskit-ai/database-runtime": "0.1.258",
13
- "@jskit-ai/database-runtime-mysql": "0.1.256",
10
+ "@jskit-ai/connectors-core": "0.2.11",
11
+ "@jskit-ai/connector-google-calendar": "0.2.11",
12
+ "@jskit-ai/database-runtime": "0.1.259",
13
+ "@jskit-ai/database-runtime-mysql": "0.1.257",
14
14
  "knex": "^3.1.0"
15
15
  }
16
16
  }
@@ -39,8 +39,10 @@ placement, and topology APIs for application composition.
39
39
 
40
40
  ## Example files
41
41
 
42
- `example/` contains concrete console root, landing, and settings routes. Adapt
43
- them together with the surface policy and placement examples described here.
42
+ `example/` contains concrete console root, landing, and settings routes, and
43
+ `src/placement.js` declares Settings as the console's main-navigation
44
+ destination, so it starts a fresh trail and its sections' Up returns to it.
45
+ Adapt them together with the surface policy described here.
44
46
 
45
47
  ## Variation points
46
48
 
@@ -1,43 +1,13 @@
1
1
  <template>
2
- <section class="console-home-screen d-flex flex-column ga-4">
3
- <div class="console-home-screen__actions">
4
- <v-btn color="primary" variant="flat" to="/home">Back to home</v-btn>
5
- </div>
6
-
7
- <v-sheet rounded="lg" border class="console-home-screen__panel">
8
- <div class="console-home-screen__status-row">
9
- <v-chip color="secondary" variant="tonal" label>Route: /console</v-chip>
10
- <v-chip color="info" variant="tonal" label>Surface status: enabled</v-chip>
11
- </div>
12
- <p class="text-body-2 text-medium-emphasis mb-0">
13
- Use this surface for operator actions and technical insights that should stay out of the end-user app.
14
- </p>
15
- </v-sheet>
2
+ <section class="d-flex flex-column ga-4">
3
+ <v-card>
4
+ <v-list lines="two">
5
+ <v-list-item title="/console" subtitle="Route" />
6
+ <v-list-item title="Enabled" subtitle="Surface status" />
7
+ </v-list>
8
+ </v-card>
9
+ <p class="text-body-medium on-surface-variant mb-0">
10
+ Use this surface for operator actions and technical insights that should stay out of the end-user app.
11
+ </p>
16
12
  </section>
17
13
  </template>
18
-
19
- <style scoped>
20
- .console-home-screen__actions {
21
- display: flex;
22
- justify-content: flex-end;
23
- }
24
-
25
- .console-home-screen__panel {
26
- display: grid;
27
- gap: 1rem;
28
- padding: 1rem;
29
- }
30
-
31
- .console-home-screen__status-row {
32
- display: flex;
33
- flex-wrap: wrap;
34
- gap: 0.5rem;
35
- }
36
-
37
- @media (max-width: 640px) {
38
- .console-home-screen__actions :deep(.v-btn) {
39
- min-height: 48px;
40
- width: 100%;
41
- }
42
- }
43
- </style>
@@ -1,16 +1,8 @@
1
1
  <template>
2
- <section class="console-settings-empty">
3
- <p class="text-body-2 text-medium-emphasis mb-0">
2
+ <section class="on-surface-variant text-center py-12">
3
+ <v-icon icon="$settings" size="48" />
4
+ <p class="text-body-large mt-4 mb-0">
4
5
  Console settings sections will appear here when installed.
5
6
  </p>
6
7
  </section>
7
8
  </template>
8
-
9
- <style scoped>
10
- .console-settings-empty {
11
- margin-inline: auto;
12
- max-width: 34rem;
13
- padding: 2rem 1.25rem;
14
- text-align: center;
15
- }
16
- </style>
@@ -1,81 +1,33 @@
1
1
  <script setup>
2
+ import { computed } from "vue";
3
+ import { RouterView, useRoute } from "vue-router";
4
+ import ShellListDetail from "@jskit-ai/shell-web/client/components/ShellListDetail";
2
5
  import ShellOutlet from "@jskit-ai/shell-web/client/components/ShellOutlet";
3
- import { RouterView } from "vue-router";
6
+
7
+ definePage({
8
+ meta: {
9
+ jskit: {
10
+ title: "Settings"
11
+ }
12
+ }
13
+ });
14
+
15
+ const route = useRoute();
16
+ // The section list shows beside the open section on wide windows, and on its own at the settings landing.
17
+ const detailOpen = computed(() => !/\/settings\/?$/u.test(route.path));
4
18
  </script>
5
19
 
6
20
  <template>
7
- <section class="settings-shell d-flex flex-column ga-4">
8
- <v-sheet rounded="lg" border class="settings-shell__panel">
9
- <nav class="settings-shell__nav" aria-label="Console settings sections">
10
- <v-list nav density="compact" class="settings-shell__nav-list">
21
+ <ShellListDetail :detail-open="detailOpen">
22
+ <template #list>
23
+ <nav aria-label="Console settings sections">
24
+ <v-list nav>
11
25
  <ShellOutlet target="console-settings:primary-menu" />
12
26
  </v-list>
13
27
  </nav>
14
- <main class="settings-shell__content">
15
- <RouterView />
16
- </main>
17
- </v-sheet>
18
- </section>
28
+ </template>
29
+ <template #detail>
30
+ <RouterView />
31
+ </template>
32
+ </ShellListDetail>
19
33
  </template>
20
-
21
- <style scoped>
22
- .settings-shell__panel {
23
- display: grid;
24
- gap: 1rem;
25
- grid-template-columns: minmax(12rem, 16rem) minmax(0, 1fr);
26
- padding: 1rem;
27
- }
28
-
29
- .settings-shell__nav-list {
30
- padding: 0.35rem;
31
- }
32
-
33
- .settings-shell__nav-list :deep(.v-list-item) {
34
- min-height: 48px;
35
- padding-inline: 0.6rem 0.7rem;
36
- }
37
-
38
- .settings-shell__nav-list :deep(.v-list-item__prepend) {
39
- margin-inline-end: 0;
40
- }
41
-
42
- .settings-shell__nav-list :deep(.v-list-item__spacer) {
43
- min-width: 0.5rem;
44
- width: 0.5rem;
45
- }
46
-
47
- .settings-shell__nav-list :deep(.v-list-item-title) {
48
- line-height: 1.2;
49
- }
50
-
51
- .settings-shell__content {
52
- border-left: 1px solid rgba(var(--v-theme-on-surface), 0.18);
53
- min-width: 0;
54
- padding-left: 1rem;
55
- }
56
-
57
- @media (max-width: 960px) {
58
- .settings-shell__panel {
59
- grid-template-columns: 1fr;
60
- }
61
-
62
- .settings-shell__nav {
63
- overflow-x: auto;
64
- }
65
-
66
- .settings-shell__nav-list {
67
- display: flex;
68
- gap: 0.25rem;
69
- min-width: max-content;
70
- }
71
-
72
- .settings-shell__nav-list :deep(.v-list-item) {
73
- min-height: 48px;
74
- }
75
-
76
- .settings-shell__content {
77
- border-left: 0;
78
- padding-left: 0;
79
- }
80
- }
81
- </style>
@@ -0,0 +1,28 @@
1
+ import { createPlacementRegistry } from "@jskit-ai/shell-web/client/placement";
2
+
3
+ const registry = createPlacementRegistry();
4
+ const { addPlacement } = registry;
5
+
6
+ export { addPlacement };
7
+
8
+ // Keep the default export near the top so module installers can append addPlacement(...)
9
+ // blocks at the bottom of this file without changing the export section.
10
+ export default function getPlacements() {
11
+ return registry.build();
12
+ }
13
+
14
+ // Settings is a main destination of the console: choosing it starts a fresh trail, and its sections' Up returns to
15
+ // the settings list.
16
+ addPlacement({
17
+ id: "console.web.menu.settings",
18
+ target: "shell.primary-nav",
19
+ kind: "link",
20
+ surfaces: ["console"],
21
+ order: 100,
22
+ props: {
23
+ label: "Settings",
24
+ surface: "console",
25
+ scopedSuffix: "/settings",
26
+ unscopedSuffix: "/settings"
27
+ }
28
+ });
@@ -35,7 +35,20 @@ questionnaire.
35
35
 
36
36
  - Route pages stay thin and use `useCrudListScreen()`, `useCrudViewScreen()`,
37
37
  or `useCrudAddEditScreen()`.
38
+ - Each route page declares its app bar title and its parent with
39
+ `definePage({ meta: { jskit: { title, parent } } })`. The list is a main
40
+ menu destination with a title only; the view and new pages name the list as
41
+ their parent, and the edit page names the view. The shell's Up arrow follows
42
+ the parent, so screens and pages add no Back links.
38
43
  - Route pages do not add a page header or standalone heading by default.
44
+ - The shared screens put their actions in the top app bar: Refresh on the list,
45
+ Edit and the `actions` slot (such as `CrudDeleteAction`) on the view, and
46
+ Cancel and Save on a form. The list's create action is an extended FAB on
47
+ compact and medium windows and the app bar's primary button on wider ones.
48
+ - Save, Cancel and a completed delete replace the form's or the deleted record's
49
+ history entry, so neither Up nor Back reopens it.
50
+ - View fields are two-line list items with the value first:
51
+ `<v-list-item :title="record.author" subtitle="Author" />`.
39
52
  - Transport and validators come from the shared resource contract.
40
53
  - Initial visible loading uses structure-matching skeletons; pending buttons use
41
54
  stable disabled labels, never spinners.
@@ -7,6 +7,8 @@ import { bookResource } from "@local/books/shared";
7
7
  import BookFormFields from "./BookFormFields.vue";
8
8
  import { bookFormFields } from "./formFields.js";
9
9
 
10
+ definePage({ meta: { jskit: { title: "Edit book", parent: "/books/:bookId" } } });
11
+
10
12
  const route = useRoute();
11
13
  const routeRecordId = computed(() => String(route.params.bookId || "").trim());
12
14
 
@@ -20,8 +20,6 @@ defineProps({
20
20
  <v-text-field
21
21
  v-model="title"
22
22
  label="Title"
23
- variant="outlined"
24
- density="comfortable"
25
23
  maxlength="255"
26
24
  :readonly="readonly"
27
25
  :error-messages="resolveFieldErrors('title')"
@@ -31,8 +29,6 @@ defineProps({
31
29
  <v-text-field
32
30
  v-model="author"
33
31
  label="Author"
34
- variant="outlined"
35
- density="comfortable"
36
32
  maxlength="255"
37
33
  :readonly="readonly"
38
34
  :error-messages="resolveFieldErrors('author')"
@@ -42,8 +38,6 @@ defineProps({
42
38
  <v-textarea
43
39
  v-model="notes"
44
40
  label="Notes"
45
- variant="outlined"
46
- density="comfortable"
47
41
  auto-grow
48
42
  :readonly="readonly"
49
43
  :error-messages="resolveFieldErrors('notes')"
@@ -4,6 +4,9 @@ import { useCrudListScreen } from "@jskit-ai/http-web/client/composables/useCrud
4
4
  import { bookResource } from "@local/books/shared";
5
5
  import { listBulkActions, listFilters, listRowActions } from "./listExtensions.js";
6
6
 
7
+ // A main menu destination: the app bar shows its title and no Up arrow.
8
+ definePage({ meta: { jskit: { title: "Books" } } });
9
+
7
10
  const screen = useCrudListScreen({
8
11
  resource: bookResource,
9
12
  resourceNamespace: "books",
@@ -31,8 +34,8 @@ const screen = useCrudListScreen({
31
34
  <template #card-fields="{ record, formatListCardValue }">
32
35
  <dl class="d-grid ga-2 mb-0">
33
36
  <div>
34
- <dt class="text-caption text-medium-emphasis">Author</dt>
35
- <dd class="text-body-2 mb-0">{{ formatListCardValue(record.author) }}</dd>
37
+ <dt class="text-body-small on-surface-variant">Author</dt>
38
+ <dd class="text-body-medium ma-0">{{ formatListCardValue(record.author) }}</dd>
36
39
  </div>
37
40
  </dl>
38
41
  </template>
@@ -5,6 +5,8 @@ import { bookResource } from "@local/books/shared";
5
5
  import BookFormFields from "./BookFormFields.vue";
6
6
  import { bookFormFields } from "./formFields.js";
7
7
 
8
+ definePage({ meta: { jskit: { title: "New book", parent: "/books" } } });
9
+
8
10
  const screen = useCrudAddEditScreen({
9
11
  mode: "new",
10
12
  saveLabel: "Save book",
@@ -5,6 +5,9 @@ import { useCrudDeleteAction } from "@jskit-ai/http-web/client/composables/useCr
5
5
  import { useCrudViewScreen } from "@jskit-ai/http-web/client/composables/useCrudViewScreen";
6
6
  import { bookResource } from "@local/books/shared";
7
7
 
8
+ // Up returns to the page the book was opened from, or else to the list.
9
+ definePage({ meta: { jskit: { title: "Book", parent: "/books" } } });
10
+
8
11
  const screen = useCrudViewScreen({
9
12
  resource: bookResource,
10
13
  resourceNamespace: "books",
@@ -29,21 +32,14 @@ const deleteAction = useCrudDeleteAction({
29
32
  <CrudViewScreen
30
33
  :screen="screen"
31
34
  resource-singular-title="Book"
32
- resource-plural-title="Books"
33
35
  >
34
36
  <template #actions>
35
37
  <CrudDeleteAction :action="deleteAction" resource-singular-title="Book" />
36
38
  </template>
37
39
 
38
40
  <template #fields="{ view }">
39
- <v-col cols="12" md="6">
40
- <div class="text-caption text-medium-emphasis">Author</div>
41
- <div class="text-body-1">{{ view.record?.author }}</div>
42
- </v-col>
43
- <v-col cols="12">
44
- <div class="text-caption text-medium-emphasis">Notes</div>
45
- <div class="text-body-1 text-pre-wrap">{{ view.record?.notes || "No notes" }}</div>
46
- </v-col>
41
+ <v-list-item :title="view.record?.author" subtitle="Author" />
42
+ <v-list-item :title="view.record?.notes || 'No notes'" subtitle="Notes" />
47
43
  </template>
48
44
  </CrudViewScreen>
49
45
  </template>
@@ -9,8 +9,8 @@
9
9
  "./shared": "./src/shared/index.js"
10
10
  },
11
11
  "dependencies": {
12
- "@jskit-ai/crud-core": "0.2.10",
13
- "@jskit-ai/resource-crud-core": "0.1.200"
12
+ "@jskit-ai/crud-core": "0.2.11",
13
+ "@jskit-ai/resource-crud-core": "0.1.201"
14
14
  },
15
15
  "jskit": {
16
16
  "kind": "runtime",
@@ -8,6 +8,6 @@
8
8
  "db:migrate:status": "knex --knexfile ./knexfile.js migrate:list"
9
9
  },
10
10
  "dependencies": {
11
- "@jskit-ai/database-runtime-mysql": "0.1.256"
11
+ "@jskit-ai/database-runtime-mysql": "0.1.257"
12
12
  }
13
13
  }
@@ -8,6 +8,6 @@
8
8
  "db:migrate:status": "knex --knexfile ./knexfile.js migrate:list"
9
9
  },
10
10
  "dependencies": {
11
- "@jskit-ai/database-runtime-postgres": "0.1.255"
11
+ "@jskit-ai/database-runtime-postgres": "0.1.256"
12
12
  }
13
13
  }
@@ -2,7 +2,7 @@
2
2
  "private": true,
3
3
  "type": "module",
4
4
  "dependencies": {
5
- "@jskit-ai/realtime": "0.2.13",
6
- "@jskit-ai/shell-web": "0.2.10"
5
+ "@jskit-ai/realtime": "0.2.14",
6
+ "@jskit-ai/shell-web": "0.2.11"
7
7
  }
8
8
  }