@levo-so/site-runtime 0.3.7 → 0.3.9

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.
Files changed (45) hide show
  1. package/CollectionField-C-6a1ud4.js +270 -0
  2. package/{CollectionInput-B1qV4QEH.js → CollectionInput-BJ__qcbk.js} +40 -40
  3. package/DateTimeWidget-LfaosVVW.js +255 -0
  4. package/{Dialog-DVB4WpBS.js → Dialog-dT7y641z.js} +43 -43
  5. package/{KBChatWidget-Cnq0DCOQ.js → KBChatWidget-CuAtGhHT.js} +240 -239
  6. package/{LevoProvider-nmIbMlsk.js → LevoProvider-Bsjkcwc8.js} +8 -8
  7. package/PhoneWidget-D-CcDuie.js +99 -0
  8. package/{Popover-C7zZHBIc.js → Popover-BTdlOQP_.js} +20 -20
  9. package/{PopupBody-DZVwDLkg-yrot8Uqb.js → PopupBody-BI-MJqmd-C0qNyN7V.js} +299 -182
  10. package/PopupRenderer-D66Gx63H-C6RnOnl2.js +388 -0
  11. package/{RichTextWidget-BOrVIR2j.js → RichTextWidget-BFWVevY7.js} +140 -140
  12. package/ThemeProvider-DutrjSTF.js +116 -0
  13. package/{Tooltip-BIgrpetu.js → Tooltip-CQB0LyxK.js} +20 -20
  14. package/{VerifyButton-CA1GtEZJ.js → VerifyButton-BUT70lgz.js} +65 -65
  15. package/{dist-Cb6sb7nO.js → dist-Rjs__H25.js} +14 -14
  16. package/dist-orLT2eNz.js +3663 -0
  17. package/index.d.ts +1071 -3
  18. package/index.js +1365 -733
  19. package/inlineBaseTheme-BB9e6h5f.js +9 -0
  20. package/{inlineCollectionTheme-DYYMrmcE.js → inlineCollectionTheme-CWcMCUti.js} +1 -1
  21. package/{kbChat-DIb4AS7E.js → kbChat-L55effMi.js} +28 -28
  22. package/{nodeAlignment-D70kOcui.js → nodeAlignment-COvc-rIj.js} +1 -1
  23. package/package.json +37 -27
  24. package/popups.js +1 -1
  25. package/{react-6kO0cqgr.js → react-B9yvlbH0.js} +1 -1
  26. package/routes-CyKmkoRM.js +316 -0
  27. package/start.d.ts +38 -0
  28. package/start.js +19 -0
  29. package/styles.css +1 -1
  30. package/{generateRadiusScale-54mE9ikx.js → themeVars.cssm-ByhhC2Jm.js} +17 -17
  31. package/usePopupRedirect-CAAdcpaW-D9XoiVhG.js +82 -0
  32. package/CollectionField-C59pmeQw.js +0 -270
  33. package/DateTimeWidget-Cctsvcrs.js +0 -255
  34. package/PhoneWidget-J3VTMWJH.js +0 -99
  35. package/PopupRenderer-BjW1jg70-Biwj2bIc.js +0 -387
  36. package/ThemeProvider-BQmIB5tr.js +0 -116
  37. package/dist-C8gLeklT.js +0 -3559
  38. package/inlineBaseTheme-B6E9zzyp.js +0 -9
  39. package/usePopupRedirect-BThP_YPW-DoixMAB9.js +0 -80
  40. /package/{createThemeExtension-DhGk81nV.js → createThemeExtension-4AUn51iJ.js} +0 -0
  41. /package/{es-CztjLuNy.js → es-Bj3CsMJz.js} +0 -0
  42. /package/{pillChrome-BAu5AfCT.js → pillChrome-uieiq_SK.js} +0 -0
  43. /package/{popupState-JmpeKzgM-qhNTV79U.js → popupState-JmpeKzgM-D_77LiAa.js} +0 -0
  44. /package/{rteTheme.cssm-xg0gJ28J.js → rteTheme.cssm-CaRzrwtu.js} +0 -0
  45. /package/{theme.cssm-mkQwezuj.js → theme.cssm-DUzmx76l.js} +0 -0
