@absolutejs/absolute 0.20.0-beta.54 → 0.20.0-beta.56

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/dist/angular/components/core/streamingSlotRegistrar.js +1 -1
  2. package/dist/angular/components/core/streamingSlotRegistry.js +2 -2
  3. package/dist/angular/index.js +25 -4
  4. package/dist/angular/index.js.map +6 -5
  5. package/dist/angular/server.js +25 -4
  6. package/dist/angular/server.js.map +6 -5
  7. package/dist/build.js +66 -10
  8. package/dist/build.js.map +11 -10
  9. package/dist/cli/config/server.js +4 -1
  10. package/dist/cli/index.js +53 -3
  11. package/dist/client/index.js +126 -7
  12. package/dist/client/index.js.map +8 -6
  13. package/dist/index.js +289 -233
  14. package/dist/index.js.map +13 -12
  15. package/dist/islands/index.js +17 -2
  16. package/dist/islands/index.js.map +5 -4
  17. package/dist/mobile/index.js +1332 -64
  18. package/dist/mobile/index.js.map +8 -6
  19. package/dist/mobile/remoteMacAgentEntry.js +101 -92
  20. package/dist/mobile/shellBootstrap.js +258 -4
  21. package/dist/react/index.js +19 -3
  22. package/dist/react/index.js.map +6 -5
  23. package/dist/react/server.js +17 -2
  24. package/dist/react/server.js.map +5 -4
  25. package/dist/src/client/browserTranslation.d.ts +19 -0
  26. package/dist/src/client/index.d.ts +1 -0
  27. package/dist/src/core/browserTranslation.d.ts +6 -0
  28. package/dist/src/ember/browser.d.ts +0 -16
  29. package/dist/src/mobile/adaptiveShell.d.ts +27 -0
  30. package/dist/src/mobile/deviceCapabilities.d.ts +1 -0
  31. package/dist/src/mobile/index.d.ts +1 -0
  32. package/dist/src/vue/browser.d.ts +1 -0
  33. package/dist/src/vue/browserTranslation.d.ts +5 -0
  34. package/dist/src/vue/index.d.ts +1 -0
  35. package/dist/svelte/index.js +19 -3
  36. package/dist/svelte/index.js.map +6 -5
  37. package/dist/svelte/server.js +17 -2
  38. package/dist/svelte/server.js.map +5 -4
  39. package/dist/vue/browser.js +96 -1
  40. package/dist/vue/browser.js.map +5 -3
  41. package/dist/vue/index.js +114 -3
  42. package/dist/vue/index.js.map +8 -5
  43. package/dist/vue/server.js +17 -2
  44. package/dist/vue/server.js.map +5 -4
  45. package/package.json +7 -7
@@ -636,6 +636,254 @@ var http = createAbsoluteHttpClient();
636
636
  // src/mobile/shellHttp.ts
637
637
  var installAbsoluteMobileShellHttp = (origin, fetch2 = globalThis.fetch) => installAbsoluteHttpTransport(createAbsoluteHttpTransport({ fetch: fetch2, origin, runtime: "native" }));
638
638
 
