vike-react 0.5.0 → 0.5.2-commit-c9911b5

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/+config.d.ts CHANGED
@@ -16,6 +16,7 @@ declare const _default: {
16
16
  env: {
17
17
  server: true;
18
18
  };
19
+ cumulative: true;
19
20
  };
20
21
  Layout: {
21
22
  env: {
@@ -91,11 +92,13 @@ declare const _default: {
91
92
  env: {
92
93
  client: true;
93
94
  };
95
+ cumulative: true;
94
96
  };
95
97
  onAfterRenderClient: {
96
98
  env: {
97
99
  client: true;
98
100
  };
101
+ cumulative: true;
99
102
  };
100
103
  Wrapper: {
101
104
  cumulative: true;
@@ -104,16 +107,6 @@ declare const _default: {
104
107
  server: true;
105
108
  };
106
109
  };
107
- name: {
108
- env: {
109
- config: true;
110
- };
111
- };
112
- require: {
113
- env: {
114
- config: true;
115
- };
116
- };
117
110
  reactStrictMode: {
118
111
  env: {
119
112
  client: true;
package/dist/+config.js CHANGED
@@ -23,7 +23,8 @@ export default {
23
23
  // https://vike.dev/meta
24
24
  meta: {
25
25
  Head: {
26
- env: { server: true }
26
+ env: { server: true },
27
+ cumulative: true
27
28
  },
28
29
  Layout: {
29
30
  env: { server: true, client: true },
@@ -69,23 +70,17 @@ export default {
69
70
  env: { server: true }
70
71
  },
71
72
  onBeforeRenderClient: {
72
- env: { client: true }
73
+ env: { client: true },
74
+ cumulative: true
73
75
  },
74
76
  onAfterRenderClient: {
75
- env: { client: true }
77
+ env: { client: true },
78
+ cumulative: true
76
79
  },
77
80
  Wrapper: {
78
81
  cumulative: true,
79
82
  env: { client: true, server: true }
80
83
  },
81
- // Vike already defines the setting 'name', but we redundantly define it here for older Vike versions (otherwise older Vike versions will complain that 'name` is an unknown config). TODO/eventually: remove this once <=0.4.172 versions become rare (also because we use the `require` setting starting from `0.4.173`).
82
- name: {
83
- env: { config: true }
84
- },
85
- // Vike already defines the setting 'require', but we redundantly define it here for older Vike versions (otherwise older Vike versions will complain that 'require` is an unknown config). TODO/eventually: remove this once <=0.4.172 versions become rare (also because we use the `require` setting starting from `0.4.173`).
86
- require: {
87
- env: { config: true }
88
- },
89
84
  reactStrictMode: {
90
85
  env: { client: true, server: true }
91
86
  },
@@ -1,11 +1 @@
1
- export { Head };
2
- /**
3
- * Add arbitrary `<head>` tags.
4
- *
5
- * (The children are teleported to `<head>`.)
6
- *
7
- * https://vike.dev/Head
8
- */
9
- declare function Head({ children }: {
10
- children: React.ReactNode;
11
- }): null;
1
+ export declare function Head(): null;
@@ -1,15 +1,4 @@
1
- export { Head };
2
- // Same as ./Head-server.ts but importing useConfig-client.js
3
- import { useConfig } from '../../hooks/useConfig/useConfig-client.js';
4
- /**
5
- * Add arbitrary `<head>` tags.
6
- *
7
- * (The children are teleported to `<head>`.)
8
- *
9
- * https://vike.dev/Head
10
- */
11
- function Head({ children }) {
12
- const config = useConfig();
13
- config({ Head: children });
1
+ // https://vike.dev/Head#only-html
2
+ export function Head() {
14
3
  return null;
15
4
  }
@@ -1,5 +1,4 @@
1
1
  export { Head };
2
- // Same as ./Head-client.ts but importing useConfig-server.js
3
2
  import { useConfig } from '../../hooks/useConfig/useConfig-server.js';
4
3
  /**
5
4
  * Add arbitrary `<head>` tags.
@@ -1,8 +1,3 @@
1
1
  export { useConfig };
2
- import type { ConfigSetter } from './shared.js';
3
- /**
4
- * Set configurations inside React components and Vike hooks.
5
- *
6
- * https://vike.dev/useConfig
7
- */
8
- declare function useConfig(): ConfigSetter;
2
+ import type { ConfigFromHook } from '../../types/Config.js';
3
+ declare function useConfig(): (config: ConfigFromHook) => void;
@@ -1,41 +1,28 @@
1
1
  export { useConfig };
2
2
  import { usePageContext } from '../usePageContext.js';
3
3
  import { getPageContext } from 'vike/getPageContext';
4
- /**
5
- * Set configurations inside React components and Vike hooks.
6
- *
7
- * https://vike.dev/useConfig
8
- */
9
4
  function useConfig() {
10
- const configSetter = (config) => setConfigOverPageContext(config, pageContext);
11
5
  // Vike hook
12
6
  let pageContext = getPageContext();
13
7
  if (pageContext)
14
- return configSetter;
15
- // React component
8
+ return (config) => setPageContextConfigFromHook(config, pageContext);
9
+ // Component
16
10
  pageContext = usePageContext();
17
11
  return (config) => {
18
12
  if (!('_headAlreadySet' in pageContext)) {
19
- configSetter(config);
13
+ setPageContextConfigFromHook(config, pageContext);
20
14
  }
21
15
  else {
22
- sideEffect(config);
16
+ apply(config);
23
17
  }
24
18
  };
25
19
  }
26
- const configsClientSide = ['title'];
27
- function setConfigOverPageContext(config, pageContext) {
20
+ function setPageContextConfigFromHook(config, pageContext) {
28
21
  pageContext._configFromHook ?? (pageContext._configFromHook = {});
29
- configsClientSide.forEach((configName) => {
30
- const configValue = config[configName];
31
- if (!configValue)
32
- return;
33
- pageContext._configFromHook[configName] = configValue;
34
- });
22
+ Object.assign(pageContext._configFromHook, config);
35
23
  }
36
- function sideEffect(config) {
24
+ function apply(config) {
37
25
  const { title } = config;
38
- if (title) {
26
+ if (title)
39
27
  window.document.title = title;
40
- }
41
28
  }
@@ -1,8 +1,10 @@
1
1
  export { useConfig };
2
- import type { ConfigSetter } from './shared.js';
2
+ export type ConfigFromHookCumulative = (typeof configsCumulative)[number];
3
+ import type { ConfigFromHook } from '../../types/Config.js';
3
4
  /**
4
- * Set configurations inside React components and Vike hooks.
5
+ * Set configurations inside components and Vike hooks.
5
6
  *
6
7
  * https://vike.dev/useConfig
7
8
  */
8
- declare function useConfig(): ConfigSetter;
9
+ declare function useConfig(): (config: ConfigFromHook) => void;
10
+ declare const configsCumulative: readonly ["Head", "bodyAttributes", "htmlAttributes"];
@@ -2,58 +2,58 @@ export { useConfig };
2
2
  import { usePageContext } from '../usePageContext.js';
3
3
  import { getPageContext } from 'vike/getPageContext';
4
4
  import { useStream } from 'react-streaming';
5
+ import { objectKeys } from '../../utils/objectKeys.js';
6
+ import { includes } from '../../utils/includes.js';
5
7
  /**
6
- * Set configurations inside React components and Vike hooks.
8
+ * Set configurations inside components and Vike hooks.
7
9
  *
8
10
  * https://vike.dev/useConfig
9
11
  */
10
12
  function useConfig() {
11
- const configSetter = (config) => setConfigOverPageContext(config, pageContext);
12
13
  // Vike hook
13
14
  let pageContext = getPageContext();
14
15
  if (pageContext)
15
- return configSetter;
16
- // React component
16
+ return (config) => setPageContextConfigFromHook(config, pageContext);
17
+ // Component
17
18
  pageContext = usePageContext();
18
19
  const stream = useStream();
19
20
  return (config) => {
20
21
  if (!pageContext._headAlreadySet) {
21
- configSetter(config);
22
+ setPageContextConfigFromHook(config, pageContext);
22
23
  }
23
24
  else {
24
25
  // <head> already sent to the browser => send DOM-manipulating scripts during HTML streaming
25
- sideEffect(config, stream);
26
+ apply(config, stream);
26
27
  }
27
28
  };
28
29
  }
29
- const configsHtmlOnly = ['Head', 'description', 'image'];
30
- const configsCumulative = ['Head'];
31
- const configsOverridable = ['title', 'description', 'image'];
32
- function setConfigOverPageContext(config, pageContext) {
30
+ const configsClientSide = ['title'];
31
+ const configsCumulative = ['Head', 'bodyAttributes', 'htmlAttributes'];
32
+ function setPageContextConfigFromHook(config, pageContext) {
33
33
  pageContext._configFromHook ?? (pageContext._configFromHook = {});
34
- if (pageContext.isClientSideNavigation) {
35
- // Remove HTML only configs which the client-side doesn't need (also avoiding serialization errors)
36
- for (const configName of configsHtmlOnly)
37
- delete config[configName];
38
- }
39
- // Cumulative values
40
- configsCumulative.forEach((configName) => {
34
+ objectKeys(config).forEach((configName) => {
41
35
  var _a;
42
- const configValue = config[configName];
43
- if (!configValue)
44
- return;
45
- (_a = pageContext._configFromHook)[configName] ?? (_a[configName] = []);
46
- pageContext._configFromHook[configName].push(configValue);
47
- });
48
- // Overridable values
49
- configsOverridable.forEach((configName) => {
50
- const configValue = config[configName];
51
- if (!configValue)
36
+ // Skip HTML only configs which the client-side doesn't need, saving KBs sent to the client as well as avoiding serialization errors.
37
+ if (pageContext.isClientSideNavigation && !configsClientSide.includes(configName))
52
38
  return;
53
- pageContext._configFromHook[configName] = configValue;
39
+ if (!includes(configsCumulative, configName)) {
40
+ // Overridable config
41
+ const configValue = config[configName];
42
+ if (configValue === undefined)
43
+ return;
44
+ pageContext._configFromHook[configName] = configValue;
45
+ }
46
+ else {
47
+ // Cumulative config
48
+ const configValue = config[configName];
49
+ if (!configValue)
50
+ return;
51
+ (_a = pageContext._configFromHook)[configName] ?? (_a[configName] = []);
52
+ pageContext._configFromHook[configName].push(configValue);
53
+ }
54
54
  });
55
55
  }
56
- function sideEffect(config, stream) {
56
+ function apply(config, stream) {
57
57
  const { title } = config;
58
58
  if (title) {
59
59
  const htmlSnippet = `<script>document.title = ${JSON.stringify(title)}</script>`;
@@ -1,4 +1,6 @@
1
1
  export { getHeadSetting };
2
+ import type { PageContext } from 'vike/types';
2
3
  import type { PageContextInternal } from '../types/PageContext.js';
3
- type HeadSetting = 'favicon' | 'lang' | 'title' | 'description' | 'image';
4
- declare function getHeadSetting(headSetting: HeadSetting, pageContext: PageContextInternal): undefined | null | string;
4
+ import type { ConfigFromHookResolved } from '../types/Config.js';
5
+ type HeadSetting = Exclude<keyof ConfigFromHookResolved, 'Head'>;
6
+ declare function getHeadSetting<T>(headSetting: HeadSetting, pageContext: PageContext & PageContextInternal): undefined | T;
@@ -1,27 +1,16 @@
1
1
  export { getHeadSetting };
2
2
  import { isCallable } from '../utils/isCallable.js';
3
3
  function getHeadSetting(headSetting, pageContext) {
4
+ // Set by useConfig()
4
5
  {
5
6
  const val = pageContext._configFromHook?.[headSetting];
6
7
  if (val !== undefined)
7
8
  return val;
8
9
  }
9
- const config = pageContext.configEntries[headSetting]?.[0];
10
- if (!config)
11
- return undefined;
12
- const val = config.configValue;
13
- if (typeof val === 'string')
14
- return val;
15
- if (!val)
16
- return null;
17
- if (isCallable(val)) {
18
- const valStr = val(pageContext);
19
- if (typeof valStr !== 'string') {
20
- throw new Error(config.configDefinedAt + ' should return a string');
21
- }
22
- return valStr;
23
- }
24
- else {
25
- throw new Error(config.configDefinedAt + ' should be a string or a function returning a string');
26
- }
10
+ // Set by +configName.js
11
+ const getCallable = (val) => (isCallable(val) ? val() : val);
12
+ const val = pageContext.config[headSetting];
13
+ if (Array.isArray(val))
14
+ return val.map(getCallable); // cumulative configs
15
+ return getCallable(val);
27
16
  }
@@ -1,4 +1,4 @@
1
1
  export { onRenderClient };
2
- import type { OnRenderClientSync } from 'vike/types';
2
+ import type { OnRenderClientAsync } from 'vike/types';
3
3
  import './styles.css';
4
- declare const onRenderClient: OnRenderClientSync;
4
+ declare const onRenderClient: OnRenderClientAsync;
@@ -4,11 +4,12 @@ import ReactDOM from 'react-dom/client';
4
4
  import { getHeadSetting } from './getHeadSetting.js';
5
5
  import { getPageElement } from './getPageElement.js';
6
6
  import './styles.css';
7
+ import { callCumulativeHooks } from '../utils/callCumulativeHooks.js';
7
8
  let root;
8
- const onRenderClient = (pageContext) => {
9
+ const onRenderClient = async (pageContext) => {
9
10
  // Use case:
10
11
  // - Store hydration https://github.com/vikejs/vike-react/issues/110
11
- pageContext.config.onBeforeRenderClient?.(pageContext);
12
+ await callCumulativeHooks(pageContext.config.onBeforeRenderClient, pageContext);
12
13
  const page = getPageElement(pageContext);
13
14
  pageContext.page = page;
14
15
  // TODO: implement this? So that, upon errors, onRenderClient() throws an error and Vike can render the error. As of April 2024 it isn't released yet.
@@ -41,18 +42,18 @@ const onRenderClient = (pageContext) => {
41
42
  updateDocument(pageContext);
42
43
  }
43
44
  // Use cases:
44
- // - Custom user settings: https://vike.dev/head#custom-settings
45
+ // - Custom user settings: https://vike.dev/head-tags#custom-settings
45
46
  // - Testing tools: https://github.com/vikejs/vike-react/issues/95
46
- pageContext.config.onAfterRenderClient?.(pageContext);
47
+ await callCumulativeHooks(pageContext.config.onAfterRenderClient, pageContext);
47
48
  };
48
49
  function updateDocument(pageContext) {
49
- ;
50
50
  pageContext._headAlreadySet = true;
51
51
  const title = getHeadSetting('title', pageContext);
52
52
  const lang = getHeadSetting('lang', pageContext);
53
53
  // - We skip if `undefined` as we shouldn't remove values set by the Head setting.
54
54
  // - Setting a default prevents the previous value to be leaked: upon client-side navigation, the value set by the previous page won't be removed if the next page doesn't override it.
55
55
  // - Most of the time, the user sets a default himself (i.e. a value defined at /pages/+config.js)
56
+ // - If he doesn't have a default then he can use `null` to opt into Vike's defaults
56
57
  if (title !== undefined)
57
58
  document.title = title || '';
58
59
  if (lang !== undefined)
@@ -3,18 +3,19 @@ export { onRenderHtml };
3
3
  import React from 'react';
4
4
  import { renderToString, renderToStaticMarkup } from 'react-dom/server';
5
5
  import { renderToStream } from 'react-streaming/server';
6
- import { dangerouslySkipEscape, escapeInject, version } from 'vike/server';
6
+ import { dangerouslySkipEscape, escapeInject } from 'vike/server';
7
7
  import { PageContextProvider } from '../hooks/usePageContext.js';
8
8
  import { getHeadSetting } from './getHeadSetting.js';
9
9
  import { getPageElement } from './getPageElement.js';
10
10
  import { isReactElement } from '../utils/isReactElement.js';
11
11
  import { getTagAttributesString } from '../utils/getTagAttributesString.js';
12
- checkVikeVersion();
13
12
  addEcosystemStamp();
14
13
  const onRenderHtml = async (pageContext) => {
15
14
  const pageHtml = await getPageHtml(pageContext);
16
15
  const headHtml = getHeadHtml(pageContext);
17
16
  const { htmlAttributesString, bodyAttributesString } = getTagAttributes(pageContext);
17
+ // Not needed on the client-side, thus we remove it to save KBs sent to the client
18
+ delete pageContext._configFromHook;
18
19
  return escapeInject `<!DOCTYPE html>
19
20
  <html${dangerouslySkipEscape(htmlAttributesString)}>
20
21
  <head>
@@ -65,24 +66,22 @@ function getHeadHtml(pageContext) {
65
66
  const imageTags = !image
66
67
  ? ''
67
68
  : escapeInject `<meta property="og:image" content="${image}"><meta name="twitter:card" content="summary_large_image">`;
69
+ const viewportTag = dangerouslySkipEscape(getViewportTag(getHeadSetting('viewport', pageContext)));
68
70
  const headElementsHtml = dangerouslySkipEscape([
69
- // <Head> set by +Head
70
- pageContext.config.Head,
71
- // <Head> set by useConfig()
71
+ // Added by +Head
72
+ ...(pageContext.config.Head ?? []),
73
+ // Added by useConfig()
72
74
  ...(pageContext._configFromHook?.Head ?? [])
73
75
  ]
74
76
  .filter((Head) => Head !== null && Head !== undefined)
75
77
  .map((Head) => getHeadElementHtml(Head, pageContext))
76
78
  .join('\n'));
77
- // Not needed on the client-side, thus we remove it to save KBs sent to the client
78
- delete pageContext._configFromHook;
79
- const viewportTag = dangerouslySkipEscape(getViewportTag(pageContext.config.viewport));
80
79
  const headHtml = escapeInject `
81
80
  ${titleTags}
82
- ${headElementsHtml}
83
81
  ${viewportTag}
84
- ${descriptionTags}
82
+ ${headElementsHtml}
85
83
  ${faviconTag}
84
+ ${descriptionTags}
86
85
  ${imageTags}
87
86
  `;
88
87
  return headHtml;
@@ -106,8 +105,8 @@ function getTagAttributes(pageContext) {
106
105
  // Don't set `lang` to its default value if it's `null` (so that users can set it to `null` in order to remove the default value)
107
106
  if (lang === undefined)
108
107
  lang = 'en';
109
- const bodyAttributes = mergeTagAttributesList(pageContext.config.bodyAttributes);
110
- const htmlAttributes = mergeTagAttributesList(pageContext.config.htmlAttributes);
108
+ const bodyAttributes = mergeTagAttributesList(getHeadSetting('bodyAttributes', pageContext));
109
+ const htmlAttributes = mergeTagAttributesList(getHeadSetting('htmlAttributes', pageContext));
111
110
  const bodyAttributesString = getTagAttributesString(bodyAttributes);
112
111
  const htmlAttributesString = getTagAttributesString({ ...htmlAttributes, lang: lang ?? htmlAttributes.lang });
113
112
  return { htmlAttributesString, bodyAttributesString };
@@ -128,21 +127,6 @@ function getViewportTag(viewport) {
128
127
  }
129
128
  return '';
130
129
  }
131
- // We don't need this anymore starting from vike@0.4.173 which added the `require` setting.
132
- // TODO/eventually: remove this once <=0.4.172 versions become rare.
133
- function checkVikeVersion() {
134
- if (version) {
135
- const versionParts = version.split('.').map((s) => parseInt(s, 10));
136
- if (versionParts[0] > 0)
137
- return;
138
- if (versionParts[1] > 4)
139
- return;
140
- if (versionParts[2] >= 173)
141
- return;
142
- }
143
- // We can leave it 0.4.173 until we entirely remove checkVikeVersion() (because starting vike@0.4.173 we use the new `require` setting).
144
- throw new Error('Update Vike to 0.4.173 or above');
145
- }
146
130
  // For improving error messages of:
147
131
  // - react-streaming https://github.com/brillout/react-streaming/blob/6a43dd20c27fb5d751dca41466b06ee3f4f35462/src/server/useStream.ts#L21
148
132
  // - vike https://github.com/vikejs/vike/blob/96c0155380ffebd4976ab076b58e86d8eb2d603a/vike/node/runtime/html/stream/react-streaming.ts#L31
@@ -1,10 +1,15 @@
1
- import type { ImportString, PageContextClient, PageContext } from 'vike/types';
1
+ import type { ImportString, PageContextClient, PageContext as PageContext_, PageContextServer } from 'vike/types';
2
2
  import type { TagAttributes } from '../utils/getTagAttributesString.js';
3
3
  import type { Viewport } from '../renderer/onRenderHtml.js';
4
+ import type { ConfigFromHookCumulative } from '../hooks/useConfig/useConfig-server.js';
4
5
  declare global {
5
6
  namespace Vike {
6
7
  interface Config {
7
- /** The page's root React component */
8
+ /**
9
+ * The page's root React component.
10
+ *
11
+ * https://vike.dev/Page
12
+ */
8
13
  Page?: () => React.ReactNode;
9
14
  /**
10
15
  * Add arbitrary `<head>` tags.
@@ -13,7 +18,7 @@ declare global {
13
18
  */
14
19
  Head?: Head;
15
20
  /**
16
- * A component that defines the visual layout of the page common to several pages.
21
+ * A component that defines the visual layout common to several pages.
17
22
  *
18
23
  * Technically: the `<Layout>` component wraps the root component `<Page>`.
19
24
  *
@@ -39,7 +44,7 @@ declare global {
39
44
  *
40
45
  * https://vike.dev/title
41
46
  */
42
- title?: PlainOrGetter<string>;
47
+ title?: string | null | ((pageContext: PageContext_) => string | null | undefined);
43
48
  /**
44
49
  * Set the page's description.
45
50
  *
@@ -53,7 +58,7 @@ declare global {
53
58
  *
54
59
  * https://vike.dev/description
55
60
  */
56
- description?: PlainOrGetter<string>;
61
+ description?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
57
62
  /**
58
63
  * Set the page's preview image upon URL sharing.
59
64
  *
@@ -67,15 +72,15 @@ declare global {
67
72
  *
68
73
  * https://vike.dev/image
69
74
  */
70
- image?: PlainOrGetter<string>;
75
+ image?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
71
76
  /**
72
77
  * Set the page's width shown to the user on mobile/tablet devices.
73
78
  *
74
- * https://vike.dev/viewport
75
- *
76
79
  * @default "responsive"
80
+ *
81
+ * https://vike.dev/viewport
77
82
  */
78
- viewport?: Viewport;
83
+ viewport?: Viewport | ((pageContext: PageContextServer) => Viewport | undefined);
79
84
  /**
80
85
  * Set the page's favicon.
81
86
  *
@@ -88,7 +93,7 @@ declare global {
88
93
  *
89
94
  * https://vike.dev/favicon
90
95
  */
91
- favicon?: PlainOrGetter<string>;
96
+ favicon?: string | null | ((pageContext: PageContextServer) => string | null | undefined);
92
97
  /**
93
98
  * Set the page's language (`<html lang>`).
94
99
  *
@@ -96,28 +101,27 @@ declare global {
96
101
  *
97
102
  * https://vike.dev/lang
98
103
  */
99
- lang?: PlainOrGetter<string> | null;
104
+ lang?: string | null | ((pageContext: PageContext_) => string | null | undefined);
100
105
  /**
101
106
  * Add tag attributes such as `<html class="dark">`.
102
107
  *
103
108
  * https://vike.dev/htmlAttributes
104
109
  */
105
- htmlAttributes?: TagAttributes;
110
+ htmlAttributes?: TagAttributes | ((pageContext: PageContextServer) => TagAttributes | undefined);
106
111
  /**
107
112
  * Add tag attributes such as `<body class="dark">`.
108
113
  *
109
114
  * https://vike.dev/bodyAttributes
110
115
  */
111
- bodyAttributes?: TagAttributes;
116
+ bodyAttributes?: TagAttributes | ((pageContext: PageContextServer) => TagAttributes | undefined);
112
117
  /**
113
118
  * If `true`, the page is rendered twice: on the server-side (to HTML) and on the client-side (hydration).
114
119
  *
115
120
  * If `false`, the page is rendered only once in the browser.
116
121
  *
117
- * https://vike.dev/ssr
118
- *
119
122
  * @default true
120
123
  *
124
+ * https://vike.dev/ssr
121
125
  */
122
126
  ssr?: boolean;
123
127
  /**
@@ -132,7 +136,6 @@ declare global {
132
136
  * @default false
133
137
  *
134
138
  * https://vike.dev/stream
135
- *
136
139
  */
137
140
  stream?: boolean | 'node' | 'web';
138
141
  /**
@@ -144,9 +147,9 @@ declare global {
144
147
  /**
145
148
  * Whether to use `<StrictMode>`.
146
149
  *
147
- * https://vike.dev/reactStrictMode
148
- *
149
150
  * @default true
151
+ *
152
+ * https://vike.dev/reactStrictMode
150
153
  */
151
154
  reactStrictMode?: boolean;
152
155
  /**
@@ -161,17 +164,24 @@ declare global {
161
164
  * https://vike.dev/onAfterRenderClient
162
165
  */
163
166
  onAfterRenderClient?: (pageContext: PageContextClient) => void;
167
+ /**
168
+ * Define loading animations.
169
+ *
170
+ * https://vike.dev/Loading
171
+ */
164
172
  Loading?: Loading | ImportString;
165
173
  }
166
174
  interface ConfigResolved {
167
175
  Wrapper?: Wrapper[];
168
176
  Layout?: Layout[];
177
+ Head?: Head[];
169
178
  bodyAttributes?: TagAttributes[];
170
179
  htmlAttributes?: TagAttributes[];
180
+ onBeforeRenderClient?: Function[];
181
+ onAfterRenderClient?: Function[];
171
182
  }
172
183
  }
173
184
  }
174
- type PlainOrGetter<T> = T | ((pageContext: PageContext) => T);
175
185
  export type Head = React.ReactNode | (() => React.ReactNode);
176
186
  type Wrapper = (props: {
177
187
  children: React.ReactNode;
@@ -184,11 +194,6 @@ type Loading = {
184
194
  type PickWithoutGetter<T, K extends keyof T> = {
185
195
  [P in K]: Exclude<T[P], Function>;
186
196
  };
187
- export type ConfigFromHook = PickWithoutGetter<Vike.Config, 'Head' | 'title' | 'description' | 'image'>;
188
- export type ConfigFromHookResolved = {
189
- Head?: Head[];
190
- title?: string;
191
- description?: string;
192
- image?: string;
193
- };
197
+ export type ConfigFromHook = PickWithoutGetter<Vike.Config, 'Head' | 'title' | 'description' | 'image' | 'favicon' | 'lang' | 'viewport' | 'bodyAttributes' | 'htmlAttributes'>;
198
+ export type ConfigFromHookResolved = Omit<ConfigFromHook, ConfigFromHookCumulative> & Pick<Vike.ConfigResolved, ConfigFromHookCumulative>;
194
199
  export {};
@@ -2,7 +2,6 @@ import type React from 'react';
2
2
  import type { JSX } from 'react';
3
3
  import type ReactDOM from 'react-dom/client';
4
4
  import type { ConfigFromHookResolved } from './Config.js';
5
- import type { PageContext } from 'vike/types';
6
5
  declare global {
7
6
  namespace Vike {
8
7
  interface PageContext {
@@ -15,7 +14,7 @@ declare global {
15
14
  }
16
15
  }
17
16
  }
18
- export type PageContextInternal = PageContext & {
17
+ export type PageContextInternal = {
19
18
  _configFromHook?: ConfigFromHookResolved;
20
19
  _headAlreadySet?: true;
21
20
  };
@@ -0,0 +1 @@
1
+ export declare function callCumulativeHooks(values: undefined | unknown[], pageContext: unknown): Promise<unknown[]>;
@@ -0,0 +1,16 @@
1
+ export async function callCumulativeHooks(values, pageContext) {
2
+ if (!values)
3
+ return [];
4
+ const valuesPromises = values.map((val) => {
5
+ if (typeof val === 'function') {
6
+ // Hook
7
+ return val(pageContext);
8
+ }
9
+ else {
10
+ // Plain value
11
+ return val;
12
+ }
13
+ });
14
+ const valuesResolved = await Promise.all(valuesPromises);
15
+ return valuesResolved;
16
+ }
@@ -0,0 +1,2 @@
1
+ /** Same as Array.prototype.includes() but with type inference */
2
+ export declare function includes<T>(values: readonly T[], x: unknown): x is T;
@@ -0,0 +1,10 @@
1
+ // https://stackoverflow.com/questions/56565528/typescript-const-assertions-how-to-use-array-prototype-includes/74213179#74213179
2
+ /** Same as Array.prototype.includes() but with type inference */
3
+ export function includes(values, x) {
4
+ return values.includes(x);
5
+ }
6
+ /*
7
+ export function includes<Arr extends any[] | readonly any[]>(arr: Arr, el: unknown): el is Arr[number] {
8
+ return arr.includes(el as any)
9
+ }
10
+ */
@@ -0,0 +1,2 @@
1
+ /** Same as Object.keys() but with type inference */
2
+ export declare function objectKeys<T extends object>(obj: T): (keyof T)[];
@@ -0,0 +1,6 @@
1
+ // https://stackoverflow.com/questions/52856496/typescript-object-keys-return-string
2
+ // https://github.com/sindresorhus/ts-extras/blob/main/source/object-keys.ts
3
+ /** Same as Object.keys() but with type inference */
4
+ export function objectKeys(obj) {
5
+ return Object.keys(obj);
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vike-react",
3
- "version": "0.5.0",
3
+ "version": "0.5.2-commit-c9911b5",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -11,15 +11,15 @@
11
11
  "browser": "./dist/hooks/useConfig/useConfig-client.js",
12
12
  "default": "./dist/hooks/useConfig/useConfig-server.js"
13
13
  },
14
- "./ClientOnly": "./dist/components/ClientOnly.js",
15
- "./Head": {
16
- "browser": "./dist/components/Head/Head-client.js",
17
- "default": "./dist/components/Head/Head-server.js"
18
- },
19
14
  "./Config": {
20
15
  "browser": "./dist/components/Config/Config-client.js",
21
16
  "default": "./dist/components/Config/Config-server.js"
22
17
  },
18
+ "./Head": {
19
+ "browser": "./dist/components/Head/Head-client.js",
20
+ "default": "./dist/components/Head/Head-server.js"
21
+ },
22
+ "./ClientOnly": "./dist/components/ClientOnly.js",
23
23
  "./clientOnly": "./dist/helpers/clientOnly.js",
24
24
  ".": "./dist/index.js",
25
25
  "./config": "./dist/+config.js",
@@ -38,8 +38,7 @@
38
38
  "peerDependencies": {
39
39
  "react": ">=18.0.0",
40
40
  "react-dom": ">=18.0.0",
41
- "vike": ">=0.4.182",
42
- "vite": ">=4.3.8"
41
+ "vike": ">=0.4.182"
43
42
  },
44
43
  "devDependencies": {
45
44
  "@biomejs/biome": "^1.6.4",
@@ -47,11 +46,13 @@
47
46
  "@types/node": "^20.11.17",
48
47
  "@types/react": "^18.2.55",
49
48
  "@types/react-dom": "^18.2.19",
50
- "react": "^18.2.0",
51
- "react-dom": "^18.2.0",
49
+ "react": "^18.3.1",
50
+ "react-dom": "^18.3.1",
51
+ "react-streaming": "^0.3.43",
52
52
  "rimraf": "^5.0.5",
53
- "typescript": "^5.5.3",
54
- "vike": "^0.4.182"
53
+ "typescript": "^5.5.4",
54
+ "vike": "^0.4.183",
55
+ "vite": "^5.4.0"
55
56
  },
56
57
  "dependencies": {
57
58
  "react-streaming": "^0.3.42"
@@ -67,12 +68,12 @@
67
68
  "useConfig": [
68
69
  "./dist/hooks/useConfig/useConfig-server.d.ts"
69
70
  ],
70
- "Head": [
71
- "./dist/components/Head/Head-server.d.ts"
72
- ],
73
71
  "Config": [
74
72
  "./dist/components/Config/Config-server.d.ts"
75
73
  ],
74
+ "Head": [
75
+ "./dist/components/Head/Head-server.d.ts"
76
+ ],
76
77
  "ClientOnly": [
77
78
  "./dist/components/ClientOnly.d.ts"
78
79
  ],
@@ -1,3 +0,0 @@
1
- export type { ConfigSetter };
2
- import type { ConfigFromHook } from '../../types/Config.js';
3
- type ConfigSetter = (config: ConfigFromHook) => void;
@@ -1 +0,0 @@
1
- export {};