@sevenfold/setto-client 0.7.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export { SettoProvider, useSetto } from './provider';
2
2
  export { GuestEditProvider, useGuestEdit } from './guest-edit';
3
+ export { SettoPreviewBar, isPreviewHost } from './preview-bar';
3
4
  export { T } from './T';
4
5
  export { SettoSection } from './SettoSection';
5
6
  export { SettoBlock } from './SettoBlock';
@@ -0,0 +1,3 @@
1
+ /** True when this page is served from a Setto preview address. */
2
+ export declare function isPreviewHost(hostname: string): boolean;
3
+ export declare function SettoPreviewBar(): import("react").ReactPortal | null;
@@ -21358,6 +21358,136 @@ function useSiteAccess(supabase, session, siteId) {
21358
21358
  }, [supabase, session, siteId]);
21359
21359
  return state;
21360
21360
  }
21361
+ const PREVIEW_HOST = /(^|\.)site\.setto\.no$/i;
21362
+ function isPreviewHost(hostname) {
21363
+ return PREVIEW_HOST.test(hostname);
21364
+ }
21365
+ function SettoPreviewBar() {
21366
+ const { supabase, api, config, session, authLoading, currentSite, sites, editMode } = useSetto();
21367
+ const [onPreview, setOnPreview] = useState(false);
21368
+ const [busy, setBusy] = useState(false);
21369
+ const [error, setError] = useState(null);
21370
+ const [paid, setPaid] = useState(false);
21371
+ useEffect(() => {
21372
+ setOnPreview(isPreviewHost(window.location.hostname));
21373
+ setPaid(new URLSearchParams(window.location.search).get("betaling") === "ok");
21374
+ }, []);
21375
+ if (!onPreview || authLoading) return null;
21376
+ if (session && sites === null) return null;
21377
+ const bought = paid || currentSite?.status === "live";
21378
+ const owner = !!session && !!currentSite && !bought;
21379
+ const name = currentSite?.display_name?.trim() || config.displayName?.trim() || config.siteId;
21380
+ if (bought) return null;
21381
+ const signIn = () => {
21382
+ window.location.href = "/setto";
21383
+ };
21384
+ const publish = async () => {
21385
+ setBusy(true);
21386
+ setError(null);
21387
+ try {
21388
+ const token = (await supabase.auth.getSession()).data.session?.access_token;
21389
+ if (!token) {
21390
+ signIn();
21391
+ return;
21392
+ }
21393
+ const data = await api.request(
21394
+ `/onboarding/sites/${config.siteId}/checkout`,
21395
+ {
21396
+ method: "POST",
21397
+ // Back to the page they were looking at, not to a chat window.
21398
+ body: { returnTo: window.location.origin + window.location.pathname }
21399
+ },
21400
+ "checkout"
21401
+ );
21402
+ if (!data.url) throw new Error("checkout_failed");
21403
+ window.location.href = data.url;
21404
+ } catch (err) {
21405
+ const detail = err instanceof Error ? err.message : "";
21406
+ setError(
21407
+ detail.includes("already_paid") ? "Denne siden er allerede betalt." : detail.includes("not_found") ? "Fant ingen bestilling for denne siden på kontoen din." : detail.includes("stripe_not_configured") ? "Betaling er ikke satt opp ennå." : "Klarte ikke starte betalingen. Prøv igjen."
21408
+ );
21409
+ setBusy(false);
21410
+ }
21411
+ };
21412
+ return createPortal(
21413
+ /*
21414
+ * Lifted above the editor's floating button when edit mode is on, which
21415
+ * sits in the same corner band. Sideways would collide again the moment
21416
+ * its toolbar opens, since that expands rightward.
21417
+ */
21418
+ /* @__PURE__ */ jsx(
21419
+ "div",
21420
+ {
21421
+ style: editMode ? { ...barStyle, bottom: "calc(max(16px, env(safe-area-inset-bottom, 0px)) + 68px)" } : barStyle,
21422
+ "data-setto-preview-bar": "",
21423
+ children: owner ? /* @__PURE__ */ jsxs(Fragment, { children: [
21424
+ /* @__PURE__ */ jsx("span", { style: dotStyle, "aria-hidden": true }),
21425
+ /* @__PURE__ */ jsxs("span", { style: labelStyle, children: [
21426
+ "Du forhåndsviser nå ",
21427
+ /* @__PURE__ */ jsx("strong", { style: { fontWeight: 600 }, children: name })
21428
+ ] }),
21429
+ error && /* @__PURE__ */ jsx("span", { style: errorStyle$1, children: error }),
21430
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryStyle, onClick: publish, disabled: busy, children: busy ? "Åpner betaling …" : "Publiser" })
21431
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
21432
+ /* @__PURE__ */ jsx("span", { style: dotStyle, "aria-hidden": true }),
21433
+ /* @__PURE__ */ jsxs("span", { style: labelStyle, children: [
21434
+ "Forhåndsvisning av ",
21435
+ name
21436
+ ] }),
21437
+ /* @__PURE__ */ jsx("button", { type: "button", style: primaryStyle, onClick: signIn, children: "Rediger" })
21438
+ ] })
21439
+ }
21440
+ ),
21441
+ document.body
21442
+ );
21443
+ }
21444
+ const barStyle = {
21445
+ position: "fixed",
21446
+ left: "50%",
21447
+ bottom: "max(16px, env(safe-area-inset-bottom, 0px))",
21448
+ transform: "translateX(-50%)",
21449
+ zIndex: 2147483e3,
21450
+ display: "flex",
21451
+ alignItems: "center",
21452
+ gap: 14,
21453
+ maxWidth: "calc(100vw - 24px)",
21454
+ padding: "10px 10px 10px 18px",
21455
+ borderRadius: 999,
21456
+ background: "#211711",
21457
+ color: "#fffdf8",
21458
+ fontFamily: 'system-ui, -apple-system, "Segoe UI", sans-serif',
21459
+ fontSize: 14,
21460
+ lineHeight: 1.3,
21461
+ boxShadow: "0 18px 40px -18px rgba(0, 0, 0, 0.65)"
21462
+ };
21463
+ const dotStyle = {
21464
+ width: 7,
21465
+ height: 7,
21466
+ borderRadius: "50%",
21467
+ background: "#c4502a",
21468
+ flex: "none"
21469
+ };
21470
+ const labelStyle = {
21471
+ whiteSpace: "nowrap",
21472
+ overflow: "hidden",
21473
+ textOverflow: "ellipsis"
21474
+ };
21475
+ const primaryStyle = {
21476
+ flex: "none",
21477
+ padding: "9px 18px",
21478
+ border: 0,
21479
+ borderRadius: 999,
21480
+ background: "#c4502a",
21481
+ color: "#fffdf8",
21482
+ font: "inherit",
21483
+ fontWeight: 600,
21484
+ cursor: "pointer"
21485
+ };
21486
+ const errorStyle$1 = {
21487
+ color: "#ffb4a2",
21488
+ fontSize: 13,
21489
+ whiteSpace: "nowrap"
21490
+ };
21361
21491
  const SETTO_BASE = "/setto";
