@koine/next 2.0.0-beta.72 → 2.0.0-beta.73

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.
@@ -0,0 +1,37 @@
1
+ "use client";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useRouter } from "next/router";
4
+ import Script from "next/script";
5
+ import { useEffect, useState } from "react";
6
+ import { gtagPageview } from "@koine/browser";
7
+ export let AnalyticsGoogle = ({ id }) => {
8
+ const uid = id || process.env["NEXT_PUBLIC_GTM_ID"];
9
+ const { events, asPath, query } = useRouter();
10
+ const [ready, setReady] = useState(false);
11
+ const [routed, setRouted] = useState(false);
12
+ useEffect(() => {
13
+ const handleRouteChange = () => {
14
+ setRouted(true);
15
+ };
16
+ events.on("routeChangeComplete", handleRouteChange);
17
+ return () => {
18
+ events.off("routeChangeComplete", handleRouteChange);
19
+ };
20
+ }, [events]);
21
+ useEffect(() => {
22
+ if (routed && ready && asPath) {
23
+ gtagPageview(asPath);
24
+ }
25
+ }, [asPath, query, routed, ready]);
26
+ if (!uid) {
27
+ return null;
28
+ }
29
+ return (_jsxs(_Fragment, { children: [_jsx(Script, { id: "google-tagmanager", src: `https://www.googletagmanager.com/gtag/js?id=${id}`, strategy: "afterInteractive", onLoad: () => setReady(true) }), _jsx(Script, { id: "google-analytics", strategy: "afterInteractive", children: `
30
+ window.dataLayer = window.dataLayer || [];
31
+ function gtag(){window.dataLayer.push(arguments);}
32
+ gtag('js', new Date());
33
+
34
+ gtag('config', '${id}', { 'send_page_view': false });
35
+ ` })] }));
36
+ };
37
+ export default AnalyticsGoogle;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Head from "next/head";
3
+ export let DisableErrorOverlay = () => (_jsx(Head, { children: process.env["NODE_ENV"] === "development" && (_jsx("script", { dangerouslySetInnerHTML: {
4
+ __html: `window.addEventListener('error',event =>{event.stopImmediatePropagation()});window.addEventListener('unhandledrejection',event =>{event.stopImmediatePropagation()});`,
5
+ } })) }));
6
+ export default DisableErrorOverlay;
package/12/Seo.js ADDED
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Head from "next/head";
3
+ import { seoBuildTags } from "./seoBuildTags";
4
+ export let Seo = (props) => _jsx(Head, { children: seoBuildTags(props) });
5
+ export default Seo;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import Head from "next/head";
3
+ import { seoBuildTags } from "./seoBuildTags";
4
+ export let SeoDefaults = (props) => (_jsx(Head, { children: seoBuildTags(props) }));
5
+ export default SeoDefaults;
@@ -0,0 +1,94 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import React from "react";
3
+ import { isArray } from "@koine/utils";
4
+ const defaults = {
5
+ tplTitle: "",
6
+ };
7
+ export const seoBuildTags = ({ seo, hidden, keywords, title = "", titleTemplate, defaultTitle, noindex, nofollow, description, languageAlternates = [], twitter, facebook, openGraph, og: ogAlias, canonical, metaTags, linkTags, schema, } = {}) => {
8
+ const id = "seo-";
9
+ const render = [];
10
+ const $names = {};
11
+ const $properties = {};
12
+ if (titleTemplate) {
13
+ defaults.tplTitle = titleTemplate;
14
+ }
15
+ title = title || seo?.title || "";
16
+ if (title) {
17
+ if (defaults.tplTitle && defaults.tplTitle !== title) {
18
+ title = defaults.tplTitle.replace(/%s/g, title);
19
+ }
20
+ }
21
+ else if (defaultTitle) {
22
+ title = defaultTitle;
23
+ }
24
+ if (title) {
25
+ render.push(_jsx("title", { children: title }, id + "title"));
26
+ $properties["og:title"] = title;
27
+ }
28
+ $names["robots"] = `${noindex || hidden ? "noindex" : "index"},${nofollow || hidden ? "nofollow" : "follow"}`;
29
+ description = description || seo?.description;
30
+ if (description) {
31
+ $names["description"] = description;
32
+ $properties["og:description"] = description;
33
+ }
34
+ keywords = keywords || seo?.keywords;
35
+ if (keywords) {
36
+ $names["keywords"] = isArray(keywords) ? keywords.join(", ") : keywords;
37
+ }
38
+ if (languageAlternates?.length > 0) {
39
+ languageAlternates.forEach(({ href, hrefLang }) => {
40
+ render.push(_jsx("link", { rel: "alternate", hrefLang: hrefLang, href: href }, id + "languageAlternate-" + hrefLang));
41
+ });
42
+ }
43
+ if (canonical) {
44
+ render.push(_jsx("link", { rel: "canonical", href: canonical }, id + "canonical"));
45
+ $properties["og:url"] = canonical;
46
+ }
47
+ if (facebook?.appId)
48
+ $properties["fb:app_id"] = facebook.appId;
49
+ if (twitter) {
50
+ if (twitter.cardType)
51
+ $names["twitter:card"] = twitter.cardType;
52
+ if (twitter.site)
53
+ $names["twitter:site"] = twitter.site;
54
+ if (twitter.handle)
55
+ $names["twitter:creator"] = twitter.handle;
56
+ }
57
+ const og = ogAlias || openGraph;
58
+ if (og?.title)
59
+ $properties["og:title"] = og?.title;
60
+ if (og?.description)
61
+ $properties["og:description"] = og?.description;
62
+ if (og?.url)
63
+ $properties["og:url"] = og.url;
64
+ if (og?.type)
65
+ $properties["og:type"] = og.type.toLowerCase();
66
+ if (og?.locale)
67
+ $properties["og:locale"] = og.locale;
68
+ if (og?.siteName)
69
+ $properties["og:siteName"] = og.siteName;
70
+ const ogimage = og?.image || seo?.ogimage;
71
+ if (ogimage)
72
+ $properties["og:image"] = ogimage;
73
+ Object.keys($names).forEach((key) => {
74
+ render.push(_jsx("meta", { name: key, content: $names[key] }, id + "name-" + key));
75
+ });
76
+ Object.keys($properties).forEach((key) => {
77
+ render.push(_jsx("meta", { property: key, content: $properties[key] }, id + "prop-" + +key));
78
+ });
79
+ if (metaTags && metaTags.length > 0) {
80
+ metaTags.forEach((tag) => {
81
+ render.push(_jsx("meta", { ...tag }, id + "meta-" + (tag.name || tag.property || tag.httpEquiv)));
82
+ });
83
+ }
84
+ if (linkTags?.length) {
85
+ linkTags.forEach((tag) => {
86
+ render.push(_jsx("link", { ...tag }, id + "link-" + (tag.href || tag.rel)));
87
+ });
88
+ }
89
+ if (schema) {
90
+ render.push(_jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: { __html: JSON.stringify(schema) } }, id + "schema"));
91
+ }
92
+ return render;
93
+ };
94
+ export default seoBuildTags;
package/12/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/12.js ADDED
@@ -0,0 +1,3 @@
1
+ export { AnalyticsGoogle, } from "./12/AnalyticsGoogle";
2
+ export { DisableErrorOverlay } from "./12/DisableErrorOverlay";
3
+ export * from "./12/types";
package/config.js ADDED
@@ -0,0 +1,60 @@
1
+ import { withI18n, withI18nAsync, withI18nLegacy, } from "@koine/i18n/next";
2
+ export let withKoine = (options = {}) => {
3
+ const { nx, svg, i18nRoutes, i18nCompiler, ...restNextConfig } = options;
4
+ const nextConfig = {
5
+ eslint: {
6
+ ignoreDuringBuilds: true,
7
+ },
8
+ typescript: {
9
+ ignoreBuildErrors: true,
10
+ },
11
+ poweredByHeader: false,
12
+ experimental: {
13
+ scrollRestoration: true,
14
+ ...(restNextConfig.experimental || {}),
15
+ },
16
+ ...restNextConfig,
17
+ };
18
+ if (svg) {
19
+ if (nx) {
20
+ nextConfig["nx"] = { svgr: true };
21
+ }
22
+ else {
23
+ delete nextConfig["nx"];
24
+ nextConfig.webpack = (_config, options) => {
25
+ const webpackConfig = typeof nextConfig.webpack === "function"
26
+ ? nextConfig.webpack(_config, options)
27
+ : _config;
28
+ webpackConfig.module.rules.push({
29
+ test: /\.svg$/,
30
+ use: [
31
+ {
32
+ loader: "@svgr/webpack",
33
+ options: {
34
+ svgoConfig: {
35
+ plugins: [
36
+ {
37
+ name: "removeViewBox",
38
+ active: false,
39
+ },
40
+ ],
41
+ },
42
+ },
43
+ },
44
+ ],
45
+ });
46
+ return webpackConfig;
47
+ };
48
+ }
49
+ }
50
+ if (i18nRoutes) {
51
+ return withI18nLegacy({ ...nextConfig, i18nRoutes });
52
+ }
53
+ if (i18nCompiler) {
54
+ if (nx) {
55
+ return withI18nAsync({ ...nextConfig, i18nCompiler });
56
+ }
57
+ return withI18n({ ...nextConfig, i18nCompiler });
58
+ }
59
+ return nextConfig;
60
+ };
package/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export { load } from "./utils/load";
2
+ export { ThemeContext } from "./theme/ThemeContext";
3
+ export { ThemeProvider } from "./theme/ThemeProvider";
4
+ export { useTheme } from "./theme/useTheme";
package/package.json CHANGED
@@ -2,9 +2,9 @@
2
2
  "name": "@koine/next",
