@unhead/react 3.0.0-beta.9 → 3.0.0-rc.4

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/dist/client.d.mts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as unhead_types from 'unhead/types';
4
- import { CreateClientHeadOptions, Unhead } from 'unhead/types';
4
+ import { Unhead, CreateClientHeadOptions } from 'unhead/types';
5
5
  export { CreateClientHeadOptions, Unhead } from 'unhead/types';
6
+ import { ClientUnhead } from 'unhead/client';
6
7
  export { renderDOMHead } from 'unhead/client';
7
8
 
8
- declare function createHead(options?: CreateClientHeadOptions): Unhead;
9
+ declare function createHead(options?: CreateClientHeadOptions): ClientUnhead;
9
10
  declare function UnheadProvider({ children, head }: {
10
11
  children: ReactNode;
11
- head?: ReturnType<typeof createHead>;
12
+ head?: Unhead<any, any>;
12
13
  }): react.FunctionComponentElement<react.ProviderProps<Unhead<unhead_types.ResolvableHead, unknown> | null>>;
13
14
 
14
15
  export { UnheadProvider, createHead };
package/dist/client.d.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
3
  import * as unhead_types from 'unhead/types';
4
- import { CreateClientHeadOptions, Unhead } from 'unhead/types';
4
+ import { Unhead, CreateClientHeadOptions } from 'unhead/types';
5
5
  export { CreateClientHeadOptions, Unhead } from 'unhead/types';
6
+ import { ClientUnhead } from 'unhead/client';
6
7
  export { renderDOMHead } from 'unhead/client';
7
8
 
8
- declare function createHead(options?: CreateClientHeadOptions): Unhead;
9
+ declare function createHead(options?: CreateClientHeadOptions): ClientUnhead;
9
10
  declare function UnheadProvider({ children, head }: {
10
11
  children: ReactNode;
11
- head?: ReturnType<typeof createHead>;
12
+ head?: Unhead<any, any>;
12
13
  }): react.FunctionComponentElement<react.ProviderProps<Unhead<unhead_types.ResolvableHead, unknown> | null>>;
13
14
 
14
15
  export { UnheadProvider, createHead };
