nuxt-unified-ui 0.5.16 → 0.5.18
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 +1 -1
- package/app/components/un-table.vue +32 -2
- package/app/utils/unified-set.ts +8 -1
- package/package.json +3 -3
- package/skills/nuxt-unified-ui/SKILL.md +171 -169
- package/skills/nuxt-unified-ui/references/apply.md +160 -0
- package/skills/nuxt-unified-ui/references/code-style.md +603 -481
- package/skills/nuxt-unified-ui/references/data-fetching.md +10 -98
- package/skills/nuxt-unified-ui/references/dialogs.md +27 -72
- package/skills/nuxt-unified-ui/references/forms.md +95 -54
- package/skills/nuxt-unified-ui/references/layer-setup.md +10 -2
- package/skills/nuxt-unified-ui/references/pages.md +24 -116
- package/skills/nuxt-unified-ui/references/resources.md +144 -12
- package/skills/nuxt-unified-ui/references/tables.md +11 -53
- package/skills/nuxt-unified-ui/references/toast-and-ui.md +57 -41
- package/skills/nuxt-unified-ui/references/dialogs-impl.md +0 -57
- package/skills/nuxt-unified-ui/references/form-elements.md +0 -59
- package/skills/nuxt-unified-ui/references/form-field-schema.md +0 -50
- package/skills/nuxt-unified-ui/references/public-surface.md +0 -77
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ vpr serve
|
|
|
20
20
|
|
|
21
21
|
## Agent Skills
|
|
22
22
|
|
|
23
|
-
One installable Agent Skill lives under `skills/nuxt-unified-ui/` (`npx skills` compatible). It covers the layer API **and** mandatory Nuxt code style (forms, dialogs, radashi, formatting).
|
|
23
|
+
One installable Agent Skill lives under `skills/nuxt-unified-ui/` (`npx skills` compatible). It covers the layer API **and** mandatory Nuxt code style (forms, dialogs, radashi, formatting). When an agent finishes implementing work, it runs `/nuxt-unified-ui apply`: one subagent per `.vue`, `.ts`, or `.js` file, launched using a cheap fast model, applies the skill's logical, structural, and code-style rules. On `dev`, `main`, or `master`, it targets uncommitted files and falls back to the whole project when the branch is clean; outside a Git worktree it also targets the whole project. On other branches, it targets files changed relative to the base branch. You can also invoke `/nuxt-unified-ui apply` directly.
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
26
|
npx skills add . --list
|
|
@@ -134,15 +134,44 @@ function getExtraActionItems(row) {
|
|
|
134
134
|
'href',
|
|
135
135
|
'disabled',
|
|
136
136
|
'onClick',
|
|
137
|
+
'onSelect',
|
|
137
138
|
]),
|
|
138
139
|
href: resolveActionValue(it.href, row),
|
|
139
140
|
to: resolveActionValue(it.to, row),
|
|
140
141
|
disabled: resolveActionValue(it.disabled, row),
|
|
141
|
-
|
|
142
|
+
onSelect: () => it.onClick?.(row.original),
|
|
142
143
|
};
|
|
143
144
|
});
|
|
144
145
|
}
|
|
145
146
|
|
|
147
|
+
function handleRowSelect(_event, row) {
|
|
148
|
+
|
|
149
|
+
if (!props.rowTo) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
const destination = props.rowTo(row.original);
|
|
155
|
+
|
|
156
|
+
if (!destination) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
return navigateTo(destination);
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
const rowSelectHandler = computed(() => {
|
|
167
|
+
if (!props.rowTo) {
|
|
168
|
+
return undefined;
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
return handleRowSelect;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
146
175
|
|
|
147
176
|
/* pagination */
|
|
148
177
|
|
|
@@ -174,7 +203,8 @@ const pageSizeItems = computed(() => {
|
|
|
174
203
|
:data="props.data || []"
|
|
175
204
|
:column-pinning="columnPinning"
|
|
176
205
|
:ui="tableUi"
|
|
177
|
-
:meta="props.meta"
|
|
206
|
+
:meta="props.meta"
|
|
207
|
+
:on-select="rowSelectHandler">
|
|
178
208
|
|
|
179
209
|
<template v-for="(_, name) in $slots" #[name]="slotData">
|
|
180
210
|
<slot
|
package/app/utils/unified-set.ts
CHANGED
|
@@ -11,8 +11,15 @@
|
|
|
11
11
|
* @example
|
|
12
12
|
* unSet({}, 'cards[0].value', 2)
|
|
13
13
|
* // => { cards: [{ value: 2 }] }
|
|
14
|
+
*
|
|
15
|
+
* Paths that contain `__proto__`, `prototype`, or `constructor` are ignored.
|
|
14
16
|
*/
|
|
15
17
|
|
|
18
|
+
function isUnsafePathSegment(segment: string) {
|
|
19
|
+
return segment === '__proto__' || segment === 'prototype' || segment === 'constructor';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
16
23
|
export function unSet(target: any, key: string, value: any) {
|
|
17
24
|
|
|
18
25
|
const segments = (
|
|
@@ -22,7 +29,7 @@ export function unSet(target: any, key: string, value: any) {
|
|
|
22
29
|
.filter(Boolean)
|
|
23
30
|
);
|
|
24
31
|
|
|
25
|
-
if (segments.length === 0) {
|
|
32
|
+
if (segments.length === 0 || segments.some(isUnsafePathSegment)) {
|
|
26
33
|
return target;
|
|
27
34
|
}
|
|
28
35
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-unified-ui",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.18",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"types": "./index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@formkit/tempo": "1.1.0",
|
|
23
|
-
"@iconify-json/lucide": "1.2.
|
|
23
|
+
"@iconify-json/lucide": "1.2.138",
|
|
24
24
|
"@nuxt/kit": "4.5.2",
|
|
25
|
-
"@nuxt/ui": "4.11.
|
|
25
|
+
"@nuxt/ui": "4.11.3",
|
|
26
26
|
"@nuxtjs/i18n": "10.6.0",
|
|
27
27
|
"@types/canvas-confetti": "1.9.0",
|
|
28
28
|
"@vueuse/core": "15.0.0",
|
|
@@ -1,181 +1,183 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nuxt-unified-ui
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
or whenever generating Vue/Nuxt code that must match unified code style.
|
|
4
|
+
Builds and edits Nuxt apps and layers that use nuxt-unified-ui: un-form /
|
|
5
|
+
useForm schema forms, un-card, un-table, launchFormPickerDialog /
|
|
6
|
+
launchChoicePickerDialog / launchDialog, toast helpers, radXxx radashi
|
|
7
|
+
auto-imports, and the companion unified stack (ufetch, useUFetch,
|
|
8
|
+
resource-manager, createUnifiedResourceController). Use when package.json
|
|
9
|
+
depends on nuxt-unified-ui, nuxt.config extends it, or code uses these
|
|
10
|
+
APIs. Whenever implementation work is finished, run `/nuxt-unified-ui
|
|
11
|
+
apply`, which applies the skill file by file to uncommitted work (on dev,
|
|
12
|
+
main, or master) or to the current branch's changed files, falling back to
|
|
13
|
+
the whole project when there is no Git worktree or the default branch is
|
|
14
|
+
clean; users can also invoke it directly.
|
|
16
15
|
---
|
|
17
16
|
|
|
18
17
|
# nuxt-unified-ui
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
|
36
|
-
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
|
|
|
41
|
-
|
|
|
42
|
-
|
|
|
43
|
-
|
|
|
44
|
-
|
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
19
|
+
The main agent decides what code exists, where it lives, and which APIs it calls. When the work is done, the apply pipeline runs one subagent per file to check the skill's rules and apply the code style; it is the only place formatting rules apply. The main agent does not load `references/code-style.md`.
|
|
20
|
+
|
|
21
|
+
## Finishing work: `/nuxt-unified-ui apply`
|
|
22
|
+
|
|
23
|
+
Whenever you finish implementing work that added or edited a `.vue`, `.js`, or `.ts` file, run `/nuxt-unified-ui apply` before your final reply: follow [references/apply.md](references/apply.md). Do the same when the skill is invoked with the argument `apply`, or the user asks to apply nuxt-unified-ui across the project or the current branch. Invoked without an argument, the skill only loads its guidance for the task at hand.
|
|
24
|
+
|
|
25
|
+
On `dev`, `main`, or `master` it processes uncommitted `.vue`, `.js`, and `.ts` files; when that branch is clean, or the project is not a Git worktree, it processes every eligible file. On any other branch, it processes only the files that branch added or changed relative to its base branch. One subagent per file, launched using a cheap fast model, applies the logical, structural, and code-style rules, then the main agent carries out the cross-file follow-ups.
|
|
26
|
+
|
|
27
|
+
## APIs
|
|
28
|
+
|
|
29
|
+
**Layer** APIs come from this layer and are auto-imported across the app and every layer. **Companion** APIs come from the companion unified layers, which real projects always include next to this one. When an API is not listed here, check the source before using it.
|
|
30
|
+
|
|
31
|
+
| API | Use it to | From | Reference |
|
|
32
|
+
|---|---|---|---|
|
|
33
|
+
| `un-form` / `useForm` | Render a schema-driven form; `useForm` returns `{ form, formTag }` | layer | [forms.md](references/forms.md) |
|
|
34
|
+
| `registerFormExtraElement` | Add a custom form element `identifier` (call from a Nuxt plugin) | layer | [forms.md](references/forms.md) |
|
|
35
|
+
| `useFormExtraElements` | Read the registered custom elements (add them with `registerFormExtraElement`) | layer | [forms.md](references/forms.md) |
|
|
36
|
+
| `un-card` | Card with icon / title / subtitle header, body, and action rows | layer | [toast-and-ui.md](references/toast-and-ui.md) |
|
|
37
|
+
| `un-typography` | Icon + title + subtitle + text block | layer | [toast-and-ui.md](references/toast-and-ui.md) |
|
|
38
|
+
| `un-spinner` | Show a loading spinner | layer | [toast-and-ui.md](references/toast-and-ui.md) |
|
|
39
|
+
| `un-table` | Show one page of rows with row actions and a pagination footer | layer | [tables.md](references/tables.md) |
|
|
40
|
+
| `launchFormPickerDialog` | Ask for form input in a modal; submit logic goes in `submitButton.onClick` | layer | [dialogs.md](references/dialogs.md) |
|
|
41
|
+
| `launchChoicePickerDialog` | Confirm or choose in a modal; logic goes in each button's `onClick` | layer | [dialogs.md](references/dialogs.md) |
|
|
42
|
+
| `launchDialog` | Open any dialog component; resolves with its `close` payload | layer | [dialogs.md](references/dialogs.md) |
|
|
43
|
+
| `toast`, `toastSuccess`, `toastError`, `toastWarning`, `toastInfo` | Show a toast (typed helpers set icon and color) | layer | [toast-and-ui.md](references/toast-and-ui.md) |
|
|
44
|
+
| `smartMatch` | Test a function, mongo-style filter, or truthy value against an object | layer | [forms.md](references/forms.md) |
|
|
45
|
+
| `unSet` | Set a nested path on an object, creating missing levels (mutates) | layer | — |
|
|
46
|
+
| `formatDate` / `parseDate` | Format and parse dates (`@formkit/tempo`) | layer | — |
|
|
47
|
+
| `isSlotFilled` | Check whether a slot has content | layer | — |
|
|
48
|
+
| `pathRelativeToBase` | Resolve a path against a file URL; also exported from the package for `nuxt.config` | layer | [layer-setup.md](references/layer-setup.md) |
|
|
49
|
+
| `makeConfetti` | Fire confetti: `template` picks a built-in effect (`parade`, `on-top` / `on-left` / `on-right` / `on-bottom`, `on-frame`, `split-on-top`, `on-curtain`), `amount` sets particles per burst, other args go to `canvas-confetti` | layer | — |
|
|
50
|
+
| `radXxx` | Any radashi function (`radGet`, `radPick`, …), in app and server | layer | [radashi.md](references/radashi.md) |
|
|
51
|
+
| `ufetch` | Make a one-off API request (submit, delete, click) | companion | [data-fetching.md](references/data-fetching.md) |
|
|
52
|
+
| `useUFetch` | Load reactive page data (`data`, `pending`, `refresh`) | companion | [data-fetching.md](references/data-fetching.md) |
|
|
53
|
+
| `parseSchema` | Compile a resource schema DSL into `{ schema, type, inferred }` | companion | [resources.md](references/resources.md) |
|
|
54
|
+
| `createUnifiedResourceController` / `UnifiedResourceController` | Create the typed Mongo controller (`dbo`) for a resource | companion | [resources.md](references/resources.md) |
|
|
55
|
+
| `app` / `UnifiedAppRegistry` | Global typed registry of resources (`app.users.dbo`) | companion | [resources.md](references/resources.md) |
|
|
56
|
+
| `handleResourceSchema`, `handleResourceList`, `handleResourceCreate`, `handleResourceCount`, `handleResourceRetrieve`, `handleResourceUpdate`, `handleResourceDelete` | Implement the standard REST routes of a resource | companion | [resources.md](references/resources.md) |
|
|
57
|
+
| `useResourceName` | Derive a resource's API path and display titles from its name | companion | [resources.md](references/resources.md) |
|
|
58
|
+
| `useResourceMeta` | Map a resource schema to form fields and table columns | companion | [resources.md](references/resources.md) |
|
|
59
|
+
| `<resource-manager>` | Full CRUD dashboard card for a resource; exposes `refreshResources()` | companion | [resources.md](references/resources.md) |
|
|
60
|
+
| `<resource-explorer-table>` | Filter bar + sortable headers + `un-table` for a resource | companion | [tables.md](references/tables.md) |
|
|
61
|
+
| `assertBody` | Validate a request body against a schema in a server route | companion | — |
|
|
62
|
+
| `assertRateLimit` | Rate-limit a server route | companion | — |
|
|
63
|
+
| `createUnauthenticatedError` | Throw a 401 from a server route | companion | — |
|
|
64
|
+
| `generateUuid` | Generate a UUID | companion | — |
|
|
65
|
+
| `useToken` | Read or set the auth token | companion | — |
|
|
66
|
+
| `is-authenticated` middleware; `dashboard` / `empty` layouts | Protect pages; dashboard and full-bleed page layouts | companion | [pages.md](references/pages.md) |
|
|
67
|
+
| `useJsonld` | Emit JSON-LD on public pages, only when `nuxt-jsonld` is installed | `nuxt-jsonld` | [pages.md](references/pages.md) |
|
|
68
|
+
|
|
69
|
+
## File structure
|
|
70
|
+
|
|
71
|
+
The main agent decides where a file lives and which one job it has, and does it while implementing. Apply subagents only report misplaced files; they never move files or update callers.
|
|
72
|
+
|
|
73
|
+
Each `.vue`, `.js`, and `.ts` file has one responsibility. When a file would have two independent jobs, create two files.
|
|
74
|
+
|
|
75
|
+
Nuxt auto-imports `app/components/` and `app/utils/` across every layer. `app/composables/` is public in the same way. A file that must stay inside one layer does not go in those directories.
|
|
76
|
+
|
|
77
|
+
| Role | Directory | Visibility |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Private Vue component | `app/atoms/` | This layer only |
|
|
80
|
+
| Private function, composable, or helper | `app/libs/` | This layer only |
|
|
81
|
+
| Public Vue component | `app/components/` | Whole app, auto-imported |
|
|
82
|
+
| Public util | `app/utils/` | Whole app, auto-imported |
|
|
83
|
+
|
|
84
|
+
Generate private first. New components start in `app/atoms/`. New functions and similar helpers start in `app/libs/`. Promote a file to `app/components/` or `app/utils/` only when another layer needs it. After a promote, update every caller and remove the relative import; public modules are auto-imported.
|
|
85
|
+
|
|
86
|
+
Import `atoms` and `libs` with relative paths only (`../atoms/foo.vue`, `../libs/bar`). Never use `~/`, `@/`, `#layers/`, or another alias. Never import another layer's `atoms` or `libs`; promote that file first, then use the public auto-import.
|
|
87
|
+
|
|
88
|
+
Do not register `atoms` or `libs` with Nuxt `components` or `imports` config.
|
|
89
|
+
|
|
90
|
+
## Before writing
|
|
91
|
+
|
|
92
|
+
Read the reference that matches the task before creating or editing files. The details stay in that reference.
|
|
93
|
+
|
|
94
|
+
| Task | Read first |
|
|
95
|
+
|---|---|
|
|
96
|
+
| Layer installation and required CSS | [references/layer-setup.md](references/layer-setup.md) |
|
|
97
|
+
| Forms, field schema, built-in and custom elements | [references/forms.md](references/forms.md) |
|
|
98
|
+
| Dialogs | [references/dialogs.md](references/dialogs.md) |
|
|
99
|
+
| Toasts, `un-*` UI, button / badge / icon conventions | [references/toast-and-ui.md](references/toast-and-ui.md) |
|
|
100
|
+
| Tables | [references/tables.md](references/tables.md) |
|
|
101
|
+
| Pages and routing | [references/pages.md](references/pages.md) |
|
|
102
|
+
| `ufetch` / `useUFetch` | [references/data-fetching.md](references/data-fetching.md) |
|
|
103
|
+
| Unified resources | [references/resources.md](references/resources.md) |
|
|
104
|
+
| Radashi `radXxx` exports | [references/radashi.md](references/radashi.md) |
|
|
105
|
+
|
|
106
|
+
## Decisions the main agent owns
|
|
107
|
+
|
|
108
|
+
Make these choices while implementing. The apply pipeline checks them again afterward.
|
|
109
|
+
|
|
110
|
+
- Prefer the APIs above over hand-rolled equivalents (raw `$fetch`, hand-built `u-modal` flows, direct `radashi` imports).
|
|
111
|
+
- A new resource includes its server plugin, the full REST route set, and a dashboard nav entry or a custom `<resource-manager>` page.
|
|
112
|
+
- Use `ufetch` for a one-off request. Use `useUFetch` for reactive page data.
|
|
113
|
+
- Every page has an explicit `definePageMeta.name` and sets SEO with `useHead` (title) and `useSeoMeta` (description).
|
|
114
|
+
- Buttons, badges, and icons follow the component conventions in [references/toast-and-ui.md](references/toast-and-ui.md#component-conventions). Read them before writing any button.
|
|
115
|
+
- When splitting or promoting a file, update its callers in the same task.
|
|
116
|
+
- Installing the layer includes the required host `assets/css/main.css` and the `pathRelativeToBase` CSS entry in `nuxt.config`.
|
|
117
|
+
|
|
118
|
+
## i18n
|
|
119
|
+
|
|
120
|
+
**i18n is optional. Conform to the project's current state.**
|
|
121
|
+
|
|
122
|
+
- If the project does not translate its own strings (literal text, no `$t`, no locale files of its own), keep writing literal strings. Do not introduce `$t`, locale files, or i18n config unless the user decides to integrate i18n.
|
|
123
|
+
- If the project already uses i18n in another layout, follow that layout.
|
|
124
|
+
- The rules below apply once the project has decided to integrate i18n, or already follows them. This layer's own `$t` usage does not count as a decision for the project.
|
|
125
|
+
- Examples in the references often use English literals for brevity. In an i18n project those strings are `$t('...')` keys.
|
|
126
|
+
|
|
127
|
+
**When i18n is integrated**
|
|
128
|
+
|
|
129
|
+
- Every user-facing string goes through `$t`, in templates and in script. `$t` is available in both without calling `useI18n()`.
|
|
130
|
+
- Global i18n settings — `strategy`, `defaultLocale`, and the full `locales` list (codes, names, languages) — go in the `nuxt.config.ts` of the **aarde layer**: the project's base app layer that extends `nuxt-unified-ui` (for example `layers/100-aarde/`). If the project has no aarde layer, use the layer that extends `nuxt-unified-ui`.
|
|
131
|
+
- Every other layer (feature) keeps its own locale files in its own `i18n/locales/<code>.json`. In its own `nuxt.config.ts` it declares only those files — `i18n: { locales: [{ code, file }] }` — and no other i18n settings. `@nuxtjs/i18n` loads a layer's locale files only when that layer lists them, then merges the same locale from every layer into one message tree.
|
|
132
|
+
- The layer that owns a file is the nearest directory above it with a `nuxt.config`. Its strings go in that layer's locale files only — never in another layer's or the host's.
|
|
133
|
+
- Each layer's locale file has **exactly one top-level key**: the layer's namespace, such as `patients` or `billing`. Every key nests under it (`$t('patients.single.title')`), so merged trees never clash.
|
|
134
|
+
- Add every new key to each locale that layer declares.
|
|
135
|
+
- This layer owns two top-level keys: `un` for its components and `common` for shared labels (`common.submit`, `common.cancel`, `common.close`, …). Reuse `common.*` instead of duplicating those labels, but never add keys to `un` or `common` from another layer.
|
|
136
|
+
|
|
137
|
+
Aarde layer `nuxt.config.ts` (fragment):
|
|
138
|
+
|
|
139
|
+
```ts
|
|
140
|
+
i18n: {
|
|
141
|
+
strategy: 'no_prefix',
|
|
142
|
+
defaultLocale: 'en',
|
|
143
|
+
locales: [
|
|
144
|
+
{
|
|
145
|
+
code: 'en',
|
|
146
|
+
name: 'English',
|
|
147
|
+
file: 'en.json',
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
code: 'de',
|
|
151
|
+
name: 'Deutsch',
|
|
152
|
+
file: 'de.json',
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
},
|
|
92
156
|
```
|
|
93
157
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
158
|
+
Feature layer `nuxt.config.ts` (fragment) and its `i18n/locales/en.json`:
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
i18n: {
|
|
162
|
+
locales: [
|
|
163
|
+
{
|
|
164
|
+
code: 'en',
|
|
165
|
+
file: 'en.json',
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
code: 'de',
|
|
169
|
+
file: 'de.json',
|
|
170
|
+
},
|
|
102
171
|
],
|
|
103
|
-
|
|
104
|
-
'nuxt-unified-ui',
|
|
105
|
-
],
|
|
106
|
-
});
|
|
172
|
+
},
|
|
107
173
|
```
|
|
108
174
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|--------|------|
|
|
119
|
-
| `nuxt-unified-ui` | `./nuxt.config.ts` (also re-exports `pathRelativeToBase`) |
|
|
120
|
-
| `nuxt-unified-ui/app` | `./app` |
|
|
121
|
-
| `nuxt-unified-ui/nuxt-ui-fixes.css` | `./app/assets/css/nuxt-ui-fixes.css` |
|
|
122
|
-
|
|
123
|
-
Published: `nuxt.config.ts`, `index.d.ts`, `app/`, `i18n/`, `modules/`.
|
|
124
|
-
|
|
125
|
-
## Mental model (`app/`)
|
|
126
|
-
|
|
127
|
-
| Path | Role |
|
|
128
|
-
|------|------|
|
|
129
|
-
| `app/components/` | `un-form`, `un-card`, `un-typography`, `un-spinner`, `un-table` |
|
|
130
|
-
| `app/composables/` | `useForm`, `useFormExtraElements` |
|
|
131
|
-
| `app/elements/` | Built-in form field renderers |
|
|
132
|
-
| `app/dialogs/` | Form / choice picker modal UIs |
|
|
133
|
-
| `app/utils/` | `launchDialog*`, `toast*`, `smartMatch`, `unSet`, dates, … |
|
|
134
|
-
| `app/plugins/` | `$toaster` via `useToast()` |
|
|
135
|
-
| `modules/radashi.ts` | Auto-imports radashi as `rad*` |
|
|
136
|
-
| `i18n/locales/` | `en.json`, `de.json` |
|
|
137
|
-
|
|
138
|
-
## Layer config (inherited)
|
|
139
|
-
|
|
140
|
-
From `nuxt.config.ts`: `@vueuse/nuxt`, `@nuxt/ui`, `@nuxtjs/i18n`; `ui.colorMode: false`; default variant `neutral`; i18n `no_prefix` with `en`/`de`; `experimental.typedPages: true`.
|
|
141
|
-
|
|
142
|
-
## Common tasks
|
|
143
|
-
|
|
144
|
-
| Task | Prefer |
|
|
145
|
-
|------|--------|
|
|
146
|
-
| Schema form | `useForm` + `<form-tag />` / `<un-form>` → [forms.md](references/forms.md) |
|
|
147
|
-
| Modal form | `launchFormPickerDialog` + `submitButton.onClick` → [dialogs.md](references/dialogs.md) |
|
|
148
|
-
| Confirm / choice | `launchChoicePickerDialog` + button `onClick` (avoid `value`) |
|
|
149
|
-
| Feedback | `toastSuccess` / `toastError` / `toastWarning` / `toastInfo` / `toast` |
|
|
150
|
-
| Page chrome | `un-typography` + `un-card` |
|
|
151
|
-
| Data table | `un-table` + parent-owned fetch / sort / filter → [tables.md](references/tables.md) |
|
|
152
|
-
| Custom field | `registerFormExtraElement` in a plugin |
|
|
153
|
-
| Utilities | `radXxx` → [radashi.md](references/radashi.md) |
|
|
154
|
-
| New page / route | [pages.md](references/pages.md) |
|
|
155
|
-
| List/detail fetch or mutation | [data-fetching.md](references/data-fetching.md) |
|
|
156
|
-
| New / custom resource | [resources.md](references/resources.md) |
|
|
157
|
-
| New component / util in a layer | Start in `app/atoms/` or `app/libs/`; relative imports; promote to `components/` / `utils/` only if another layer needs it → [code-style.md](references/code-style.md) |
|
|
158
|
-
| Formatting any of the above | [code-style.md](references/code-style.md) |
|
|
159
|
-
|
|
160
|
-
## Do / don’t
|
|
161
|
-
|
|
162
|
-
**Do**
|
|
163
|
-
|
|
164
|
-
- Extend via `extends: ['nuxt-unified-ui']`
|
|
165
|
-
- Keep required host `main.css` + `pathRelativeToBase` CSS entry + `nuxt-ui-fixes.css`
|
|
166
|
-
- Use field `identifier` for element kind; `type` only for HTML input types
|
|
167
|
-
- Handle dialog actions in `onClick`
|
|
168
|
-
- Follow code style for every generated file
|
|
169
|
-
- Resources: plugin → full REST set → dashboard nav / custom `<resource-manager>` page → [resources.md](references/resources.md)
|
|
170
|
-
- Start generated layer components in `app/atoms/` and functions in `app/libs/`; import them with relative paths; move to `app/components/` / `app/utils/` only when another layer needs them
|
|
171
|
-
|
|
172
|
-
**Don’t**
|
|
173
|
-
|
|
174
|
-
- Invent APIs not in source
|
|
175
|
-
- Reference any local playground as consumer docs
|
|
176
|
-
- Use PascalCase component tags in templates
|
|
177
|
-
- Set choice-button `value` unless the await result must distinguish buttons
|
|
178
|
-
- Assume color mode is enabled (layer disables it)
|
|
179
|
-
- Reimplement resource CRUD in route files (use `handleResource*`; customize via dedicated pages + domain APIs)
|
|
180
|
-
- Put a layer-private component or util in `components/` or `utils/` (becomes app-global)
|
|
181
|
-
- Import `atoms`/`libs` via `~/`, `#layers`, or from another layer — use relative paths; promote first if another layer needs them
|
|
175
|
+
```json
|
|
176
|
+
{
|
|
177
|
+
"patients": {
|
|
178
|
+
"single": {
|
|
179
|
+
"title": "Patient"
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|