nuxt-unified-ui 0.5.13 → 0.5.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,14 +4,16 @@
4
4
 
5
5
  const props = defineProps({
6
6
  columns: Array,
7
+ ui: Object,
7
8
  loading: Boolean,
8
9
  data: Array,
9
10
  hidePagination: Boolean,
10
11
  totalItems: Number,
12
+ itemsPerPageItems: Array,
13
+ rowTo: Function,
14
+ stickyActions: Boolean,
11
15
  actions: Array,
12
16
  extraActions: Array,
13
- stickyActions: Boolean,
14
- ui: Object,
15
17
  meta: Object,
16
18
  });
17
19
 
@@ -66,8 +68,12 @@ const columnPinning = computed(() => {
66
68
 
67
69
  const tableUi = computed(() => {
68
70
  return {
69
- tr: 'data-[expanded=true]:bg-elevated!',
70
- ...(props.ui || {}),
71
+ ...(props.ui ?? {}),
72
+ tr: [
73
+ 'data-[expanded=true]:bg-elevated!',
74
+ props.rowTo ? 'cursor-pointer' : '',
75
+ (props.ui ?? {}).tr,
76
+ ].filter(Boolean).join(' '),
71
77
  };
72
78
  });
73
79
 
@@ -140,13 +146,20 @@ function getExtraActionItems(row) {
140
146
 
141
147
  /* pagination */
142
148
 
143
- const pageSizeItems = [
144
- 5,
145
- 10,
146
- 25,
147
- 50,
148
- 100,
149
- ];
149
+ const pageSizeItems = computed(() => {
150
+ if (props.itemsPerPageItems?.length) {
151
+ return props.itemsPerPageItems;
152
+ }
153
+ else {
154
+ return [
155
+ 5,
156
+ 10,
157
+ 25,
158
+ 50,
159
+ 100,
160
+ ];
161
+ }
162
+ });
150
163
 
151
164
  </script>
152
165
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-unified-ui",
3
3
  "type": "module",
4
- "version": "0.5.13",
4
+ "version": "0.5.15",
5
5
  "main": "./nuxt.config.ts",
6
6
  "types": "./index.d.ts",
7
7
  "exports": {
@@ -22,13 +22,13 @@
22
22
  "@formkit/tempo": "1.1.0",
23
23
  "@iconify-json/lucide": "1.2.135",
24
24
  "@nuxt/kit": "4.5.2",
25
- "@nuxt/ui": "4.11.1",
25
+ "@nuxt/ui": "4.11.2",
26
26
  "@nuxtjs/i18n": "10.6.0",
27
27
  "@types/canvas-confetti": "1.9.0",
28
28
  "@vueuse/core": "15.0.0",
29
29
  "@vueuse/nuxt": "15.0.0",
30
30
  "canvas-confetti": "1.9.4",
31
- "radashi": "12.9.5",
31
+ "radashi": "12.9.6",
32
32
  "unified-mongo-filter": "0.4.0"
33
33
  },
34
34
  "peerDependencies": {
@@ -8,10 +8,11 @@ description: >-
8
8
  (attribute order, row actions, pagination), pages /
9
9
  definePageMeta, page /* params */ and /* seo */ blocks, ufetch / useUFetch wrapping, unified resources
10
10
  (server plugins, REST handleResource*, resource-manager dashboard /
11
- customization), attribute order/defaults, and whitespace/formatting
12
- conventions for all Nuxt-generated code. Use when working in or consuming
13
- nuxt-unified-ui, declaring or customizing resources, or whenever generating
14
- Vue/Nuxt code that must match unified code style.
11
+ customization), layer-private app/atoms and app/libs vs public
12
+ components/utils (relative imports), attribute order/defaults, and
13
+ whitespace/formatting conventions for all Nuxt-generated code. Use when
14
+ working in or consuming nuxt-unified-ui, declaring or customizing resources,
15
+ or whenever generating Vue/Nuxt code that must match unified code style.
15
16
  ---
16
17
 
17
18
  # nuxt-unified-ui
@@ -75,6 +76,7 @@ Absolute highlights:
75
76
  - Light naming: `handleXxx` handlers, `it` in short callbacks, descriptive `for...of`, computeds use block + `return`
76
77
  - Pages: explicit `definePageMeta.name`, `/* params */` for `route.params` / `route.query`, required `/* seo */` (`useHead` + `useSeoMeta`, `useJsonld` when installed) → [pages.md](references/pages.md)
77
78
  - Fetching: `ufetch(url, {` one line; `useUFetch` with URL on next line + `data*Data` / `is*Loading` / `refresh*` → [data-fetching.md](references/data-fetching.md)
79
+ - Layer modules: generate private first (`app/atoms/` components, `app/libs/` functions and similar); promote to `app/components/` / `app/utils/` only when another layer needs them; import `atoms`/`libs` with relative paths → [code-style.md](references/code-style.md)
78
80
 
79
81
  ---
80
82
 
@@ -152,6 +154,7 @@ From `nuxt.config.ts`: `@vueuse/nuxt`, `@nuxt/ui`, `@nuxtjs/i18n`; `ui.colorMode
152
154
  | New page / route | [pages.md](references/pages.md) |
153
155
  | List/detail fetch or mutation | [data-fetching.md](references/data-fetching.md) |
154
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) |
155
158
  | Formatting any of the above | [code-style.md](references/code-style.md) |
156
159
 
157
160
  ## Do / don’t
@@ -164,6 +167,7 @@ From `nuxt.config.ts`: `@vueuse/nuxt`, `@nuxt/ui`, `@nuxtjs/i18n`; `ui.colorMode
164
167
  - Handle dialog actions in `onClick`
165
168
  - Follow code style for every generated file
166
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
167
171
 
168
172
  **Don’t**
169
173
 
@@ -173,3 +177,5 @@ From `nuxt.config.ts`: `@vueuse/nuxt`, `@nuxt/ui`, `@nuxtjs/i18n`; `ui.colorMode
173
177
  - Set choice-button `value` unless the await result must distinguish buttons
174
178
  - Assume color mode is enabled (layer disables it)
175
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
@@ -1,8 +1,8 @@
1
1
  # Nuxt unified code style
2
2
 
3
- **Mandatory** whenever generating or editing code in a Nuxt project that uses this stack. Applies to **all** Nuxt project files: Vue SFCs and `.ts`/`.js` under `app/`, `server/`, composables, utils, plugins, middleware, etc.
3
+ **Mandatory** whenever generating or editing code in a Nuxt project that uses this stack. Applies to **all** Nuxt project files: Vue SFCs and `.ts`/`.js` under `app/` (including `atoms/` and `libs/`), `server/`, composables, utils, plugins, middleware, etc.
4
4
 
5
- This document is about the **look and shape** of code — whitespace, wrapping, braces, template structure, sectioning, and light naming that affects scanning — not business logic or architecture.
5
+ This document is about the **look and shape** of code — whitespace, wrapping, braces, template structure, sectioning, file placement for layer-private vs public modules, and light naming that affects scanning — not business logic.
6
6
 
7
7
  ---
8
8
 
@@ -372,7 +372,7 @@ The comment names a logical domain, not a declaration kind. Follow it with a bla
372
372
  ```ts
373
373
  /* resource */
374
374
 
375
- import ResourceExplorerCell from '~/atoms/resource-explorer-cell.vue';
375
+ import ResourceExplorerCell from '../atoms/resource-explorer-cell.vue';
376
376
 
377
377
 
378
378
  const itemsPerPage = ref(20);
@@ -431,6 +431,39 @@ Place non-auto-imported imports **inside the section that uses them**, not hoist
431
431
  import { VisXYContainer, VisLine } from '@unovis/vue';
432
432
  ```
433
433
 
434
+ ### Layer-private `atoms` / `libs` vs public `components` / `utils`
435
+
436
+ Nuxt auto-imports `app/components/` and `app/utils/` across the **entire** app (every layer). Files that must stay inside one layer do not belong there.
437
+
438
+ Any component or util in a layer which is not supposed to be used from another layer should be put in (`atoms` for components) and (`libs` for functions and ...), and if we notice that one of these is needed in another layer, we move it to `components` or `utils` folder. A generated component or util starts in these private folders, then moves into public ones if needed. These should be imported with relative path in their callsites.
439
+
440
+ | Role | Directory | Visibility |
441
+ |------|-----------|------------|
442
+ | Private Vue component | `app/atoms/` | This layer only |
443
+ | Private function / helper / similar | `app/libs/` | This layer only |
444
+ | Public Vue component | `app/components/` | Whole app (auto-imported) |
445
+ | Public util | `app/utils/` | Whole app (auto-imported) |
446
+
447
+ `app/composables/` is public like `utils/`. Private composables and other non-component helpers go in `app/libs/`.
448
+
449
+ **Generate private first.** New components go in `app/atoms/`. New functions and similar go in `app/libs/`. Promote (move the file, update call sites) to `app/components/` or `app/utils/` only when another layer needs them. After a promote, drop the relative import — public modules are auto-imported.
450
+
451
+ **Import `atoms` / `libs` with relative paths only** (`../atoms/foo.vue`, `../libs/bar`). Never `~/`, `@/`, `#layers/`, or other aliases. Never import another layer's `atoms` or `libs`; promote first, then use the public auto-import.
452
+
453
+ Do not register `atoms` or `libs` with Nuxt `components` / `imports` config.
454
+
455
+ ```ts
456
+ // ✅ same layer
457
+ import ResourceExplorerCell from '../atoms/resource-explorer-cell.vue';
458
+ import { formatColumn } from '../libs/format-column';
459
+ ```
460
+
461
+ ```ts
462
+ // ❌ aliases / other layers
463
+ import ResourceExplorerCell from '~/atoms/resource-explorer-cell.vue';
464
+ import { formatColumn } from '#layers/other-layer/libs/format-column';
465
+ ```
466
+
434
467
  ### Watcher formatting
435
468
 
436
469
  - Prefer `watchImmediate` over `watch(..., { immediate: true })`
@@ -523,7 +556,7 @@ Practical shortcuts:
523
556
  - `u-button`: `variant` → `color` → `size` → `icon` → label/value → `block` → `disabled` → `loading-auto` → events
524
557
  - `u-input` / `u-select*`: user-facing props (`:placeholder`, `:label`) → transient state (`:loading`, `:disabled`) → data source (`:items`) → `class` → `v-model` → events
525
558
  - Action objects (`:actions`, `:append-actions`, table row actions): `vIf` → `actionType` → `color` → `icon` → `label` → `tooltip` → `warning` → `disabled` → `to` → `href` → `onClick` → `items`
526
- - `un-table`: `:columns` → `class` / `:ui` → `:loading` → `:data` → `hide-pagination` → `:total-items` → `v-model:items-per-page` → `v-model:current-page` → `sticky-actions` → `:actions` → `:extra-actions` → `:meta` (omit unused). Full table rules → [tables.md](tables.md)
559
+ - `un-table`: `:columns` → `class` / `:ui` → `:loading` → `:data` → `hide-pagination` → `:total-items` → `:items-per-page-items` → `:row-to` → `v-model:items-per-page` → `v-model:current-page` → `sticky-actions` → `:actions` → `:extra-actions` → `:meta` (omit unused). Full table rules → [tables.md](tables.md)
527
560
  - Tab / select item objects: `value` → `icon` → `label`
528
561
 
529
562
  ### Default attribute values (omit noise)
@@ -781,6 +814,10 @@ export default defineEventHandler(async event => {
781
814
  | `.ts`/`.js` with no leading blanks (and no imports) | two blank lines at file start |
782
815
  | Blank lines before first `import` | `import` on line 1 |
783
816
  | Blank lines around a function that is only one `for` / `if` / `try` chain | Function `{` / `}` flush against that block |
817
+ | Layer-private component in `components/` | `app/atoms/` |
818
+ | Layer-private util in `utils/` or `composables/` | `app/libs/` |
819
+ | `~/atoms/...` / `#layers/.../atoms` / `#layers/.../libs` | Relative `../atoms/...` / `../libs/...` |
820
+ | Import another layer's `atoms` or `libs` | Promote to `components/` / `utils/`, then auto-import |
784
821
 
785
822
  ---
786
823
 
@@ -808,3 +845,4 @@ export default defineEventHandler(async event => {
808
845
  - [ ] Computeds that return structures use block + `return`
809
846
  - [ ] Pages: explicit `definePageMeta.name`, `/* params */` + `/* seo */` placement, named navigation ([pages.md](pages.md))
810
847
  - [ ] Fetching: `ufetch` / `useUFetch` wrap styles and destructure names ([data-fetching.md](data-fetching.md))
848
+ - [ ] New layer components/utils start in `app/atoms/` or `app/libs/`; `atoms`/`libs` imported with relative paths only; promote to `components/` / `utils/` only when another layer needs them
@@ -27,9 +27,11 @@ Do **not** add sort, filter, or selection props to `un-table`. Resource dashboar
27
27
  | `actions` | Visible row buttons; adds the trailing `actions` column |
28
28
  | `extraActions` | Overflow `u-dropdown-menu` (ellipsis); also creates the column |
29
29
  | `stickyActions` | Pin the `actions` column to the right |
30
- | `ui` | Merged into `u-table` `:ui` after the expanded-row `tr` class |
30
+ | `rowTo` | Adds `cursor-pointer` on rows; parent still owns navigation |
31
+ | `ui` | Merged into `u-table` `:ui`. Default `tr` classes (`data-[expanded=true]:bg-elevated!`, plus `cursor-pointer` when `rowTo` is set) are prepended to `ui.tr` |
31
32
  | `meta` | Passed through to `u-table` |
32
33
  | `v-model:itemsPerPage` | Page size (default `'25'`; choices 5 / 10 / 25 / 50 / 100) |
34
+ | `itemsPerPageItems` | Overrides the page-size select options |
33
35
  | `v-model:currentPage` | Page number (default `'1'`) |
34
36
 
35
37
  The actions column is added when **either** `actions` or `extraActions` has length. `#actions-cell` is then owned by the wrapper — do not override it.
@@ -46,12 +48,14 @@ Omit unused props. When present, write them in this order:
46
48
  4. `:data`
47
49
  5. `hide-pagination`
48
50
  6. `:total-items`
49
- 7. `v-model:items-per-page`
50
- 8. `v-model:current-page`
51
- 9. `sticky-actions`
52
- 10. `:actions`
53
- 11. `:extra-actions`
54
- 12. `:meta`
51
+ 7. `:items-per-page-items`
52
+ 8. `:row-to`
53
+ 9. `v-model:items-per-page`
54
+ 10. `v-model:current-page`
55
+ 11. `sticky-actions`
56
+ 12. `:actions`
57
+ 13. `:extra-actions`
58
+ 14. `:meta`
55
59
 
56
60
  Models are always **page size, then page**. Closing `>` sits on the same line as the last attribute.
57
61
 
@@ -281,6 +285,7 @@ const currentPage = ref(1);
281
285
  ```
282
286
 
283
287
  - Layer default page size is `25` if the parent does not bind the model. Host pages often use `10` or `20` — set the ref explicitly.
288
+ - Page-size choices default to `5 / 10 / 25 / 50 / 100`. Pass `:items-per-page-items` to replace that list.
284
289
  - Server lists: `skip = (currentPage - 1) * itemsPerPage`, `limit = itemsPerPage`, `total-items` from the `/count` endpoint.
285
290
  - Client lists: pass `data` already sliced; `total-items` is the uncut length.
286
291
  - Reset `currentPage` to `1` when page size, filters, or the resource path change.