@@ -0,0 +1,73 @@
1
+ import react__default, { ReactNode } from 'react';
2
+
3
+ interface HelmetProps {
4
+ children?: ReactNode;
5
+ /**
6
+ * A default title to use when no `<title>` child is provided.
7
+ *
8
+ * Equivalent to react-helmet's `defaultTitle`.
9
+ */
10
+ defaultTitle?: string;
11
+ /**
12
+ * A template for the title. Use `%s` as a placeholder for the page title.
13
+ *
14
+ * @example `%s | My Site`
15
+ */
16
+ titleTemplate?: string;
17
+ /**
18
+ * Called after the document head has been updated in the browser.
19
+ *
20
+ * Equivalent to react-helmet's `onChangeClientState`.
21
+ *
22
+ * @param newState - The new head state after rendering.
23
+ * @param addedTags - Always empty — unhead manages DOM diffing internally.
24
+ * @param removedTags - Always empty — unhead manages DOM diffing internally.
25
+ */
26
+ onChangeClientState?: (newState: Record<string, any>, addedTags: Record<string, HTMLElement[]>, removedTags: Record<string, HTMLElement[]>) => void;
27
+ /**
28
+ * Whether to encode special characters in attributes.
29
+ *
30
+ * @default true
31
+ * @deprecated Unhead handles encoding automatically. This prop is accepted for compatibility but has no effect.
32
+ */
33
+ encodeSpecialCharacters?: boolean;
34
+ /**
35
+ * Whether to defer DOM updates until the browser is idle.
36
+ *
37
+ * @default true
38
+ * @deprecated Unhead batches DOM updates automatically. This prop is accepted for compatibility but has no effect.
39
+ */
40
+ defer?: boolean;
41
+ title?: string;
42
+ base?: Record<string, any>;
43
+ meta?: Array<Record<string, any>>;
44
+ link?: Array<Record<string, any>>;
45
+ script?: Array<Record<string, any>>;
46
+ style?: Array<Record<string, any>>;
47
+ noscript?: Array<Record<string, any>>;
48
+ htmlAttributes?: Record<string, any>;
49
+ bodyAttributes?: Record<string, any>;
50
+ }
51
+ /**
52
+ * A react-helmet compatible component powered by unhead.
53
+ *
54
+ * Drop-in replacement for `<Helmet>` — import from `@unhead/react/helmet` instead of `react-helmet`.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * import { Helmet } from '@unhead/react/helmet'
59
+ *
60
+ * <Helmet
61
+ * defaultTitle="My Site"
62
+ * titleTemplate="%s | My Site"
63
+ * onChangeClientState={(newState) => console.log(newState)}
64
+ * >
65
+ * <title>Page Title</title>
66
+ * <meta name="description" content="Page description" />
67
+ * </Helmet>
68
+ * ```
69
+ */
70
+ declare const Helmet: react__default.FC<HelmetProps>;
71
+
72
+ export { Helmet };
73
+ export type { HelmetProps };
@@ -0,0 +1,73 @@
1
+ import react__default, { ReactNode } from 'react';
2
+
3
+ interface HelmetProps {
4
+ children?: ReactNode;
5
+ /**
6
+ * A default title to use when no `<title>` child is provided.
7
+ *
8
+ * Equivalent to react-helmet's `defaultTitle`.
9
+ */
10
+ defaultTitle?: string;
11
+ /**
12
+ * A template for the title. Use `%s` as a placeholder for the page title.
13
+ *
14
+ * @example `%s | My Site`
15
+ */
16
+ titleTemplate?: string;
17
+ /**
18
+ * Called after the document head has been updated in the browser.
19
+ *
20
+ * Equivalent to react-helmet's `onChangeClientState`.
21
+ *
22
+ * @param newState - The new head state after rendering.
23
+ * @param addedTags - Always empty — unhead manages DOM diffing internally.
24
+ * @param removedTags - Always empty — unhead manages DOM diffing internally.
25
+ */
26
+ onChangeClientState?: (newState: Record<string, any>, addedTags: Record<string, HTMLElement[]>, removedTags: Record<string, HTMLElement[]>) => void;
27
+ /**
28
+ * Whether to encode special characters in attributes.
29
+ *
30
+ * @default true
31
+ * @deprecated Unhead handles encoding automatically. This prop is accepted for compatibility but has no effect.
32
+ */
33
+ encodeSpecialCharacters?: boolean;
34
+ /**
35
+ * Whether to defer DOM updates until the browser is idle.
36
+ *
37
+ * @default true
38
+ * @deprecated Unhead batches DOM updates automatically. This prop is accepted for compatibility but has no effect.
39
+ */
40
+ defer?: boolean;
41
+ title?: string;
42
+ base?: Record<string, any>;
43
+ meta?: Array<Record<string, any>>;
44
+ link?: Array<Record<string, any>>;
45
+ script?: Array<Record<string, any>>;
46
+ style?: Array<Record<string, any>>;
47
+ noscript?: Array<Record<string, any>>;
48
+ htmlAttributes?: Record<string, any>;
49
+ bodyAttributes?: Record<string, any>;
50
+ }
51
+ /**
52
+ * A react-helmet compatible component powered by unhead.
53
+ *
54
+ * Drop-in replacement for `<Helmet>` — import from `@unhead/react/helmet` instead of `react-helmet`.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * import { Helmet } from '@unhead/react/helmet'
59
+ *
60
+ * <Helmet
61
+ * defaultTitle="My Site"
62
+ * titleTemplate="%s | My Site"
63
+ * onChangeClientState={(newState) => console.log(newState)}
64
+ * >
65
+ * <title>Page Title</title>
66
+ * <meta name="description" content="Page description" />
67
+ * </Helmet>
68
+ * ```
69
+ */
70
+ declare const Helmet: react__default.FC<HelmetProps>;
71
+
72
+ export { Helmet };
73
+ export type { HelmetProps };
@@ -0,0 +1,152 @@
1
+ import React, { useMemo, useCallback, useRef, useEffect, useContext } from 'react';
2
+ import { createDomRenderer, createDebouncedFn, createHead } from 'unhead/client';
3
+ import { ValidHeadTags, TagsWithInnerContent, HasElementTags } from 'unhead/utils';
4
+ import { U as UnheadContext } from './shared/react.DF9T1fqs.mjs';
5
+
6
+ let _singletonHead = null;
7
+ function useHelmetHead() {
8
+ const ctx = useContext(UnheadContext);
9
+ if (ctx) {
10
+ return ctx;
11
+ }
12
+ if (!_singletonHead) {
13
+ if (typeof window === "undefined") {
14
+ throw new TypeError("Helmet requires UnheadProvider on the server. Wrap your app with <UnheadProvider>.");
15
+ }
16
+ const domRenderer = createDomRenderer();
17
+ let head;
18
+ const debouncedRenderer = createDebouncedFn(() => domRenderer(head), (fn) => setTimeout(fn, 0));
19
+ head = createHead({ render: debouncedRenderer });
20
+ _singletonHead = head;
21
+ }
22
+ return _singletonHead;
23
+ }
24
+ const Helmet = ({
25
+ children,
26
+ defaultTitle,
27
+ titleTemplate,
28
+ onChangeClientState,
29
+ title: titleProp,
30
+ base: baseProp,
31
+ meta: metaProp,
32
+ link: linkProp,
33
+ script: scriptProp,
34
+ style: styleProp,
35
+ noscript: noscriptProp,
36
+ htmlAttributes,
37
+ bodyAttributes,
38
+ // accepted for compat, intentionally unused
39
+ encodeSpecialCharacters: _encodeSpecialCharacters,
40
+ defer: _defer
41
+ }) => {
42
+ const head = useHelmetHead();
43
+ const processedElements = useMemo(() => React.Children.toArray(children).filter(React.isValidElement), [children]);
44
+ const getHeadChanges = useCallback(() => {
45
+ const input = {};
46
+ if (titleTemplate) {
47
+ input.titleTemplate = titleTemplate;
48
+ }
49
+ if (titleProp != null) {
50
+ input.title = titleProp;
51
+ }
52
+ if (baseProp) {
53
+ input.base = baseProp;
54
+ }
55
+ if (metaProp) {
56
+ input.meta = [...metaProp];
57
+ }
58
+ if (linkProp) {
59
+ input.link = [...linkProp];
60
+ }
61
+ if (scriptProp) {
62
+ input.script = [...scriptProp];
63
+ }
64
+ if (styleProp) {
65
+ input.style = [...styleProp];
66
+ }
67
+ if (noscriptProp) {
68
+ input.noscript = [...noscriptProp];
69
+ }
70
+ if (htmlAttributes) {
71
+ input.htmlAttrs = htmlAttributes;
72
+ }
73
+ if (bodyAttributes) {
74
+ input.bodyAttrs = bodyAttributes;
75
+ }
76
+ let hasTitle = !!titleProp;
77
+ for (const element of processedElements) {
78
+ const reactElement = element;
79
+ const { type, props } = reactElement;
80
+ let tagName = String(type);
81
+ if (tagName === "html")
82
+ tagName = "htmlAttrs";
83
+ else if (tagName === "body")
84
+ tagName = "bodyAttrs";
85
+ if (!ValidHeadTags.has(tagName)) {
86
+ continue;
87
+ }
88
+ const data = { ...typeof props === "object" ? props : {} };
89
+ if (TagsWithInnerContent.has(tagName) && data.children != null) {
90
+ const contentKey = tagName === "script" ? "innerHTML" : "textContent";
91
+ data[contentKey] = Array.isArray(data.children) ? data.children.map(String).join("") : String(data.children);
92
+ }
93
+ delete data.children;
94
+ if (tagName === "title") {
95
+ hasTitle = true;
96
+ }
97
+ if (HasElementTags.has(tagName)) {
98
+ const key = tagName;
99
+ if (!Array.isArray(input[key])) {
100
+ input[key] = [];
101
+ }
102
+ input[key].push(data);
103
+ } else {
104
+ input[tagName] = data;
105
+ }
106
+ }
107
+ if (!hasTitle && defaultTitle) {
108
+ input.title = defaultTitle;
109
+ }
110
+ if (defaultTitle) {
111
+ input.templateParams = {
112
+ ...input.templateParams,
113
+ defaultTitle
114
+ };
115
+ }
116
+ return input;
117
+ }, [processedElements, titleTemplate, defaultTitle, titleProp, baseProp, metaProp, linkProp, scriptProp, styleProp, noscriptProp, htmlAttributes, bodyAttributes]);
118
+ const headRef = useRef(null);
119
+ const onChangeClientStateRef = useRef(onChangeClientState);
120
+ onChangeClientStateRef.current = onChangeClientState;
121
+ if (head.ssr && !headRef.current) {
122
+ headRef.current = head.push(getHeadChanges());
123
+ }
124
+ useEffect(() => {
125
+ const options = {
126
+ onRendered: () => {
127
+ const cb = onChangeClientStateRef.current;
128
+ if (!cb)
129
+ return;
130
+ const titleEl = document.querySelector("title");
131
+ const state = {
132
+ title: titleEl?.textContent || ""
133
+ };
134
+ for (const tag of ["meta", "link", "script", "style", "base"]) {
135
+ state[`${tag}Tags`] = Array.from(document.querySelectorAll(`head ${tag}`));
136
+ }
137
+ cb(state, {}, {});
138
+ }
139
+ };
140
+ headRef.current = head.push(getHeadChanges(), options);
141
+ return () => {
142
+ headRef.current?.dispose();
143
+ headRef.current = null;
144
+ };
145
+ }, [head]);
146
+ useEffect(() => {
147
+ headRef.current?.patch(getHeadChanges());
148
+ }, [getHeadChanges]);
149
+ return null;
150
+ };
151
+
152
+ export { Helmet };
package/dist/index.mjs CHANGED
@@ -20,25 +20,25 @@ function useUnhead() {
20
20
  return instance;
21
21
  }
