@sevenfold/setto-client 0.28.1 → 0.29.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/dist/LanguageSwitcher.d.ts +8 -3
- package/dist/setto-client.js +267 -230
- package/dist/setto-client.js.map +1 -1
- package/package.json +1 -1
|
@@ -18,8 +18,13 @@
|
|
|
18
18
|
* back to nothing.
|
|
19
19
|
*/
|
|
20
20
|
export interface SettoLanguagesProps {
|
|
21
|
-
/**
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Every language the site speaks, primary first. Read from the provider's
|
|
23
|
+
* config when left out, which is what a site should do: the list lives in
|
|
24
|
+
* `setto.config.json` and grows when a customer adds a language in Språk,
|
|
25
|
+
* so a header that hard-codes it goes stale the first time they do.
|
|
26
|
+
*/
|
|
27
|
+
languages?: readonly string[];
|
|
23
28
|
/**
|
|
24
29
|
* Rendered in the flow of the page rather than fixed in a corner.
|
|
25
30
|
*
|
|
@@ -28,7 +33,7 @@ export interface SettoLanguagesProps {
|
|
|
28
33
|
*/
|
|
29
34
|
inline?: boolean;
|
|
30
35
|
}
|
|
31
|
-
export declare function SettoLanguages({ languages, inline }: SettoLanguagesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
36
|
+
export declare function SettoLanguages({ languages: given, inline }: SettoLanguagesProps): import("react/jsx-runtime").JSX.Element | null;
|
|
32
37
|
/**
|
|
33
38
|
* The floating copy, mounted by the provider.
|
|
34
39
|
*
|
package/dist/setto-client.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { useState, useRef, useEffect, useMemo, useId, useInsertionEffect, Children, createContext, useContext, useCallback, useLayoutEffect, useSyncExternalStore, forwardRef, Fragment as Fragment$1 } from "react";
|
|
4
4
|
import { useTranslation } from "react-i18next";
|
|
@@ -72,235 +72,6 @@ function pickInitialLanguage(available, browserLanguages = typeof navigator ===
|
|
|
72
72
|
}
|
|
73
73
|
return fallback;
|
|
74
74
|
}
|
|
75
|
-
function normalise(pathname) {
|
|
76
|
-
const path2 = pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
77
|
-
return path2.length > 1 && path2.endsWith("/") ? path2.slice(0, -1) : path2;
|
|
78
|
-
}
|
|
79
|
-
function languageFromPath(pathname, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
80
|
-
const path2 = normalise(pathname);
|
|
81
|
-
const first = path2.split("/")[1] ?? "";
|
|
82
|
-
const match = languages.find(
|
|
83
|
-
(tag) => tag !== primary && tag.toLowerCase() === first.toLowerCase()
|
|
84
|
-
);
|
|
85
|
-
if (!match) return { language: primary, basename: "", rest: path2 };
|
|
86
|
-
const rest = path2.slice(first.length + 1);
|
|
87
|
-
return { language: match, basename: `/${match}`, rest: rest === "" ? "/" : rest };
|
|
88
|
-
}
|
|
89
|
-
function pathForLanguage(pathname, target, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
90
|
-
const { rest } = languageFromPath(pathname, languages, primary);
|
|
91
|
-
if (target === primary) return rest;
|
|
92
|
-
return rest === "/" ? `/${target}` : `/${target}${rest}`;
|
|
93
|
-
}
|
|
94
|
-
function alternateLinks(origin, pathname, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
95
|
-
if (languages.length < 2) return [];
|
|
96
|
-
const links = languages.map((tag) => ({
|
|
97
|
-
hreflang: tag,
|
|
98
|
-
href: origin + pathForLanguage(pathname, tag, languages, primary)
|
|
99
|
-
}));
|
|
100
|
-
links.push({
|
|
101
|
-
hreflang: "x-default",
|
|
102
|
-
href: origin + pathForLanguage(pathname, primary, languages, primary)
|
|
103
|
-
});
|
|
104
|
-
return links;
|
|
105
|
-
}
|
|
106
|
-
function isReservedPath(pathname) {
|
|
107
|
-
return pathname === "/setto" || pathname.startsWith("/setto/");
|
|
108
|
-
}
|
|
109
|
-
function redirectForVisitor(pathname, languages, browserLanguages, stored, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
110
|
-
if (languages.length < 2) return null;
|
|
111
|
-
if (isReservedPath(pathname)) return null;
|
|
112
|
-
const current = languageFromPath(pathname, languages, primary);
|
|
113
|
-
if (current.basename !== "") return null;
|
|
114
|
-
if (stored) {
|
|
115
|
-
return stored !== primary && languages.includes(stored) ? pathForLanguage(pathname, stored, languages, primary) : null;
|
|
116
|
-
}
|
|
117
|
-
for (const wanted of browserLanguages) {
|
|
118
|
-
const base = wanted.toLowerCase().split("-")[0];
|
|
119
|
-
if (!base) continue;
|
|
120
|
-
if (base === primary.toLowerCase().split("-")[0]) return null;
|
|
121
|
-
const norwegian2 = ["no", "nb", "nn"];
|
|
122
|
-
if (norwegian2.includes(base) && norwegian2.includes(primary.toLowerCase())) return null;
|
|
123
|
-
const hit = languages.find((tag) => tag.toLowerCase().split("-")[0] === base);
|
|
124
|
-
if (hit && hit !== primary) return pathForLanguage(pathname, hit, languages, primary);
|
|
125
|
-
}
|
|
126
|
-
return null;
|
|
127
|
-
}
|
|
128
|
-
const INLINE_MARKER = "data-setto-languages-inline";
|
|
129
|
-
function SettoLanguages({ languages, inline = false }) {
|
|
130
|
-
const { i18n } = useTranslation();
|
|
131
|
-
const [open, setOpen] = useState(false);
|
|
132
|
-
const ref = useRef(null);
|
|
133
|
-
useEffect(() => {
|
|
134
|
-
if (!inline) return;
|
|
135
|
-
const root2 = document.documentElement;
|
|
136
|
-
const count = Number(root2.getAttribute(INLINE_MARKER) ?? "0") + 1;
|
|
137
|
-
root2.setAttribute(INLINE_MARKER, String(count));
|
|
138
|
-
return () => {
|
|
139
|
-
const left = Number(root2.getAttribute(INLINE_MARKER) ?? "1") - 1;
|
|
140
|
-
if (left > 0) root2.setAttribute(INLINE_MARKER, String(left));
|
|
141
|
-
else root2.removeAttribute(INLINE_MARKER);
|
|
142
|
-
};
|
|
143
|
-
}, [inline]);
|
|
144
|
-
useEffect(() => {
|
|
145
|
-
if (!open) return;
|
|
146
|
-
const onDown = (e) => {
|
|
147
|
-
if (!ref.current?.contains(e.target)) setOpen(false);
|
|
148
|
-
};
|
|
149
|
-
const onKey = (e) => {
|
|
150
|
-
if (e.key === "Escape") setOpen(false);
|
|
151
|
-
};
|
|
152
|
-
document.addEventListener("mousedown", onDown);
|
|
153
|
-
document.addEventListener("keydown", onKey);
|
|
154
|
-
return () => {
|
|
155
|
-
document.removeEventListener("mousedown", onDown);
|
|
156
|
-
document.removeEventListener("keydown", onKey);
|
|
157
|
-
};
|
|
158
|
-
}, [open]);
|
|
159
|
-
if (languages.length < 2) return null;
|
|
160
|
-
const current = i18n.language;
|
|
161
|
-
const choose = (tag) => {
|
|
162
|
-
setOpen(false);
|
|
163
|
-
if (tag === current) return;
|
|
164
|
-
storeLanguage(tag);
|
|
165
|
-
const target = pathForLanguage(window.location.pathname, tag, languages);
|
|
166
|
-
window.location.assign(target + window.location.search + window.location.hash);
|
|
167
|
-
};
|
|
168
|
-
return /* @__PURE__ */ jsxs("div", { ref, style: inline ? inlineWrapStyle : floatingWrapStyle, children: [
|
|
169
|
-
/* @__PURE__ */ jsxs(
|
|
170
|
-
"button",
|
|
171
|
-
{
|
|
172
|
-
type: "button",
|
|
173
|
-
onClick: () => setOpen((o) => !o),
|
|
174
|
-
"aria-expanded": open,
|
|
175
|
-
"aria-haspopup": "listbox",
|
|
176
|
-
"aria-label": `Språk: ${languageName(current)}`,
|
|
177
|
-
style: inline ? inlineTriggerStyle : floatingTriggerStyle,
|
|
178
|
-
children: [
|
|
179
|
-
/* @__PURE__ */ jsx(GlobeIcon, {}),
|
|
180
|
-
languageName(current)
|
|
181
|
-
]
|
|
182
|
-
}
|
|
183
|
-
),
|
|
184
|
-
open ? /* @__PURE__ */ jsx("ul", { role: "listbox", style: inline ? inlineListStyle : floatingListStyle, children: languages.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
185
|
-
"button",
|
|
186
|
-
{
|
|
187
|
-
type: "button",
|
|
188
|
-
role: "option",
|
|
189
|
-
"aria-selected": tag === current,
|
|
190
|
-
onClick: () => choose(tag),
|
|
191
|
-
style: {
|
|
192
|
-
...optionStyle,
|
|
193
|
-
fontWeight: tag === current ? 600 : 400
|
|
194
|
-
},
|
|
195
|
-
children: languageName(tag)
|
|
196
|
-
}
|
|
197
|
-
) }, tag)) }) : null
|
|
198
|
-
] });
|
|
199
|
-
}
|
|
200
|
-
function AutoLanguageSwitcher({ languages }) {
|
|
201
|
-
const [inlineElsewhere, setInlineElsewhere] = useState(false);
|
|
202
|
-
useEffect(() => {
|
|
203
|
-
const check = () => setInlineElsewhere(document.documentElement.hasAttribute(INLINE_MARKER));
|
|
204
|
-
check();
|
|
205
|
-
const observer = new MutationObserver(check);
|
|
206
|
-
observer.observe(document.documentElement, {
|
|
207
|
-
attributes: true,
|
|
208
|
-
attributeFilter: [INLINE_MARKER]
|
|
209
|
-
});
|
|
210
|
-
return () => observer.disconnect();
|
|
211
|
-
}, []);
|
|
212
|
-
if (inlineElsewhere || languages.length < 2) return null;
|
|
213
|
-
return /* @__PURE__ */ jsx(SettoLanguages, { languages });
|
|
214
|
-
}
|
|
215
|
-
function GlobeIcon() {
|
|
216
|
-
return /* @__PURE__ */ jsxs(
|
|
217
|
-
"svg",
|
|
218
|
-
{
|
|
219
|
-
width: "15",
|
|
220
|
-
height: "15",
|
|
221
|
-
viewBox: "0 0 24 24",
|
|
222
|
-
fill: "none",
|
|
223
|
-
stroke: "currentColor",
|
|
224
|
-
strokeWidth: "1.8",
|
|
225
|
-
strokeLinecap: "round",
|
|
226
|
-
strokeLinejoin: "round",
|
|
227
|
-
"aria-hidden": "true",
|
|
228
|
-
children: [
|
|
229
|
-
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
230
|
-
/* @__PURE__ */ jsx("path", { d: "M3 12h18M12 3c2.4 2.6 3.6 5.6 3.6 9s-1.2 6.4-3.6 9c-2.4-2.6-3.6-5.6-3.6-9S9.6 5.6 12 3z" })
|
|
231
|
-
]
|
|
232
|
-
}
|
|
233
|
-
);
|
|
234
|
-
}
|
|
235
|
-
const floatingWrapStyle = {
|
|
236
|
-
position: "fixed",
|
|
237
|
-
left: "max(16px, env(safe-area-inset-left))",
|
|
238
|
-
bottom: "max(16px, env(safe-area-inset-bottom))",
|
|
239
|
-
zIndex: 2147482e3,
|
|
240
|
-
fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif'
|
|
241
|
-
};
|
|
242
|
-
const inlineWrapStyle = {
|
|
243
|
-
position: "relative",
|
|
244
|
-
display: "inline-block",
|
|
245
|
-
fontFamily: "inherit"
|
|
246
|
-
};
|
|
247
|
-
const triggerBase = {
|
|
248
|
-
display: "inline-flex",
|
|
249
|
-
alignItems: "center",
|
|
250
|
-
gap: 7,
|
|
251
|
-
minHeight: 40,
|
|
252
|
-
fontSize: 13.5,
|
|
253
|
-
fontWeight: 500,
|
|
254
|
-
lineHeight: 1,
|
|
255
|
-
cursor: "pointer"
|
|
256
|
-
};
|
|
257
|
-
const floatingTriggerStyle = {
|
|
258
|
-
...triggerBase,
|
|
259
|
-
padding: "8px 14px",
|
|
260
|
-
borderRadius: 999,
|
|
261
|
-
border: "1px solid rgba(127, 127, 127, 0.32)",
|
|
262
|
-
background: "rgba(255, 255, 255, 0.82)",
|
|
263
|
-
backdropFilter: "blur(8px)",
|
|
264
|
-
WebkitBackdropFilter: "blur(8px)",
|
|
265
|
-
color: "#1a1a1a",
|
|
266
|
-
boxShadow: "0 4px 14px rgba(0, 0, 0, 0.12)"
|
|
267
|
-
};
|
|
268
|
-
const inlineTriggerStyle = {
|
|
269
|
-
...triggerBase,
|
|
270
|
-
padding: "8px 6px",
|
|
271
|
-
border: 0,
|
|
272
|
-
borderRadius: 8,
|
|
273
|
-
background: "transparent",
|
|
274
|
-
color: "inherit",
|
|
275
|
-
opacity: 0.75
|
|
276
|
-
};
|
|
277
|
-
const listBase = {
|
|
278
|
-
position: "absolute",
|
|
279
|
-
margin: 0,
|
|
280
|
-
padding: 4,
|
|
281
|
-
listStyle: "none",
|
|
282
|
-
minWidth: 150,
|
|
283
|
-
borderRadius: 12,
|
|
284
|
-
border: "1px solid rgba(127, 127, 127, 0.24)",
|
|
285
|
-
background: "#ffffff",
|
|
286
|
-
boxShadow: "0 12px 32px rgba(0, 0, 0, 0.18)",
|
|
287
|
-
zIndex: 1
|
|
288
|
-
};
|
|
289
|
-
const floatingListStyle = { ...listBase, left: 0, bottom: "calc(100% + 8px)" };
|
|
290
|
-
const inlineListStyle = { ...listBase, left: 0, top: "calc(100% + 8px)" };
|
|
291
|
-
const optionStyle = {
|
|
292
|
-
display: "block",
|
|
293
|
-
width: "100%",
|
|
294
|
-
minHeight: 40,
|
|
295
|
-
padding: "9px 12px",
|
|
296
|
-
border: 0,
|
|
297
|
-
borderRadius: 8,
|
|
298
|
-
background: "transparent",
|
|
299
|
-
color: "#1a1a1a",
|
|
300
|
-
fontSize: 13.5,
|
|
301
|
-
textAlign: "left",
|
|
302
|
-
cursor: "pointer"
|
|
303
|
-
};
|
|
304
75
|
function __rest(s, e) {
|
|
305
76
|
var t = {};
|
|
306
77
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -21473,6 +21244,59 @@ class I18nStore {
|
|
|
21473
21244
|
for (const fn of this.listeners) fn(this.cachedSnapshot);
|
|
21474
21245
|
}
|
|
21475
21246
|
}
|
|
21247
|
+
function normalise(pathname) {
|
|
21248
|
+
const path2 = pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
21249
|
+
return path2.length > 1 && path2.endsWith("/") ? path2.slice(0, -1) : path2;
|
|
21250
|
+
}
|
|
21251
|
+
function languageFromPath(pathname, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
21252
|
+
const path2 = normalise(pathname);
|
|
21253
|
+
const first = path2.split("/")[1] ?? "";
|
|
21254
|
+
const match = languages.find(
|
|
21255
|
+
(tag) => tag !== primary && tag.toLowerCase() === first.toLowerCase()
|
|
21256
|
+
);
|
|
21257
|
+
if (!match) return { language: primary, basename: "", rest: path2 };
|
|
21258
|
+
const rest = path2.slice(first.length + 1);
|
|
21259
|
+
return { language: match, basename: `/${match}`, rest: rest === "" ? "/" : rest };
|
|
21260
|
+
}
|
|
21261
|
+
function pathForLanguage(pathname, target, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
21262
|
+
const { rest } = languageFromPath(pathname, languages, primary);
|
|
21263
|
+
if (target === primary) return rest;
|
|
21264
|
+
return rest === "/" ? `/${target}` : `/${target}${rest}`;
|
|
21265
|
+
}
|
|
21266
|
+
function alternateLinks(origin, pathname, languages, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
21267
|
+
if (languages.length < 2) return [];
|
|
21268
|
+
const links = languages.map((tag) => ({
|
|
21269
|
+
hreflang: tag,
|
|
21270
|
+
href: origin + pathForLanguage(pathname, tag, languages, primary)
|
|
21271
|
+
}));
|
|
21272
|
+
links.push({
|
|
21273
|
+
hreflang: "x-default",
|
|
21274
|
+
href: origin + pathForLanguage(pathname, primary, languages, primary)
|
|
21275
|
+
});
|
|
21276
|
+
return links;
|
|
21277
|
+
}
|
|
21278
|
+
function isReservedPath(pathname) {
|
|
21279
|
+
return pathname === "/setto" || pathname.startsWith("/setto/");
|
|
21280
|
+
}
|
|
21281
|
+
function redirectForVisitor(pathname, languages, browserLanguages, stored, primary = languages[0] ?? DEFAULT_LANGUAGE) {
|
|
21282
|
+
if (languages.length < 2) return null;
|
|
21283
|
+
if (isReservedPath(pathname)) return null;
|
|
21284
|
+
const current = languageFromPath(pathname, languages, primary);
|
|
21285
|
+
if (current.basename !== "") return null;
|
|
21286
|
+
if (stored) {
|
|
21287
|
+
return stored !== primary && languages.includes(stored) ? pathForLanguage(pathname, stored, languages, primary) : null;
|
|
21288
|
+
}
|
|
21289
|
+
for (const wanted of browserLanguages) {
|
|
21290
|
+
const base = wanted.toLowerCase().split("-")[0];
|
|
21291
|
+
if (!base) continue;
|
|
21292
|
+
if (base === primary.toLowerCase().split("-")[0]) return null;
|
|
21293
|
+
const norwegian2 = ["no", "nb", "nn"];
|
|
21294
|
+
if (norwegian2.includes(base) && norwegian2.includes(primary.toLowerCase())) return null;
|
|
21295
|
+
const hit = languages.find((tag) => tag.toLowerCase().split("-")[0] === base);
|
|
21296
|
+
if (hit && hit !== primary) return pathForLanguage(pathname, hit, languages, primary);
|
|
21297
|
+
}
|
|
21298
|
+
return null;
|
|
21299
|
+
}
|
|
21476
21300
|
const SETTO_IMAGE_REPO_DIR = "public/images/setto";
|
|
21477
21301
|
const SETTO_IMAGE_URL_PREFIX = "/images/setto";
|
|
21478
21302
|
const MIME_EXT = {
|
|
@@ -36368,6 +36192,219 @@ function useSetto() {
|
|
|
36368
36192
|
}
|
|
36369
36193
|
return ctx;
|
|
36370
36194
|
}
|
|
36195
|
+
const INLINE_MARKER = "data-setto-languages-inline";
|
|
36196
|
+
function SettoLanguages({ languages: given, inline = false }) {
|
|
36197
|
+
const { i18n } = useTranslation();
|
|
36198
|
+
const setto = useContext(SettoContext);
|
|
36199
|
+
const configured = setto?.config.languages;
|
|
36200
|
+
const languages = given ?? siteLanguages(configured, configured?.[0]);
|
|
36201
|
+
const [open, setOpen] = useState(false);
|
|
36202
|
+
const [hover, setHover] = useState(false);
|
|
36203
|
+
const [surface, setSurface] = useState(null);
|
|
36204
|
+
const ref = useRef(null);
|
|
36205
|
+
useEffect(() => {
|
|
36206
|
+
if (!inline) return;
|
|
36207
|
+
const root2 = document.documentElement;
|
|
36208
|
+
const count = Number(root2.getAttribute(INLINE_MARKER) ?? "0") + 1;
|
|
36209
|
+
root2.setAttribute(INLINE_MARKER, String(count));
|
|
36210
|
+
return () => {
|
|
36211
|
+
const left = Number(root2.getAttribute(INLINE_MARKER) ?? "1") - 1;
|
|
36212
|
+
if (left > 0) root2.setAttribute(INLINE_MARKER, String(left));
|
|
36213
|
+
else root2.removeAttribute(INLINE_MARKER);
|
|
36214
|
+
};
|
|
36215
|
+
}, [inline]);
|
|
36216
|
+
useEffect(() => {
|
|
36217
|
+
if (!open) return;
|
|
36218
|
+
const onDown = (e) => {
|
|
36219
|
+
if (!ref.current?.contains(e.target)) setOpen(false);
|
|
36220
|
+
};
|
|
36221
|
+
const onKey = (e) => {
|
|
36222
|
+
if (e.key === "Escape") setOpen(false);
|
|
36223
|
+
};
|
|
36224
|
+
document.addEventListener("mousedown", onDown);
|
|
36225
|
+
document.addEventListener("keydown", onKey);
|
|
36226
|
+
return () => {
|
|
36227
|
+
document.removeEventListener("mousedown", onDown);
|
|
36228
|
+
document.removeEventListener("keydown", onKey);
|
|
36229
|
+
};
|
|
36230
|
+
}, [open]);
|
|
36231
|
+
if (languages.length < 2) return null;
|
|
36232
|
+
const current = i18n.language;
|
|
36233
|
+
const toggle = () => {
|
|
36234
|
+
if (!open && inline && ref.current) setSurface(surroundings(ref.current));
|
|
36235
|
+
setOpen((o) => !o);
|
|
36236
|
+
};
|
|
36237
|
+
const choose = (tag) => {
|
|
36238
|
+
setOpen(false);
|
|
36239
|
+
if (tag === current) return;
|
|
36240
|
+
storeLanguage(tag);
|
|
36241
|
+
const target = pathForLanguage(window.location.pathname, tag, languages);
|
|
36242
|
+
window.location.assign(target + window.location.search + window.location.hash);
|
|
36243
|
+
};
|
|
36244
|
+
return /* @__PURE__ */ jsxs("div", { ref, style: inline ? inlineWrapStyle : floatingWrapStyle, children: [
|
|
36245
|
+
/* @__PURE__ */ jsxs(
|
|
36246
|
+
"button",
|
|
36247
|
+
{
|
|
36248
|
+
type: "button",
|
|
36249
|
+
onClick: toggle,
|
|
36250
|
+
onMouseEnter: () => setHover(true),
|
|
36251
|
+
onMouseLeave: () => setHover(false),
|
|
36252
|
+
"aria-expanded": open,
|
|
36253
|
+
"aria-haspopup": "listbox",
|
|
36254
|
+
"aria-label": `Språk: ${languageName(current)}`,
|
|
36255
|
+
title: inline ? languageName(current) : void 0,
|
|
36256
|
+
style: inline ? { ...inlineTriggerStyle, opacity: hover || open ? 1 : inlineTriggerStyle.opacity } : floatingTriggerStyle,
|
|
36257
|
+
children: [
|
|
36258
|
+
/* @__PURE__ */ jsx(GlobeIcon, {}),
|
|
36259
|
+
inline ? shortCode(current) : languageName(current)
|
|
36260
|
+
]
|
|
36261
|
+
}
|
|
36262
|
+
),
|
|
36263
|
+
open ? /* @__PURE__ */ jsx(
|
|
36264
|
+
"ul",
|
|
36265
|
+
{
|
|
36266
|
+
role: "listbox",
|
|
36267
|
+
style: inline ? { ...inlineListStyle, ...surface ? { background: surface.background, color: surface.color } : {} } : floatingListStyle,
|
|
36268
|
+
children: languages.map((tag) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
36269
|
+
"button",
|
|
36270
|
+
{
|
|
36271
|
+
type: "button",
|
|
36272
|
+
role: "option",
|
|
36273
|
+
"aria-selected": tag === current,
|
|
36274
|
+
onClick: () => choose(tag),
|
|
36275
|
+
style: {
|
|
36276
|
+
...optionStyle,
|
|
36277
|
+
...inline ? { color: "inherit" } : {},
|
|
36278
|
+
fontWeight: tag === current ? 600 : 400
|
|
36279
|
+
},
|
|
36280
|
+
children: languageName(tag)
|
|
36281
|
+
}
|
|
36282
|
+
) }, tag))
|
|
36283
|
+
}
|
|
36284
|
+
) : null
|
|
36285
|
+
] });
|
|
36286
|
+
}
|
|
36287
|
+
function AutoLanguageSwitcher({ languages }) {
|
|
36288
|
+
const [inlineElsewhere, setInlineElsewhere] = useState(false);
|
|
36289
|
+
useEffect(() => {
|
|
36290
|
+
const check = () => setInlineElsewhere(document.documentElement.hasAttribute(INLINE_MARKER));
|
|
36291
|
+
check();
|
|
36292
|
+
const observer = new MutationObserver(check);
|
|
36293
|
+
observer.observe(document.documentElement, {
|
|
36294
|
+
attributes: true,
|
|
36295
|
+
attributeFilter: [INLINE_MARKER]
|
|
36296
|
+
});
|
|
36297
|
+
return () => observer.disconnect();
|
|
36298
|
+
}, []);
|
|
36299
|
+
if (inlineElsewhere || languages.length < 2) return null;
|
|
36300
|
+
return /* @__PURE__ */ jsx(SettoLanguages, { languages });
|
|
36301
|
+
}
|
|
36302
|
+
function shortCode(tag) {
|
|
36303
|
+
return tag.toUpperCase();
|
|
36304
|
+
}
|
|
36305
|
+
function surroundings(el) {
|
|
36306
|
+
const color2 = getComputedStyle(el).color;
|
|
36307
|
+
for (let node2 = el; node2; node2 = node2.parentElement) {
|
|
36308
|
+
const background = getComputedStyle(node2).backgroundColor;
|
|
36309
|
+
if (background && !/^(transparent|rgba\(.*,\s*0\))$/.test(background)) return { background, color: color2 };
|
|
36310
|
+
}
|
|
36311
|
+
return { background: "#ffffff", color: "#1a1a1a" };
|
|
36312
|
+
}
|
|
36313
|
+
function GlobeIcon() {
|
|
36314
|
+
return /* @__PURE__ */ jsxs(
|
|
36315
|
+
"svg",
|
|
36316
|
+
{
|
|
36317
|
+
width: "15",
|
|
36318
|
+
height: "15",
|
|
36319
|
+
viewBox: "0 0 24 24",
|
|
36320
|
+
fill: "none",
|
|
36321
|
+
stroke: "currentColor",
|
|
36322
|
+
strokeWidth: "1.8",
|
|
36323
|
+
strokeLinecap: "round",
|
|
36324
|
+
strokeLinejoin: "round",
|
|
36325
|
+
"aria-hidden": "true",
|
|
36326
|
+
children: [
|
|
36327
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "9" }),
|
|
36328
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12h18M12 3c2.4 2.6 3.6 5.6 3.6 9s-1.2 6.4-3.6 9c-2.4-2.6-3.6-5.6-3.6-9S9.6 5.6 12 3z" })
|
|
36329
|
+
]
|
|
36330
|
+
}
|
|
36331
|
+
);
|
|
36332
|
+
}
|
|
36333
|
+
const floatingWrapStyle = {
|
|
36334
|
+
position: "fixed",
|
|
36335
|
+
left: "max(16px, env(safe-area-inset-left))",
|
|
36336
|
+
bottom: "max(16px, env(safe-area-inset-bottom))",
|
|
36337
|
+
zIndex: 2147482e3,
|
|
36338
|
+
fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif'
|
|
36339
|
+
};
|
|
36340
|
+
const inlineWrapStyle = {
|
|
36341
|
+
position: "relative",
|
|
36342
|
+
display: "inline-block",
|
|
36343
|
+
fontFamily: "inherit"
|
|
36344
|
+
};
|
|
36345
|
+
const triggerBase = {
|
|
36346
|
+
display: "inline-flex",
|
|
36347
|
+
alignItems: "center",
|
|
36348
|
+
gap: 7,
|
|
36349
|
+
minHeight: 40,
|
|
36350
|
+
fontSize: 13.5,
|
|
36351
|
+
fontWeight: 500,
|
|
36352
|
+
lineHeight: 1,
|
|
36353
|
+
cursor: "pointer"
|
|
36354
|
+
};
|
|
36355
|
+
const floatingTriggerStyle = {
|
|
36356
|
+
...triggerBase,
|
|
36357
|
+
padding: "8px 14px",
|
|
36358
|
+
borderRadius: 999,
|
|
36359
|
+
border: "1px solid rgba(127, 127, 127, 0.32)",
|
|
36360
|
+
background: "rgba(255, 255, 255, 0.82)",
|
|
36361
|
+
backdropFilter: "blur(8px)",
|
|
36362
|
+
WebkitBackdropFilter: "blur(8px)",
|
|
36363
|
+
color: "#1a1a1a",
|
|
36364
|
+
boxShadow: "0 4px 14px rgba(0, 0, 0, 0.12)"
|
|
36365
|
+
};
|
|
36366
|
+
const inlineTriggerStyle = {
|
|
36367
|
+
...triggerBase,
|
|
36368
|
+
gap: 5,
|
|
36369
|
+
minHeight: 36,
|
|
36370
|
+
padding: "6px 6px",
|
|
36371
|
+
border: 0,
|
|
36372
|
+
borderRadius: 8,
|
|
36373
|
+
background: "transparent",
|
|
36374
|
+
color: "inherit",
|
|
36375
|
+
fontSize: 12,
|
|
36376
|
+
fontWeight: 500,
|
|
36377
|
+
letterSpacing: "0.06em",
|
|
36378
|
+
opacity: 0.7,
|
|
36379
|
+
transition: "opacity 160ms ease"
|
|
36380
|
+
};
|
|
36381
|
+
const listBase = {
|
|
36382
|
+
position: "absolute",
|
|
36383
|
+
margin: 0,
|
|
36384
|
+
padding: 4,
|
|
36385
|
+
listStyle: "none",
|
|
36386
|
+
minWidth: 150,
|
|
36387
|
+
borderRadius: 12,
|
|
36388
|
+
border: "1px solid rgba(127, 127, 127, 0.24)",
|
|
36389
|
+
background: "#ffffff",
|
|
36390
|
+
boxShadow: "0 12px 32px rgba(0, 0, 0, 0.18)",
|
|
36391
|
+
zIndex: 1
|
|
36392
|
+
};
|
|
36393
|
+
const floatingListStyle = { ...listBase, left: 0, bottom: "calc(100% + 8px)" };
|
|
36394
|
+
const inlineListStyle = { ...listBase, right: 0, top: "calc(100% + 8px)" };
|
|
36395
|
+
const optionStyle = {
|
|
36396
|
+
display: "block",
|
|
36397
|
+
width: "100%",
|
|
36398
|
+
minHeight: 40,
|
|
36399
|
+
padding: "9px 12px",
|
|
36400
|
+
border: 0,
|
|
36401
|
+
borderRadius: 8,
|
|
36402
|
+
background: "transparent",
|
|
36403
|
+
color: "#1a1a1a",
|
|
36404
|
+
fontSize: 13.5,
|
|
36405
|
+
textAlign: "left",
|
|
36406
|
+
cursor: "pointer"
|
|
36407
|
+
};
|
|
36371
36408
|
function GuestEditProvider({ children }) {
|
|
36372
36409
|
const { guestEdit, themeStore } = useSetto();
|
|
36373
36410
|
const SectionTools = useSettoChromeSlot("section-toolbar");
|