@farm.js/core 0.1.0-beta.22 → 0.1.0-beta.23

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 (132) hide show
  1. package/dist/agent-runtime.d.mts +2 -1
  2. package/dist/agent-runtime.d.ts +2 -1
  3. package/dist/{app-BB8GCH1g.d.ts → app-CTFnOJaI.d.ts} +5 -3
  4. package/dist/{app-DwsTpyNZ.d.mts → app-DA6ospIq.d.mts} +5 -3
  5. package/dist/app-markdown.d.mts +2 -1
  6. package/dist/app-markdown.d.ts +2 -1
  7. package/dist/chunk-4IVNW5QD.mjs +82 -0
  8. package/dist/chunk-4IVNW5QD.mjs.map +1 -0
  9. package/dist/{chunk-DAUR3WUZ.mjs → chunk-5NOVWCFL.mjs} +2 -2
  10. package/dist/chunk-5NOVWCFL.mjs.map +1 -0
  11. package/dist/chunk-D42BNPZH.mjs +79 -0
  12. package/dist/chunk-D42BNPZH.mjs.map +1 -0
  13. package/dist/{chunk-LLPN5SEZ.mjs → chunk-DVPRBMU2.mjs} +2 -2
  14. package/dist/{chunk-ZP73P4VR.mjs → chunk-FJGTYLCO.mjs} +67 -20
  15. package/dist/chunk-FJGTYLCO.mjs.map +1 -0
  16. package/dist/chunk-GQVQESLY.mjs +25 -0
  17. package/dist/chunk-GQVQESLY.mjs.map +1 -0
  18. package/dist/chunk-H53KVQUU.mjs +48 -0
  19. package/dist/chunk-H53KVQUU.mjs.map +1 -0
  20. package/dist/chunk-HCGQYYHI.mjs +1 -0
  21. package/dist/chunk-HCGQYYHI.mjs.map +1 -0
  22. package/dist/{chunk-UCYWGN2P.mjs → chunk-OHNSROHS.mjs} +1 -1
  23. package/dist/{chunk-FRPWCMMG.mjs → chunk-SBWOTAX4.mjs} +63 -2
  24. package/dist/chunk-SBWOTAX4.mjs.map +1 -0
  25. package/dist/{chunk-XBKXKJX5.mjs → chunk-TX54PXAJ.mjs} +81 -25
  26. package/dist/chunk-TX54PXAJ.mjs.map +1 -0
  27. package/dist/{chunk-CEVMYGDL.mjs → chunk-YD5IRKVS.mjs} +13 -9
  28. package/dist/chunk-YD5IRKVS.mjs.map +1 -0
  29. package/dist/{client-plugins-QQntVkrv.d.mts → client-plugins-CCilIb_G.d.mts} +6 -2
  30. package/dist/{client-plugins-CbRum1fj.d.ts → client-plugins-DuuleQKk.d.ts} +6 -2
  31. package/dist/client-plugins.d.mts +2 -1
  32. package/dist/client-plugins.d.ts +2 -1
  33. package/dist/client.cjs +122 -35
  34. package/dist/client.cjs.map +1 -1
  35. package/dist/client.d.mts +2 -0
  36. package/dist/client.d.ts +2 -0
  37. package/dist/client.mjs +13 -2
  38. package/dist/config.d.mts +2 -1
  39. package/dist/config.d.ts +2 -1
  40. package/dist/{devtools-52FYXIEK.mjs → devtools-326RBQCN.mjs} +7 -6
  41. package/dist/{devtools-52FYXIEK.mjs.map → devtools-326RBQCN.mjs.map} +1 -1
  42. package/dist/docs.cjs.map +1 -1
  43. package/dist/docs.mjs +6 -5
  44. package/dist/index.cjs +431 -55
  45. package/dist/index.cjs.map +1 -1
  46. package/dist/index.d.mts +10 -7
  47. package/dist/index.d.ts +10 -7
  48. package/dist/index.mjs +66 -49
  49. package/dist/index.mjs.map +1 -1
  50. package/dist/integrations.d.mts +2 -1
  51. package/dist/integrations.d.ts +2 -1
  52. package/dist/internal/build-runtime.cjs +337 -34
  53. package/dist/internal/build-runtime.cjs.map +1 -1
  54. package/dist/internal/build-runtime.d.mts +4 -3
  55. package/dist/internal/build-runtime.d.ts +4 -3
  56. package/dist/internal/build-runtime.mjs +15 -12
  57. package/dist/internal/config-runtime.cjs +41 -0
  58. package/dist/internal/config-runtime.cjs.map +1 -1
  59. package/dist/internal/config-runtime.d.mts +3 -2
  60. package/dist/internal/config-runtime.d.ts +3 -2
  61. package/dist/internal/config-runtime.mjs +5 -4
  62. package/dist/internal/production-runtime.cjs +178 -0
  63. package/dist/internal/production-runtime.cjs.map +1 -1
  64. package/dist/internal/production-runtime.d.mts +20 -6
  65. package/dist/internal/production-runtime.d.ts +20 -6
  66. package/dist/internal/production-runtime.mjs +13 -1
  67. package/dist/internal/production-runtime.mjs.map +1 -1
  68. package/dist/{metadata-B5jBJHq1.d.ts → metadata-DyPRG0wX.d.ts} +1 -1
  69. package/dist/{metadata-BxOJ4FJl.d.mts → metadata-_GHcAySx.d.mts} +1 -1
  70. package/dist/middleware.d.mts +4 -3
  71. package/dist/middleware.d.ts +4 -3
  72. package/dist/plugin.cjs +219 -14
  73. package/dist/plugin.cjs.map +1 -1
  74. package/dist/plugin.d.mts +2 -1
  75. package/dist/plugin.d.ts +2 -1
  76. package/dist/plugin.mjs +11 -8
  77. package/dist/{production-runtime-Bxua86uR.d.mts → production-runtime-C4cO3esK.d.mts} +1 -1
  78. package/dist/{production-runtime-CZqXjRVi.d.ts → production-runtime-DrEy8kBO.d.ts} +1 -1
  79. package/dist/{request-7V0GaZK_.d.mts → request-B2PpOxYK.d.mts} +1 -1
  80. package/dist/{request-B5XYBv5a.d.ts → request-D40lt6aN.d.ts} +1 -1
  81. package/dist/request.d.mts +3 -2
  82. package/dist/request.d.ts +3 -2
  83. package/dist/routes.d.mts +2 -1
  84. package/dist/routes.d.ts +2 -1
  85. package/dist/server-plugins.d.mts +3 -2
  86. package/dist/server-plugins.d.ts +3 -2
  87. package/dist/server.cjs +241 -19
  88. package/dist/server.cjs.map +1 -1
  89. package/dist/server.d.mts +8 -6
  90. package/dist/server.d.ts +8 -6
  91. package/dist/server.mjs +20 -11
  92. package/dist/server.mjs.map +1 -1
  93. package/dist/testing.d.mts +2 -1
  94. package/dist/testing.d.ts +2 -1
  95. package/dist/theme/client.cjs +115 -0
  96. package/dist/theme/client.cjs.map +1 -0
  97. package/dist/theme/client.d.mts +17 -0
  98. package/dist/theme/client.d.ts +17 -0
  99. package/dist/theme/client.mjs +16 -0
  100. package/dist/theme/client.mjs.map +1 -0
  101. package/dist/theme/index.cjs +71 -0
  102. package/dist/theme/index.cjs.map +1 -0
  103. package/dist/theme/index.d.mts +6 -0
  104. package/dist/theme/index.d.ts +6 -0
  105. package/dist/theme/index.mjs +9 -0
  106. package/dist/theme/index.mjs.map +1 -0
  107. package/dist/theme/server.cjs +191 -0
  108. package/dist/theme/server.cjs.map +1 -0
  109. package/dist/theme/server.d.mts +8 -0
  110. package/dist/theme/server.d.ts +8 -0
  111. package/dist/theme/server.mjs +18 -0
  112. package/dist/theme/server.mjs.map +1 -0
  113. package/dist/types-CsR8fpgF.d.mts +30 -0
  114. package/dist/types-CsR8fpgF.d.ts +30 -0
  115. package/dist/{utils-xTFxzu47.d.ts → utils-3sQgfkya.d.ts} +1 -1
  116. package/dist/{utils-s9pN0Yep.d.mts → utils-Bop7bly-.d.mts} +1 -1
  117. package/dist/version.cjs +1 -1
  118. package/dist/version.cjs.map +1 -1
  119. package/dist/version.mjs +1 -1
  120. package/dist/vite.cjs +242 -15
  121. package/dist/vite.cjs.map +1 -1
  122. package/dist/vite.d.mts +2 -1
  123. package/dist/vite.d.ts +2 -1
  124. package/dist/vite.mjs +11 -8
  125. package/package.json +25 -1
  126. package/dist/chunk-CEVMYGDL.mjs.map +0 -1
  127. package/dist/chunk-DAUR3WUZ.mjs.map +0 -1
  128. package/dist/chunk-FRPWCMMG.mjs.map +0 -1
  129. package/dist/chunk-XBKXKJX5.mjs.map +0 -1
  130. package/dist/chunk-ZP73P4VR.mjs.map +0 -1
  131. /package/dist/{chunk-LLPN5SEZ.mjs.map → chunk-DVPRBMU2.mjs.map} +0 -0
  132. /package/dist/{chunk-UCYWGN2P.mjs.map → chunk-OHNSROHS.mjs.map} +0 -0