639
+ // src/mobile/adaptiveShell.ts
640
+ import {
641
+ keyboard,
642
+ network,
643
+ platform,
644
+ systemBars
645
+ } from "@absolutejs/devices";
646
+ var STYLE_ID = "absolute-mobile-adaptive-shell";
647
+ var ANNOUNCER_ID = "absolute-mobile-announcer";
648
+ var HOST_METRICS_EVENT = "absolute:native-host-metrics";
649
+ var STATUS_STYLE = `
650
+ [data-absolute-mobile-status] {
651
+ display: grid;
652
+ min-height: var(--absolute-available-height, 100dvh);
653
+ place-items: center;
654
+ padding: max(1.5rem, var(--absolute-safe-area-inset-top, 0px)) max(1.5rem, var(--absolute-safe-area-inset-right, 0px)) max(1.5rem, var(--absolute-safe-area-inset-bottom, 0px)) max(1.5rem, var(--absolute-safe-area-inset-left, 0px));
655
+ box-sizing: border-box;
656
+ color: CanvasText;
657
+ background: Canvas;
658
+ font: 500 1rem/1.5 system-ui, sans-serif;
659
+ text-align: center;
660
+ }
661
+ [data-absolute-mobile-announcer] {
662
+ position: fixed;
663
+ width: 1px;
664
+ height: 1px;
665
+ padding: 0;
666
+ margin: -1px;
667
+ overflow: hidden;
668
+ clip: rect(0, 0, 0, 0);
669
+ white-space: nowrap;
670
+ border: 0;
671
+ }
672
+ `;
673
+ var DEFAULT_KEYBOARD = {
674
+ heightPx: 0,
675
+ visible: false
676
+ };
677
+ var DEFAULT_NETWORK = {
678
+ connected: true,
679
+ connectionType: "unknown"
680
+ };
681
+ var DEFAULT_PLATFORM = {
682
+ formFactor: "unknown",
683
+ isNative: true,
684
+ os: "unknown",
685
+ runtime: "capacitor"
686
+ };
687
+ var finitePixels = (value) => Number.isFinite(value) ? Math.max(0, Math.round(value ?? 0)) : 0;
688
+ var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
689
+ var viewportSize = () => ({
690
+ height: finitePixels(globalThis.visualViewport?.height ?? innerHeight),
691
+ width: finitePixels(globalThis.visualViewport?.width ?? innerWidth)
692
+ });
693
+ var setPixels = (name, value) => document.documentElement.style.setProperty(name, `${finitePixels(value)}px`);
694
+ var ensureStyle = () => {
695
+ let style = document.getElementById(STYLE_ID);
696
+ if (!(style instanceof HTMLStyleElement)) {
697
+ style = document.createElement("style");
698
+ style.id = STYLE_ID;
699
+ style.textContent = STATUS_STYLE;
700
+ document.head.append(style);
701
+ }
702
+ };
703
+ var ensureViewport = () => {
704
+ let viewport = document.head.querySelector('meta[name="viewport"]');
705
+ if (!viewport) {
706
+ viewport = document.createElement("meta");
707
+ viewport.name = "viewport";
708
+ document.head.prepend(viewport);
709
+ }
710
+ const values = new Set(viewport.content.split(",").map((value) => value.trim()).filter(Boolean));
711
+ values.add("width=device-width");
712
+ values.add("initial-scale=1");
713
+ values.add("viewport-fit=cover");
714
+ viewport.content = [...values].join(",");
715
+ };
716
+ var ensureAnnouncer = () => {
717
+ let announcer = document.getElementById(ANNOUNCER_ID);
718
+ if (!(announcer instanceof HTMLElement)) {
719
+ announcer = document.createElement("div");
720
+ announcer.id = ANNOUNCER_ID;
721
+ announcer.dataset.absoluteMobileAnnouncer = "";
722
+ announcer.setAttribute("aria-atomic", "true");
723
+ announcer.setAttribute("aria-live", "polite");
724
+ announcer.setAttribute("role", "status");
725
+ document.body.append(announcer);
726
+ }
727
+ return announcer;
728
+ };
729
+ var dispatchState = (state) => dispatchEvent(new CustomEvent("absolute:adaptive-shell-change", { detail: state }));
730
+ var defaultDevices = {
731
+ keyboard,
732
+ network,
733
+ platform,
734
+ systemBars
735
+ };
736
+ var hostSafeAreaInsets = (value) => {
737
+ if (typeof value !== "object" || value === null)
738
+ return;
739
+ const candidate = Reflect.get(value, "safeAreaInsets");
740
+ if (typeof candidate !== "object" || candidate === null)
741
+ return;
742
+ const insets = {
743
+ bottom: Reflect.get(candidate, "bottom"),
744
+ left: Reflect.get(candidate, "left"),
745
+ right: Reflect.get(candidate, "right"),
746
+ top: Reflect.get(candidate, "top")
747
+ };
748
+ if (!isFiniteNumber(insets.bottom) || !isFiniteNumber(insets.left) || !isFiniteNumber(insets.right) || !isFiniteNumber(insets.top))
749
+ return;
750
+ return {
751
+ bottom: finitePixels(insets.bottom),
752
+ left: finitePixels(insets.left),
753
+ right: finitePixels(insets.right),
754
+ top: finitePixels(insets.top)
755
+ };
756
+ };
757
+ var installAbsoluteMobileAdaptiveShell = async (devices = defaultDevices) => {
758
+ let disposed = false;
759
+ let keyboardState = { ...DEFAULT_KEYBOARD };
760
+ let networkState = { ...DEFAULT_NETWORK };
761
+ let platformInfo = { ...DEFAULT_PLATFORM };
762
+ let viewport = viewportSize();
763
+ const subscriptions = [];
764
+ const state = () => ({
765
+ availableHeight: globalThis.visualViewport ? viewport.height : Math.max(0, viewport.height - keyboardState.heightPx),
766
+ keyboard: keyboardState,
767
+ network: networkState,
768
+ platform: platformInfo,
769
+ viewportHeight: viewport.height,
770
+ viewportWidth: viewport.width
771
+ });
772
+ const refreshDocument = () => {
773
+ if (disposed || !document.head || !document.body)
774
+ return;
775
+ ensureViewport();
776
+ ensureStyle();
777
+ const root = document.documentElement;
778
+ const current = state();
779
+ root.dataset.absoluteMobile = "";
780
+ root.dataset.absoluteRuntime = current.platform.runtime;
781
+ root.dataset.absolutePlatform = current.platform.os;
782
+ root.dataset.absoluteFormFactor = current.platform.formFactor;
783
+ root.dataset.absoluteKeyboard = current.keyboard.visible ? "visible" : "hidden";
784
+ root.dataset.absoluteNetwork = current.network.connected ? "online" : "offline";
785
+ root.dataset.absoluteConnection = current.network.connectionType;
786
+ root.dataset.absoluteReducedMotion = current.platform.prefersReducedMotion ? "reduce" : "no-preference";
787
+ const insets = current.platform.safeAreaInsets ?? {
788
+ bottom: 0,
789
+ left: 0,
790
+ right: 0,
791
+ top: 0
792
+ };
793
+ setPixels("--absolute-safe-area-inset-top", insets.top);
794
+ setPixels("--absolute-safe-area-inset-right", insets.right);
795
+ setPixels("--absolute-safe-area-inset-bottom", insets.bottom);
796
+ setPixels("--absolute-safe-area-inset-left", insets.left);
797
+ setPixels("--absolute-keyboard-height", current.keyboard.heightPx);
798
+ setPixels("--absolute-viewport-height", current.viewportHeight);
799
+ setPixels("--absolute-viewport-width", current.viewportWidth);
800
+ setPixels("--absolute-available-height", current.availableHeight);
801
+ ensureAnnouncer();
802
+ };
803
+ const publish = () => {
804
+ refreshDocument();
805
+ dispatchState(state());
806
+ };
807
+ const updateViewport = () => {
808
+ viewport = viewportSize();
809
+ devices.platform.getInfo().then((info) => {
810
+ platformInfo = info;
811
+ publish();
812
+ return;
813
+ }).catch(() => publish());
814
+ };
815
+ const updateKeyboard = (next) => {
816
+ keyboardState = {
817
+ heightPx: finitePixels(next.heightPx),
818
+ visible: next.visible
819
+ };
820
+ publish();
821
+ };
822
+ const updateNetwork = (next) => {
823
+ const changed = networkState.connected !== next.connected;
824
+ networkState = next;
825
+ publish();
826
+ if (changed || !next.connected)
827
+ ensureAnnouncer().textContent = next.connected ? "Connection restored." : "You are offline.";
828
+ };
829
+ const updateHostMetrics = (event) => {
830
+ const insets = hostSafeAreaInsets(Reflect.get(event, "detail"));
831
+ if (!insets)
832
+ return;
833
+ platformInfo = { ...platformInfo, safeAreaInsets: insets };
834
+ publish();
835
+ };
836
+ const installKeyboard = async () => {
837
+ const capability = await devices.keyboard.capability();
838
+ if (!capability.available)
839
+ return;
840
+ keyboardState = await devices.keyboard.getState();
841
+ subscriptions.push(await devices.keyboard.onChange(updateKeyboard));
842
+ };
843
+ try {
844
+ platformInfo = await devices.platform.getInfo();
845
+ } catch {}
846
+ const initialHostInsets = hostSafeAreaInsets(Reflect.get(globalThis, "__absoluteNativeHostMetrics"));
847
+ if (initialHostInsets)
848
+ platformInfo = {
849
+ ...platformInfo,
850
+ safeAreaInsets: initialHostInsets
851
+ };
852
+ try {
853
+ networkState = await devices.network.getStatus();
854
+ subscriptions.push(await devices.network.onChange(updateNetwork));
855
+ } catch {}
856
+ try {
857
+ await installKeyboard();
858
+ } catch {}
859
+ try {
860
+ const capability = await devices.systemBars.capability("appearance");
861
+ if (capability.available)
862
+ await devices.systemBars.setAppearance("automatic");
863
+ } catch {}
864
+ addEventListener("resize", updateViewport);
865
+ addEventListener(HOST_METRICS_EVENT, updateHostMetrics);
866
+ globalThis.visualViewport?.addEventListener("resize", updateViewport);
867
+ globalThis.visualViewport?.addEventListener("scroll", updateViewport);
868
+ publish();
869
+ if (!networkState.connected)
870
+ ensureAnnouncer().textContent = "You are offline.";
871
+ return {
872
+ refreshDocument,
873
+ state,
874
+ dispose: async () => {
875
+ if (disposed)
876
+ return;
877
+ disposed = true;
878
+ removeEventListener("resize", updateViewport);
879
+ removeEventListener(HOST_METRICS_EVENT, updateHostMetrics);
880
+ globalThis.visualViewport?.removeEventListener("resize", updateViewport);
881
+ globalThis.visualViewport?.removeEventListener("scroll", updateViewport);
882
+ await Promise.all(subscriptions.map((unsubscribe) => unsubscribe()));
883
+ }
884
+ };
885
+ };
886
+
639
887
  // src/mobile/shellBootstrap.ts
