nuxt-ui-basekit 0.1.1 → 0.2.0
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 +93 -79
- package/app/composables/useBaseKit.ts +40 -35
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
# nuxt-ui-basekit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
in
|
|
3
|
+
Base components for Nuxt 4 on top of [Nuxt UI](https://ui.nuxt.com) — as a Nuxt
|
|
4
|
+
layer. Tables, tabs, charts, pickers, empty states: the parts that come up again
|
|
5
|
+
in every admin frontend and that Nuxt UI does not ship.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
The package knows nothing about your application. It has no stores beyond the
|
|
8
|
+
one behind the confirmation dialog, no endpoints, no translation keys and no
|
|
9
|
+
colours that belong to a brand. Whatever it displays is handed in.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
**[→ Every component with a screenshot](https://github.com/McGo/nuxt-ui-basekit/blob/main/COMPONENTS.md)**
|
|
12
|
+
|
|
13
|
+
## Install
|
|
12
14
|
|
|
13
15
|
```bash
|
|
14
16
|
npm i -D nuxt-ui-basekit
|
|
@@ -21,30 +23,39 @@ export default defineNuxtConfig({
|
|
|
21
23
|
})
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
`@nuxt/ui`, `nuxt`
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
`@nuxt/ui`, `nuxt` and `pinia` are peers — they live in the consumer and are not
|
|
27
|
+
bundled along. The components are globally available afterwards, no import.
|
|
28
|
+
|
|
29
|
+
Nuxt UI itself still needs its stylesheet, the same as in any project that uses
|
|
30
|
+
it:
|
|
31
|
+
|
|
32
|
+
```css
|
|
33
|
+
/* app/assets/css/main.css, referenced from nuxt.config.ts */
|
|
34
|
+
@import "tailwindcss";
|
|
35
|
+
@import "@nuxt/ui";
|
|
36
|
+
```
|
|
27
37
|
|
|
28
|
-
##
|
|
38
|
+
## What is in it
|
|
29
39
|
|
|
30
|
-
|
|
|
40
|
+
| Group | Components |
|
|
31
41
|
|---|---|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
42
|
+
| Structure | `BaseKitTabs` · `BaseKitSettingRow` · `BaseKitEmptyState` · `BaseKitChoiceCard` · `BaseKitPending` |
|
|
43
|
+
| Lists | `BaseKitDataTable` · `BaseKitStatTile` |
|
|
44
|
+
| Pickers | `BaseKitRecordPicker` · `BaseKitIconPicker` · `BaseKitFileUpload` |
|
|
45
|
+
| Navigation | `BaseKitBackLink` · `BaseKitViewLink` |
|
|
46
|
+
| Confirmation | `BaseKitConfirmModal` + `useConfirm()` |
|
|
37
47
|
| Text | `BaseKitMarkdownEditor` |
|
|
38
|
-
|
|
|
48
|
+
| Charts | `BaseKitChartBars` · `-Columns` · `-Donut` · `-Meter` · `-Figure` |
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
|
|
50
|
+
Each component carries its reasoning in the file header — what it does, when it
|
|
51
|
+
is the right choice and when it is not. [COMPONENTS.md](https://github.com/McGo/nuxt-ui-basekit/blob/main/COMPONENTS.md) has the
|
|
52
|
+
short version of each, with a screenshot.
|
|
42
53
|
|
|
43
|
-
##
|
|
54
|
+
## Labels and language
|
|
44
55
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
The components never call `vue-i18n` and know no translation keys. Left alone
|
|
57
|
+
they render English defaults; anyone with their own wording or several
|
|
58
|
+
languages hands them in through a plugin:
|
|
48
59
|
|
|
49
60
|
```ts
|
|
50
61
|
// plugins/basekit.ts
|
|
@@ -65,95 +76,98 @@ export default defineNuxtPlugin((nuxtApp) => {
|
|
|
65
76
|
})
|
|
66
77
|
```
|
|
67
78
|
|
|
68
|
-
|
|
79
|
+
`locale` is a BCP-47 tag and drives `Intl` — thousands separators, percentages
|
|
80
|
+
and date formats in the charts follow it.
|
|
81
|
+
|
|
82
|
+
Two things that can cost an afternoon:
|
|
69
83
|
|
|
70
|
-
- **`useI18n()`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- **
|
|
76
|
-
|
|
84
|
+
- **`useI18n()` does not belong in the plugin.** It requires a component setup
|
|
85
|
+
context and throws `MUST_BE_CALL_SETUP_TOP` (error 26) there. Under server-side
|
|
86
|
+
rendering that means a 500 on every page. Take the instance from
|
|
87
|
+
`nuxtApp.$i18n`, and only when the `computed` is read — then plugin order
|
|
88
|
+
stops mattering too.
|
|
89
|
+
- **Individual labels stay overridable as props.** The table above only decides
|
|
90
|
+
what comes out when nothing is passed.
|
|
77
91
|
|
|
78
|
-
##
|
|
92
|
+
## Colours
|
|
79
93
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
darauf:
|
|
94
|
+
The components only ever reach for `--basekit-*`. The defaults live in
|
|
95
|
+
`app/assets/css/basekit.css` and are loaded by the layer. A project with its own
|
|
96
|
+
theme puts its values on top, in its own stylesheet:
|
|
84
97
|
|
|
85
98
|
```css
|
|
86
99
|
:root {
|
|
87
|
-
--basekit-accent: var(--
|
|
88
|
-
--basekit-surface: var(--
|
|
100
|
+
--basekit-accent: var(--my-brand-colour, #2563eb);
|
|
101
|
+
--basekit-surface: var(--my-card-surface, #ffffff);
|
|
89
102
|
}
|
|
90
103
|
```
|
|
91
104
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
105
|
+
The five chart colours are validated as a set — lightness band, chroma and the
|
|
106
|
+
distance between neighbours, colour vision deficiency included. Override them as
|
|
107
|
+
a set rather than one at a time; if you have more than five series, group them
|
|
108
|
+
instead of inventing a sixth colour.
|
|
96
109
|
|
|
97
|
-
##
|
|
110
|
+
## Development
|
|
98
111
|
|
|
99
112
|
```bash
|
|
100
113
|
npm install
|
|
101
|
-
npx nuxi prepare #
|
|
114
|
+
npx nuxi prepare # writes .nuxt/tsconfig.json, without it the tests fail
|
|
102
115
|
npm test
|
|
103
116
|
npm run lint # nuxi typecheck
|
|
104
117
|
```
|
|
105
118
|
|
|
106
|
-
`tests/grenze.test.ts`
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
119
|
+
`tests/grenze.test.ts` pins down what the package is not allowed to do: no
|
|
120
|
+
imports from outside the package, no dependency that is missing from
|
|
121
|
+
`package.json`, no `vue-i18n`, no translation keys, no foreign CSS variables.
|
|
122
|
+
That test is the reason the package could be carved out at all — without it the
|
|
123
|
+
separation would have closed up again by the third feature.
|
|
124
|
+
|
|
125
|
+
`playground/` is a small Nuxt app that pulls the layer in the way a consumer
|
|
126
|
+
would. It is the place to look at a component, and the source of the
|
|
127
|
+
screenshots in [COMPONENTS.md](https://github.com/McGo/nuxt-ui-basekit/blob/main/COMPONENTS.md):
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
cd playground && npm install && npm run dev
|
|
131
|
+
```
|
|
112
132
|
|
|
113
133
|
### Lockfile
|
|
114
134
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
`npm ci` im Workflow bricht ab:
|
|
135
|
+
Adding a dependency on macOS or Windows means pulling the lockfile through
|
|
136
|
+
Linux/x64 afterwards — otherwise the platform-specific optional packages
|
|
137
|
+
(`@emnapi/*` and relatives) are missing and `npm ci` fails in the workflow:
|
|
119
138
|
|
|
120
139
|
```bash
|
|
121
140
|
docker run --rm --platform linux/amd64 -v "$PWD:/app" -w /app \
|
|
122
141
|
node:24 npm install --package-lock-only
|
|
123
142
|
```
|
|
124
143
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
zurück.
|
|
129
|
-
|
|
130
|
-
## Veröffentlichen
|
|
144
|
+
The architecture matters: on Apple Silicon the container runs as arm64 without
|
|
145
|
+
`--platform`, and then exactly the x64 variants the runner needs are still
|
|
146
|
+
missing. Run `npm ci` locally afterwards to get your own binaries back.
|
|
131
147
|
|
|
132
|
-
|
|
133
|
-
jedem Pull Request und führt `nuxi prepare`, `nuxi typecheck` und die Tests
|
|
134
|
-
aus. `veroeffentlichen` hängt an einem Tag `vX.Y.Z`, prüft noch einmal und
|
|
135
|
-
schiebt das Paket dann nach npmjs.com. Ein Build-Schritt fehlt, weil der Layer
|
|
136
|
-
als Rohquelle ausgeliefert wird und Nuxt ihn im Konsumenten übersetzt.
|
|
148
|
+
## Releasing
|
|
137
149
|
|
|
138
|
-
|
|
150
|
+
Two workflows under `.github/workflows`. `pruefen` runs on `main` and on every
|
|
151
|
+
pull request and does `nuxi prepare`, `nuxi typecheck` and the tests.
|
|
152
|
+
`veroeffentlichen` hangs off a `vX.Y.Z` tag, checks again and publishes to
|
|
153
|
+
npmjs.com. There is no build step: the layer ships as raw source and Nuxt
|
|
154
|
+
compiles it in the consumer.
|
|
139
155
|
|
|
140
156
|
```bash
|
|
141
|
-
npm version patch #
|
|
157
|
+
npm version patch # bumps package.json and sets the tag
|
|
142
158
|
git push --follow-tags
|
|
143
159
|
```
|
|
144
160
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
Dafür braucht das Repo ein Secret `NPM_TOKEN` — ein Automation-Token aus dem
|
|
150
|
-
npm-Konto, einzutragen unter *Settings → Secrets and variables → Actions*.
|
|
161
|
+
The job compares the tag against the number in `package.json` and stops if they
|
|
162
|
+
disagree. Publishing runs over OIDC through npm's trusted publishing — no token
|
|
163
|
+
in the repository — and with `--provenance`, so npmjs records which commit the
|
|
164
|
+
package was built from.
|
|
151
165
|
|
|
152
|
-
##
|
|
166
|
+
## Origin
|
|
153
167
|
|
|
154
|
-
|
|
155
|
-
|
|
168
|
+
Grown inside an admin frontend and in use there for months before it became a
|
|
169
|
+
package of its own.
|
|
156
170
|
|
|
157
|
-
##
|
|
171
|
+
## License
|
|
158
172
|
|
|
159
|
-
MIT —
|
|
173
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -16,11 +16,15 @@ import { computed, inject, type ComputedRef, type InjectionKey } from 'vue'
|
|
|
16
16
|
* export default defineNuxtPlugin((nuxtApp) => {
|
|
17
17
|
* const config = computed(() => ({
|
|
18
18
|
* locale: 'de-DE',
|
|
19
|
-
* labels: { ...BASEKIT_DEFAULTS.labels, search: 'Suchen' },
|
|
19
|
+
* labels: { ...BASEKIT_DEFAULTS.labels, search: 'Suchen', cancel: 'Abbrechen' },
|
|
20
20
|
* }))
|
|
21
21
|
* nuxtApp.vueApp.provide(baseKitKey, config)
|
|
22
22
|
* })
|
|
23
23
|
*
|
|
24
|
+
* Wer eine andere Sprache fährt, überschreibt die Tabelle vollständig — die
|
|
25
|
+
* Voreinstellung unten ist englisch und deckt nur den Fall ab, dass niemand
|
|
26
|
+
* etwas bereitstellt.
|
|
27
|
+
*
|
|
24
28
|
* Wer nichts bereitstellt, bekommt die Voreinstellungen unten. Wichtig, wenn
|
|
25
29
|
* die Werte aus einer i18n-Bibliothek kommen: `useI18n()` verlangt einen
|
|
26
30
|
* Komponenten-Setup-Kontext und wirft im Plugin. Die Instanz gehört über
|
|
@@ -93,45 +97,46 @@ export interface BaseKitConfig {
|
|
|
93
97
|
}
|
|
94
98
|
|
|
95
99
|
/**
|
|
96
|
-
* Voreinstellung:
|
|
97
|
-
*
|
|
100
|
+
* Voreinstellung: englisch. Das Paket weiß nicht, in welcher Sprache die
|
|
101
|
+
* Anwendung läuft, und Englisch ist die Sprache, die am wenigsten Leser
|
|
102
|
+
* ausschließt. Wer deutsch fährt, reicht `BASEKIT_DEFAULTS_DE` herein.
|
|
98
103
|
*/
|
|
99
104
|
export const BASEKIT_DEFAULTS: BaseKitConfig = {
|
|
100
|
-
locale: '
|
|
105
|
+
locale: 'en-US',
|
|
101
106
|
labels: {
|
|
102
|
-
search: '
|
|
103
|
-
all: '
|
|
104
|
-
select: '
|
|
105
|
-
change: '
|
|
106
|
-
edit: '
|
|
107
|
-
cancel: '
|
|
108
|
-
confirm: '
|
|
109
|
-
confirmTitle: '
|
|
110
|
-
confirmBody: '
|
|
111
|
-
empty: '
|
|
112
|
-
noResults: '
|
|
113
|
-
noResultsHint: '
|
|
114
|
-
back: '
|
|
115
|
-
view: '
|
|
116
|
-
upload: '
|
|
117
|
-
perPage: '
|
|
118
|
-
iconChoose: '
|
|
119
|
-
iconEmpty: '
|
|
120
|
-
iconClear: '
|
|
121
|
-
chartAsTable: '
|
|
122
|
-
chartAsChart: '
|
|
123
|
-
paginationRange: ({ from, to, total }) => `${from}–${to}
|
|
107
|
+
search: 'Search',
|
|
108
|
+
all: 'All',
|
|
109
|
+
select: 'Select',
|
|
110
|
+
change: 'Change',
|
|
111
|
+
edit: 'Edit',
|
|
112
|
+
cancel: 'Cancel',
|
|
113
|
+
confirm: 'Confirm',
|
|
114
|
+
confirmTitle: 'Are you sure?',
|
|
115
|
+
confirmBody: 'This action cannot be undone.',
|
|
116
|
+
empty: 'Nothing here yet',
|
|
117
|
+
noResults: 'No matches',
|
|
118
|
+
noResultsHint: 'Try a different spelling or fewer filters.',
|
|
119
|
+
back: 'Back to overview',
|
|
120
|
+
view: 'View',
|
|
121
|
+
upload: 'Choose file',
|
|
122
|
+
perPage: 'per page',
|
|
123
|
+
iconChoose: 'Choose icon',
|
|
124
|
+
iconEmpty: 'No icon found',
|
|
125
|
+
iconClear: 'No icon',
|
|
126
|
+
chartAsTable: 'As table',
|
|
127
|
+
chartAsChart: 'As chart',
|
|
128
|
+
paginationRange: ({ from, to, total }) => `${from}–${to} of ${total}`,
|
|
124
129
|
markdown: {
|
|
125
|
-
bold: '
|
|
126
|
-
italic: '
|
|
127
|
-
h2: '
|
|
128
|
-
h3: '
|
|
129
|
-
bullet: '
|
|
130
|
-
ordered: '
|
|
131
|
-
quote: '
|
|
130
|
+
bold: 'Bold',
|
|
131
|
+
italic: 'Italic',
|
|
132
|
+
h2: 'Heading 2',
|
|
133
|
+
h3: 'Heading 3',
|
|
134
|
+
bullet: 'Bullet list',
|
|
135
|
+
ordered: 'Numbered list',
|
|
136
|
+
quote: 'Quote',
|
|
132
137
|
code: 'Code',
|
|
133
138
|
link: 'Link',
|
|
134
|
-
linkPrompt: 'Link
|
|
139
|
+
linkPrompt: 'Link URL',
|
|
135
140
|
},
|
|
136
141
|
},
|
|
137
142
|
}
|
|
@@ -140,7 +145,7 @@ export const baseKitKey: InjectionKey<ComputedRef<BaseKitConfig>> = Symbol('base
|
|
|
140
145
|
|
|
141
146
|
/**
|
|
142
147
|
* Konfiguration für eine BaseKit-Komponente. Ohne bereitgestellten Wert
|
|
143
|
-
* greifen die Voreinstellungen — die Komponente rendert dann auf
|
|
148
|
+
* greifen die Voreinstellungen — die Komponente rendert dann auf Englisch,
|
|
144
149
|
* statt leere Beschriftungen zu zeigen.
|
|
145
150
|
*/
|
|
146
151
|
export function useBaseKit(): ComputedRef<BaseKitConfig> {
|
package/package.json
CHANGED