21362
21492
  function siteHomeUrl(pathname = "/") {
21363
21493
  const u = new URL(window.location.href);
@@ -24872,7 +25002,10 @@ function SettoProvider({ config, children }) {
24872
25002
  assetStore: storeReady ? assetStoreRef.current : null
24873
25003
  };
24874
25004
  const editShellActive = editMode && !!value.store;
24875
- return /* @__PURE__ */ jsx(SettoContext.Provider, { value, children: /* @__PURE__ */ jsx(SectionEditProvider, { children: /* @__PURE__ */ jsx(EditModeShell, { active: editShellActive, themeStore: value.themeStore, children }) }) });
25005
+ return /* @__PURE__ */ jsx(SettoContext.Provider, { value, children: /* @__PURE__ */ jsxs(SectionEditProvider, { children: [
25006
+ /* @__PURE__ */ jsx(EditModeShell, { active: editShellActive, themeStore: value.themeStore, children }),
25007
+ !onAdminRoute && /* @__PURE__ */ jsx(SettoPreviewBar, {})
25008
+ ] }) });
24876
25009
  }
24877
25010
  function useSetto() {
24878
25011
  const ctx = useContext(SettoContext);
@@ -26643,6 +26776,7 @@ export {
26643
26776
  SettoForm,
26644
26777
  SettoIcon,
26645
26778
  SettoImage,
26779
+ SettoPreviewBar,
26646
26780
  SettoProvider,
26647
26781
  SettoRepeater,
26648
26782
  SettoSection,
@@ -26652,6 +26786,7 @@ export {
26652
26786
  extractContentKeys,
26653
26787
  formFieldsPrefix,
26654
26788
  isFormFieldType,
26789
+ isPreviewHost,
26655
26790
  nodeChildren,
26656
26791
  parseBlockTree,
26657
26792
  readLocaleFields,