@smalt-ui/nuxt 1.0.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/LICENSE +21 -0
- package/README.md +49 -0
- package/dist/module.d.mts +63 -0
- package/dist/module.json +12 -0
- package/dist/module.mjs +191 -0
- package/dist/runtime/color-mode.client.d.ts +2 -0
- package/dist/runtime/color-mode.client.js +5 -0
- package/dist/types.d.mts +3 -0
- package/package.json +64 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stanislav Dyachenko
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @smalt-ui/nuxt
|
|
2
|
+
|
|
3
|
+
Nuxt module for [`@smalt-ui/core`](../core/README.md): component auto-import, styles, color mode
|
|
4
|
+
and SSR setup out of the box.
|
|
5
|
+
|
|
6
|
+
> Part of the **Smalt UI** monorepo. Shared requirements, installation and workspace commands are
|
|
7
|
+
> described in the [root README](../../README.md).
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm add @smalt-ui/nuxt @smalt-ui/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// nuxt.config.ts
|
|
17
|
+
export default defineNuxtConfig({
|
|
18
|
+
modules: ['@smalt-ui/nuxt'],
|
|
19
|
+
sui: {
|
|
20
|
+
// options (see below)
|
|
21
|
+
},
|
|
22
|
+
})
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The module registers the components for auto-import, includes `@smalt-ui/core/styles.css`, adds
|
|
26
|
+
the `.s-root` isolation container and sets up color mode. `reka-ui` is a peer dependency.
|
|
27
|
+
|
|
28
|
+
**Nuxt 3 and Nuxt 4** are supported: `@nuxt/kit` is declared with the `^3.0.0 || ^4.0.0` range, so
|
|
29
|
+
the module uses the app's kit instead of pulling in a second copy.
|
|
30
|
+
|
|
31
|
+
## Options (`sui` config key)
|
|
32
|
+
|
|
33
|
+
| Option | Type | Default | Description |
|
|
34
|
+
| ----------- | ------------------------ | ------- | ----------------------------------------------------------- |
|
|
35
|
+
| `prefix` | `string` | `''` | Name prefix for auto-imported components |
|
|
36
|
+
| `css` | `boolean` | `true` | Include the global `@smalt-ui/core/styles.css` styles |
|
|
37
|
+
| `colorMode` | `boolean` | `true` | Enable light/dark control (`data-theme`) |
|
|
38
|
+
| `container` | `boolean` | `true` | Add the `.s-root` isolation class to the app root |
|
|
39
|
+
| `locale` | `'en'` | `'en'` | Locale of the library strings (the only built-in one) |
|
|
40
|
+
| `messages` | `Record<string, string>` | — | Override individual library strings, e.g. to translate them |
|
|
41
|
+
|
|
42
|
+
## Package scripts
|
|
43
|
+
|
|
44
|
+
| Script | Description |
|
|
45
|
+
| ------------------ | ---------------------------------------------- |
|
|
46
|
+
| `pnpm dev:prepare` | Stub + module type preparation for development |
|
|
47
|
+
| `pnpm build` | Build the module (`nuxt-module-build`) |
|
|
48
|
+
|
|
49
|
+
Run from the root: `pnpm --filter @smalt-ui/nuxt <script>`.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { NuxtModule } from '@nuxt/schema';
|
|
2
|
+
|
|
3
|
+
interface ModuleOptions {
|
|
4
|
+
/** Component name prefix for auto-import. Defaults to `''` (e.g. `SButton`). */
|
|
5
|
+
prefix: string;
|
|
6
|
+
/** Auto-import components. Defaults to `true`. */
|
|
7
|
+
components: boolean;
|
|
8
|
+
/** Include the global `@smalt-ui/core/styles.css` styles. Defaults to `true`. */
|
|
9
|
+
css: boolean;
|
|
10
|
+
/** Initialize color mode on the client (applies `data-theme`). Defaults to `true`. */
|
|
11
|
+
colorMode: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Add the `.s-root .s-root--app` container classes to the app root (`#__nuxt`) for CSS isolation
|
|
14
|
+
* and base typography. Defaults to `true`.
|
|
15
|
+
*/
|
|
16
|
+
container: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Base locale of the library strings (`aria-label`, visually hidden labels, etc.). Defaults to
|
|
19
|
+
* `'en'`, the only built-in locale; other languages are provided through `messages`. With
|
|
20
|
+
* `locale`/`messages` set, the module provides the dictionary to the whole application. The
|
|
21
|
+
* strings type is `SMessages` from `@smalt-ui/core` (a loose `Record` here keeps the module's
|
|
22
|
+
* types portable).
|
|
23
|
+
*/
|
|
24
|
+
locale?: 'en';
|
|
25
|
+
/** Partial override of individual strings on top of the locale (`SMessages` keys). */
|
|
26
|
+
messages?: Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* App-level prop defaults (keys are `global` and component names).
|
|
29
|
+
* The type is a loose `Record` to keep the module's types portable; in core it is `SDefaults`.
|
|
30
|
+
*/
|
|
31
|
+
defaults?: Record<string, Record<string, unknown>>;
|
|
32
|
+
/** Built-in preset name (`compact`/`comfortable`): "theme + defaults" in one value. */
|
|
33
|
+
preset?: 'compact' | 'comfortable';
|
|
34
|
+
/**
|
|
35
|
+
* Include the Inter font: the `@font-face` rules and serving the files from the package.
|
|
36
|
+
* Defaults to `true`: the `--s-font-sans` token starts with `Inter`, and without the font files
|
|
37
|
+
* the app silently falls back to the system font.
|
|
38
|
+
*
|
|
39
|
+
* Turn it off if the app already includes Inter itself: otherwise the same font is declared
|
|
40
|
+
* twice and preload downloads an extra copy.
|
|
41
|
+
*/
|
|
42
|
+
fonts: boolean | {
|
|
43
|
+
/** Include the CSS with `@font-face`. Defaults to `true`. */
|
|
44
|
+
css?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Subsets for `<link rel="preload">`. Defaults to basic Latin (`['latin']`), the one
|
|
47
|
+
* the first screen is set in.
|
|
48
|
+
*/
|
|
49
|
+
preload?: boolean | readonly SFontFace[];
|
|
50
|
+
/** Base URL Nitro serves the files from. Defaults to `'/_fonts/smalt'`. */
|
|
51
|
+
baseURL?: string;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/** Subset of the vendored font, a key for the `fonts.preload` option. */
|
|
55
|
+
type SFontFace = 'latin' | 'latin-ext' | 'cyrillic' | 'cyrillic-ext';
|
|
56
|
+
/**
|
|
57
|
+
* Explicit type annotation: without it the inferred module type references @nuxt/schema in a way
|
|
58
|
+
* that cannot be named (TS2742), and rollup-plugin-dts fails when generating .d.ts.
|
|
59
|
+
*/
|
|
60
|
+
declare const module$1: NuxtModule<ModuleOptions>;
|
|
61
|
+
|
|
62
|
+
export { module$1 as default };
|
|
63
|
+
export type { ModuleOptions, SFontFace };
|
package/dist/module.json
ADDED
package/dist/module.mjs
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join, dirname } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { defineNuxtModule, createResolver, addTemplate, addComponent, addPluginTemplate, addPlugin } from '@nuxt/kit';
|
|
5
|
+
import { colorModeScript } from '@smalt-ui/core/color-mode-script';
|
|
6
|
+
|
|
7
|
+
const COMPONENT_NAMES = [
|
|
8
|
+
"SAccordion",
|
|
9
|
+
"SAccordionItem",
|
|
10
|
+
"SAlert",
|
|
11
|
+
"SAlertDialog",
|
|
12
|
+
"SAspectRatio",
|
|
13
|
+
"SAutocomplete",
|
|
14
|
+
"SAvatar",
|
|
15
|
+
"SBadge",
|
|
16
|
+
"SBreadcrumb",
|
|
17
|
+
"SButton",
|
|
18
|
+
"SCalendar",
|
|
19
|
+
"SCard",
|
|
20
|
+
"SCheckbox",
|
|
21
|
+
"SCollapsible",
|
|
22
|
+
"SColorField",
|
|
23
|
+
"SColorPicker",
|
|
24
|
+
"SContextMenu",
|
|
25
|
+
"SDateField",
|
|
26
|
+
"SDatePicker",
|
|
27
|
+
"SDateRangePicker",
|
|
28
|
+
"SDialog",
|
|
29
|
+
"SDrawer",
|
|
30
|
+
"SDropdownMenu",
|
|
31
|
+
"SFormField",
|
|
32
|
+
"SHoverCard",
|
|
33
|
+
"SIcon",
|
|
34
|
+
"SInput",
|
|
35
|
+
"SMenubar",
|
|
36
|
+
"SNavigationMenu",
|
|
37
|
+
"SNumberField",
|
|
38
|
+
"SPagination",
|
|
39
|
+
"SPinInput",
|
|
40
|
+
"SPopover",
|
|
41
|
+
"SProgress",
|
|
42
|
+
"SRadio",
|
|
43
|
+
"SRadioGroup",
|
|
44
|
+
"SRating",
|
|
45
|
+
"SSelect",
|
|
46
|
+
"SSeparator",
|
|
47
|
+
"SSkeleton",
|
|
48
|
+
"SSlider",
|
|
49
|
+
"SSpinner",
|
|
50
|
+
"SSplitter",
|
|
51
|
+
"SStepper",
|
|
52
|
+
"SSwitch",
|
|
53
|
+
"STabs",
|
|
54
|
+
"STag",
|
|
55
|
+
"STextarea",
|
|
56
|
+
"STimeField",
|
|
57
|
+
"SToast",
|
|
58
|
+
"SToggle",
|
|
59
|
+
"SToggleGroup",
|
|
60
|
+
"SToolbar",
|
|
61
|
+
"STooltip",
|
|
62
|
+
"STree"
|
|
63
|
+
];
|
|
64
|
+
const PROVIDER_NAMES = ["ConfigProvider", "ConfirmProvider", "ToastProvider"];
|
|
65
|
+
const EXPLICIT_ONLY_PROVIDERS = ["ConfigProvider"];
|
|
66
|
+
|
|
67
|
+
const FONT_FILES = {
|
|
68
|
+
latin: "Inter-Latin.woff2",
|
|
69
|
+
"latin-ext": "Inter-LatinExt.woff2",
|
|
70
|
+
cyrillic: "Inter-Cyrillic.woff2",
|
|
71
|
+
"cyrillic-ext": "Inter-CyrillicExt.woff2"
|
|
72
|
+
};
|
|
73
|
+
const DEFAULT_PRELOAD = ["latin"];
|
|
74
|
+
const explicitOnly = EXPLICIT_ONLY_PROVIDERS;
|
|
75
|
+
const COMPONENTS = [
|
|
76
|
+
...COMPONENT_NAMES,
|
|
77
|
+
...PROVIDER_NAMES.filter((name) => !explicitOnly.includes(name))
|
|
78
|
+
];
|
|
79
|
+
const module$1 = defineNuxtModule({
|
|
80
|
+
meta: {
|
|
81
|
+
name: "@smalt-ui/nuxt",
|
|
82
|
+
configKey: "sui",
|
|
83
|
+
compatibility: { nuxt: ">=3.0.0" }
|
|
84
|
+
},
|
|
85
|
+
defaults: {
|
|
86
|
+
prefix: "",
|
|
87
|
+
components: true,
|
|
88
|
+
css: true,
|
|
89
|
+
colorMode: true,
|
|
90
|
+
container: true,
|
|
91
|
+
fonts: true
|
|
92
|
+
},
|
|
93
|
+
setup(options, nuxt) {
|
|
94
|
+
const resolver = createResolver(import.meta.url);
|
|
95
|
+
nuxt.options.build.transpile.push("reka-ui", "@smalt-ui/core");
|
|
96
|
+
const fonts = options.fonts === true ? {} : options.fonts;
|
|
97
|
+
if (fonts) {
|
|
98
|
+
const baseURL = (fonts.baseURL ?? "/_fonts/smalt").replace(/\/$/, "");
|
|
99
|
+
const cssFile = fileURLToPath(import.meta.resolve("@smalt-ui/core/fonts.css"));
|
|
100
|
+
nuxt.options.nitro.publicAssets = nuxt.options.nitro.publicAssets ?? [];
|
|
101
|
+
nuxt.options.nitro.publicAssets.push({
|
|
102
|
+
dir: join(dirname(cssFile), "fonts"),
|
|
103
|
+
baseURL,
|
|
104
|
+
maxAge: 60 * 60 * 24 * 365
|
|
105
|
+
});
|
|
106
|
+
if (fonts.css !== false) {
|
|
107
|
+
const source = readFileSync(cssFile, "utf8");
|
|
108
|
+
const css = source.replaceAll("./fonts/", `${baseURL}/`);
|
|
109
|
+
if (css === source) {
|
|
110
|
+
throw new Error(
|
|
111
|
+
'[@smalt-ui/nuxt] no url("./fonts/\u2026") found in @smalt-ui/core/fonts.css: the core version is incompatible with the module'
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
addTemplate({ filename: "smalt-fonts.css", write: true, getContents: () => css });
|
|
115
|
+
nuxt.options.css.push(join(nuxt.options.buildDir, "smalt-fonts.css"));
|
|
116
|
+
}
|
|
117
|
+
const preload = fonts.preload ?? true;
|
|
118
|
+
const faces = preload === true ? DEFAULT_PRELOAD : preload === false ? [] : preload;
|
|
119
|
+
nuxt.options.app.head.link = nuxt.options.app.head.link ?? [];
|
|
120
|
+
for (const face of faces) {
|
|
121
|
+
nuxt.options.app.head.link.push({
|
|
122
|
+
rel: "preload",
|
|
123
|
+
as: "font",
|
|
124
|
+
type: "font/woff2",
|
|
125
|
+
crossorigin: "",
|
|
126
|
+
href: `${baseURL}/${FONT_FILES[face]}`
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (options.css) {
|
|
131
|
+
nuxt.options.css.push("@smalt-ui/core/styles.css");
|
|
132
|
+
}
|
|
133
|
+
if (options.container) {
|
|
134
|
+
const rootAttrs = nuxt.options.app.rootAttrs ??= {};
|
|
135
|
+
rootAttrs.class = [rootAttrs.class, "s-root", "s-root--app"].filter(Boolean).join(" ");
|
|
136
|
+
}
|
|
137
|
+
if (options.components) {
|
|
138
|
+
for (const name of COMPONENTS) {
|
|
139
|
+
addComponent({
|
|
140
|
+
name: `${options.prefix}${name}`,
|
|
141
|
+
export: name,
|
|
142
|
+
filePath: "@smalt-ui/core"
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (options.locale || options.messages) {
|
|
147
|
+
const localeOptions = JSON.stringify({ locale: options.locale, messages: options.messages });
|
|
148
|
+
addPluginTemplate({
|
|
149
|
+
filename: "smalt-locale.mjs",
|
|
150
|
+
getContents: () => `import { defineNuxtPlugin } from '#app'
|
|
151
|
+
import { installLocale } from '@smalt-ui/core'
|
|
152
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
153
|
+
installLocale(nuxtApp.vueApp, ${localeOptions})
|
|
154
|
+
})
|
|
155
|
+
`
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
if (options.defaults || options.preset) {
|
|
159
|
+
for (const [component, props] of Object.entries(options.defaults ?? {})) {
|
|
160
|
+
for (const [prop, value] of Object.entries(props ?? {})) {
|
|
161
|
+
if (typeof value === "function") {
|
|
162
|
+
console.warn(
|
|
163
|
+
`[@smalt-ui/nuxt] default ${component}.${prop} is a function; module options cannot serialize it, so it will be dropped. Set it with installDefaults in your own plugin.`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
const defaultsOption = JSON.stringify(options.defaults ?? {});
|
|
169
|
+
const presetOption = JSON.stringify(options.preset ?? null);
|
|
170
|
+
addPluginTemplate({
|
|
171
|
+
filename: "smalt-defaults.mjs",
|
|
172
|
+
getContents: () => `import { defineNuxtPlugin } from '#app'
|
|
173
|
+
import { installDefaults, injectTheme, createTheme, mergeDefaults, BUILTIN_PRESETS } from '@smalt-ui/core'
|
|
174
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
175
|
+
const presetName = ${presetOption}
|
|
176
|
+
const preset = presetName ? BUILTIN_PRESETS[presetName] : undefined
|
|
177
|
+
if (preset?.tokens) injectTheme(createTheme(preset.tokens), preset.name)
|
|
178
|
+
installDefaults(nuxtApp.vueApp, mergeDefaults(preset?.defaults, ${defaultsOption}))
|
|
179
|
+
})
|
|
180
|
+
`
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
if (options.colorMode) {
|
|
184
|
+
nuxt.options.app.head.script = nuxt.options.app.head.script ?? [];
|
|
185
|
+
nuxt.options.app.head.script.push({ innerHTML: colorModeScript(), tagPosition: "head" });
|
|
186
|
+
addPlugin({ src: resolver.resolve("./runtime/color-mode.client"), mode: "client" });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
export { module$1 as default };
|
package/dist/types.d.mts
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smalt-ui/nuxt",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Nuxt module for @smalt-ui/core: component auto-import, styles, color mode",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Stanislav Dyachenko",
|
|
7
|
+
"homepage": "https://technical-jade.github.io/smalt-ui/",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/technical-jade/smalt-ui.git",
|
|
11
|
+
"directory": "packages/nuxt"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/technical-jade/smalt-ui/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"vue",
|
|
18
|
+
"nuxt",
|
|
19
|
+
"nuxt-module",
|
|
20
|
+
"ui",
|
|
21
|
+
"components",
|
|
22
|
+
"design-system"
|
|
23
|
+
],
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "./dist/module.mjs",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/types.d.mts",
|
|
29
|
+
"import": "./dist/module.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"files": [
|
|
34
|
+
"dist"
|
|
35
|
+
],
|
|
36
|
+
"engines": {
|
|
37
|
+
"node": ">=22.12.0"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@nuxt/kit": "^3.0.0 || ^4.0.0"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"@smalt-ui/core": "*",
|
|
47
|
+
"reka-ui": "^2.10.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@nuxt/module-builder": "^1.0.3",
|
|
51
|
+
"@nuxt/schema": "^4.5.2",
|
|
52
|
+
"nuxt": "^4.5.2",
|
|
53
|
+
"reka-ui": "^2.0.0",
|
|
54
|
+
"vue": "^3.5.0",
|
|
55
|
+
"@smalt-ui/core": "1.0.0"
|
|
56
|
+
},
|
|
57
|
+
"scripts": {
|
|
58
|
+
"dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare",
|
|
59
|
+
"prebuild": "nuxi prepare ./playground",
|
|
60
|
+
"build": "nuxt-module-build build",
|
|
61
|
+
"pretypecheck": "pnpm --filter @smalt-ui/core build && nuxi prepare ./playground",
|
|
62
|
+
"typecheck": "vue-tsc --noEmit -p tsconfig.json"
|
|
63
|
+
}
|
|
64
|
+
}
|