22
22
  function withSideEffects(input, options, fn) {
23
- const unhead = options.head || useUnhead();
23
+ const head = options.head || useUnhead();
24
24
  const entryRef = useRef(null);
25
25
  const inputRef = useRef(input);
26
26
  inputRef.current = input;
27
- if (unhead.ssr && !entryRef.current) {
28
- entryRef.current = fn(unhead, input, options);
27
+ if (head.ssr && !entryRef.current) {
28
+ entryRef.current = fn(head, input, options);
29
29
  }
30
30
  useEffect(() => {
31
- const entry = fn(unhead, inputRef.current, options);
31
+ const entry = fn(head, inputRef.current, options);
32
32
  entryRef.current = entry;
33
33
  return () => {
34
34
  entry.dispose();
35
35
  entryRef.current = null;
36
36
  };
37
- }, [unhead]);
37
+ }, [head]);
38
38
  useEffect(() => {
39
39
  entryRef.current?.patch(input);
40
40
  }, [input]);
41
- if (unhead.ssr) {
41
+ if (head.ssr) {
42
42
  return entryRef.current;
43
43
  }
44
44
  const proxyRef = useRef(null);
@@ -2,7 +2,7 @@ import { Writable } from 'node:stream';
2
2
  import { ReactNode } from 'react';
3
3
  import { StreamableHeadContext, CreateStreamableServerHeadOptions } from 'unhead/stream/server';
4
4
  export { BaseStreamableHeadContext, CreateStreamableServerHeadOptions, StreamableHeadContext, StreamingTemplateParts, WebStreamableHeadContext, prepareStreamingTemplate, renderSSRHeadShell, renderSSRHeadSuspenseChunk, wrapStream } from 'unhead/stream/server';
5
- import { Unhead, ResolvableHead } from 'unhead/types';
5
+ import { ResolvableHead, Unhead } from 'unhead/types';
6
6
 
7
7
  declare function UnheadProvider({ value, children }: {
8
8
  value: Unhead;
@@ -2,7 +2,7 @@ import { Writable } from 'node:stream';
2
2
  import { ReactNode } from 'react';
3
3
  import { StreamableHeadContext, CreateStreamableServerHeadOptions } from 'unhead/stream/server';
4
4
  export { BaseStreamableHeadContext, CreateStreamableServerHeadOptions, StreamableHeadContext, StreamingTemplateParts, WebStreamableHeadContext, prepareStreamingTemplate, renderSSRHeadShell, renderSSRHeadSuspenseChunk, wrapStream } from 'unhead/stream/server';
5
- import { Unhead, ResolvableHead } from 'unhead/types';
5
+ import { ResolvableHead, Unhead } from 'unhead/types';
6
6
 
7
7
  declare function UnheadProvider({ value, children }: {
8
8
  value: Unhead;
@@ -1,5 +1,5 @@
1
1
  import { PassThrough } from 'node:stream';
2
- import { createElement, useContext } from 'react';
2
+ import { useContext, createElement } from 'react';
3
3
  import { renderSSRHeadSuspenseChunk, createStreamableHead as createStreamableHead$1, prepareStreamingTemplate } from 'unhead/stream/server';
4
4
  export { prepareStreamingTemplate, renderSSRHeadShell, renderSSRHeadSuspenseChunk, wrapStream } from 'unhead/stream/server';
5
5
  import { U as UnheadContext } from '../shared/react.DF9T1fqs.mjs';
@@ -2,6 +2,7 @@ import MagicString from 'magic-string';
2
2
  import { parseAndWalk } from 'oxc-walker';
3
3
  import { createStreamingPlugin } from 'unhead/stream/vite';
4
4
 
5
+ const FILTER_RE = /\.[jt]sx$/;
5
6
  function transform(code, id, isSSR, s) {
6
7
  const lang = id.endsWith(".tsx") ? "tsx" : id.endsWith(".jsx") ? "jsx" : "tsx";
7
8
  const returns = [];
@@ -84,7 +85,7 @@ import { HeadStream } from '${importPath}'`);
84
85
  function unheadReactPlugin(options) {
85
86
  return createStreamingPlugin({
86
87
  framework: "@unhead/react",
87
- filter: /\.[jt]sx$/,
88
+ filter: FILTER_RE,
88
89
  mode: options?.mode,
89
90
  transform(code, id, opts) {
90
91
  const s = new MagicString(code);
@@ -0,0 +1,33 @@
1
+ import { VitePluginOptions } from '@unhead/bundler/vite';
2
+ import { StreamingPluginOptions } from 'unhead/stream/vite';
3
+ import { Plugin } from 'vite';
4
+
5
+ interface UnheadReactViteOptions extends VitePluginOptions {
6
+ /**
7
+ * Enable streaming SSR support.
8
+ * Set to `true` or a config object to enable.
9
+ * @default false
10
+ */
11
+ streaming?: true | Pick<StreamingPluginOptions, 'mode'> | false;
12
+ }
13
+ /**
14
+ * Unified Vite plugin for `@unhead/react`.
15
+ *
16
+ * Combines build optimizations (tree-shaking, useSeoMeta transform, minification)
17
+ * with streaming SSR support into a single plugin.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // vite.config.ts
22
+ * import react from '@vitejs/plugin-react'
23
+ * import { Unhead } from '@unhead/react/vite'
24
+ *
25
+ * export default defineConfig({
26
+ * plugins: [react(), Unhead()],
27
+ * })
28
+ * ```
29
+ */
30
+ declare function Unhead(options?: UnheadReactViteOptions): Plugin[];
31
+
32
+ export { Unhead };
33
+ export type { UnheadReactViteOptions };
package/dist/vite.d.ts ADDED
@@ -0,0 +1,33 @@
1
+ import { VitePluginOptions } from '@unhead/bundler/vite';
2
+ import { StreamingPluginOptions } from 'unhead/stream/vite';
3
+ import { Plugin } from 'vite';
4
+
5
+ interface UnheadReactViteOptions extends VitePluginOptions {
6
+ /**
7
+ * Enable streaming SSR support.
8
+ * Set to `true` or a config object to enable.
9
+ * @default false
10
+ */
11
+ streaming?: true | Pick<StreamingPluginOptions, 'mode'> | false;
12
+ }
13
+ /**
14
+ * Unified Vite plugin for `@unhead/react`.
15
+ *
16
+ * Combines build optimizations (tree-shaking, useSeoMeta transform, minification)
17
+ * with streaming SSR support into a single plugin.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * // vite.config.ts
22
+ * import react from '@vitejs/plugin-react'
23
+ * import { Unhead } from '@unhead/react/vite'
24
+ *
25
+ * export default defineConfig({
26
+ * plugins: [react(), Unhead()],
27
+ * })
28
+ * ```
29
+ */
30
+ declare function Unhead(options?: UnheadReactViteOptions): Plugin[];
31
+
32
+ export { Unhead };
33
+ export type { UnheadReactViteOptions };
package/dist/vite.mjs ADDED
@@ -0,0 +1,16 @@
1
+ import { Unhead as Unhead$1 } from '@unhead/bundler/vite';
2
+ import unheadReactPlugin from './stream/vite.mjs';
3
+ import 'magic-string';
4
+ import 'oxc-walker';
5
+ import 'unhead/stream/vite';
6
+
7
+ function Unhead(options = {}) {
8
+ const plugins = [...Unhead$1({ ...options, _framework: "@unhead/react" })];
9
+ if (options.streaming) {
10
+ const streamingOpts = typeof options.streaming === "object" ? options.streaming : void 0;
11
+ plugins.push(unheadReactPlugin(streamingOpts));
12
+ }
13
+ return plugins;
14
+ }
15
+
16
+ export { Unhead };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@unhead/react",
3
3
  "type": "module",
4
- "version": "3.0.0-beta.9",
4
+ "version": "3.0.0-rc.4",
5
5
  "description": "Full-stack <head> manager built for React.",
6
6
  "author": "Harlan Wilton <harlan@harlanzw.com>",
7
7
  "license": "MIT",
@@ -45,9 +45,17 @@
45
45
  "types": "./dist/plugins.d.ts",
46
46
  "default": "./dist/plugins.mjs"
47
47
  },
48
+ "./vite": {
49
+ "types": "./dist/vite.d.ts",
50
+ "default": "./dist/vite.mjs"
51
+ },
48
52
  "./stream/vite": {
49
53
  "types": "./dist/stream/vite.d.ts",
50
54
  "default": "./dist/stream/vite.mjs"
55
+ },
56
+ "./helmet": {
57
+ "types": "./dist/helmet.d.ts",
58
+ "default": "./dist/helmet.mjs"
51
59
  }
52
60
  },
53
61
  "main": "dist/index.mjs",
@@ -73,8 +81,14 @@
73
81
  "utils": [
74
82
  "dist/utils"
75
83
  ],
84
+ "vite": [
85
+ "dist/vite"
86
+ ],
76
87
  "stream/vite": [
77
88
  "dist/stream/vite"
89
+ ],
90
+ "helmet": [
91
+ "dist/helmet"
78
92
  ]
79
93
  }
80
94
  },
@@ -83,8 +97,8 @@
83
97
  "dist"
84
98
  ],
85
99
  "peerDependencies": {
86
- "react": ">=18.3.1",
87
- "vite": ">=6"
100
+ "react": ">=19.2.4",
101
+ "vite": ">=6.4.2"
88
102
  },
89
103
  "peerDependenciesMeta": {
90
104
  "vite": {
@@ -98,17 +112,18 @@
98
112
  },
99
113
  "dependencies": {
100
114
  "magic-string": "^0.30.21",
101
- "oxc-parser": "^0.106.0",
115
+ "oxc-parser": "^0.124.0",
102
116
  "oxc-walker": "^0.7.0",
103
- "unhead": "3.0.0-beta.9"
117
+ "@unhead/bundler": "3.0.0-rc.4",
118
+ "unhead": "3.0.0-rc.4"
104
119
  },
105
120
  "devDependencies": {
106
- "@testing-library/react": "^16.3.1",
107
- "@types/react": "^19.2.8",
121
+ "@testing-library/react": "^16.3.2",
122
+ "@types/react": "^19.2.14",
108
123
  "@types/react-dom": "^19.2.3",
109
- "react": "^19.2.3",
110
- "react-dom": "^19.2.3",
111
- "vite": "^7.2.2"
124
+ "react": "^19.2.5",
125
+ "react-dom": "^19.2.5",
126
+ "vite": "^8.0.8"
112
127
  },
113
128
  "scripts": {
114
129
  "build": "unbuild",