package/dist/index.cjs CHANGED
@@ -14325,12 +14325,201 @@ body {
14325
14325
  }
14326
14326
  });
14327
14327
 
14328
+ // src/theme/config.ts
14329
+ function resolveFarmThemeConfig(config, basePath = "/") {
14330
+ if (config && "enabled" in config) {
14331
+ return config;
14332
+ }
14333
+ if (!config) {
14334
+ return {
14335
+ enabled: false,
14336
+ default: "system",
14337
+ storageKey: DEFAULT_FARM_THEME_STORAGE_KEY,
14338
+ cookiePath: normalizeCookiePath(basePath)
14339
+ };
14340
+ }
14341
+ const storageKey = config.storageKey?.trim() || DEFAULT_FARM_THEME_STORAGE_KEY;
14342
+ if (!STORAGE_KEY_PATTERN.test(storageKey)) {
14343
+ throw new Error(
14344
+ "theme.storageKey may only contain letters, numbers, dots, underscores, and hyphens."
14345
+ );
14346
+ }
14347
+ const defaultTheme = config.default ?? "system";
14348
+ if (defaultTheme !== "light" && defaultTheme !== "dark" && defaultTheme !== "system") {
14349
+ throw new Error('theme.default must be "light", "dark", or "system".');
14350
+ }
14351
+ return {
14352
+ enabled: true,
14353
+ default: defaultTheme,
14354
+ storageKey,
14355
+ cookiePath: normalizeCookiePath(basePath)
14356
+ };
14357
+ }
14358
+ function normalizeCookiePath(basePath) {
14359
+ const normalized = `/${basePath}`.replace(/\/{2,}/g, "/");
14360
+ if (normalized === "/") return normalized;
14361
+ return normalized.replace(/\/$/, "");
14362
+ }
14363
+ var DEFAULT_FARM_THEME_STORAGE_KEY, STORAGE_KEY_PATTERN;
14364
+ var init_config2 = __esm({
14365
+ "src/theme/config.ts"() {
14366
+ "use strict";
14367
+ DEFAULT_FARM_THEME_STORAGE_KEY = "farm-theme";
14368
+ STORAGE_KEY_PATTERN = /^[A-Za-z0-9._-]+$/;
14369
+ __name(resolveFarmThemeConfig, "resolveFarmThemeConfig");
14370
+ __name(normalizeCookiePath, "normalizeCookiePath");
14371
+ }
14372
+ });
14373
+
14374
+ // src/theme/server-runtime.ts
14375
+ function createFarmThemeDocumentParts(input, basePath = "/", serverTheme) {
14376
+ const config = resolveFarmThemeConfig(input, basePath);
14377
+ if (!config.enabled) return { attributes: "", head: "" };
14378
+ const hydrationTheme = serverTheme ?? config.default;
14379
+ const initialTheme = hydrationTheme === "system" ? "light" : hydrationTheme;
14380
+ const script = createFarmThemeBootstrapScript(config, hydrationTheme);
14381
+ return {
14382
+ attributes: ` data-theme="${initialTheme}"`,
14383
+ head: `<style id="${THEME_STYLE_ID}">:root[data-theme="light"]{color-scheme:light}:root[data-theme="dark"]{color-scheme:dark}</style><script id="${THEME_SCRIPT_ID}">${script}</script>`
14384
+ };
14385
+ }
14386
+ function createFarmThemeBootstrapScript(config, serverTheme = config.default) {
14387
+ return `(function(config,serverTheme){
14388
+ var isTheme=function(value){return value==="light"||value==="dark"||value==="system";};
14389
+ var decode=function(value){try{return decodeURIComponent(value);}catch(_error){return value;}};
14390
+ var readCookie=function(){var entries=document.cookie.split(";");for(var index=0;index<entries.length;index++){var entry=entries[index];var separator=entry.indexOf("=");if(separator<0)continue;if(decode(entry.slice(0,separator).trim())===config.storageKey)return decode(entry.slice(separator+1).trim());}};
14391
+ var media=window.matchMedia("(prefers-color-scheme: dark)");
14392
+ var resolveTheme=function(theme){return theme==="system"?(media.matches?"dark":"light"):theme;};
14393
+ var storedTheme=readCookie();
14394
+ var preference=isTheme(storedTheme)?storedTheme:config.default;
14395
+ var serverSnapshot={theme:serverTheme,resolvedTheme:serverTheme==="system"?undefined:serverTheme,mounted:false};
14396
+ var apply=function(){var resolvedTheme=resolveTheme(preference);document.documentElement.dataset.theme=resolvedTheme;var snapshot={theme:preference,resolvedTheme:resolvedTheme,mounted:true};if(window.__FARM_THEME__)window.__FARM_THEME__.snapshot=snapshot;return snapshot;};
14397
+ var emit=function(){var snapshot=apply();window.dispatchEvent(new CustomEvent("farm:themechange",{detail:snapshot}));};
14398
+ var persist=function(theme){var secure=window.location.protocol==="https:"?"; Secure":"";document.cookie=encodeURIComponent(config.storageKey)+"="+encodeURIComponent(theme)+"; Path="+config.cookiePath+"; Max-Age=31536000; SameSite=Lax"+secure;try{localStorage.setItem(config.storageKey,theme);}catch(_error){}};
14399
+ var setTheme=function(theme){if(!isTheme(theme))throw new TypeError("Unknown FARMJS theme: "+String(theme));preference=theme;persist(theme);emit();};
14400
+ var initialSnapshot={theme:preference,resolvedTheme:resolveTheme(preference),mounted:true};
14401
+ window.__FARM_THEME__={config:config,serverSnapshot:serverSnapshot,snapshot:initialSnapshot,setTheme:setTheme};
14402
+ document.documentElement.dataset.theme=initialSnapshot.resolvedTheme;
14403
+ var handleSystemChange=function(){if(preference==="system")emit();};
14404
+ if(typeof media.addEventListener==="function")media.addEventListener("change",handleSystemChange);else if(typeof media.addListener==="function")media.addListener(handleSystemChange);
14405
+ window.addEventListener("storage",function(event){if(event.key!==config.storageKey||!isTheme(event.newValue))return;preference=event.newValue;persist(preference);emit();});
14406
+ })(${serializeInlineValue(config)},${serializeInlineValue(serverTheme)});`;
14407
+ }
14408
+ function serializeInlineValue(value) {
14409
+ return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
14410
+ }
14411
+ var THEME_SCRIPT_ID, THEME_STYLE_ID;
14412
+ var init_server_runtime = __esm({
14413
+ "src/theme/server-runtime.ts"() {
14414
+ "use strict";
14415
+ init_config2();
14416
+ THEME_SCRIPT_ID = "farm-theme-script";
14417
+ THEME_STYLE_ID = "farm-theme-style";
14418
+ __name(createFarmThemeDocumentParts, "createFarmThemeDocumentParts");
14419
+ __name(createFarmThemeBootstrapScript, "createFarmThemeBootstrapScript");
14420
+ __name(serializeInlineValue, "serializeInlineValue");
14421
+ }
14422
+ });
14423
+
14424
+ // src/theme/bridge.ts
14425
+ function _setFarmThemeServerSnapshotResolver(resolver) {
14426
+ globalThis[FARM_THEME_SERVER_SNAPSHOT_RESOLVER] = resolver;
14427
+ }
14428
+ function getFarmThemeServerSnapshot() {
14429
+ return globalThis[FARM_THEME_SERVER_SNAPSHOT_RESOLVER]?.() ?? FALLBACK_SERVER_SNAPSHOT;
14430
+ }
14431
+ var FALLBACK_SERVER_SNAPSHOT, FARM_THEME_SERVER_SNAPSHOT_RESOLVER;
14432
+ var init_bridge2 = __esm({
14433
+ "src/theme/bridge.ts"() {
14434
+ "use strict";
14435
+ FALLBACK_SERVER_SNAPSHOT = Object.freeze({
14436
+ theme: "system",
14437
+ resolvedTheme: void 0,
14438
+ mounted: false
14439
+ });
14440
+ FARM_THEME_SERVER_SNAPSHOT_RESOLVER = /* @__PURE__ */ Symbol.for("farm.js.theme.server-snapshot-resolver");
14441
+ __name(_setFarmThemeServerSnapshotResolver, "_setFarmThemeServerSnapshotResolver");
14442
+ __name(getFarmThemeServerSnapshot, "getFarmThemeServerSnapshot");
14443
+ }
14444
+ });
14445
+
14446
+ // src/theme/server.ts
14447
+ function _setDefaultFarmThemeConfig(config, basePath = "/") {
14448
+ defaultThemeConfig = resolveFarmThemeConfig(config, basePath);
14449
+ }
14450
+ function getTheme(request = getCurrentRequest()) {
14451
+ return readFarmThemePreference(request, defaultThemeConfig);
14452
+ }
14453
+ function getThemeSnapshot(request = getCurrentRequest()) {
14454
+ const theme = readFarmThemePreference(request, defaultThemeConfig);
14455
+ return {
14456
+ theme,
14457
+ resolvedTheme: theme === "system" ? void 0 : theme,
14458
+ mounted: false
14459
+ };
14460
+ }
14461
+ function readFarmThemePreference(request, config) {
14462
+ if (!config.enabled) return config.default;
14463
+ const stored = readCookie3(request.headers.get("cookie"), config.storageKey);
14464
+ return isFarmThemePreference(stored) ? stored : config.default;
14465
+ }
14466
+ function readCookie3(cookieHeader, name) {
14467
+ if (!cookieHeader) return void 0;
14468
+ for (const entry of cookieHeader.split(";")) {
14469
+ const separator = entry.indexOf("=");
14470
+ if (separator < 0) continue;
14471
+ const key = decodeCookieValue(entry.slice(0, separator).trim());
14472
+ if (key !== name) continue;
14473
+ return decodeCookieValue(entry.slice(separator + 1).trim());
14474
+ }
14475
+ return void 0;
14476
+ }
14477
+ function decodeCookieValue(value) {
14478
+ try {
14479
+ return decodeURIComponent(value);
14480
+ } catch {
14481
+ return value;
14482
+ }
14483
+ }
14484
+ function isFarmThemePreference(value) {
14485
+ return value === "light" || value === "dark" || value === "system";
14486
+ }
14487
+ var defaultThemeConfig;
14488
+ var init_server3 = __esm({
14489
+ "src/theme/server.ts"() {
14490
+ "use strict";
14491
+ init_request();
14492
+ init_bridge2();
14493
+ init_config2();
14494
+ defaultThemeConfig = resolveFarmThemeConfig(void 0);
14495
+ __name(_setDefaultFarmThemeConfig, "_setDefaultFarmThemeConfig");
14496
+ __name(getTheme, "getTheme");
14497
+ __name(getThemeSnapshot, "getThemeSnapshot");
14498
+ __name(readFarmThemePreference, "readFarmThemePreference");
14499
+ __name(readCookie3, "readCookie");
14500
+ __name(decodeCookieValue, "decodeCookieValue");
14501
+ __name(isFarmThemePreference, "isFarmThemePreference");
14502
+ _setFarmThemeServerSnapshotResolver(() => {
14503
+ try {
14504
+ return getThemeSnapshot();
14505
+ } catch {
14506
+ const theme = defaultThemeConfig.default;
14507
+ return {
14508
+ theme,
14509
+ resolvedTheme: theme === "system" ? void 0 : theme,
14510
+ mounted: false
14511
+ };
14512
+ }
14513
+ });
14514
+ }
14515
+ });
14516
+
14328
14517
  // src/server/renderer.ts
