@levo-so/site-runtime 0.3.8 → 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.
@@ -1,5 +1,5 @@
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";
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
3
  import { jsx as p, jsxs as m } from "react/jsx-runtime";
4
4
  import { useEffect as h, useRef as g, useState as _ } from "react";
5
5
  import { ArrowUp as v, Sparkles as y } from "lucide-react";
@@ -64,7 +64,7 @@ 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-ClHFDgJ5.js"), E = (e) => {
67
+ }, w = (...e) => e.filter(Boolean).join(" "), T = () => import("./KBChatWidget-CuAtGhHT.js"), E = (e) => {
68
68
  let [t, n] = _(null), [r, i] = _(!1), [a, o] = _("");
69
69
  return t ? /* @__PURE__ */ p(t, {
70
70
  initialOpen: !0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@levo-so/site-runtime",
3
- "version": "0.3.8",
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.8",
81
- "@levo-so/insights": "0.3.8"
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-DPmVG7VB.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
@@ -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 };