nuxt-unified-ui 0.5.15 → 0.5.16
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/package.json +2 -2
- package/skills/nuxt-unified-ui/SKILL.md +1 -1
- package/skills/nuxt-unified-ui/references/code-style.md +72 -37
- package/skills/nuxt-unified-ui/references/dialogs.md +2 -2
- package/skills/nuxt-unified-ui/references/tables.md +3 -9
- package/skills/nuxt-unified-ui/references/toast-and-ui.md +4 -1
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.16",
|
|
5
5
|
"main": "./nuxt.config.ts",
|
|
6
6
|
"types": "./index.d.ts",
|
|
7
7
|
"exports": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@formkit/tempo": "1.1.0",
|
|
23
|
-
"@iconify-json/lucide": "1.2.
|
|
23
|
+
"@iconify-json/lucide": "1.2.136",
|
|
24
24
|
"@nuxt/kit": "4.5.2",
|
|
25
25
|
"@nuxt/ui": "4.11.2",
|
|
26
26
|
"@nuxtjs/i18n": "10.6.0",
|
|
@@ -70,7 +70,7 @@ Absolute highlights:
|
|
|
70
70
|
- Kebab-case tags (`u-button`, `un-card`)
|
|
71
71
|
- `v-if` / `v-for` on `<template>` wrappers — not on rendered nodes
|
|
72
72
|
- If a condition changes several component attributes, prefer explicit `<template v-if>` / `v-else` component variants over nested ternaries and overly dynamic bindings
|
|
73
|
-
-
|
|
73
|
+
- Tags with children keep all attributes on one line with the opening tag unless a multiline attribute (multi-line array/object/function binding) forces a split — then the opening tag goes on its own line, one attribute per line, value styled like JS; childless tags are self-closing — one single-line attribute stays inline, otherwise tag and attributes each go on their own line with `/>` on its own line; attribute order + default omissions (`variant="subtle"`, **Cancel only → `ghost`**, omit neutral `color`, `loading-auto`); split non-self-closing `>` on same line as last attr; split self-closing `/>` on its own line
|
|
74
74
|
- `{{ ... }}` on its own line (static + dynamic text may mix)
|
|
75
75
|
- `/* section */` comments; imports co-located under the section that uses them
|
|
76
76
|
- Light naming: `handleXxx` handlers, `it` in short callbacks, descriptive `for...of`, computeds use block + `return`
|
|
@@ -19,8 +19,8 @@ Write code so a reader can **scan vertically** and see structure before details.
|
|
|
19
19
|
3. **One idea per line in structured data.**
|
|
20
20
|
Object/array literals in script are multi-line with trailing commas — even single-property objects passed to helpers (`toastSuccess`, `ufetch` options, etc.). Compact one-liners hide diffs and force horizontal reading.
|
|
21
21
|
|
|
22
|
-
4. **Templates
|
|
23
|
-
|
|
22
|
+
4. **Templates stay single-line unless a multiline attribute — or a childless multi-attribute tag — forces a split.**
|
|
23
|
+
A tag with children keeps all attributes on the same single line as the opening tag — no wrapping for length or attribute count. Only a multiline attribute (an array, object, or function literal bound to an attribute that spans multiple lines) forces such a tag to split: then the opening tag goes on its own line, every other attribute gets its own line, and the multiline value is formatted like a JS literal. Childless tags follow their own exception (self-closing; split when they carry more than one attribute or a multiline attribute). Closing `>` / `/>` placement is consistent; interpolations sit on their own line (static + dynamic text may share one `{{ ... }}` or surrounding text).
|
|
24
24
|
|
|
25
25
|
5. **Section comments are the map.**
|
|
26
26
|
`/* section */` labels define logical domains, while declaration-kind spacing exposes the structure inside each domain. Imports sit in the section that needs them, not in a hoisted pile at the top.
|
|
@@ -49,6 +49,7 @@ When editing an existing file, **absolute rules below always win**. For choices
|
|
|
49
49
|
| Braces | always for `if` / `else` / `for` / `while` — no brace-less single-liners |
|
|
50
50
|
| `else` / `catch` | on their **own line** after `}` |
|
|
51
51
|
| `.js` / `.ts` file start | **two** blank lines at the top, **unless** the file starts with imports — then **no** blank lines before the first `import` |
|
|
52
|
+
| **Single-line principle (JS/TS only)** | **Do not wrap JS/TS code solely because it has grown long**; keep every statement on a single line unless the explicit JS/TS wrapping rules below dictate otherwise. The default is single-statement-per-line; only break across lines when a specific rule permits or requires it. Template sections have their own rule (single-line attributes unless a multiline attribute forces a split) — see Template rules. |
|
|
52
53
|
|
|
53
54
|
---
|
|
54
55
|
|
|
@@ -296,9 +297,9 @@ const response = await ufetch(
|
|
|
296
297
|
|
|
297
298
|
### Template bindings — compactness
|
|
298
299
|
|
|
299
|
-
-
|
|
300
|
-
- Multi-key template object/array bindings are
|
|
301
|
-
- Simple scalars and simple ternaries stay inline; break only when
|
|
300
|
+
- A bound array, object, or function literal that spans multiple lines is a **multiline attribute** and forces the tag to split (see Attribute wrapping). A single-pair object with scalar values stays inline and does **not** trigger a split: `:ui="{ content: 'max-w-7xl' }"`
|
|
301
|
+
- Multi-key or nested template object/array bindings are multiline attributes: split the tag and format the value like a JS literal
|
|
302
|
+
- Simple scalars and simple ternaries stay inline; break only when a branch becomes a multiline object/array or nested structure
|
|
302
303
|
- When one condition changes several attributes, labels/icons, or an object-shaped binding such as `to`, use adjacent `<template v-if>` / `v-else-if` / `v-else` branches with explicit component variants. Prefer small markup duplication over nested ternaries and overly dynamic attributes.
|
|
303
304
|
|
|
304
305
|
```vue
|
|
@@ -508,40 +509,69 @@ Keep tight `v-if` / `v-else` chains adjacent (no blank line between matching bra
|
|
|
508
509
|
|
|
509
510
|
### Attribute wrapping (hard rule)
|
|
510
511
|
|
|
511
|
-
- **
|
|
512
|
-
- **
|
|
513
|
-
- **
|
|
514
|
-
-
|
|
512
|
+
- **Childless tags must be self-closing:** a tag with no children is written `<tag ... />` — never an empty open/close pair (`<tag ...></tag>`).
|
|
513
|
+
- **Tags with children — single line unless multiline:** all attributes stay on the **same single line** as the opening tag, regardless of attribute count or line length. Never wrap only because the line got long or because there are 2+ attributes. This applies equally to rendered elements, components, `u-modal`, and structural `<template>` wrappers.
|
|
514
|
+
- **Only trigger for tags with children — multiline attribute:** such a tag splits only when one of its attributes is a **multiline attribute**: an array, object, or function literal bound to the attribute that spans multiple lines (e.g. `:class="{\n … \n}"`, `:items="[\n … \n]"`). References, calls, and scalar expressions (`:field="field"`, `v-bind="radOmit(action, [...])"`, `:is="elementsMap[x]"`, `@click="handleSave"`) are **not** multiline attributes, even when their runtime value is an object. A single-pair object with scalar values (`:ui="{ content: 'max-w-5xl' }"`) stays inline and does **not** trigger a split.
|
|
515
|
+
- **Childless exception:** a childless (self-closing) tag with a single single-line attribute stays on one line with the tag (`<u-icon name="lucide:check" />`). When it has more than one attribute **or** at least one multiline attribute, the tag and its attributes each go on their own line: the opening tag on its own line (`<tag`), one attribute per line in attribute order, and `/>` on its own line.
|
|
516
|
+
- **Split shape (tags with children):** when a multiline attribute triggers the split, the opening tag goes on its **own line** (`<tag`), every other attribute gets **its own line** in attribute order, and the multiline attribute's value is formatted **like a JS value** (one entry per line, trailing commas). Closing `>` / `/>` placement follows [`>` and `/>` placement](#-and--placement).
|
|
515
517
|
|
|
516
518
|
```vue
|
|
517
|
-
<!-- ✅
|
|
518
|
-
<
|
|
519
|
-
<u-form-field label="Captcha">
|
|
519
|
+
<!-- ✅ tag with children, no multiline attribute — one line, however many attributes -->
|
|
520
|
+
<u-modal :ui="{ content: 'max-w-5xl' }" scrollable @update:open="!$event && emit('close')">
|
|
520
521
|
...
|
|
521
|
-
</u-
|
|
522
|
-
<u-icon name="lucide:check" />
|
|
522
|
+
</u-modal>
|
|
523
523
|
|
|
524
|
-
<!-- ✅ structural template wrappers
|
|
524
|
+
<!-- ✅ structural template wrappers follow the same rule -->
|
|
525
525
|
<template v-for="column in columns" :key="column.accessorKey" #[column.accessorKey+'-cell']="{ row }">
|
|
526
526
|
...
|
|
527
527
|
</template>
|
|
528
528
|
|
|
529
|
-
<!-- ✅
|
|
530
|
-
<
|
|
529
|
+
<!-- ✅ tag with children + multiline attribute — splits, value styled like JS -->
|
|
530
|
+
<div
|
|
531
|
+
v-if="show"
|
|
532
|
+
:class="{
|
|
533
|
+
'p-3': !fluidBody,
|
|
534
|
+
}">
|
|
531
535
|
...
|
|
532
|
-
</
|
|
536
|
+
</div>
|
|
537
|
+
|
|
538
|
+
<!-- ✅ childless, single single-line attribute — one line -->
|
|
539
|
+
<u-icon name="lucide:check" />
|
|
533
540
|
|
|
534
|
-
<!-- ✅
|
|
541
|
+
<!-- ✅ childless, more than one attribute — tag and attributes each on their own line -->
|
|
535
542
|
<u-button
|
|
536
543
|
variant="subtle"
|
|
537
544
|
icon="lucide:refresh-ccw"
|
|
538
545
|
@click="refresh"
|
|
539
546
|
/>
|
|
547
|
+
|
|
548
|
+
<!-- ✅ childless with a multiline attribute — same split shape -->
|
|
549
|
+
<component
|
|
550
|
+
:is="elementsMap[field.identifier]"
|
|
551
|
+
:field="field"
|
|
552
|
+
:class="{
|
|
553
|
+
'p-2': true,
|
|
554
|
+
}"
|
|
555
|
+
/>
|
|
556
|
+
|
|
557
|
+
<!-- ❌ childless multi-attribute tag on one line -->
|
|
558
|
+
<u-button variant="subtle" icon="lucide:refresh-ccw" @click="refresh" />
|
|
559
|
+
|
|
560
|
+
<!-- ❌ empty open/close pair — self-close instead -->
|
|
561
|
+
<div class="grow"></div>
|
|
562
|
+
|
|
563
|
+
<!-- ❌ splitting a tag with children that has no multiline attribute -->
|
|
564
|
+
<un-card
|
|
565
|
+
icon="lucide:key"
|
|
566
|
+
:title="title"
|
|
567
|
+
fluid-body>
|
|
568
|
+
...
|
|
569
|
+
</un-card>
|
|
540
570
|
```
|
|
541
571
|
|
|
542
572
|
### Attribute order
|
|
543
573
|
|
|
544
|
-
When
|
|
574
|
+
When a multiline attribute forces a split, order attributes as:
|
|
545
575
|
|
|
546
576
|
1. Refs / identity: `ref`, `id`, `name`
|
|
547
577
|
2. Component visual props: `variant`, `color`, `size`, `icon`, static `label`
|
|
@@ -606,27 +636,30 @@ Prefer defaults by **omitting** props rather than restating them:
|
|
|
606
636
|
```
|
|
607
637
|
### `>` and `/>` placement
|
|
608
638
|
|
|
609
|
-
|
|
639
|
+
Single-line tags keep their closer on the same line (`<u-icon name="lucide:check" />`, `<div class="space-y-3">`).
|
|
640
|
+
|
|
641
|
+
**Split (multiline-attribute) non-self-closing:** `>` on the **same line** as the last attribute:
|
|
610
642
|
|
|
611
643
|
```vue
|
|
612
|
-
<
|
|
613
|
-
|
|
614
|
-
:
|
|
615
|
-
|
|
644
|
+
<div
|
|
645
|
+
v-if="show"
|
|
646
|
+
:class="{
|
|
647
|
+
'p-3': !fluidBody,
|
|
648
|
+
}">
|
|
616
649
|
...
|
|
617
|
-
</
|
|
650
|
+
</div>
|
|
618
651
|
```
|
|
619
652
|
|
|
620
|
-
**
|
|
653
|
+
**Split self-closing (childless multi-attribute or multiline attribute):** `/>` on its **own line**; always a space before `/>`:
|
|
621
654
|
|
|
622
655
|
```vue
|
|
623
|
-
<
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
656
|
+
<component
|
|
657
|
+
:is="elementsMap[field.identifier]"
|
|
658
|
+
:field="field"
|
|
659
|
+
:class="{
|
|
660
|
+
'p-2': true,
|
|
661
|
+
}"
|
|
627
662
|
/>
|
|
628
|
-
|
|
629
|
-
<u-icon name="lucide:check" />
|
|
630
663
|
```
|
|
631
664
|
|
|
632
665
|
Closing tags for block components (`</un-card>`, `</u-modal>`, …) always on their own line.
|
|
@@ -799,8 +832,10 @@ export default defineEventHandler(async event => {
|
|
|
799
832
|
| `if (!x) return;` | braced block |
|
|
800
833
|
| `} else {` | `}\nelse {` |
|
|
801
834
|
| `toastSuccess({ title: 'x' })` one-liner object | multi-line object + trailing comma |
|
|
802
|
-
|
|
|
803
|
-
|
|
|
835
|
+
| Splitting a tag with children that has no multiline attribute (wrapping for count/length) | keep all attributes on one line with the opening tag |
|
|
836
|
+
| Childless multi-attribute tag on one line | split: opening tag on its own line, one attribute per line, `/>` on its own line |
|
|
837
|
+
| Empty open/close pair (`<div ...></div>`) | self-close (`<div ... />`) |
|
|
838
|
+
| Keeping a tag single-line when it has a multiline attribute | split: opening tag on its own line, one attribute per line, value like JS |
|
|
804
839
|
| `>` on its own line after attrs | `>` after last attr |
|
|
805
840
|
| `{{ x }}` glued to tags | interpolation on its own line (static + dynamic mix OK) |
|
|
806
841
|
| `ghost` on non-Cancel buttons | `ghost` only for Cancel |
|
|
@@ -833,11 +868,11 @@ export default defineEventHandler(async event => {
|
|
|
833
868
|
- [ ] Tiny helpers stay tight
|
|
834
869
|
- [ ] Return-only multi-criteria functions use a compact exhaustive `if` / `else if` / `else`; broader functions may use early returns
|
|
835
870
|
- [ ] `else` / `catch` on new line
|
|
836
|
-
- [ ] Script objects multi-line; template single-
|
|
871
|
+
- [ ] Script objects multi-line (the JS/TS single-line principle does not cover templates); template tags stay single-line unless a multiline attribute (multi-line array/object/function binding) forces a split; single-pair scalar objects (e.g. `:ui="{ content: '...' }"`) stay inline
|
|
837
872
|
- [ ] Kebab-case component tags
|
|
838
873
|
- [ ] `v-if` / `v-for` on `<template>` wrappers
|
|
839
874
|
- [ ] Conditional states that change several attributes use explicit `<template v-if>` component variants, not nested ternaries
|
|
840
|
-
- [ ]
|
|
875
|
+
- [ ] Tags with children keep all attributes on one line with the opening tag unless a multiline attribute forces a split (opening tag on its own line, one attribute per line, value like JS); childless tags are self-closing — single single-line attribute stays inline, otherwise tag and attributes each go on their own line with `/>` on its own line; closing `>` / `/>` placement is correct
|
|
841
876
|
- [ ] Attribute order + default-value omissions respected (`subtle`, **Cancel → `ghost` only**, no neutral color noise, `loading-auto`)
|
|
842
877
|
- [ ] `{{ }}` on own line (static + dynamic mix OK)
|
|
843
878
|
- [ ] Every section is named; imports are co-located with the section that uses them
|
|
@@ -156,7 +156,7 @@ Action entries support `actionType: 'spacer'` (flex grow) and optional `tooltip`
|
|
|
156
156
|
|
|
157
157
|
Cancel / dismiss actions use `variant: 'ghost'` (or `variant="ghost"`). Do **not** use `ghost` on primary/submit/other actions — prefer omit / `subtle`.
|
|
158
158
|
|
|
159
|
-
Hand-rolled dialog shells
|
|
159
|
+
Hand-rolled dialog shells follow the template single-line rule — this shell has no multiline attribute, so it stays on one line (see [code-style.md](code-style.md)):
|
|
160
160
|
|
|
161
161
|
```vue
|
|
162
162
|
<u-modal :ui="{ content: 'max-w-5xl' }" scrollable @update:open="!$event && emit('close')">
|
|
@@ -169,7 +169,7 @@ Hand-rolled dialog shells keep **`u-modal` attributes on one line** (see [code-s
|
|
|
169
169
|
- Prefer `launchFormPickerDialog` / `launchChoicePickerDialog` over hand-rolled `u-modal` for these flows
|
|
170
170
|
- Handle actions in button / submit `onClick`
|
|
171
171
|
- Keep field lists consistent with `un-form` (`identifier`, not `type`, for element kind)
|
|
172
|
-
- Mark Cancel with `variant: 'ghost'`; keep
|
|
172
|
+
- Mark Cancel with `variant: 'ghost'`; keep dialog shells single-line unless a multiline attribute forces a split
|
|
173
173
|
|
|
174
174
|
**Don’t**
|
|
175
175
|
|
|
@@ -57,7 +57,7 @@ Omit unused props. When present, write them in this order:
|
|
|
57
57
|
13. `:extra-actions`
|
|
58
58
|
14. `:meta`
|
|
59
59
|
|
|
60
|
-
Models are always **page size, then page**.
|
|
60
|
+
Models are always **page size, then page**. Attributes stay on one line with the opening tag (a multiline attribute is the only split trigger — see [code-style.md](code-style.md)).
|
|
61
61
|
|
|
62
62
|
### Paged table
|
|
63
63
|
|
|
@@ -84,10 +84,7 @@ Models are always **page size, then page**. Closing `>` sits on the same line as
|
|
|
84
84
|
No footer, no page models, no `total-items`:
|
|
85
85
|
|
|
86
86
|
```vue
|
|
87
|
-
<un-card
|
|
88
|
-
:icon="icon"
|
|
89
|
-
:title="title"
|
|
90
|
-
fluid-body>
|
|
87
|
+
<un-card :icon="icon" :title="title" fluid-body>
|
|
91
88
|
<un-table
|
|
92
89
|
:columns="columns"
|
|
93
90
|
:data="rows"
|
|
@@ -298,10 +295,7 @@ const currentPage = ref(1);
|
|
|
298
295
|
Prefer an `un-card` with `fluid-body` so the table and footer are edge-to-edge:
|
|
299
296
|
|
|
300
297
|
```vue
|
|
301
|
-
<un-card
|
|
302
|
-
:title="`Manage ${titlePlural}`"
|
|
303
|
-
fluid-body
|
|
304
|
-
:append-actions="toolbarActions">
|
|
298
|
+
<un-card :title="`Manage ${titlePlural}`" fluid-body :append-actions="toolbarActions">
|
|
305
299
|
<un-table
|
|
306
300
|
:columns="columns"
|
|
307
301
|
:loading="isItemsLoading"
|
|
@@ -60,7 +60,10 @@ Action buttons: `loading-auto`, props via `radOmit` excluding `actionType` / `to
|
|
|
60
60
|
## `un-spinner` — `app/components/un-spinner.vue`
|
|
61
61
|
|
|
62
62
|
```vue
|
|
63
|
-
<u-icon
|
|
63
|
+
<u-icon
|
|
64
|
+
name="lucide:loader-circle"
|
|
65
|
+
class="animate-spin"
|
|
66
|
+
/>
|
|
64
67
|
```
|
|
65
68
|
|
|
66
69
|
No props.
|