@m3ui-vue/nuxt 0.2.4 → 0.3.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 +8 -2
- package/dist/module.d.mts +7 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -1
- package/dist/runtime/plugin.js +20 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -75,6 +75,7 @@ The composables are prefixed so they can't clash with other modules (`useDevice`
|
|
|
75
75
|
| Library | Auto-imported as |
|
|
76
76
|
|---|---|
|
|
77
77
|
| `useTheme` | `useM3Theme` |
|
|
78
|
+
| `useThemeTokens` | `useM3ThemeTokens` |
|
|
78
79
|
| `useColorPalette` | `useM3ColorPalette` |
|
|
79
80
|
| `useToast` | `useM3Toast` |
|
|
80
81
|
| `useNotification` | `useM3Notification` |
|
|
@@ -83,7 +84,7 @@ The composables are prefixed so they can't clash with other modules (`useDevice`
|
|
|
83
84
|
| `useWindowSizeClass` | `useM3WindowSizeClass` |
|
|
84
85
|
| `useConfetti` | `useM3Confetti` |
|
|
85
86
|
| `useContainerTransform` | `useM3ContainerTransform` |
|
|
86
|
-
| `useFieldBg`, `useDebounce`, `usePageProgress`, `useSpring` | `useM3FieldBg`, `useM3Debounce`, `useM3PageProgress`, `useM3Spring` |
|
|
87
|
+
| `useFieldBg`, `useDebounce`, `useAutoGrow`, `usePageProgress`, `useSpring`, `useScrollReveal` | `useM3FieldBg`, `useM3Debounce`, `useM3AutoGrow`, `useM3PageProgress`, `useM3Spring`, `useM3ScrollReveal` |
|
|
87
88
|
| `useMap`, `useMapLayers`, `useMapFilter` (with `maplibre-gl`) | `useM3Map`, `useM3MapLayers`, `useM3MapFilter` |
|
|
88
89
|
|
|
89
90
|
Anything else (types, `palettes`, `motionSprings`…) is imported from `@m3ui-vue/m3ui-vue` as usual.
|
|
@@ -100,6 +101,7 @@ Everything `createM3UI()` takes, plus what the module itself does:
|
|
|
100
101
|
| `composables` | `{ prefix: 'M3' }` | Auto-import the composables with this prefix; `false` to import them yourself |
|
|
101
102
|
| `css` | `true` | Add `@m3ui-vue/m3ui-vue/styles` |
|
|
102
103
|
| `cookies` | `true` | Keep the theme, palette and contrast in cookies too, so the server renders with them |
|
|
104
|
+
| `viewportHints` | `false` | Ask Chromium for the window's exact size with client hints, so the adaptive layouts render at it on a first visit too (that visit's request is repeated once) |
|
|
103
105
|
| `themeScript` | `true` | Inline `themeInitScript()` in `<head>` |
|
|
104
106
|
|
|
105
107
|
## With @nuxtjs/i18n
|
|
@@ -148,7 +150,11 @@ a theme saved in the user's account, for instance.
|
|
|
148
150
|
The adaptive layouts (`MNavigationSuite`, `MListDetail`, `MSupportingPane`) measure their own size, which the server
|
|
149
151
|
can't. With `cookies`, the window's size is kept in a cookie too (`m3-viewport`), so from the second visit on they
|
|
150
152
|
render on the server for the user's screen (one in a narrower column corrects itself on the client). On a first visit
|
|
151
|
-
|
|
153
|
+
there's no cookie yet: with `@m3ui-vue/m3ui-vue` 1.2.0 or later the server renders for a size standing for the kind of
|
|
154
|
+
device (a phone, a tablet or a desktop, from `Sec-CH-UA-Mobile` and the user agent), and the layout settles on the exact
|
|
155
|
+
one once the page is interactive; before 1.2.0, the compact layout. With `viewportHints`, Chromium sends the exact size
|
|
156
|
+
on a first visit too: the server asks for it (`Accept-CH` / `Critical-CH: Sec-CH-Viewport-Width,
|
|
157
|
+
Sec-CH-Viewport-Height`) and Chromium repeats that first request once with it.
|
|
152
158
|
|
|
153
159
|
A `seed` default can't be generated before the app loads: on the first visit the page shows the baseline palette
|
|
154
160
|
until it does (later visits use the cached scheme).
|
package/dist/module.d.mts
CHANGED
|
@@ -38,6 +38,13 @@ interface ModuleOptions extends Omit<M3UIOptions, 'locale'> {
|
|
|
38
38
|
* `MListDetail`, `MSupportingPane`) render for the user's screen instead of compact. Default `true`.
|
|
39
39
|
*/
|
|
40
40
|
cookies?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Ask Chromium for the window's exact size with client hints (`Accept-CH` / `Critical-CH: Sec-CH-Viewport-Width,
|
|
43
|
+
* Sec-CH-Viewport-Height`), so the adaptive layouts render at it even on a first visit. It costs that first
|
|
44
|
+
* visit one repeated request in Chromium; later visits have the size in a cookie anyway. Without it, a first
|
|
45
|
+
* visit renders at a size guessed from the kind of device (phone, tablet, desktop). Needs `cookies`. Default `false`.
|
|
46
|
+
*/
|
|
47
|
+
viewportHints?: boolean;
|
|
41
48
|
/**
|
|
42
49
|
* Inline `themeInitScript()` in `<head>`, so dark mode, the palette and the contrast level the user picked are
|
|
43
50
|
* on the server-rendered page before the first paint. Default `true`.
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -25,12 +25,13 @@ const module$1 = defineNuxtModule({
|
|
|
25
25
|
composables: { prefix: "M3" },
|
|
26
26
|
css: true,
|
|
27
27
|
cookies: true,
|
|
28
|
+
viewportHints: false,
|
|
28
29
|
themeScript: true
|
|
29
30
|
},
|
|
30
31
|
async setup(options, nuxt) {
|
|
31
32
|
const logger = useLogger("@m3ui-vue/nuxt");
|
|
32
33
|
const resolver = createResolver(import.meta.url);
|
|
33
|
-
const { components, composables, css, cookies, themeScript, locale, ...plugin } = options;
|
|
34
|
+
const { components, composables, css, cookies, viewportHints, themeScript, locale, ...plugin } = options;
|
|
34
35
|
const entry = await resolvePath(LIB, { extensions: [".js", ".mjs"] });
|
|
35
36
|
let api;
|
|
36
37
|
try {
|
|
@@ -79,6 +80,7 @@ const module$1 = defineNuxtModule({
|
|
|
79
80
|
`export const autoLocale = ${auto}`,
|
|
80
81
|
`export const localePresets = ${auto ? `{ ${Object.entries(LOCALE_PRESETS).map(([code, name]) => `${code}: presets.${name}`).join(", ")} }` : "{}"}`,
|
|
81
82
|
`export const cookies = ${JSON.stringify(cookies)}`,
|
|
83
|
+
`export const viewportHints = ${JSON.stringify(!!viewportHints)}`,
|
|
82
84
|
`export const themeScript = ${JSON.stringify(themeScript)}`
|
|
83
85
|
].join("\n")
|
|
84
86
|
});
|
|
@@ -91,6 +93,7 @@ const module$1 = defineNuxtModule({
|
|
|
91
93
|
` export const autoLocale: boolean`,
|
|
92
94
|
` export const localePresets: Record<string, Partial<import('${LIB}').M3Locale>>`,
|
|
93
95
|
` export const cookies: boolean`,
|
|
96
|
+
` export const viewportHints: boolean`,
|
|
94
97
|
` export const themeScript: boolean`,
|
|
95
98
|
`}`
|
|
96
99
|
].join("\n")
|
package/dist/runtime/plugin.js
CHANGED
|
@@ -1,18 +1,34 @@
|
|
|
1
1
|
import { computed } from "vue";
|
|
2
|
+
import * as m3 from "@m3ui-vue/m3ui-vue";
|
|
2
3
|
import { createM3UI, themeInitScript } from "@m3ui-vue/m3ui-vue";
|
|
3
|
-
import { defineNuxtPlugin, useCookie, useHead } from "#app";
|
|
4
|
-
import { autoLocale, cookies, locale, localePresets, options, themeScript } from "#build/m3ui.options.mjs";
|
|
4
|
+
import { defineNuxtPlugin, useCookie, useHead, useRequestEvent, useRequestHeaders, useState } from "#app";
|
|
5
|
+
import { autoLocale, cookies, locale, localePresets, options, themeScript, viewportHints } from "#build/m3ui.options.mjs";
|
|
6
|
+
const fromHeaders = m3.viewportFromHeaders;
|
|
7
|
+
const HINTS = "Sec-CH-Viewport-Width, Sec-CH-Viewport-Height";
|
|
5
8
|
export default defineNuxtPlugin({
|
|
6
9
|
name: "m3ui",
|
|
7
10
|
enforce: "pre",
|
|
8
11
|
setup(nuxtApp) {
|
|
9
12
|
const read = (name) => useCookie(name, { decode: decodeURIComponent, readonly: true }).value;
|
|
10
|
-
const
|
|
13
|
+
const viewport = useState("m3ui-viewport", () => {
|
|
14
|
+
if (import.meta.server && fromHeaders) return fromHeaders(useRequestHeaders()) ?? null;
|
|
15
|
+
const [width, height] = (read("m3-viewport") ?? "").split("x").map(Number);
|
|
16
|
+
return width && height ? { width, height } : null;
|
|
17
|
+
});
|
|
18
|
+
if (import.meta.server && cookies && viewportHints) {
|
|
19
|
+
const res = useRequestEvent()?.node.res;
|
|
20
|
+
if (res && !res.headersSent) {
|
|
21
|
+
res.setHeader("Accept-CH", HINTS);
|
|
22
|
+
res.setHeader("Critical-CH", HINTS);
|
|
23
|
+
const vary = [res.getHeader("Vary")].flat().filter(Boolean).join(", ");
|
|
24
|
+
res.setHeader("Vary", vary ? `${vary}, ${HINTS}` : HINTS);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
11
27
|
const initialState = cookies ? {
|
|
12
28
|
theme: read("m3-theme"),
|
|
13
29
|
palette: read("m3-palette"),
|
|
14
30
|
contrast: read("m3-contrast"),
|
|
15
|
-
viewport:
|
|
31
|
+
viewport: viewport.value ?? void 0
|
|
16
32
|
} : void 0;
|
|
17
33
|
const appLocale = autoLocale ? computed(() => {
|
|
18
34
|
const i18n = nuxtApp.$i18n;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m3ui-vue/nuxt",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Nuxt module for m3ui-vue, the Material Design 3 component library for Vue 3 + Tailwind CSS v4",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"nuxt",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"@m3ui-vue/m3ui-vue": "^1.1.3"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@m3ui-vue/m3ui-vue": "^1.
|
|
56
|
+
"@m3ui-vue/m3ui-vue": "^1.2.0",
|
|
57
57
|
"@nuxt/module-builder": "^1.0.3",
|
|
58
58
|
"@nuxt/schema": "^4.6.2",
|
|
59
59
|
"@nuxt/test-utils": "^4.3.4",
|