@@ -0,0 +1,9 @@
1
+ import { t as e } from "./createThemeExtension-4AUn51iJ.js";
2
+ import { n as t, t as n } from "./themeVars.cssm-ByhhC2Jm.js";
3
+ //#region ../../libraries/levocn/dist/styles/inlineBaseTheme.js
4
+ var r = e(n), i = (e) => e ? e.radius && !e.radiusScale ? r({
5
+ ...e,
6
+ radiusScale: t(e.radius)
7
+ }) : r(e) : {};
8
+ //#endregion
9
+ export { i as t };
@@ -1,4 +1,4 @@
1
- import { t as e } from "./createThemeExtension-DhGk81nV.js";
1
+ import { t as e } from "./createThemeExtension-4AUn51iJ.js";
2
2
  //#region ../../libraries/react-collection/dist/theme/collectionThemeVars.cssm.js
3
3
  var t = {
4
4
  form: {
@@ -1,7 +1,7 @@
1
1
  "use client";
2
- import { a as e, c as t, f as n, h as r, l as i, m as a, n as o, o as s, p as c, r as l, t as u, u as d, y as f } from "./pillChrome-BAu5AfCT.js";
3
- import { useEffect as p, useRef as m, useState as h } from "react";
4
- import { jsx as g, jsxs as _ } from "react/jsx-runtime";
2
+ import { a as e, c as t, f as n, h as r, l as i, m as a, n as o, o as s, p as c, r as l, t as u, u as d, y as f } from "./pillChrome-uieiq_SK.js";
3
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
4
+ import { useEffect as h, useRef as g, useState as _ } from "react";
5
5
  import { ArrowUp as v, Sparkles as y } from "lucide-react";
6
6
  //#region ../../libraries/ai-chat/src/useActiveAgent.ts
7
7
  var b = (e) => f("active_agent", e), x = (e) => {
@@ -21,16 +21,16 @@ var b = (e) => f("active_agent", e), x = (e) => {
21
21
  t === null ? window.sessionStorage.removeItem(n) : window.sessionStorage.setItem(n, JSON.stringify(t));
22
22
  } catch {}
23
23
  }, C = ({ url: e, workspaceId: t, headers: n, path: r }) => {
24
- let [i, a] = h({ status: "loading" });
25
- p(() => {
24
+ let [i, a] = _({ status: "loading" });
25
+ h(() => {
26
26
  let e = x(t);
27
27
  a(e ? {
28
28
  status: "ready",
29
29
  agent: e
30
30
  } : (e) => e.status === "ready" ? { status: "loading" } : e);
31
31
  }, [t]);
32
- let o = m(n);
33
- return o.current = n, p(() => {
32
+ let o = g(n);
33
+ return o.current = n, h(() => {
34
34
  if (!t || !e) return;
35
35
  let n = r ? `${e}${e.includes("?") ? "&" : "?"}path=${encodeURIComponent(r)}` : e, i = new AbortController();
36
36
  return (async () => {
@@ -64,13 +64,13 @@ var b = (e) => f("active_agent", e), x = (e) => {
64
64
  e,
65
65
  r
66
66
  ]), i;
67
- }, w = (...e) => e.filter(Boolean).join(" "), T = () => import("./KBChatWidget-Cnq0DCOQ.js"), E = (e) => {
68
- let [t, n] = h(null), [r, i] = h(!1), [a, o] = h("");
69
- return t ? /* @__PURE__ */ g(t, {
67
+ }, w = (...e) => e.filter(Boolean).join(" "), T = () => import("./KBChatWidget-CuAtGhHT.js"), E = (e) => {
68
+ let [t, n] = _(null), [r, i] = _(!1), [a, o] = _("");
69
+ return t ? /* @__PURE__ */ p(t, {
70
70
  initialOpen: !0,
71
71
  initialDraft: a,
72
72
  ...e
73
- }) : /* @__PURE__ */ g(O, {
73
+ }) : /* @__PURE__ */ p(O, {
74
74
  siteName: e.siteName,
75
75
  draft: a,
76
76
  loading: r,
@@ -84,38 +84,38 @@ var b = (e) => f("active_agent", e), x = (e) => {
84
84
  T().catch(() => {});
85
85
  }
86
86
  });
87
- }, D = () => /* @__PURE__ */ g("span", {
87
+ }, D = () => /* @__PURE__ */ p("span", {
88
88
  "aria-hidden": !0,
89
89
  className: "h-5 w-5 animate-spin rounded-full border-2 border-current border-t-transparent"
90
- }), O = ({ siteName: f, draft: p, loading: b, onDraftChange: x, onActivate: S, onPrefetch: C }) => {
91
- let T = m(null), E = m(null), O = r(f), [k, A] = h(!1);
92
- return /* @__PURE__ */ g("div", {
90
+ }), O = ({ siteName: f, draft: h, loading: b, onDraftChange: x, onActivate: S, onPrefetch: C }) => {
91
+ let T = g(null), E = g(null), O = r(f), [k, A] = _(!1);
92
+ return /* @__PURE__ */ p("div", {
93
93
  onPointerEnter: C,
94
94
  className: w("ai-chat-launcher fixed bottom-8 left-1/2 z-[60] -translate-x-1/2", c),
95
- children: /* @__PURE__ */ g("div", {
95
+ children: /* @__PURE__ */ p("div", {
96
96
  className: w(o, t, "ai-chat-intro-morph"),
97
- children: /* @__PURE__ */ _("div", {
97
+ children: /* @__PURE__ */ m("div", {
98
98
  ref: E,
99
99
  className: w(d, k && "ai-chat-pill-surface--stacked"),
100
100
  children: [
101
- /* @__PURE__ */ g("button", {
101
+ /* @__PURE__ */ p("button", {
102
102
  type: "button",
103
103
  onClick: S,
104
104
  onFocus: C,
105
105
  "aria-label": "Open AI chat",
106
106
  className: i,
107
- children: b ? /* @__PURE__ */ g(D, {}) : /* @__PURE__ */ g(y, { className: "h-5 w-5" })
107
+ children: b ? /* @__PURE__ */ p(D, {}) : /* @__PURE__ */ p(y, { className: "h-5 w-5" })
108
108
  }),
109
- /* @__PURE__ */ _("div", {
109
+ /* @__PURE__ */ m("div", {
110
110
  className: l,
111
- children: [/* @__PURE__ */ g("textarea", {
111
+ children: [/* @__PURE__ */ p("textarea", {
112
112
  ref: T,
113
113
  rows: 1,
114
114
  autoComplete: "off",
115
115
  autoCorrect: "off",
116
116
  autoCapitalize: "none",
117
117
  inputMode: "text",
118
- value: p,
118
+ value: h,
119
119
  "aria-label": O,
120
120
  onFocus: S,
121
121
  onChange: (e) => {
@@ -123,21 +123,21 @@ var b = (e) => f("active_agent", e), x = (e) => {
123
123
  x(t.value), E.current && A(a(E.current, t));
124
124
  },
125
125
  className: n
126
- }), !p && /* @__PURE__ */ g("span", {
126
+ }), !h && /* @__PURE__ */ p("span", {
127
127
  className: w("ai-chat-pill-label pointer-events-none absolute inset-y-0 left-0 flex max-w-full items-center truncate bg-clip-text font-semibold text-[15px] text-transparent", "ai-chat-intro-label"),
128
128
  "aria-hidden": !0,
129
129
  children: O
130
130
  })]
131
131
  }),
132
- /* @__PURE__ */ g("div", {
132
+ /* @__PURE__ */ p("div", {
133
133
  className: u,
134
- children: /* @__PURE__ */ g("button", {
134
+ children: /* @__PURE__ */ p("button", {
135
135
  type: "button",
136
136
  onClick: S,
137
137
  "aria-label": "Open AI chat",
138
138
  className: e,
139
139
  style: s,
140
- children: b ? /* @__PURE__ */ g(D, {}) : /* @__PURE__ */ g(v, { className: "h-5 w-5 stroke-[2.5px]" })
140
+ children: b ? /* @__PURE__ */ p(D, {}) : /* @__PURE__ */ p(v, { className: "h-5 w-5 stroke-[2.5px]" })
141
141
  })
142
142
  })
143
143
  ]
@@ -154,9 +154,9 @@ var b = (e) => f("active_agent", e), x = (e) => {
154
154
  } : a,
155
155
  path: c
156
156
  });
157
- return l.status === "ready" ? /* @__PURE__ */ g("div", {
157
+ return l.status === "ready" ? /* @__PURE__ */ p("div", {
158
158
  "data-ai-chat-root": !0,
159
- children: /* @__PURE__ */ g(E, {
159
+ children: /* @__PURE__ */ p(E, {
160
160
  workspaceId: e,
161
161
  siteName: t,
162
162
  siteLogo: n,
@@ -1,4 +1,4 @@
1
- import { t as e } from "./createThemeExtension-DhGk81nV.js";
1
+ import { t as e } from "./createThemeExtension-4AUn51iJ.js";
2
2
  import { Extension as t, findParentNodeClosestToPos as n } from "@tiptap/core";
3
3
  import { NodeSelection as r } from "@tiptap/pm/state";
4
4
  import { CellSelection as i, cellAround as a } from "@tiptap/pm/tables";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levo-so/site-runtime",
3
- "version": "0.3.7",
3
+ "version": "0.3.9",
4
4
  "description": "Runtime for Levo Studio v3 sites — the editor preview inspector, page head metadata, and the Levo data client.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -21,6 +21,10 @@
21
21
  "types": "./popups.d.ts",
22
22
  "default": "./popups.js"
23
23
  },
24
+ "./start": {
25
+ "types": "./start.d.ts",
26
+ "default": "./start.js"
27
+ },
24
28
  "./setup.css": "./styles.css"
25
29
  },
26
30
  "files": [
@@ -31,15 +35,15 @@
31
35
  "dependencies": {
32
36
  "@tabler/icons-react": "3.34.1",
33
37
  "@theinternetfolks/snowflake": "1.3.0",
34
- "@tiptap/core": "3.23.5",
35
- "@tiptap/extension-subscript": "3.23.5",
36
- "@tiptap/extension-superscript": "3.23.5",
37
- "@tiptap/extension-typography": "3.23.5",
38
- "@tiptap/extension-unique-id": "3.23.5",
39
- "@tiptap/extensions": "3.23.5",
40
- "@tiptap/pm": "3.23.5",
41
- "@tiptap/react": "3.23.5",
42
- "@tiptap/starter-kit": "3.23.5",
38
+ "@tiptap/core": "3.30.0",
39
+ "@tiptap/extension-subscript": "3.30.0",
40
+ "@tiptap/extension-superscript": "3.30.0",
41
+ "@tiptap/extension-typography": "3.30.0",
42
+ "@tiptap/extension-unique-id": "3.30.0",
43
+ "@tiptap/extensions": "3.30.0",
44
+ "@tiptap/pm": "3.30.0",
45
+ "@tiptap/react": "3.30.0",
46
+ "@tiptap/starter-kit": "3.30.0",
43
47
  "altcha": "2.0.2",
44
48
  "clsx": "2.1.1",
45
49
  "dayjs": "1.11.13",
@@ -52,17 +56,17 @@
52
56
  "react-select-async-paginate": "0.7.5",
53
57
  "use-debounce": "10.0.2",
54
58
  "yup": "1.7.1",
55
- "@tiptap/extension-blockquote": "3.23.5",
56
- "@tiptap/extension-code-block": "3.23.5",
57
- "@tiptap/extension-details": "3.23.5",
58
- "@tiptap/extension-document": "3.23.5",
59
- "@tiptap/extension-horizontal-rule": "3.23.5",
60
- "@tiptap/extension-image": "3.23.5",
61
- "@tiptap/extension-link": "3.23.5",
62
- "@tiptap/extension-list": "3.23.5",
63
- "@tiptap/extension-mention": "3.23.5",
64
- "@tiptap/extension-table": "3.23.5",
65
- "@tiptap/extension-text-style": "3.23.5",
59
+ "@tiptap/extension-blockquote": "3.30.0",
60
+ "@tiptap/extension-code-block": "3.30.0",
61
+ "@tiptap/extension-details": "3.30.0",
62
+ "@tiptap/extension-document": "3.30.0",
63
+ "@tiptap/extension-horizontal-rule": "3.30.0",
64
+ "@tiptap/extension-image": "3.30.0",
65
+ "@tiptap/extension-link": "3.30.0",
66
+ "@tiptap/extension-list": "3.30.0",
67
+ "@tiptap/extension-mention": "3.30.0",
68
+ "@tiptap/extension-table": "3.30.0",
69
+ "@tiptap/extension-text-style": "3.30.0",
66
70
  "@vanilla-extract/recipes": "0.5.7",
67
71
  "lowlight": "3.1.0",
68
72
  "@vanilla-extract/dynamic": "2.1.5",
@@ -74,11 +78,11 @@
74
78
  "@assistant-ui/store": "0.3.7",
75
79
  "@assistant-ui/tap": "0.9.10",
76
80
  "remark-gfm": "4.0.1",
77
- "@stripe/react-stripe-js": "^3.1.1",
78
- "@stripe/stripe-js": "^5.5.0",
79
- "react-razorpay": "^3.0.1",
80
- "@levo-so/core": "0.3.7",
81
- "@levo-so/insights": "0.3.7"
81
+ "@stripe/react-stripe-js": "3.1.1",
82
+ "@stripe/stripe-js": "5.5.0",
83
+ "react-razorpay": "3.0.1",
84
+ "@levo-so/core": "0.3.9",
85
+ "@levo-so/insights": "0.3.9"
82
86
  },
83
87
  "peerDependencies": {
84
88
  "@base-ui/react": "^1.5.0",
@@ -86,6 +90,12 @@
86
90
  "@tanstack/react-router": ">=1.170.0",
87
91
  "lucide-react": ">=0.4",
88
92
  "react": ">=19",
89
- "react-dom": ">=19"
93
+ "react-dom": ">=19",
94
+ "@tanstack/react-start": ">=1.168.0"
95
+ },
96
+ "peerDependenciesMeta": {
97
+ "@tanstack/react-start": {
98
+ "optional": true
99
+ }
90
100
  }
91
101
  }
package/popups.js CHANGED
@@ -1,4 +1,4 @@
1
- import { t as e } from "./dist-Cb6sb7nO.js";
1
+ import { t as e } from "./dist-Rjs__H25.js";
2
2
  //#region src/popups/usePopup.ts
3
3
  var t = () => e();
4
4
  //#endregion
@@ -1,4 +1,4 @@
1
- import { t as e } from "./inlineBaseTheme-B6E9zzyp.js";
1
+ import { t as e } from "./inlineBaseTheme-BB9e6h5f.js";
2
2
  import { useCallback as t, useRef as n, useSyncExternalStore as r } from "react";
3
3
  //#region ../../node_modules/.pnpm/nanostores@0.11.4/node_modules/nanostores/listen-keys/index.js
4
4
  function i(e, t, n) {
@@ -0,0 +1,316 @@
1
+ //#region src/locale/tag.ts
2
+ var e = (e) => e.replaceAll("_", "-").toLowerCase(), t = (t) => e(t).split("-")[0] || "", n = (t) => {
3
+ let [, ...n] = e(t).split("-"), r = n.filter((e) => /^[a-z]{2}$/.test(e)).pop();
4
+ return r ? r.toUpperCase() : null;
5
+ }, r = (t, n) => {
6
+ if (!t) return null;
7
+ let r = e(t);
8
+ return n.find((t) => e(t) === r) ?? null;
9
+ }, i = (e, n) => {
10
+ let r = t(e);
11
+ return r ? n.filter((e) => t(e) === r) : [];
12
+ }, a = "private, no-store", o = (e) => {
13
+ let { locale: n, defaultLocale: i, prefix: a, neutralPath: o, locales: s, hasRoute: c, currentPath: l } = e, u = (e) => o === "/" ? `/${e}` : `/${e}${o}`;
14
+ if (s.length <= 1) return null;
15
+ if (a) {
16
+ let e = u(a);
17
+ return l && l !== e ? e : null;
18
+ }
19
+ let d = [
20
+ n,
21
+ t(n),
22
+ i,
23
+ t(i)
24
+ ].map((e) => r(e, s)).filter((e, t, n) => !!e && n.indexOf(e) === t);
25
+ for (let e of d) {
26
+ let t = u(e);
27
+ if (!c || c(t)) return t;
28
+ }
29
+ return null;
30
+ }, s = (e) => {
31
+ try {
32
+ return decodeURIComponent(e);
33
+ } catch {
34
+ return e;
35
+ }
36
+ }, c = (e) => {
37
+ let t = e["cf-ipcountry"];
38
+ if (t && t !== "XX") return {
39
+ countryCode: t,
40
+ source: "Cloudflare CDN"
41
+ };
42
+ let n = e["x-vercel-ip-country"];
43
+ if (n) {
44
+ let t = e["x-vercel-ip-city"];
45
+ return {
46
+ countryCode: n,
47
+ city: t ? s(t) : void 0,
48
+ region: e["x-vercel-ip-country-region"],
49
+ latitude: e["x-vercel-ip-latitude"],
50
+ longitude: e["x-vercel-ip-longitude"],
51
+ source: "Vercel Edge"
52
+ };
53
+ }
54
+ let r = e["cloudfront-viewer-country"];
55
+ if (r) return {
56
+ countryCode: r,
57
+ source: "AWS CloudFront"
58
+ };
59
+ let i = e["x-azure-country"];
60
+ if (i) return {
61
+ countryCode: i,
62
+ source: "Azure CDN"
63
+ };
64
+ let a = e["x-edge-country"];
65
+ if (a) return {
66
+ countryCode: a,
67
+ source: "BunnyCDN"
68
+ };
69
+ let o = e["x-client-country"] || e["x-forwarded-country"] || e["x-country"];
70
+ if (o) return {
71
+ countryCode: o,
72
+ source: "Generic CDN"
73
+ };
74
+ let c = e["x-country-code"];
75
+ if (c) return {
76
+ countryCode: c,
77
+ city: e["x-city"],
78
+ latitude: e["x-latitude"],
79
+ longitude: e["x-longitude"],
80
+ source: "nginx-ingress"
81
+ };
82
+ let l = e["x-geoip2-country"];
83
+ return l ? {
84
+ countryCode: l,
85
+ city: e["x-geoip2-city"],
86
+ region: e["x-geoip2-region"],
87
+ source: "traefik-geoip2"
88
+ } : null;
89
+ }, l = (e) => {
90
+ if (!e) return {
91
+ languages: [],
92
+ primaryLanguage: "unknown",
93
+ inferredRegions: []
94
+ };
95
+ let t = e.split(",").map((e) => {
96
+ let [t, n] = e.trim().split(";q="), [r, i] = (t || "").split("-"), a = Number.parseFloat(n ?? "");
97
+ return {
98
+ locale: t?.trim() || "",
99
+ language: r?.trim() || "",
100
+ region: i?.trim().toUpperCase(),
101
+ quality: Number.isFinite(a) ? a : 1
102
+ };
103
+ }).filter((e) => e.locale).sort((e, t) => t.quality - e.quality), n = t.map((e) => e.region).filter((e) => !!e).filter((e, t, n) => n.indexOf(e) === t);
104
+ return {
105
+ languages: t,
106
+ primaryLanguage: t[0]?.locale || "unknown",
107
+ inferredRegions: n
108
+ };
109
+ }, u = (e) => {
110
+ if (!e) return {};
111
+ if (typeof e.entries == "function") {
112
+ let t = {};
113
+ for (let [n, r] of e.entries()) t[n.toLowerCase()] = r;
114
+ return t;
115
+ }
116
+ let t = {};
117
+ for (let [n, r] of Object.entries(e)) r != null && (t[n.toLowerCase()] = Array.isArray(r) ? r.join(", ") : String(r));
118
+ return t;
119
+ }, d = (e) => {
120
+ let t = u(e);
121
+ return {
122
+ bestCountry: c(t),
123
+ languageData: l(t["accept-language"] || "")
124
+ };
125
+ }, f = "levo_locale", p = [
126
+ "googlebot",
127
+ "bingbot",
128
+ "slurp",
129
+ "duckduckbot",
130
+ "baiduspider",
131
+ "yandexbot",
132
+ "applebot",
133
+ "petalbot",
134
+ "facebookexternalhit",
135
+ "twitterbot",
136
+ "linkedinbot",
137
+ "slackbot",
138
+ "whatsapp",
139
+ "telegrambot",
140
+ "discordbot"
141
+ ], m = (e) => {
142
+ if (!e) return !1;
143
+ let t = e.toLowerCase();
144
+ return p.some((e) => t.includes(e));
145
+ }, h = (e, n, a) => {
146
+ let o = t(e.language);
147
+ if (!o) return null;
148
+ if (a) {
149
+ let e = r(`${o}-${a}`, n);
150
+ if (e) return e;
151
+ }
152
+ return r(e.locale, n) || r(o, n) || (i(o, n)[0] ?? null);
153
+ }, g = (e, t) => {
154
+ let [, n = ""] = e.split("/"), i = r(n, t);
155
+ return i ? {
156
+ prefix: i,
157
+ neutralPath: e.slice(n.length + 1) || "/"
158
+ } : {
159
+ prefix: null,
160
+ neutralPath: e
161
+ };
162
+ }, _ = (e) => {
163
+ let { pathname: i, headers: a, cookieLocale: o, forceDefault: s } = e, c = e.locales ?? [], l = e.defaultLocale || c[0] || "en";
164
+ if (c.length <= 1) return {
165
+ locale: l,
166
+ source: "default",
167
+ prefix: null,
168
+ neutralPath: i
169
+ };
170
+ let { prefix: u, neutralPath: f } = g(i, c);
171
+ if (u) return {
172
+ locale: u,
173
+ source: "prefix",
174
+ prefix: u,
175
+ neutralPath: f
176
+ };
177
+ if (s) return {
178
+ locale: l,
179
+ source: "default",
180
+ prefix: null,
181
+ neutralPath: f
182
+ };
183
+ let p = r(o, c);
184
+ if (p) return {
185
+ locale: p,
186
+ source: "cookie",
187
+ prefix: null,
188
+ neutralPath: f
189
+ };
190
+ let m = a ? d(a) : null, _ = m?.bestCountry?.countryCode?.toUpperCase() ?? null;
191
+ if (m) {
192
+ for (let e of m.languageData.languages) {
193
+ let t = h(e, c, _);
194
+ if (t) return {
195
+ locale: t,
196
+ source: "header",
197
+ prefix: null,
198
+ neutralPath: f
199
+ };
200
+ }
201
+ if (_) {
202
+ let e = c.filter((e) => n(e) === _), r = e.find((e) => t(e) === t(l)) ?? e[0];
203
+ if (r) return {
204
+ locale: r,
205
+ source: "geo",
206
+ prefix: null,
207
+ neutralPath: f
208
+ };
209
+ }
210
+ }
211
+ return {
212
+ locale: l,
213
+ source: "default",
214
+ prefix: null,
215
+ neutralPath: f
216
+ };
217
+ }, v = (e, t) => {
218
+ if (!e) return null;
219
+ for (let n of e.split(";")) {
220
+ let [e, ...r] = n.split("=");
221
+ if (e?.trim() === t) try {
222
+ return decodeURIComponent(r.join("=").trim());
223
+ } catch {
224
+ return r.join("=").trim();
225
+ }
226
+ }
227
+ return null;
228
+ }, y = (e, t) => {
229
+ let n = t?.secure ?? (typeof location < "u" && location.protocol === "https:");
230
+ return `${f}=${encodeURIComponent(e)}; Path=/; Max-Age=31536000; SameSite=Lax${n ? "; Secure" : ""}`;
231
+ }, b = (e, t) => {
232
+ if (!e) return null;
233
+ if (typeof e.get == "function") return e.get(t);
234
+ let n = e, r = n[t] ?? n[Object.keys(n).find((e) => e.toLowerCase() === t) ?? ""];
235
+ return r == null ? null : Array.isArray(r) ? r.join(", ") : r;
236
+ }, x = (e) => {
237
+ let { pathname: t, locales: n, defaultLocale: r, headers: i, cookie: s, hasRoute: c } = e, l = v(s === void 0 ? b(i, "cookie") : s, f), u = _({
238
+ locales: n,
239
+ defaultLocale: r,
240
+ pathname: t,
241
+ headers: i,
242
+ cookieLocale: l,
243
+ forceDefault: m(b(i, "user-agent"))
244
+ }), d = {
245
+ kind: "render",
246
+ locale: u.locale,
247
+ source: u.source
248
+ }, p = o({
249
+ locale: u.locale,
250
+ defaultLocale: r,
251
+ prefix: u.prefix,
252
+ neutralPath: u.neutralPath,
253
+ locales: n,
254
+ hasRoute: c,
255
+ currentPath: t
256
+ });
257
+ if (!p) return d;
258
+ let h = {
259
+ location: p,
260
+ "cache-control": a
261
+ };
262
+ return l !== u.locale && (h["set-cookie"] = y(u.locale, { secure: b(i, "x-forwarded-proto")?.split(",")[0]?.trim() === "https" })), {
263
+ ...d,
264
+ kind: "redirect",
265
+ path: p,
266
+ status: 302,
267
+ headers: h
268
+ };
269
+ }, S = (e, t = "", n = "") => new Response(null, {
270
+ status: e.status,
271
+ headers: new Headers({
272
+ ...e.headers,
273
+ location: `${e.path}${t}${n}`
274
+ })
275
+ }), C = (e, t) => t === "/" ? `/${e}` : `/${e}${t}`, w = (e, t, n) => {
276
+ if (!t || n.length <= 1) return e;
277
+ let { prefix: r } = g(e, n);
278
+ return r ? e : C(t, e);
279
+ }, T = (e) => e.options?.id ?? e.options?.path ?? e.id, E = (e, t) => !e || t === e || t.startsWith(`${e}/`) ? t : `${e}${t}`, D = (e) => {
280
+ let t = e.split("/").filter((e) => e && !e.startsWith("_"));
281
+ return t.length ? `/${t.join("/")}` : "/";
282
+ }, O = (e) => {
283
+ let t = (e, n) => {
284
+ let r = T(e), i = r?.startsWith("/") ? E(n, r) : n, a = r?.startsWith("/") ? [D(i)] : [];
285
+ return (e.children ? Array.isArray(e.children) ? e.children : Object.values(e.children) : []).reduce((e, n) => e.concat(t(n, i)), a);
286
+ };
287
+ return t(e ?? {}, "");
288
+ }, k = (e) => {
289
+ let t = null;
290
+ return (n) => {
291
+ if (!t) {
292
+ let n = O(e);
293
+ t = n.length === 0 ? () => !0 : A(n);
294
+ }
295
+ return t(n);
296
+ };
297
+ }, A = (e) => {
298
+ let t = e.map((e) => e.split("/").filter(Boolean));
299
+ return (e) => {
300
+ let n = e.split("/").filter(Boolean);
301
+ return t.some((e) => {
302
+ for (let t = 0; t < e.length; t++) {
303
+ let r = e[t];
304
+ if (r === "$") return !0;
305
+ if (t >= n.length || !r?.startsWith("$") && r !== n[t]) return !1;
306
+ }
307
+ return n.length === e.length;
308
+ });
309
+ };
310
+ }, j = /* @__PURE__ */ new WeakMap(), M = (e) => {
311
+ if (typeof e != "object" || !e) return k(e);
312
+ let t = e, n = j.get(t);
313
+ return n || (n = k(e), j.set(t, n)), n;
314
+ };
315
+ //#endregion
316
+ export { x as a, y as c, a as d, o as f, S as i, g as l, w as n, f as o, M as r, _ as s, k as t, d as u };
package/start.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { RequestMiddlewareAfterServer } from '@tanstack/react-start';
2
+
3
+ /**
4
+ * The server doorway: send a visitor to the URL that serves their language.
5
+ *
6
+ * It does NOT change what a URL renders — every URL renders exactly one language, which is what
7
+ * lets every page be cached by any shared cache. The redirect it emits carries
8
+ * `Cache-Control: private, no-store`, which is the property the whole model rests on and is
9
+ * built into the response rather than left to a caller to attach.
10
+ *
11
+ * Wire it as the site's entire `src/start.ts`:
12
+ *
13
+ * export const startInstance = createStart(() => ({
14
+ * requestMiddleware: [createLocaleMiddleware(LOCALE, routeTree)],
15
+ * }));
16
+ *
17
+ * Inert on a single-locale site, which is every site until a workspace adds a second locale.
18
+ */
19
+ export declare const createLocaleMiddleware: (config: ILocaleConfig, routeTree: unknown) => RequestMiddlewareAfterServer< {}, undefined, undefined>;
20
+
21
+ declare interface ILocaleConfig {
22
+ /** Every locale the site publishes. Empty or single-entry on a non-localized site. */
23
+ locales: string[];
24
+ /** The locale served at unprefixed URLs. */
25
+ defaultLocale: string;
26
+ /**
27
+ * Whether this site does localization at all. Every site is single-locale until a workspace
28
+ * adds a second one, and the whole mechanism is inert while this is false.
29
+ */
30
+ isLocalized: boolean;
31
+ /**
32
+ * Absolute origin for hreflang, or null when the site has no domain stamped yet. hreflang
33
+ * requires absolute URLs, so an unstamped `site.json` means no tags rather than broken ones.
34
+ */
35
+ origin: string | null;
36
+ }
37
+
38
+ export { }
package/start.js ADDED
@@ -0,0 +1,19 @@
1
+ import { a as e, i as t, r as n } from "./routes-CyKmkoRM.js";
2
+ import { createMiddleware as r } from "@tanstack/react-start";
3
+ //#region src/start/index.ts
4
+ var i = (i, a) => {
5
+ let o = n(a);
6
+ return r({ type: "request" }).server(async ({ request: n, next: r }) => {
7
+ if (!i.isLocalized) return r();
8
+ let a = new URL(n.url), s = e({
9
+ pathname: a.pathname,
10
+ locales: i.locales,
11
+ defaultLocale: i.defaultLocale,
12
+ headers: n.headers,
13
+ hasRoute: o
14
+ });
15
+ return s.kind === "redirect" ? t(s, a.search, a.hash) : r();
16
+ });
17
+ };
18
+ //#endregion
19
+ export { i as createLocaleMiddleware };