640
888
  var MANIFEST_PATH = "./absolute-mobile-manifest.json";
641
889
  var STATUS_ID = "absolute-mobile-status";
@@ -672,6 +920,7 @@ var notifyExpoNavigationPath = (path) => {
672
920
  }
673
921
  };
674
922
  var navigationGeneration = 0;
923
+ var adaptiveShell;
675
924
  var notifyCapacitorSystemBarsDomReady = () => {
676
925
  const provider = Reflect.get(globalThis, "CapacitorSystemBarsAndroidInterface");
677
926
  if (typeof provider !== "object" || provider === null)
@@ -691,18 +940,20 @@ var readManifest = async () => {
691
940
  const manifest = await response.json();
692
941
  return manifest;
693
942
  };
694
- var renderStatus = (message) => {
943
+ var renderStatus = (message, kind = "loading") => {
695
944
  document.title = "AbsoluteJS";
696
945
  document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">';
697
- document.body.innerHTML = `<main id="${STATUS_ID}" role="status"></main>`;
946
+ document.body.innerHTML = `<main id="${STATUS_ID}" data-absolute-mobile-status="${kind}" role="status" aria-atomic="true" aria-live="polite"></main>`;
698
947
  const status = document.getElementById(STATUS_ID);
699
948
  if (status)
700
949
  status.textContent = message;
950
+ adaptiveShell?.refreshDocument();
701
951
  };
702
952
  var renderPageTarget = () => {
703
953
  document.title = "AbsoluteJS";
704
954
  document.head.innerHTML = '<meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">';
705
955
  document.body.innerHTML = '<div id="root"></div>';
956
+ adaptiveShell?.refreshDocument();
706
957
  };
707
958
  var localBundleUrl = (manifest, pageId, contract) => {
708
959
  const page = manifest.pages.find((candidate) => candidate.pageId === pageId && candidate.contract === contract);
@@ -744,9 +995,10 @@ var navigate = async (manifest, path, pushHistory, fetchImpl) => {
744
995
  }
745
996
  });
746
997
  if (activation.kind === "upgrade-required") {
747
- renderStatus("This app version must be updated to continue.");
998
+ renderStatus("This app version must be updated to continue.", "update");
748
999
  return;
749
1000
  }
1001
+ adaptiveShell?.refreshDocument();
750
1002
  if (pushHistory)
751
1003
  pushNavigationHistory(path);
752
1004
  };