3
3
  "sideEffects": false,
4
4
  "dependencies": {
5
- "@koine/browser": "2.0.0-beta.72",
6
- "@koine/utils": "2.0.0-beta.72",
7
- "@koine/i18n": "2.0.0-beta.72"
5
+ "@koine/browser": "2.0.0-beta.73",
6
+ "@koine/utils": "2.0.0-beta.73",
7
+ "@koine/i18n": "2.0.0-beta.73"
8
8
  },
9
9
  "peerDependencies": {
10
10
  "next": "^14.0.4",
@@ -36,5 +36,5 @@
36
36
  },
37
37
  "module": "./index.esm.js",
38
38
  "main": "./index.cjs.js",
39
- "version": "2.0.0-beta.72"
39
+ "version": "2.0.0-beta.73"
40
40
  }
@@ -0,0 +1,6 @@
1
+ import { createContext } from "react";
2
+ export const ThemeContext = createContext({
3
+ setTheme: (_) => { },
4
+ themes: [],
5
+ });
6
+ export default ThemeContext;
@@ -0,0 +1,204 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import NextScript from "next/script";
4
+ import { memo, useCallback, useEffect, useState } from "react";
5
+ import { isServer } from "@koine/utils";
6
+ import { ThemeContext } from "./ThemeContext";
7
+ const colorSchemes = ["light", "dark"];
8
+ const MEDIA = "(prefers-color-scheme: dark)";
9
+ const THEME_STORAGE_KEY = "theme";
10
+ export const ThemeProvider = ({ forcedTheme, disableTransitionOnChange = false, enableSystem = true, enableColorScheme, themes = ["light", "dark"], defaultTheme = enableSystem ? "system" : "light", attribute = "data-theme", value, children, nonce, }) => {
11
+ const [theme, setThemeState] = useState(() => getTheme(THEME_STORAGE_KEY, defaultTheme));
12
+ const [resolvedTheme, setResolvedTheme] = useState(() => getTheme(THEME_STORAGE_KEY));
13
+ const attrs = !value ? themes : Object.values(value);
14
+ const applyTheme = useCallback((theme) => {
15
+ let resolved = theme;
16
+ if (isServer || !resolved)
17
+ return;
18
+ if (theme === "system" && enableSystem) {
19
+ resolved = getSystemTheme();
20
+ }
21
+ const name = value ? value[resolved] : resolved;
22
+ const enable = disableTransitionOnChange ? disableAnimation() : null;
23
+ const d = document.documentElement;
24
+ if (attribute === "class") {
25
+ d.classList.remove(...attrs);
26
+ if (name)
27
+ d.classList.add(name);
28
+ }
29
+ else {
30
+ if (name) {
31
+ d.setAttribute(attribute, name);
32
+ }
33
+ else {
34
+ d.removeAttribute(attribute);
35
+ }
36
+ }
37
+ if (enableColorScheme) {
38
+ const fallback = colorSchemes.includes(defaultTheme)
39
+ ? defaultTheme
40
+ : "";
41
+ const colorScheme = colorSchemes.includes(resolved)
42
+ ? resolved
43
+ : fallback;
44
+ d.style.colorScheme = colorScheme;
45
+ }
46
+ enable?.();
47
+ }, [
48
+ attribute,
49
+ attrs,
50
+ defaultTheme,
51
+ disableTransitionOnChange,
52
+ enableColorScheme,
53
+ enableSystem,
54
+ value,
55
+ ]);
56
+ const setTheme = useCallback((theme) => {
57
+ setThemeState(theme);
58
+ try {
59
+ localStorage.setItem(THEME_STORAGE_KEY, theme);
60
+ }
61
+ catch (e) {
62
+ }
63
+ }, []);
64
+ const handleMediaQuery = useCallback((e) => {
65
+ const resolved = getSystemTheme(e);
66
+ setResolvedTheme(resolved);
67
+ if (theme === "system" && enableSystem && !forcedTheme) {
68
+ applyTheme("system");
69
+ }
70
+ }, [theme, enableSystem, forcedTheme, applyTheme]);
71
+ useEffect(() => {
72
+ const media = window.matchMedia(MEDIA);
73
+ media.addListener(handleMediaQuery);
74
+ handleMediaQuery(media);
75
+ return () => media.removeListener(handleMediaQuery);
76
+ }, [handleMediaQuery]);
77
+ useEffect(() => {
78
+ const handleStorage = (e) => {
79
+ if (e.key !== THEME_STORAGE_KEY) {
80
+ return;
81
+ }
82
+ const theme = e.newValue || defaultTheme;
83
+ setTheme(theme);
84
+ };
85
+ window.addEventListener("storage", handleStorage);
86
+ return () => window.removeEventListener("storage", handleStorage);
87
+ }, [defaultTheme, setTheme]);
88
+ useEffect(() => {
89
+ applyTheme(forcedTheme ?? theme);
90
+ }, [applyTheme, forcedTheme, theme]);
91
+ return (_jsxs(ThemeContext.Provider, { value: {
92
+ theme,
93
+ setTheme,
94
+ forcedTheme,
95
+ resolvedTheme: theme === "system" ? resolvedTheme : theme,
96
+ themes: enableSystem ? [...themes, "system"] : themes,
97
+ systemTheme: (enableSystem ? resolvedTheme : undefined),
98
+ }, children: [_jsx(ThemeScript, { forcedTheme,
99
+ disableTransitionOnChange,
100
+ enableSystem,
101
+ enableColorScheme,
102
+ themes,
103
+ defaultTheme,
104
+ attribute,
105
+ value,
106
+ children,
107
+ attrs,
108
+ nonce }), children] }));
109
+ };
110
+ const ThemeScript = memo(({ forcedTheme, attribute, enableSystem, enableColorScheme, defaultTheme, value, attrs, nonce, }) => {
111
+ const defaultSystem = defaultTheme === "system";
112
+ const optimization = (() => {
113
+ const removeClasses = `d.remove(${attrs
114
+ .map((t) => `'${t}'`)
115
+ .join(",")})`;
116
+ return `var d=document.documentElement.classList;${removeClasses};`;
117
+ })();
118
+ const fallbackColorScheme = (() => {
119
+ if (!enableColorScheme) {
120
+ return "";
121
+ }
122
+ const fallback = colorSchemes.includes(defaultTheme)
123
+ ? defaultTheme
124
+ : null;
125
+ if (fallback) {
126
+ return `if(e==='light'||e==='dark'||!e)d.style.colorScheme=e||'${defaultTheme}'`;
127
+ }
128
+ else {
129
+ return `if(e==='light'||e==='dark')d.style.colorScheme=e`;
130
+ }
131
+ })();
132
+ const updateDOM = (name, literal = false, setColorScheme = true) => {
133
+ const resolvedName = value ? value[name] : name;
134
+ const val = literal ? name + `|| ''` : `'${resolvedName}'`;
135
+ let text = "";
136
+ if (enableColorScheme &&
137
+ setColorScheme &&
138
+ !literal &&
139
+ colorSchemes.includes(name)) {
140
+ text += `d.style.colorScheme = '${name}';`;
141
+ }
142
+ if (attribute === "class") {
143
+ if (literal || resolvedName) {
144
+ text += `d.add(${val})`;
145
+ }
146
+ else {
147
+ text += `null`;
148
+ }
149
+ }
150
+ else {
151
+ if (resolvedName) {
152
+ text += `d[s](n, ${val})`;
153
+ }
154
+ }
155
+ return text;
156
+ };
157
+ const scriptSrc = (() => {
158
+ if (forcedTheme) {
159
+ return `!function(){${optimization}${updateDOM(forcedTheme)}}()`;
160
+ }
161
+ if (enableSystem) {
162
+ return `!function(){try {${optimization}var e=localStorage.getItem('${THEME_STORAGE_KEY}');if("system"===e||(!e&&${defaultSystem})){var t="${MEDIA}",m=window.matchMedia(t);if(m.media!==t||m.matches){${updateDOM("dark")}}else{${updateDOM("light")}}}else if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}${!defaultSystem
163
+ ? `else{` + updateDOM(defaultTheme, false, false) + "}"
164
+ : ""}${fallbackColorScheme}}catch(e){}}()`;
165
+ }
166
+ return `!function(){try{${optimization}var e=localStorage.getItem("${THEME_STORAGE_KEY}");if(e){${value ? `var x=${JSON.stringify(value)};` : ""}${updateDOM(value ? `x[e]` : "e", true)}}else{${updateDOM(defaultTheme, false, false)};}${fallbackColorScheme}}catch(t){}}();`;
167
+ })();
168
+ const encodedScript = `data:text/javascript;base64,${encodeBase64(scriptSrc)}`;
169
+ return (_jsx(NextScript, { id: "next-theme-script", strategy: "beforeInteractive", src: encodedScript, nonce: nonce }));
170
+ }, () => true);
171
+ const getTheme = (key, fallback) => {
172
+ if (isServer)
173
+ return undefined;
174
+ let theme;
175
+ try {
176
+ theme = localStorage.getItem(key) || undefined;
177
+ }
178
+ catch (e) {
179
+ }
180
+ return theme || fallback;
181
+ };
182
+ const disableAnimation = () => {
183
+ const d = document;
184
+ const css = d.createElement("style");
185
+ css.appendChild(d.createTextNode(`*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}`));
186
+ d.head.appendChild(css);
187
+ return () => {
188
+ (() => window.getComputedStyle(d.body))();
189
+ setTimeout(() => {
190
+ d.head.removeChild(css);
191
+ }, 1);
192
+ };
193
+ };
194
+ const getSystemTheme = (e) => {
195
+ if (!e)
196
+ e = window.matchMedia(MEDIA);
197
+ const isDark = e.matches;
198
+ const systemTheme = isDark ? "dark" : "light";
199
+ return systemTheme;
200
+ };
201
+ const encodeBase64 = (str) => {
202
+ return isServer ? Buffer.from(str).toString("base64") : btoa(str);
203
+ };
204
+ export default ThemeProvider;
@@ -0,0 +1,5 @@
1
+ "use client";
2
+ import { useContext } from "react";
3
+ import { ThemeContext } from "./ThemeContext";
4
+ export const useTheme = () => useContext(ThemeContext);
5
+ export default useTheme;
package/utils/load.js ADDED
@@ -0,0 +1,5 @@
1
+ export function load(component, milliseconds) {
2
+ return new Promise((resolve) => {
3
+ setTimeout(() => resolve(component), milliseconds);
4
+ });
5
+ }