14329
14518
  function hasRequestHeader(req, name) {
14330
14519
  const value = req.headers[name.toLowerCase()];
14331
14520
  return Array.isArray(value) ? value.length > 0 : Boolean(value);
14332
14521
  }
14333
- function serializeInlineValue(value) {
14522
+ function serializeInlineValue2(value) {
14334
14523
  return JSON.stringify(value).replace(/</g, "\\u003c").replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
14335
14524
  }
14336
14525
  function escapeHtmlAttribute2(value) {
@@ -14417,7 +14606,7 @@ function createDocumentFooter(options) {
14417
14606
  }
14418
14607
  function createDeferredHydrationScript(records) {
14419
14608
  if (records.length === 0) return "";
14420
- return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue(
14609
+ return `<script>window.__FARM_DEFERRED_DATA__=${serializeInlineValue2(
14421
14610
  snapshotDeferredData(records)
14422
14611
  )};</script>`;
14423
14612
  }
@@ -14510,10 +14699,12 @@ var init_renderer = __esm({
14510
14699
  init_font_vite();
14511
14700
  init_metadata_image();
14512
14701
  init_not_found();
14702
+ init_server_runtime();
14703
+ init_server3();
14513
14704
  cachedClerkProvider = null;
14514
14705
  importRuntimeModule = new Function("specifier", "return import(specifier);");
14515
14706
  __name(hasRequestHeader, "hasRequestHeader");
14516
- __name(serializeInlineValue, "serializeInlineValue");
14707
+ __name(serializeInlineValue2, "serializeInlineValue");
14517
14708
  __name(escapeHtmlAttribute2, "escapeHtmlAttribute");
14518
14709
  __name(appendResponseHeader, "appendResponseHeader");
14519
14710
  __name(appendResponseVary, "appendResponseVary");
@@ -15601,9 +15792,9 @@ var init_renderer = __esm({
15601
15792
  slots: routeSlotPayload
15602
15793
  });
15603
15794
  const propsScript = `<script>
15604
- window.__FARM_PROPS__ = ${serializeInlineValue(deferredProps.data.page)};
15605
- window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue(deferredProps.data.slots)};
15606
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(deploymentId)};
15795
+ window.__FARM_PROPS__ = ${serializeInlineValue2(deferredProps.data.page)};
15796
+ window.__FARM_ROUTE_SLOTS__ = ${serializeInlineValue2(deferredProps.data.slots)};
15797
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(deploymentId)};
15607
15798
  window.__FARM_PATH__ = ${JSON.stringify(req.__FARM_ROUTE__ || req.url || "/")};
15608
15799
  window.__FARM_IS_CLIENT__ = ${JSON.stringify(isClientComponent)};
15609
15800
  window.__FARM_PAGE_SHOULD_HYDRATE__ = ${JSON.stringify(
@@ -15621,7 +15812,7 @@ window.__FARM_LOADING_MODULE__ = ${JSON.stringify(
15621
15812
  )};
15622
15813
  window.__FARM_MANIFEST__ = ${JSON.stringify(clientManifest)};
15623
15814
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
15624
- ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(getFarmI18nClientSnapshot())};` : ""}
15815
+ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue2(getFarmI18nClientSnapshot())};` : ""}
15625
15816
  </script>`;
15626
15817
  const hydrationClickQueueScript = isClientComponent || req.__FARM_SHOULD_HYDRATE__ === true || req.__FARM_HAS_HYDRATABLE_ROUTE_SLOTS__ === true ? createPreHydrationClickQueueScript() : "";
15627
15818
  const {
@@ -15632,6 +15823,11 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
15632
15823
  const i18nSnapshot = getFarmI18nClientSnapshot();
15633
15824
  const i18nAlternateTags = i18nSnapshot ? renderI18nAlternateLinks(req.__FARM_ROUTE__ || req.url || "/", i18nSnapshot) : "";
15634
15825
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
15826
+ const themeDocument = createFarmThemeDocumentParts(
15827
+ this.config.theme,
15828
+ this.config.basePath,
15829
+ getTheme()
15830
+ );
15635
15831
  const streamRoot = import_react5.default.createElement("div", { style: { display: "contents" } }, element);
15636
15832
  const { pipe } = (0, import_server2.renderToPipeableStream)(streamRoot, {
15637
15833
  onShellReady() {
@@ -15645,8 +15841,9 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
15645
15841
  console.log(`[FARM STREAM] onShellReady at ${shellReadyMs}ms`);
15646
15842
  }
15647
15843
  const shell = `<!DOCTYPE html>
15648
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
15844
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
15649
15845
  <head>
15846
+ ${themeDocument.head}
15650
15847
  <meta charset="utf-8">
15651
15848
  <meta name="viewport" content="width=device-width, initial-scale=1">
15652
15849
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(deploymentId)}">
@@ -15848,15 +16045,21 @@ ${getFarmI18nClientSnapshot() ? `window.__FARM_I18N__ = ${serializeInlineValue(g
15848
16045
  const i18nSnapshot = getFarmI18nClientSnapshot();
15849
16046
  const clientScript = isClientComponent ? ` <script type="module" src="/@farm/client.js"></script>` : "";
15850
16047
  const integrationManifestScript = `<script>
15851
- window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue(this.getDeploymentId())};
16048
+ window.__FARM_DEPLOYMENT_ID__ = ${serializeInlineValue2(this.getDeploymentId())};
15852
16049
  window.__FARM_INTEGRATION_API_MANIFEST__ = ${JSON.stringify(getRegisteredIntegrationAPIManifest())};
15853
- ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue(i18nSnapshot)};` : ""}
16050
+ ${i18nSnapshot ? `window.__FARM_I18N__ = ${serializeInlineValue2(i18nSnapshot)};` : ""}
15854
16051
  </script>`;
15855
16052
  const alternateLinks = i18nSnapshot ? renderI18nAlternateLinks(requestPath, i18nSnapshot) : "";
15856
16053
  const fontHead = renderFarmFontDevHead(this.config.root || process.cwd());
16054
+ const themeDocument = createFarmThemeDocumentParts(
16055
+ this.config.theme,
16056
+ this.config.basePath,
16057
+ getTheme()
16058
+ );
15857
16059
  return `<!DOCTYPE html>
15858
- <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}>
16060
+ <html lang="${escapeHtmlAttribute2(i18nSnapshot?.locale || "en")}"${i18nSnapshot ? ` dir="${i18nSnapshot.direction}"` : ""}${themeDocument.attributes}>
15859
16061
  <head>
16062
+ ${themeDocument.head}
15860
16063
  <meta charset="utf-8">
15861
16064
  <meta name="viewport" content="width=device-width, initial-scale=1">
15862
16065
  <meta name="farm-deployment-id" content="${escapeHtmlAttribute2(this.getDeploymentId())}">
@@ -16218,6 +16421,8 @@ var init_app = __esm({
16218
16421
  init_auth_config();
16219
16422
  init_preload();
16220
16423
  init_security();
16424
+ init_config2();
16425
+ init_server3();
16221
16426
  defaultDocsConfig = {
16222
16427
  enabled: false,
16223
16428
  entry: "/docs",
@@ -16228,6 +16433,7 @@ var init_app = __esm({
16228
16433
  constructor(config = {}, viteServer) {
16229
16434
  this.config = this.normalizeConfig(config);
16230
16435
  configureFarmObservability(this.config.observability);
16436
+ _setDefaultFarmThemeConfig(this.config.theme);
16231
16437
  this.i18nRuntime = createFarmI18nRuntime(this.config.i18n);
16232
16438
  _setDefaultFarmI18nRuntime(this.i18nRuntime);
16233
16439
  this.viteServer = viteServer;
@@ -16286,6 +16492,7 @@ var init_app = __esm({
16286
16492
  security: resolveFarmSecurityConfig(config.security),
16287
16493
  images: resolveFarmImageConfig(config.images),
16288
16494
  performance: resolveFarmPerformanceConfig(config.performance),
16495
+ theme: resolveFarmThemeConfig(config.theme, config.basePath || "/"),
16289
16496
  i18n: isResolvedI18nConfig(config.i18n) ? config.i18n : resolveFarmI18nConfig(config.i18n, {
16290
16497
  root,
16291
16498
  mode: process.env.NODE_ENV === "production" ? "production" : "development"
@@ -19853,7 +20060,7 @@ var init_environment_vite = __esm({
19853
20060
  var version;
19854
20061
  var init_package = __esm({
19855
20062
  "package.json"() {
19856
- version = "0.1.0-beta.22";
20063
+ version = "0.1.0-beta.23";
19857
20064
  }
19858
20065
  });
19859
20066
 
@@ -20753,6 +20960,36 @@ var init_fonts = __esm({
20753
20960
  }
20754
20961
  });
20755
20962
 
20963
+ // src/theme/vite.ts
20964
+ function createFarmThemeCssPlugin(input, basePath = "/") {
20965
+ const config = resolveFarmThemeConfig(input, basePath);
20966
+ return {
20967
+ name: "farm:theme-css",
20968
+ enforce: "pre",
20969
+ transform(code, id) {
20970
+ if (!config.enabled || !/\.css(?:\?.*)?$/.test(id) || !/@import\s+["']tailwindcss["']/.test(code) || /@custom-variant\s+dark\b/.test(code)) {
20971
+ return null;
20972
+ }
20973
+ return {
20974
+ code: `${code.trimEnd()}
20975
+
20976
+ ${FARM_DARK_VARIANT}
20977
+ `,
20978
+ map: null
20979
+ };
20980
+ }
20981
+ };
20982
+ }
20983
+ var FARM_DARK_VARIANT;
20984
+ var init_vite = __esm({
20985
+ "src/theme/vite.ts"() {
20986
+ "use strict";
20987
+ init_config2();
20988
+ FARM_DARK_VARIANT = '@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));';
20989
+ __name(createFarmThemeCssPlugin, "createFarmThemeCssPlugin");
20990
+ }
20991
+ });
20992
+
20756
20993
  // src/docs/last-modified.ts
20757
20994
  function normalizeRelativePath(value) {
20758
20995
  return value.replace(/\\/g, "/").replace(/^\.\/+/, "");
@@ -24730,6 +24967,7 @@ async function resolveConfig(userConfig, mode) {
24730
24967
  routeRules,
24731
24968
  images: resolveFarmImageConfig(userConfig.images),
24732
24969
  performance: resolveFarmPerformanceConfig(userConfig.performance),
24970
+ theme: resolveFarmThemeConfig(userConfig.theme, userConfig.basePath || "/"),
24733
24971
  publicDir: userConfig.publicDir || "public",
24734
24972
  i18n: resolveFarmI18nConfig(userConfig.i18n, { root, mode }),
24735
24973
  openapi: {
@@ -24807,7 +25045,7 @@ async function loadConfig(rootDir, configPath, mode = process.env.NODE_ENV === "
24807
25045
  return void 0;
24808
25046
  }
24809
25047
  var import_path9, FARM_RESOLVED_CUSTOM_CONTEXT, DOCS_CONFIG_FILENAMES;
24810
- var init_config2 = __esm({
25048
+ var init_config3 = __esm({
24811
25049
  "src/config.ts"() {
24812
25050
  "use strict";
24813
25051
  init_integrations();
@@ -24828,6 +25066,7 @@ var init_config2 = __esm({
24828
25066
  init_auth_config();
24829
25067
  init_preload();
24830
25068
  init_security();
25069
+ init_config2();
24831
25070
  init_config_entry();
24832
25071
  FARM_RESOLVED_CUSTOM_CONTEXT = /* @__PURE__ */ Symbol.for("farm.resolvedCustomContext");
24833
25072
  __name(hasCustomFarmRouteContext, "hasCustomFarmRouteContext");
@@ -25332,7 +25571,7 @@ var init_api = __esm({
25332
25571
  "src/docs/api.ts"() {
25333
25572
  "use strict";
25334
25573
  import_docs2 = require("@farming-labs/docs");
25335
- init_config2();
25574
+ init_config3();
25336
25575
  init_handler();
25337
25576
  __name(isRecord4, "isRecord");
25338
25577
  __name(isResolvedDocsConfig2, "isResolvedDocsConfig");
@@ -26317,7 +26556,7 @@ var init_devtools = __esm({
26317
26556
  "src/devtools.ts"() {
26318
26557
  "use strict";
26319
26558
  import_node_path14 = __toESM(require("path"));
26320
- init_config2();
26559
+ init_config3();
26321
26560
  init_cron();
26322
26561
  init_route_runtime();
26323
26562
  __name(normalizePath, "normalizePath");
@@ -31295,14 +31534,22 @@ async function renderPage(pageData) {
31295
31534
  if (!doc.documentElement || !doc.body) return false;
31296
31535
 
31297
31536
  resetReactRoots();
31537
+ const activeFarmTheme =
31538
+ window.__FARM_THEME__?.snapshot?.resolvedTheme ||
31539
+ document.documentElement.getAttribute('data-theme');
31298
31540
  Array.from(document.documentElement.attributes).forEach(function(attr) {
31541
+ if (attr.name === 'data-theme') return;
31299
31542
  if (!doc.documentElement.hasAttribute(attr.name)) {
31300
31543
  document.documentElement.removeAttribute(attr.name);
31301
31544
  }
31302
31545
  });
31303
31546
  Array.from(doc.documentElement.attributes).forEach(function(attr) {
31547
+ if (attr.name === 'data-theme') return;
31304
31548
  document.documentElement.setAttribute(attr.name, attr.value);
31305
31549
  });
31550
+ if (activeFarmTheme) {
31551
+ document.documentElement.setAttribute('data-theme', activeFarmTheme);
31552
+ }
31306
31553
 
31307
31554
  document.head.innerHTML = doc.head ? doc.head.innerHTML : '';
31308
31555
  document.body.innerHTML = doc.body.innerHTML;
@@ -31311,6 +31558,7 @@ async function renderPage(pageData) {
31311
31558
 
31312
31559
  setTimeout(function() {
31313
31560
  Array.from(document.querySelectorAll('script')).forEach(function(script) {
31561
+ if (script.id === 'farm-theme-script') return;
31314
31562
  const freshScript = document.createElement('script');
31315
31563
  Array.from(script.attributes).forEach(function(attr) {
31316
31564
  freshScript.setAttribute(attr.name, attr.value);
@@ -31805,6 +32053,7 @@ async function defineConfig2(config = {}) {
31805
32053
  };
31806
32054
  return {
31807
32055
  plugins: [
32056
+ createFarmThemeCssPlugin(config.theme, config.basePath),
31808
32057
  tailwindcss(),
31809
32058
  viteBrowserExternalPlugin,
31810
32059
  farmI18nClientBridgePlugin(),
@@ -31877,7 +32126,7 @@ async function defineConfig2(config = {}) {
31877
32126
  };
31878
32127
  }
31879
32128
  var fs7, path25, ALL_TYPE_ARTIFACTS, createEmptyTypeArtifactSelection, FARM_I18N_CLIENT_BRIDGE_ID, EMPTY_FARM_DOCS_SEARCH_CLIENT_RUNTIME, FARM_CONFIG_FILENAMES;
31880
- var init_vite = __esm({
32129
+ var init_vite2 = __esm({
31881
32130
  "src/vite.ts"() {
31882
32131
  "use strict";
31883
32132
  init_app();
@@ -31914,6 +32163,7 @@ var init_vite = __esm({
31914
32163
  init_fonts();
31915
32164
  init_server_http();
31916
32165
  init_cli_colors();
32166
+ init_vite();
31917
32167
  ALL_TYPE_ARTIFACTS = {
31918
32168
  routes: true,
31919
32169
  api: true,
@@ -32013,7 +32263,7 @@ var init_plugin = __esm({
32013
32263
  init_env();
32014
32264
  init_request_context();
32015
32265
  init_plugin_integration_context();
32016
- init_vite();
32266
+ init_vite2();
32017
32267
  _FarmRuntimeShutdownError = class _FarmRuntimeShutdownError extends Error {
32018
32268
  constructor(message, errors) {
32019
32269
  super(message);
@@ -33577,6 +33827,7 @@ __export(src_exports, {
33577
33827
  getServerActionInvalidations: () => getServerActionInvalidations,
33578
33828
  getServerActionSignal: () => getServerActionSignal,
33579
33829
  getStorage: () => getStorage,
33830
+ getTheme: () => getTheme2,
33580
33831
  globFiles: () => globFiles,
33581
33832
  hasFarmRouteRuntimeControls: () => hasFarmRouteRuntimeControls,
33582
33833
  hasISR: () => hasISR,
@@ -33693,6 +33944,7 @@ __export(src_exports, {
33693
33944
  resolveFarmLayoutFonts: () => resolveFarmLayoutFonts,
33694
33945
  resolveFarmRouteRuleRuntimeConfig: () => resolveFarmRouteRuleRuntimeConfig,
33695
33946
  resolveFarmRouteRuntimeConfig: () => resolveFarmRouteRuntimeConfig,
33947
+ resolveFarmThemeConfig: () => resolveFarmThemeConfig,
33696
33948
  resolveIntegrationOrmRuntimeClient: () => resolveIntegrationOrmRuntimeClient,
33697
33949
  resolveIntegrationPlugins: () => resolveIntegrationPlugins,
33698
33950
  resolveMarkdownConfig: () => resolveMarkdownConfig,
@@ -33719,12 +33971,14 @@ __export(src_exports, {
33719
33971
  segmentsToPattern: () => segmentsToPattern,
33720
33972
  serverEnv: () => serverEnv,
33721
33973
  setEnv: () => setEnv,
33974
+ setTheme: () => setTheme,
33722
33975
  snapshotDeferredData: () => snapshotDeferredData,
33723
33976
  sqliteStorage: () => sqliteStorage,
33724
33977
  storageCacheAdapter: () => storageCacheAdapter,
33725
33978
  titleFromMarkdown: () => titleFromMarkdown,
33726
33979
  toFormData: () => toFormData,
33727
33980
  toViteModuleId: () => toViteModuleId,
33981
+ toggleTheme: () => toggleTheme,
33728
33982
  unstable_cache: () => unstable_cache,
33729
33983
  unwrapMiddleware: () => unwrapMiddleware,
33730
33984
  updateTag: () => updateTag,
@@ -33740,6 +33994,7 @@ __export(src_exports, {
33740
33994
  useSearchParams: () => useSearchParams,
33741
33995
  useServerFn: () => useServerFn,
33742
33996
  useServerQuery: () => useServerQuery,
33997
+ useTheme: () => useTheme,
33743
33998
  validateServerActionRequest: () => validateServerActionRequest,
33744
33999
  vercelBlobStorage: () => vercelBlobStorage,
33745
34000
  vercelKVStorage: () => vercelKVStorage,
@@ -33769,7 +34024,7 @@ __name(FarmProvider, "FarmProvider");
33769
34024
  // src/index.ts
33770
34025
  init_request();
33771
34026
  init_plugin();
33772
- init_config2();
34027
+ init_config3();
33773
34028
  init_layers();
33774
34029
 
33775
34030
  // src/hmr.ts
@@ -37292,6 +37547,9 @@ init_cron();
37292
37547
  init_env();
37293
37548
  init_env_types();
37294
37549
 
37550
+ // src/theme/index.ts
37551
+ init_config2();
37552
+
37295
37553
  // src/environment.ts
37296
37554
  var _FarmEnvironmentError = class _FarmEnvironmentError extends Error {
37297
37555
  constructor(api3, expected, actual) {
@@ -38000,12 +38258,12 @@ function useServerQuery(query, input, options = {}) {
38000
38258
  const mountedKeyRef = (0, import_react9.useRef)(void 0);
38001
38259
  inputRef.current = input;
38002
38260
  optionsRef.current = options;
38003
- const subscribe = (0, import_react9.useCallback)(
38261
+ const subscribe2 = (0, import_react9.useCallback)(
38004
38262
  (listener) => cache.subscribe(key, listener),
38005
38263
  [cache, key]
38006
38264
  );
38007
38265
  const getSnapshot = (0, import_react9.useCallback)(() => cache.get(key), [cache, key]);
38008
- const entry = (0, import_react9.useSyncExternalStore)(subscribe, getSnapshot, () => void 0);
38266
+ const entry = (0, import_react9.useSyncExternalStore)(subscribe2, getSnapshot, () => void 0);
38009
38267
  const run = (0, import_react9.useCallback)(
38010
38268
  (force = false) => fetchServerQuery(query, inputRef.current, {
38011
38269
  ...optionsRef.current,
@@ -38131,7 +38389,7 @@ init_deployment();
38131
38389
  init_generate_route_types();
38132
38390
 
38133
38391
  // src/build/index.ts
38134
- init_config2();
38392
+ init_config3();
38135
38393
  var import_path14 = __toESM(require("path"));
38136
38394
  init_utils();
38137
38395
  init_app();
@@ -38139,7 +38397,7 @@ init_route_manager2();
38139
38397
  init_layers();
38140
38398
 
38141
38399
  // src/nitro/universal-build.ts
38142
- init_config2();
38400
+ init_config3();
38143
38401
  init_client_plugin_build();
38144
38402
  var import_os = __toESM(require("os"));
38145
38403
  var import_path12 = __toESM(require("path"));
@@ -38675,6 +38933,7 @@ __name(withVite5TransformContext, "withVite5TransformContext");
38675
38933
  init_font_vite();
38676
38934
  init_vite_config();
38677
38935
  init_not_found();
38936
+ init_vite();
38678
38937
  var import_meta = {};
38679
38938
  function preloadFarmNitroRuntime() {
38680
38939
  return import("nitro").then(
@@ -39347,7 +39606,7 @@ async function validateClientBuildOutput(root, srcDir, outputDir) {
39347
39606
  __name(validateClientBuildOutput, "validateClientBuildOutput");
39348
39607
  async function buildClient(productionVite, config, root, srcDir, outputDir, pageRoutes, layoutRoutes = [], routeSlots = []) {
39349
39608
  const viteBuild = productionVite.build;
39350
- const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
39609
+ const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
39351
39610
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
39352
39611
  const fs9 = await import("fs/promises");
39353
39612
  const pluginManager = new PluginManager2({
@@ -39539,6 +39798,7 @@ async function buildClient(productionVite, config, root, srcDir, outputDir, page
39539
39798
  }
39540
39799
  },
39541
39800
  plugins: [
39801
+ createFarmThemeCssPlugin(config.theme, config.basePath),
39542
39802
  ...tailwindVitePlugin ? [tailwindVitePlugin] : [],
39543
39803
  // Plugin to redirect @farm.js/core imports to client-only exports
39544
39804
  {
@@ -40916,7 +41176,7 @@ void hydrate();
40916
41176
  __name(generateClientHydrationEntry, "generateClientHydrationEntry");
40917
41177
  async function buildSSRInMemory(productionVite, config, root, routeManager, apiRouteManager, serverRenderer, preset, collectedPageRoutes, collectedLayoutRoutes, collectedRouteSlots) {
40918
41178
  const viteBuild = productionVite.build;
40919
- const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
41179
+ const { farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
40920
41180
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
40921
41181
  const fs9 = await import("fs/promises");
40922
41182
  const pluginManager = new PluginManager2({
@@ -41157,6 +41417,7 @@ async function buildSSRInMemory(productionVite, config, root, routeManager, apiR
41157
41417
  __FARM_PUBLIC_ENV__: JSON.stringify(config.env?.public || {})
41158
41418
  },
41159
41419
  plugins: [
41420
+ createFarmThemeCssPlugin(config.theme, config.basePath),
41160
41421
  ...tailwindVitePlugin ? [tailwindVitePlugin] : [],
41161
41422
  ...!useExternalMetadataImageRuntime && metadataImageRoutes.some((image) => image.sourceType === "module") ? [createMetadataImageWasmPlugin()] : [],
41162
41423
  {
@@ -41370,15 +41631,19 @@ function generateVirtualEntryCode(apiRoutes, pageRoutes, layoutRoutes, routeSlot
41370
41631
  _runWithCurrentRequest,
41371
41632
  _runWithMiddlewareContext,
41372
41633
  _runWithMiddlewareData,
41634
+ _setDefaultFarmThemeConfig,
41373
41635
  addMetadataImageReference,
41636
+ applyFarmThemeDocument,
41374
41637
  appendFarmLinkHeader,
41375
41638
  applyProductionMiddlewareHeaders,
41376
41639
  configureFarmCache,
41377
41640
  configureFarmObservability,
41378
41641
  createFarmCacheKey,
41642
+ createFarmThemeDocumentParts,
41379
41643
  createFarmLocaleCookie,
41380
41644
  createFarmProductionLifecycle,
41381
41645
  createProductionMiddlewareRunner,
41646
+ getTheme as getFarmTheme,
41382
41647
  emitFarmEvent,
41383
41648
  getFarmDataCache,
41384
41649
  getFarmLocaleVaryHeaders,
@@ -41573,6 +41838,8 @@ configureFarmObservability(farmObservabilityConfig);
41573
41838
  configureFarmCache(farmResolvedRuntimeConfig.cache);
41574
41839
  const farmI18nConfig = ${JSON.stringify(config.i18n)};
41575
41840
  const farmServerConfig = ${JSON.stringify(config.server)};
41841
+ const farmThemeConfig = ${JSON.stringify(config.theme)};
41842
+ _setDefaultFarmThemeConfig(farmThemeConfig);
41576
41843
  export const farmProductionLifecycle = createFarmProductionLifecycle({
41577
41844
  server: farmServerConfig,
41578
41845
  start: () => farmPluginRuntime?.startRuntime(),
@@ -43409,7 +43676,13 @@ async function handleFarmRequestInContext(
43409
43676
  !farmI18nSnapshot &&
43410
43677
  !pprCacheKey
43411
43678
  ) {
43679
+ const farmThemeDocument = createFarmThemeDocumentParts(
43680
+ farmThemeConfig,
43681
+ farmResolvedRuntimeConfig.basePath,
43682
+ getFarmTheme(request)
43683
+ );
43412
43684
  const streamPrefix = '<!DOCTYPE html>\\n<html lang="en">\\n<head>\\n' +
43685
+ farmThemeDocument.head + '\\n' +
43413
43686
  ' <meta charset="utf-8">\\n' +
43414
43687
  ' <meta name="viewport" content="width=device-width, initial-scale=1">\\n' +
43415
43688
  (hasFavicon ? '' : ' <link rel="icon" href="data:,">\\n') +
@@ -43425,9 +43698,13 @@ async function handleFarmRequestInContext(
43425
43698
  ) + '\\n' +
43426
43699
  ' <script type="module" src="/farm-client.js"></script>\\n' +
43427
43700
  '</body>\\n</html>';
43701
+ const themedStreamPrefix = streamPrefix.replace(
43702
+ '<html lang="en">',
43703
+ '<html lang="en"' + farmThemeDocument.attributes + '>'
43704
+ );
43428
43705
  const streamedDocument = createFarmDocumentStream(
43429
43706
  renderedPage.stream,
43430
- streamPrefix,
43707
+ themedStreamPrefix,
43431
43708
  streamSuffix,
43432
43709
  function() {
43433
43710
  if (pprBypassReason === "refresh") {
@@ -43510,6 +43787,12 @@ async function handleFarmRequestInContext(
43510
43787
  </html>\`;
43511
43788
  }
43512
43789
  fullHtml = applyFarmI18nDocument(fullHtml, pathname, farmI18nSnapshot);
43790
+ fullHtml = applyFarmThemeDocument(
43791
+ fullHtml,
43792
+ farmThemeConfig,
43793
+ farmResolvedRuntimeConfig.basePath,
43794
+ getFarmTheme(request)
43795
+ );
43513
43796
 
43514
43797
  if (pageStatus === 200 && pprCacheKey && request.method.toUpperCase() !== "HEAD") {
43515
43798
  await pprShellCache.setAsync(
@@ -43636,10 +43919,15 @@ async function handleFarmRequestInContext(
43636
43919
  const errorHtml = ${hasMiddlewareRuntime ? `await _runWithMiddlewareData(middlewareData, () =>
43637
43920
  _runWithMiddlewareContext(middlewareContext, renderErrorElement)
43638
43921
  )` : "await renderErrorElement()"};
43639
- const errorDocument = applyFarmI18nDocument(
43640
- createFarmErrorDocument(errorHtml, "Application Error"),
43641
- pathname,
43642
- getFarmI18nSnapshot()
43922
+ const errorDocument = applyFarmThemeDocument(
43923
+ applyFarmI18nDocument(
43924
+ createFarmErrorDocument(errorHtml, "Application Error"),
43925
+ pathname,
43926
+ getFarmI18nSnapshot()
43927
+ ),
43928
+ farmThemeConfig,
43929
+ farmResolvedRuntimeConfig.basePath,
43930
+ getFarmTheme(request)
43643
43931
  );
43644
43932
  emitFarmEvent({
43645
43933
  type: "render.complete",
@@ -43664,10 +43952,15 @@ async function handleFarmRequestInContext(
43664
43952
  const errorMessage = "Internal Server Error";
43665
43953
  const fallbackHtml = '<main><h1>Application Error</h1><p>' +
43666
43954
  escapeFarmHtmlAttribute(errorMessage) + '</p></main>';
43667
- const fallbackDocument = applyFarmI18nDocument(
43668
- createFarmErrorDocument(fallbackHtml, "Application Error"),
43669
- pathname,
43670
- getFarmI18nSnapshot()
43955
+ const fallbackDocument = applyFarmThemeDocument(
43956
+ applyFarmI18nDocument(
43957
+ createFarmErrorDocument(fallbackHtml, "Application Error"),
43958
+ pathname,
43959
+ getFarmI18nSnapshot()
43960
+ ),
43961
+ farmThemeConfig,
43962
+ farmResolvedRuntimeConfig.basePath,
43963
+ getFarmTheme(request)
43671
43964
  );
43672
43965
  return applyProductionMiddlewareHeaders(new Response(
43673
43966
  fallbackDocument,
@@ -43765,6 +44058,12 @@ async function handleFarmRequestInContext(
43765
44058
  </html>\`;
43766
44059
  }
43767
44060
  fullHtml = applyFarmI18nDocument(fullHtml, pathname, getFarmI18nSnapshot());
44061
+ fullHtml = applyFarmThemeDocument(
44062
+ fullHtml,
44063
+ farmThemeConfig,
44064
+ farmResolvedRuntimeConfig.basePath,
44065
+ getFarmTheme(request)
44066
+ );
43768
44067
 
43769
44068
  emitFarmEvent({
43770
44069
  type: "render.complete",
@@ -43783,8 +44082,14 @@ async function handleFarmRequestInContext(
43783
44082
  }), middlewareHeaders);
43784
44083
  } catch (error) {
43785
44084
  console.error("404 render error:", error);
43786
- return applyProductionMiddlewareHeaders(new Response(
44085
+ const fallbackDocument = applyFarmThemeDocument(
43787
44086
  \`<!DOCTYPE html><html><head><title>404</title></head><body><h1>404 - Page Not Found</h1><p>The page \${pathname} doesn't exist.</p><a href="/">Go Home</a></body></html>\`,
44087
+ farmThemeConfig,
44088
+ farmResolvedRuntimeConfig.basePath,
44089
+ getFarmTheme(request)
44090
+ );
44091
+ return applyProductionMiddlewareHeaders(new Response(
44092
+ fallbackDocument,
43788
44093
  {
43789
44094
  status: 404,
43790
44095
  headers: { "Content-Type": "text/html", "x-farm-preload-buffered": "1" },
@@ -45011,7 +45316,7 @@ async function createProjectModuleServer(createViteServer, config, root) {
45011
45316
  }
45012
45317
  __name(createProjectModuleServer, "createProjectModuleServer");
45013
45318
  async function buildClient2(viteBuild, config, root, srcDir, outputDir) {
45014
- const { farmI18nClientBridgePlugin: farmI18nClientBridgePlugin2, farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
45319
+ const { farmI18nClientBridgePlugin: farmI18nClientBridgePlugin2, farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
45015
45320
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
45016
45321
  const pluginManager = new PluginManager2({
45017
45322
  config,
@@ -45038,7 +45343,7 @@ async function buildClient2(viteBuild, config, root, srcDir, outputDir) {
45038
45343
  }
45039
45344
  __name(buildClient2, "buildClient");
45040
45345
  async function buildSSR(viteBuild, config, root, srcDir, outputDir) {
45041
- const { farmI18nClientBridgePlugin: farmI18nClientBridgePlugin2, farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite(), vite_exports));
45346
+ const { farmI18nClientBridgePlugin: farmI18nClientBridgePlugin2, farmPlugin: farmPlugin2 } = await Promise.resolve().then(() => (init_vite2(), vite_exports));
45042
45347
  const { PluginManager: PluginManager2 } = await Promise.resolve().then(() => (init_plugin(), plugin_exports));
45043
45348
  const pluginManager = new PluginManager2({
45044
45349
  config,
@@ -45684,8 +45989,74 @@ function createStore(initialState, extend) {
45684
45989
  }
45685
45990
  __name(createStore, "createStore");
45686
45991
 
45687
- // src/client/link.tsx
45992
+ // src/theme/client.tsx
45688
45993
  var import_react13 = require("react");
45994
+ init_bridge2();
45995
+ var FALLBACK_CLIENT_SNAPSHOT = Object.freeze({
45996
+ theme: "system",
45997
+ resolvedTheme: "light",
45998
+ mounted: true
45999
+ });
46000
+ var cachedClientSnapshot = FALLBACK_CLIENT_SNAPSHOT;
46001
+ function snapshotsMatch(left, right) {
46002
+ return left.theme === right.theme && left.resolvedTheme === right.resolvedTheme && left.mounted === right.mounted;
46003
+ }
46004
+ __name(snapshotsMatch, "snapshotsMatch");
46005
+ function getClientSnapshot() {
46006
+ const next = typeof window === "undefined" ? FALLBACK_CLIENT_SNAPSHOT : window.__FARM_THEME__?.snapshot;
46007
+ if (!next) return cachedClientSnapshot;
46008
+ if (!snapshotsMatch(cachedClientSnapshot, next)) cachedClientSnapshot = next;
46009
+ return cachedClientSnapshot;
46010
+ }
46011
+ __name(getClientSnapshot, "getClientSnapshot");
46012
+ function getHydrationSnapshot() {
46013
+ if (typeof window !== "undefined" && window.__FARM_THEME__?.serverSnapshot) {
46014
+ return window.__FARM_THEME__.serverSnapshot;
46015
+ }
46016
+ return getFarmThemeServerSnapshot();
46017
+ }
46018
+ __name(getHydrationSnapshot, "getHydrationSnapshot");
46019
+ function subscribe(listener) {
46020
+ if (typeof window === "undefined") return () => {
46021
+ };
46022
+ const handleThemeChange = /* @__PURE__ */ __name(() => {
46023
+ getClientSnapshot();
46024
+ listener();
46025
+ }, "handleThemeChange");
46026
+ window.addEventListener("farm:themechange", handleThemeChange);
46027
+ return () => window.removeEventListener("farm:themechange", handleThemeChange);
46028
+ }
46029
+ __name(subscribe, "subscribe");
46030
+ function getTheme2() {
46031
+ return getClientSnapshot();
46032
+ }
46033
+ __name(getTheme2, "getTheme");
46034
+ function setTheme(theme) {
46035
+ const runtime = typeof window === "undefined" ? void 0 : window.__FARM_THEME__;
46036
+ if (!runtime) {
46037
+ throw new Error("The FARMJS theme runtime is not enabled. Add `theme` to farm.config.ts.");
46038
+ }
46039
+ runtime.setTheme(theme);
46040
+ }
46041
+ __name(setTheme, "setTheme");
46042
+ function toggleTheme() {
46043
+ const next = getClientSnapshot().resolvedTheme === "dark" ? "light" : "dark";
46044
+ setTheme(next);
46045
+ return next;
46046
+ }
46047
+ __name(toggleTheme, "toggleTheme");
46048
+ function useTheme() {
46049
+ const snapshot = (0, import_react13.useSyncExternalStore)(subscribe, getClientSnapshot, getHydrationSnapshot);
46050
+ return {
46051
+ ...snapshot,
46052
+ setTheme,
46053
+ toggleTheme
46054
+ };
46055
+ }
46056
+ __name(useTheme, "useTheme");
46057
+
46058
+ // src/client/link.tsx
46059
+ var import_react14 = require("react");
45689
46060
  init_router();
45690
46061
  init_client_runtime();
45691
46062
  var import_jsx_runtime5 = require("react/jsx-runtime");
@@ -45747,9 +46118,9 @@ function LinkInner({
45747
46118
  onTouchStart,
45748
46119
  ...props
45749
46120
  }, ref) {
45750
- const elementRef = (0, import_react13.useRef)(null);
45751
- const intentTimeoutRef = (0, import_react13.useRef)(null);
45752
- const hasPrefetched = (0, import_react13.useRef)(false);
46121
+ const elementRef = (0, import_react14.useRef)(null);
46122
+ const intentTimeoutRef = (0, import_react14.useRef)(null);
46123
+ const hasPrefetched = (0, import_react14.useRef)(false);
45753
46124
  const { intent, viewport, render } = normalizePrefetch(prefetch2);
45754
46125
  const baseHref = resolveLinkHref(href, params, {
45755
46126
  query,
@@ -45758,17 +46129,17 @@ function LinkInner({
45758
46129
  });
45759
46130
  const resolvedHref = localizeActiveFarmHref(baseHref, locale);
45760
46131
  const isExternal = isExternalUrl(resolvedHref);
45761
- const doPrefetch = (0, import_react13.useCallback)(() => {
46132
+ const doPrefetch = (0, import_react14.useCallback)(() => {
45762
46133
  if (isExternal || hasPrefetched.current) return;
45763
46134
  const router = getRouter2();
45764
46135
  if (!router) return;
45765
46136
  hasPrefetched.current = true;
45766
46137
  router.prefetch(resolvedHref);
45767
46138
  }, [resolvedHref, isExternal]);
45768
- (0, import_react13.useEffect)(() => {
46139
+ (0, import_react14.useEffect)(() => {
45769
46140
  hasPrefetched.current = false;
45770
46141
  }, [resolvedHref]);
45771
- (0, import_react13.useEffect)(() => {
46142
+ (0, import_react14.useEffect)(() => {
45772
46143
  const element = elementRef.current;
45773
46144
  if (!element || isExternal) return;
45774
46145
  const router = getRouter2();
@@ -45778,7 +46149,7 @@ function LinkInner({
45778
46149
  return () => router.unobserveForPrefetch(element);
45779
46150
  }
45780
46151
  }, [resolvedHref, viewport, isExternal]);
45781
- (0, import_react13.useEffect)(() => {
46152
+ (0, import_react14.useEffect)(() => {
45782
46153
  if (!render || isExternal) return;
45783
46154
  let cancelled = false;
45784
46155
  let timeoutId = null;
@@ -45800,7 +46171,7 @@ function LinkInner({
45800
46171
  }
45801
46172
  };
45802
46173
  }, [render, isExternal, resolvedHref]);
45803
- (0, import_react13.useEffect)(() => {
46174
+ (0, import_react14.useEffect)(() => {
45804
46175
  return () => {
45805
46176
  if (intentTimeoutRef.current) {
45806
46177
  clearTimeout(intentTimeoutRef.current);
@@ -45808,13 +46179,13 @@ function LinkInner({
45808
46179
  }
45809
46180
  };
45810
46181
  }, []);
45811
- const cancelIntent = (0, import_react13.useCallback)(() => {
46182
+ const cancelIntent = (0, import_react14.useCallback)(() => {
45812
46183
  if (intentTimeoutRef.current) {
45813
46184
  clearTimeout(intentTimeoutRef.current);
45814
46185
  intentTimeoutRef.current = null;
45815
46186
  }
45816
46187
  }, []);
45817
- const scheduleIntentPrefetch = (0, import_react13.useCallback)(() => {
46188
+ const scheduleIntentPrefetch = (0, import_react14.useCallback)(() => {
45818
46189
  if (isExternal || !intent || hasPrefetched.current) return;
45819
46190
  cancelIntent();
45820
46191
  intentTimeoutRef.current = setTimeout(() => {
@@ -45822,42 +46193,42 @@ function LinkInner({
45822
46193
  doPrefetch();
45823
46194
  }, prefetchDelay);
45824
46195
  }, [intent, isExternal, prefetchDelay, doPrefetch, cancelIntent]);
45825
- const handleMouseEnter = (0, import_react13.useCallback)(
46196
+ const handleMouseEnter = (0, import_react14.useCallback)(
45826
46197
  (event) => {
45827
46198
  onMouseEnter?.(event);
45828
46199
  scheduleIntentPrefetch();
45829
46200
  },
45830
46201
  [onMouseEnter, scheduleIntentPrefetch]
45831
46202
  );
45832
- const handleMouseLeave = (0, import_react13.useCallback)(
46203
+ const handleMouseLeave = (0, import_react14.useCallback)(
45833
46204
  (event) => {
45834
46205
  onMouseLeave?.(event);
45835
46206
  cancelIntent();
45836
46207
  },
45837
46208
  [onMouseLeave, cancelIntent]
45838
46209
  );
45839
- const handleTouchStart = (0, import_react13.useCallback)(
46210
+ const handleTouchStart = (0, import_react14.useCallback)(
45840
46211
  (event) => {
45841
46212
  onTouchStart?.(event);
45842
46213
  scheduleIntentPrefetch();
45843
46214
  },
45844
46215
  [onTouchStart, scheduleIntentPrefetch]
45845
46216
  );
45846
- const handleFocus = (0, import_react13.useCallback)(
46217
+ const handleFocus = (0, import_react14.useCallback)(
45847
46218
  (event) => {
45848
46219
  onFocus?.(event);
45849
46220
  scheduleIntentPrefetch();
45850
46221
  },
45851
46222
  [onFocus, scheduleIntentPrefetch]
45852
46223
  );
45853
- const handleBlur = (0, import_react13.useCallback)(
46224
+ const handleBlur = (0, import_react14.useCallback)(
45854
46225
  (event) => {
45855
46226
  onBlur?.(event);
45856
46227
  cancelIntent();
45857
46228
  },
45858
46229
  [onBlur, cancelIntent]
45859
46230
  );
45860
- const handleClick = (0, import_react13.useCallback)(
46231
+ const handleClick = (0, import_react14.useCallback)(
45861
46232
  (event) => {
45862
46233
  onClick?.(event);
45863
46234
  if (event.defaultPrevented) return;
@@ -45882,7 +46253,7 @@ function LinkInner({
45882
46253
  },
45883
46254
  [resolvedHref, replace, scroll, viewTransition, target, isExternal, onClick]
45884
46255
  );
45885
- const setRefs = (0, import_react13.useCallback)(
46256
+ const setRefs = (0, import_react14.useCallback)(
45886
46257
  (node) => {
45887
46258
  elementRef.current = node;
45888
46259
  if (typeof ref === "function") ref(node);
@@ -45911,7 +46282,7 @@ function LinkInner({
45911
46282
  );
45912
46283
  }
45913
46284
  __name(LinkInner, "LinkInner");
45914
- var LinkWithRef = (0, import_react13.forwardRef)(LinkInner);
46285
+ var LinkWithRef = (0, import_react14.forwardRef)(LinkInner);
45915
46286
  LinkWithRef.displayName = "Link";
45916
46287
  var Link = LinkWithRef;
45917
46288
  function resolveLinkHref(href, params, options) {
@@ -46851,6 +47222,7 @@ __name(decodeCookiePart, "decodeCookiePart");
46851
47222
  getServerActionInvalidations,
46852
47223
  getServerActionSignal,
46853
47224
  getStorage,
47225
+ getTheme,
46854
47226
  globFiles,
46855
47227
  hasFarmRouteRuntimeControls,
46856
47228
  hasISR,
@@ -46967,6 +47339,7 @@ __name(decodeCookiePart, "decodeCookiePart");
46967
47339
  resolveFarmLayoutFonts,
46968
47340
  resolveFarmRouteRuleRuntimeConfig,
46969
47341
  resolveFarmRouteRuntimeConfig,
47342
+ resolveFarmThemeConfig,
46970
47343
  resolveIntegrationOrmRuntimeClient,
46971
47344
  resolveIntegrationPlugins,
46972
47345
  resolveMarkdownConfig,
@@ -46993,12 +47366,14 @@ __name(decodeCookiePart, "decodeCookiePart");
46993
47366
  segmentsToPattern,
46994
47367
  serverEnv,
46995
47368
  setEnv,
47369
+ setTheme,
46996
47370
  snapshotDeferredData,
46997
47371
  sqliteStorage,
46998
47372
  storageCacheAdapter,
46999
47373
  titleFromMarkdown,
47000
47374
  toFormData,
47001
47375
  toViteModuleId,
47376
+ toggleTheme,
47002
47377
  unstable_cache,
47003
47378
  unwrapMiddleware,
47004
47379
  updateTag,
@@ -47014,6 +47389,7 @@ __name(decodeCookiePart, "decodeCookiePart");
47014
47389
  useSearchParams,
47015
47390
  useServerFn,
47016
47391
  useServerQuery,
47392
+ useTheme,
47017
47393
  validateServerActionRequest,
47018
47394
  vercelBlobStorage,
47019
47395
  vercelKVStorage,