@@ -794,13 +1046,15 @@ var navigateWithFailureState = async (manifest, path, pushHistory, reinstallBrow
794
1046
  await navigate(manifest, path, pushHistory, fetchImpl);
795
1047
  } catch (error) {
796
1048
  console.error("[Absolute Mobile] Navigation failed:", error);
797
- renderStatus("Unable to load this page. Check your connection and retry.");
1049
+ renderStatus(document.documentElement.dataset.absoluteNetwork === "offline" ? "You are offline. Reconnect to load this page." : "Unable to load this page. Check your connection and retry.", "error");
798
1050
  } finally {
799
1051
  reinstallBrowserNavigation();
800
1052
  }
801
1053
  };
802
1054
  var startAbsoluteMobileShell = async (options = {}) => {
803
1055
  notifyCapacitorSystemBarsDomReady();
1056
+ await adaptiveShell?.dispose();
1057
+ adaptiveShell = await installAbsoluteMobileAdaptiveShell();
804
1058
  const manifest = await readManifest();
805
1059
  const auth = manifest.auth && options.createAuth ? await options.createAuth(manifest.auth, {
806
1060
  beforeSignOut: options.beforeSignOut
@@ -1470,6 +1470,20 @@ var init_spaRouteManifest = __esm(() => {
1470
1470
  init_resolveConvention();
1471
1471
  });
1472
1472
 
1473
+ // src/core/browserTranslation.ts
1474
+ var BASELINE_MARKER = "__ABSOLUTE_SSR_TEXT_BASELINES__", BROWSER_TRANSLATION_BASELINE_SCRIPT, browserTranslationBaselineTag = () => `<script>${BROWSER_TRANSLATION_BASELINE_SCRIPT}</script>`, injectBrowserTranslationBaseline = (html) => {
1475
+ if (html.includes(BASELINE_MARKER))
1476
+ return html;
1477
+ const script = browserTranslationBaselineTag();
1478
+ const closingBodyIndex = html.lastIndexOf("</body>");
1479
+ if (closingBodyIndex < 0)
1480
+ return `${html}${script}`;
1481
+ return `${html.slice(0, closingBodyIndex)}${script}${html.slice(closingBodyIndex)}`;
1482
+ };
1483
+ var init_browserTranslation = __esm(() => {
1484
+ BROWSER_TRANSLATION_BASELINE_SCRIPT = "window.__ABSOLUTE_SSR_TEXT_BASELINES__=new WeakMap();" + "{const r=document.body,b=window.__ABSOLUTE_SSR_TEXT_BASELINES__;" + 'if(r)for(const e of [r,...r.querySelectorAll("*")]){' + "const t=new Map();for(const [i,n]of[...e.childNodes].entries())" + 'if(n.nodeType===3)t.set(i,n.nodeValue??"");if(t.size)b.set(e,t);}}';
1485
+ });
1486
+
1473
1487
  // src/core/islandManifest.ts
1474
1488
  var toIslandFrameworkSegment = (framework) => framework[0]?.toUpperCase() + framework.slice(1), collectFrameworkIslands = (manifest, prefix) => {
1475
1489
  const entries = {};
@@ -1924,7 +1938,7 @@ var routeContextCache, cacheRouteData = (pagePath, data) => {
1924
1938
  }
1925
1939
  return html + snippet;
1926
1940
  }, injectSsrScripts = (html, requestId, indexPath, requestContext) => {
1927
- let result = html;
1941
+ let result = injectBeforeClose(html, browserTranslationBaselineTag());
1928
1942
  const registeredScripts = getAndClearClientScripts(requestId);
1929
1943
  if (registeredScripts.length > 0) {
1930
1944
  result = injectBeforeClose(result, generateClientScriptCode(registeredScripts));
@@ -1960,6 +1974,7 @@ var routeContextCache, cacheRouteData = (pagePath, data) => {
1960
1974
  };
1961
1975
  var init_ssrRender = __esm(() => {
1962
1976
  init_registerClientScript();
1977
+ init_browserTranslation();
1963
1978
  routeContextCache = new Map;
1964
1979
  selectorCache = new Map;
1965
1980
  });
@@ -4704,6 +4719,7 @@ var runWithStreamingSlotWarningScope = (task, metadata) => ensureWarningStorage(
4704
4719
  // src/react/pageHandler.ts
4705
4720
  init_spaRouteManifest();
4706
4721
  init_resolveConvention();
4722
+ init_browserTranslation();
4707
4723
  var withRequestUrl = (props, url) => Object.assign(Object.create(null), props, { url });
4708
4724
  var resolveRequestPathname = (request) => {
4709
4725
  if (!request)
@@ -4757,7 +4773,7 @@ var handleReactPageRequest = async (input) => {
4757
4773
  const refreshSetup = buildRefreshSetup();
4758
4774
  const stream = await renderToReadableStream(element, {
4759
4775
  bootstrapModules: [resolvedIndex],
4760
- bootstrapScriptContent: propsScript + refreshSetup || undefined,
4776
+ bootstrapScriptContent: BROWSER_TRANSLATION_BASELINE_SCRIPT + propsScript + refreshSetup,
4761
4777
  onError(error) {
4762
4778
  console.error("[SSR] React streaming error:", error);
4763
4779
  }
@@ -4953,5 +4969,5 @@ export {
4953
4969
  useIslandStore
4954
4970
  };
4955
4971
 
4956
- //# debugId=E00833F113ECF61A64756E2164756E21
4972
+ //# debugId=8AAED68C3E533F4B64756E2164756E21
4957
4973
  //# sourceMappingURL=index.js.map