@sevenfold/setto-client 0.8.4 → 0.9.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.
@@ -5039,26 +5039,26 @@ var PostgrestClient = class PostgrestClient2 {
5039
5039
  this.schemaName = schema;
5040
5040
  this.urlLengthLimit = urlLengthLimit;
5041
5041
  const originalFetch = fetch$1 !== null && fetch$1 !== void 0 ? fetch$1 : globalThis.fetch;
5042
- if (timeout !== void 0 && timeout > 0) this.fetch = (input, init) => {
5042
+ if (timeout !== void 0 && timeout > 0) this.fetch = (input2, init) => {
5043
5043
  const controller = new AbortController();
5044
5044
  const timeoutId = setTimeout(() => controller.abort(), timeout);
5045
5045
  const existingSignal = init === null || init === void 0 ? void 0 : init.signal;
5046
5046
  if (existingSignal) {
5047
5047
  if (existingSignal.aborted) {
5048
5048
  clearTimeout(timeoutId);
5049
- return originalFetch(input, init);
5049
+ return originalFetch(input2, init);
5050
5050
  }
5051
5051
  const abortHandler = () => {
5052
5052
  clearTimeout(timeoutId);
5053
5053
  controller.abort();
5054
5054
  };
5055
5055
  existingSignal.addEventListener("abort", abortHandler, { once: true });
5056
- return originalFetch(input, _objectSpread2$2(_objectSpread2$2({}, init), {}, { signal: controller.signal })).finally(() => {
5056
+ return originalFetch(input2, _objectSpread2$2(_objectSpread2$2({}, init), {}, { signal: controller.signal })).finally(() => {
5057
5057
  clearTimeout(timeoutId);
5058
5058
  existingSignal.removeEventListener("abort", abortHandler);
5059
5059
  });
5060
5060
  }
5061
- return originalFetch(input, _objectSpread2$2(_objectSpread2$2({}, init), {}, { signal: controller.signal })).finally(() => clearTimeout(timeoutId));
5061
+ return originalFetch(input2, _objectSpread2$2(_objectSpread2$2({}, init), {}, { signal: controller.signal })).finally(() => clearTimeout(timeoutId));
5062
5062
  };
5063
5063
  else this.fetch = originalFetch;
5064
5064
  this.retry = retry;
@@ -20182,25 +20182,25 @@ const fetchWithAuth = (supabaseKey, supabaseUrl, getAccessToken, customFetch, tr
20182
20182
  const traceEnabled = (tracePropagationOptions === null || tracePropagationOptions === void 0 ? void 0 : tracePropagationOptions.enabled) === true;
20183
20183
  const respectSampling = (tracePropagationOptions === null || tracePropagationOptions === void 0 ? void 0 : tracePropagationOptions.respectSamplingDecision) !== false;
20184
20184
  const traceTargets = traceEnabled ? getDefaultPropagationTargets(supabaseUrl) : null;
20185
- return async (input, init) => {
20185
+ return async (input2, init) => {
20186
20186
  var _await$getAccessToken;
20187
20187
  const accessToken = (_await$getAccessToken = await getAccessToken()) !== null && _await$getAccessToken !== void 0 ? _await$getAccessToken : supabaseKey;
20188
20188
  let headers = new HeadersConstructor(init === null || init === void 0 ? void 0 : init.headers);
20189
20189
  if (!headers.has("apikey")) headers.set("apikey", supabaseKey);
20190
20190
  if (!headers.has("Authorization")) headers.set("Authorization", `Bearer ${accessToken}`);
20191
20191
  if (traceTargets) {
20192
- const traceHeaders = await getTraceHeaders(input, traceTargets, respectSampling);
20192
+ const traceHeaders = await getTraceHeaders(input2, traceTargets, respectSampling);
20193
20193
  if (traceHeaders) {
20194
20194
  if (traceHeaders.traceparent && !headers.has("traceparent")) headers.set("traceparent", traceHeaders.traceparent);
20195
20195
  if (traceHeaders.tracestate && !headers.has("tracestate")) headers.set("tracestate", traceHeaders.tracestate);
20196
20196
  if (traceHeaders.baggage && !headers.has("baggage")) headers.set("baggage", traceHeaders.baggage);
20197
20197
  }
20198
20198
  }
20199
- return fetch$1(input, _objectSpread2(_objectSpread2({}, init), {}, { headers }));
20199
+ return fetch$1(input2, _objectSpread2(_objectSpread2({}, init), {}, { headers }));
20200
20200
  };
20201
20201
  };
20202
- async function getTraceHeaders(input, targets, respectSampling) {
20203
- if (!shouldPropagateToTarget(typeof input === "string" ? input : input instanceof URL ? input : input.url, targets)) return null;
20202
+ async function getTraceHeaders(input2, targets, respectSampling) {
20203
+ if (!shouldPropagateToTarget(typeof input2 === "string" ? input2 : input2 instanceof URL ? input2 : input2.url, targets)) return null;
20204
20204
  const traceContext = await extractTraceContext();
20205
20205
  if (!traceContext || !traceContext.traceparent) return null;
20206
20206
  if (respectSampling) {
@@ -21310,14 +21310,14 @@ class ThemeStore {
21310
21310
  for (const fn of this.listeners) fn(this.cachedSnapshot);
21311
21311
  }
21312
21312
  }
21313
- const EMPTY = {
21313
+ const EMPTY$1 = {
21314
21314
  sites: null,
21315
21315
  currentSite: null,
21316
21316
  loading: true,
21317
21317
  error: null
21318
21318
  };
21319
21319
  function useSiteAccess(supabase, session, siteId) {
21320
- const [state, setState] = useState(EMPTY);
21320
+ const [state, setState] = useState(EMPTY$1);
21321
21321
  const cachedUserIdRef = useRef(null);
21322
21322
  useEffect(() => {
21323
21323
  if (!session) {
@@ -21358,17 +21358,51 @@ function useSiteAccess(supabase, session, siteId) {
21358
21358
  }, [supabase, session, siteId]);
21359
21359
  return state;
21360
21360
  }
21361
+ const SETTO_BASE = "/setto";
21362
+ function siteHomeUrl(pathname = "/") {
21363
+ const u = new URL(window.location.href);
21364
+ u.pathname = pathname;
21365
+ u.search = "";
21366
+ return u.toString();
21367
+ }
21368
+ function isAdminRoute() {
21369
+ return window.location.pathname.startsWith(SETTO_BASE);
21370
+ }
21371
+ function isAdminDeploymentView() {
21372
+ return isAdminRoute() && new URLSearchParams(window.location.search).has("deployment");
21373
+ }
21374
+ function adminViewUrl(view) {
21375
+ return `${SETTO_BASE}?view=${encodeURIComponent(view)}`;
21376
+ }
21377
+ function currentAdminView() {
21378
+ return new URLSearchParams(window.location.search).get("view");
21379
+ }
21380
+ function isAdminPanelView() {
21381
+ return isAdminDeploymentView() || isAdminRoute() && currentAdminView() !== null;
21382
+ }
21383
+ const CHECKOUT_INTENT = "neste";
21384
+ function checkoutIntentUrl() {
21385
+ return `${SETTO_BASE}?${CHECKOUT_INTENT}=1`;
21386
+ }
21387
+ function wantsCheckout() {
21388
+ return new URLSearchParams(window.location.search).get(CHECKOUT_INTENT) === "1";
21389
+ }
21390
+ function withoutCheckoutIntent() {
21391
+ const u = new URL(window.location.href);
21392
+ u.searchParams.delete(CHECKOUT_INTENT);
21393
+ return u.pathname + (u.search || "") + u.hash;
21394
+ }
21361
21395
  const PREVIEW_HOST = /(^|\.)site\.setto\.no$/i;
21362
21396
  function isPreviewHost(hostname) {
21363
21397
  return PREVIEW_HOST.test(hostname);
21364
21398
  }
21365
- function previewBarState(input) {
21366
- if (!input.onPreview || input.authLoading) return "hidden";
21367
- if (input.hasSession && !input.sitesLoaded) return "hidden";
21368
- if (!input.hasSession && input.soldPublic === null) return "hidden";
21369
- const bought = input.paidMarker || input.currentSiteIsLive || input.soldPublic === true;
21399
+ function previewBarState(input2) {
21400
+ if (!input2.onPreview || input2.authLoading) return "hidden";
21401
+ if (input2.hasSession && !input2.sitesLoaded) return "hidden";
21402
+ if (!input2.hasSession && input2.soldPublic === null) return "hidden";
21403
+ const bought = input2.paidMarker || input2.currentSiteIsLive || input2.soldPublic === true;
21370
21404
  if (bought) return "hidden";
21371
- return input.hasSession && input.hasCurrentSite ? "owner" : "visitor";
21405
+ return input2.hasSession && input2.hasCurrentSite ? "owner" : "visitor";
21372
21406
  }
21373
21407
  function SettoPreviewBar() {
21374
21408
  const { supabase, api, config, session, authLoading, currentSite, sites, editMode } = useSetto();
@@ -21394,21 +21428,8 @@ function SettoPreviewBar() {
21394
21428
  cancelled = true;
21395
21429
  };
21396
21430
  }, [onPreview, session, config.apiUrl, config.siteId]);
21397
- const state = previewBarState({
21398
- onPreview,
21399
- authLoading,
21400
- hasSession: !!session,
21401
- sitesLoaded: sites !== null,
21402
- hasCurrentSite: !!currentSite,
21403
- currentSiteIsLive: currentSite?.status === "live",
21404
- soldPublic,
21405
- paidMarker: paid
21406
- });
21407
- if (state === "hidden") return null;
21408
- const owner = state === "owner";
21409
- const name = currentSite?.display_name?.trim() || config.displayName?.trim() || config.siteId;
21410
21431
  const signIn = () => {
21411
- window.location.href = "/setto";
21432
+ window.location.href = checkoutIntentUrl();
21412
21433
  };
21413
21434
  const next = () => {
21414
21435
  if (window.parent !== window) {
@@ -21445,6 +21466,28 @@ function SettoPreviewBar() {
21445
21466
  setBusy(false);
21446
21467
  }
21447
21468
  };
21469
+ const resumed = useRef(false);
21470
+ useEffect(() => {
21471
+ if (resumed.current || !onPreview || !session || !currentSite) return;
21472
+ if (!wantsCheckout()) return;
21473
+ if (paid || currentSite.status === "live") return;
21474
+ resumed.current = true;
21475
+ window.history.replaceState(null, "", withoutCheckoutIntent());
21476
+ void publish();
21477
+ }, [onPreview, session, currentSite, paid]);
21478
+ const state = previewBarState({
21479
+ onPreview,
21480
+ authLoading,
21481
+ hasSession: !!session,
21482
+ sitesLoaded: sites !== null,
21483
+ hasCurrentSite: !!currentSite,
21484
+ currentSiteIsLive: currentSite?.status === "live",
21485
+ soldPublic,
21486
+ paidMarker: paid
21487
+ });
21488
+ if (state === "hidden") return null;
21489
+ const owner = state === "owner";
21490
+ const name = currentSite?.display_name?.trim() || config.displayName?.trim() || config.siteId;
21448
21491
  return createPortal(
21449
21492
  /*
21450
21493
  * Lifted above the editor's floating button when edit mode is on, which
@@ -21462,7 +21505,7 @@ function SettoPreviewBar() {
21462
21505
  "Du forhåndsviser nå ",
21463
21506
  /* @__PURE__ */ jsx("strong", { style: { fontWeight: 600 }, children: name })
21464
21507
  ] }),
21465
- error && /* @__PURE__ */ jsx("span", { style: errorStyle$1, children: error }),
21508
+ error && /* @__PURE__ */ jsx("span", { style: errorStyle$2, children: error }),
21466
21509
  /* @__PURE__ */ jsx("button", { type: "button", style: primaryStyle, onClick: publish, disabled: busy, children: busy ? "Åpner betaling …" : "Publiser" })
21467
21510
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
21468
21511
  /* @__PURE__ */ jsx("span", { style: dotStyle, "aria-hidden": true }),
@@ -21529,7 +21572,7 @@ const primaryStyle = {
21529
21572
  fontWeight: 600,
21530
21573
  cursor: "pointer"
21531
21574
  };
21532
- const errorStyle$1 = {
21575
+ const errorStyle$2 = {
21533
21576
  color: "#ffb4a2",
21534
21577
  fontSize: 13,
21535
21578
  /*
@@ -21545,28 +21588,6 @@ const errorStyle$1 = {
21545
21588
  textOverflow: "ellipsis",
21546
21589
  whiteSpace: "nowrap"
21547
21590
  };
21548
- const SETTO_BASE = "/setto";
21549
- function siteHomeUrl(pathname = "/") {
21550
- const u = new URL(window.location.href);
21551
- u.pathname = pathname;
21552
- u.search = "";
21553
- return u.toString();
21554
- }
21555
- function isAdminRoute() {
21556
- return window.location.pathname.startsWith(SETTO_BASE);
21557
- }
21558
- function isAdminDeploymentView() {
21559
- return isAdminRoute() && new URLSearchParams(window.location.search).has("deployment");
21560
- }
21561
- function adminViewUrl(view) {
21562
- return `${SETTO_BASE}?view=${encodeURIComponent(view)}`;
21563
- }
21564
- function currentAdminView() {
21565
- return new URLSearchParams(window.location.search).get("view");
21566
- }
21567
- function isAdminPanelView() {
21568
- return isAdminDeploymentView() || isAdminRoute() && currentAdminView() !== null;
21569
- }
21570
21591
  const FAB_SIZE = 52;
21571
21592
  const FAB_INSET = 16;
21572
21593
  const STYLE_ID$3 = "setto-edit-layout";
@@ -22247,13 +22268,13 @@ function isDeploymentInProgress(status) {
22247
22268
  }
22248
22269
  const STALE_PENDING_MS = 20 * 60 * 1e3;
22249
22270
  const STALE_BUILDING_MS = 45 * 60 * 1e3;
22250
- function isDeploymentStale(row) {
22251
- if (row.status !== "pending" && row.status !== "building") return false;
22271
+ function isDeploymentStale(row2) {
22272
+ if (row2.status !== "pending" && row2.status !== "building") return false;
22252
22273
  const now = Date.now();
22253
- if (row.status === "pending") {
22254
- return now - new Date(row.started_at).getTime() > STALE_PENDING_MS;
22274
+ if (row2.status === "pending") {
22275
+ return now - new Date(row2.started_at).getTime() > STALE_PENDING_MS;
22255
22276
  }
22256
- return now - new Date(row.updated_at).getTime() > STALE_BUILDING_MS;
22277
+ return now - new Date(row2.updated_at).getTime() > STALE_BUILDING_MS;
22257
22278
  }
22258
22279
  async function fetchInProgressDeploymentId(supabase, siteId) {
22259
22280
  const { data } = await supabase.from("deployments").select("id, status, started_at, updated_at").eq("site_id", siteId).in("status", [...IN_PROGRESS_STATUSES]).order("started_at", { ascending: false }).limit(5);
@@ -22271,7 +22292,7 @@ async function waitForDeploymentByCommit(supabase, siteId, commitSha, timeoutMs
22271
22292
  return null;
22272
22293
  }
22273
22294
  function useDeploymentStatus(supabase, deploymentId) {
22274
- const [row, setRow] = useState(null);
22295
+ const [row2, setRow] = useState(null);
22275
22296
  useEffect(() => {
22276
22297
  if (!deploymentId) {
22277
22298
  setRow(null);
@@ -22301,7 +22322,7 @@ function useDeploymentStatus(supabase, deploymentId) {
22301
22322
  if (channel) supabase.removeChannel(channel);
22302
22323
  };
22303
22324
  }, [supabase, deploymentId]);
22304
- return { row, status: row?.status ?? null };
22325
+ return { row: row2, status: row2?.status ?? null };
22305
22326
  }
22306
22327
  function deploymentStepIndex(status) {
22307
22328
  switch (status) {
@@ -22440,14 +22461,14 @@ function PublishProgressBar({ status, compact, href }) {
22440
22461
  return /* @__PURE__ */ jsx("div", { style: wrapStyle, children: inner });
22441
22462
  }
22442
22463
  function PublishDialog({
22443
- row,
22464
+ row: row2,
22444
22465
  status,
22445
22466
  onClose,
22446
22467
  onComplete
22447
22468
  }) {
22448
22469
  const buildingStartedAt = useRef(null);
22449
22470
  const [elapsed, setElapsed] = useState(0);
22450
- const progressStatus = row?.status ?? status ?? "pending";
22471
+ const progressStatus = row2?.status ?? status ?? "pending";
22451
22472
  const errored = progressStatus === "error" || progressStatus === "canceled";
22452
22473
  const isReady = progressStatus === "ready";
22453
22474
  const isBuilding = progressStatus === "building";
@@ -22474,7 +22495,7 @@ function PublishDialog({
22474
22495
  /* @__PURE__ */ jsx("h2", { style: { margin: "0 0 12px", fontSize: 18, fontWeight: 600, color: "#dc2626" }, children: "Publisering feilet" }),
22475
22496
  /* @__PURE__ */ jsxs("p", { style: { margin: "0 0 20px", fontSize: 14, lineHeight: 1.5, color: "#444" }, children: [
22476
22497
  progressStatus === "error" ? "Bygg feilet." : "Avbrutt.",
22477
- row?.error_message ? ` ${row.error_message}` : ""
22498
+ row2?.error_message ? ` ${row2.error_message}` : ""
22478
22499
  ] }),
22479
22500
  /* @__PURE__ */ jsx("button", { type: "button", onClick: onComplete, style: secondaryBtnStyle$1, children: "OK" })
22480
22501
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -22555,6 +22576,226 @@ function useEditBaseline() {
22555
22576
  };
22556
22577
  }, [session, store, config.siteId]);
22557
22578
  }
22579
+ const EMPTY = {
22580
+ host: null,
22581
+ verified: false,
22582
+ status: null,
22583
+ instructions: [],
22584
+ statusLine: null
22585
+ };
22586
+ function Copyable({ value }) {
22587
+ const [copied, setCopied] = useState(false);
22588
+ return /* @__PURE__ */ jsx(
22589
+ "button",
22590
+ {
22591
+ type: "button",
22592
+ onClick: () => {
22593
+ void navigator.clipboard?.writeText(value).then(
22594
+ () => {
22595
+ setCopied(true);
22596
+ window.setTimeout(() => setCopied(false), 1400);
22597
+ },
22598
+ () => void 0
22599
+ );
22600
+ },
22601
+ title: "Kopier",
22602
+ style: {
22603
+ font: "inherit",
22604
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
22605
+ background: "none",
22606
+ border: 0,
22607
+ padding: 0,
22608
+ cursor: "pointer",
22609
+ color: "inherit",
22610
+ textAlign: "left",
22611
+ wordBreak: "break-all"
22612
+ },
22613
+ children: copied ? "Kopiert" : value
22614
+ }
22615
+ );
22616
+ }
22617
+ function DomainView({ siteId }) {
22618
+ const { api } = useSetto();
22619
+ const [state, setState] = useState(EMPTY);
22620
+ const [host, setHost] = useState("");
22621
+ const [loading, setLoading] = useState(true);
22622
+ const [busy, setBusy] = useState(false);
22623
+ const [error, setError] = useState(null);
22624
+ const load = async () => {
22625
+ try {
22626
+ setState(await api.request(`/onboarding/sites/${siteId}/domain`, {}, "domain"));
22627
+ } catch {
22628
+ setState(EMPTY);
22629
+ } finally {
22630
+ setLoading(false);
22631
+ }
22632
+ };
22633
+ useEffect(() => {
22634
+ void load();
22635
+ }, [siteId]);
22636
+ async function attach() {
22637
+ setBusy(true);
22638
+ setError(null);
22639
+ try {
22640
+ setState(
22641
+ await api.request(
22642
+ `/onboarding/sites/${siteId}/domain`,
22643
+ { method: "POST", body: { host } },
22644
+ "attachDomain"
22645
+ )
22646
+ );
22647
+ setHost("");
22648
+ } catch (err) {
22649
+ const detail = err instanceof Error ? err.message : "";
22650
+ setError(
22651
+ detail.includes("invalid_domain") ? "Det ser ikke ut som et domenenavn. Skriv det som dittfirma.no." : detail.includes("domain_taken") ? "Domenet er allerede i bruk på en annen Setto-side." : detail.includes("site_not_deployed") ? "Nettsiden er ikke publisert ennå." : "Klarte ikke legge til domenet. Prøv igjen."
22652
+ );
22653
+ } finally {
22654
+ setBusy(false);
22655
+ }
22656
+ }
22657
+ async function recheck() {
22658
+ setBusy(true);
22659
+ setError(null);
22660
+ try {
22661
+ setState(
22662
+ await api.request(
22663
+ `/onboarding/sites/${siteId}/domain/verify`,
22664
+ { method: "POST" },
22665
+ "verifyDomain"
22666
+ )
22667
+ );
22668
+ } catch {
22669
+ setError("Klarte ikke sjekke akkurat nå. Prøv igjen om litt.");
22670
+ } finally {
22671
+ setBusy(false);
22672
+ }
22673
+ }
22674
+ async function detach() {
22675
+ setBusy(true);
22676
+ setError(null);
22677
+ try {
22678
+ setState(
22679
+ await api.request(
22680
+ `/onboarding/sites/${siteId}/domain`,
22681
+ { method: "DELETE" },
22682
+ "detachDomain"
22683
+ )
22684
+ );
22685
+ } catch {
22686
+ setError("Klarte ikke fjerne domenet.");
22687
+ } finally {
22688
+ setBusy(false);
22689
+ }
22690
+ }
22691
+ if (loading) return /* @__PURE__ */ jsx("p", { style: muted, children: "Henter …" });
22692
+ if (!state.host) {
22693
+ return /* @__PURE__ */ jsxs("div", { style: wrap, children: [
22694
+ /* @__PURE__ */ jsx("p", { style: lead, children: "Har du et domene fra før — dittfirma.no — kan du peke det hit. Nettsiden beholder adressen den har nå i tillegg, så ingenting slutter å virke underveis." }),
22695
+ /* @__PURE__ */ jsxs("div", { style: row, children: [
22696
+ /* @__PURE__ */ jsx(
22697
+ "input",
22698
+ {
22699
+ value: host,
22700
+ onChange: (e) => setHost(e.target.value),
22701
+ placeholder: "dittfirma.no",
22702
+ "aria-label": "Domenet ditt",
22703
+ autoCapitalize: "off",
22704
+ autoCorrect: "off",
22705
+ spellCheck: false,
22706
+ style: input
22707
+ }
22708
+ ),
22709
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void attach(), disabled: busy || !host.trim(), style: primary, children: busy ? "Legger til …" : "Legg til domene" })
22710
+ ] }),
22711
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle$1, children: error })
22712
+ ] });
22713
+ }
22714
+ return /* @__PURE__ */ jsxs("div", { style: wrap, children: [
22715
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "baseline", gap: "0.6rem", flexWrap: "wrap" }, children: [
22716
+ /* @__PURE__ */ jsx("strong", { style: { fontSize: "1.05rem" }, children: state.host }),
22717
+ /* @__PURE__ */ jsx("span", { style: state.verified ? liveBadge : pendingBadge, children: state.verified ? "Live" : "Venter på DNS" })
22718
+ ] }),
22719
+ state.statusLine && /* @__PURE__ */ jsx("p", { style: lead, children: state.statusLine }),
22720
+ state.instructions.length > 0 && !state.verified && /* @__PURE__ */ jsxs(Fragment, { children: [
22721
+ /* @__PURE__ */ jsx("p", { style: muted, children: "Logg inn der du kjøpte domenet, finn DNS-innstillingene, og legg inn dette:" }),
22722
+ /* @__PURE__ */ jsx("div", { style: { display: "grid", gap: "0.6rem" }, children: state.instructions.map((rec) => /* @__PURE__ */ jsxs("div", { style: card, children: [
22723
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "1.2rem", flexWrap: "wrap" }, children: [
22724
+ /* @__PURE__ */ jsx(Field, { label: "Type", value: rec.type }),
22725
+ /* @__PURE__ */ jsx(Field, { label: "Navn", value: rec.name }),
22726
+ /* @__PURE__ */ jsx(Field, { label: "Peker til", value: rec.value, wide: true })
22727
+ ] }),
22728
+ /* @__PURE__ */ jsx("p", { style: { ...muted, margin: "0.35rem 0 0" }, children: rec.why })
22729
+ ] }, `${rec.type}-${rec.name}`)) })
22730
+ ] }),
22731
+ error && /* @__PURE__ */ jsx("p", { style: errorStyle$1, children: error }),
22732
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "0.6rem", flexWrap: "wrap" }, children: [
22733
+ !state.verified && /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void recheck(), disabled: busy, style: primary, children: busy ? "Sjekker …" : "Jeg har lagt inn radene" }),
22734
+ /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void detach(), disabled: busy, style: quiet, children: "Fjern domenet" })
22735
+ ] })
22736
+ ] });
22737
+ }
22738
+ function Field({ label, value, wide }) {
22739
+ return /* @__PURE__ */ jsxs("div", { style: { minWidth: wide ? "14rem" : "5rem", flex: wide ? "1 1 14rem" : "0 0 auto" }, children: [
22740
+ /* @__PURE__ */ jsx("div", { style: { ...muted, fontSize: "0.72rem", textTransform: "uppercase", letterSpacing: "0.04em" }, children: label }),
22741
+ /* @__PURE__ */ jsx(Copyable, { value })
22742
+ ] });
22743
+ }
22744
+ const wrap = { display: "grid", gap: "0.9rem", maxWidth: "42rem" };
22745
+ const lead = { margin: 0, lineHeight: 1.5 };
22746
+ const muted = { margin: 0, opacity: 0.65, lineHeight: 1.5 };
22747
+ const row = { display: "flex", gap: "0.6rem", flexWrap: "wrap" };
22748
+ const input = {
22749
+ flex: "1 1 14rem",
22750
+ padding: "0.6rem 0.75rem",
22751
+ border: "1px solid rgba(0,0,0,0.18)",
22752
+ borderRadius: "0.5rem",
22753
+ font: "inherit"
22754
+ };
22755
+ const card = {
22756
+ padding: "0.7rem 0.85rem",
22757
+ border: "1px solid rgba(0,0,0,0.12)",
22758
+ borderRadius: "0.6rem",
22759
+ background: "rgba(0,0,0,0.02)"
22760
+ };
22761
+ const primary = {
22762
+ padding: "0.6rem 1.1rem",
22763
+ borderRadius: "999px",
22764
+ border: 0,
22765
+ background: "#c4502a",
22766
+ color: "#fff",
22767
+ font: "inherit",
22768
+ fontWeight: 600,
22769
+ cursor: "pointer"
22770
+ };
22771
+ const quiet = {
22772
+ padding: "0.6rem 0.9rem",
22773
+ borderRadius: "999px",
22774
+ border: "1px solid rgba(0,0,0,0.18)",
22775
+ background: "transparent",
22776
+ font: "inherit",
22777
+ cursor: "pointer"
22778
+ };
22779
+ const errorStyle$1 = { margin: 0, color: "#b42318" };
22780
+ const liveBadge = {
22781
+ fontSize: "0.75rem",
22782
+ padding: "0.15rem 0.5rem",
22783
+ borderRadius: "999px",
22784
+ background: "rgba(15,123,79,0.12)",
22785
+ color: "#0f7b4f"
22786
+ };
22787
+ const pendingBadge = {
22788
+ fontSize: "0.75rem",
22789
+ padding: "0.15rem 0.5rem",
22790
+ borderRadius: "999px",
22791
+ background: "rgba(196,80,42,0.12)",
22792
+ color: "#c4502a"
22793
+ };
22794
+ const domainModule = {
22795
+ id: "domain",
22796
+ label: "Domene",
22797
+ AdminView: DomainView
22798
+ };
22558
22799
  const shellStyle$1 = {
22559
22800
  minHeight: "100dvh",
22560
22801
  background: "#0a0a0d",
@@ -22825,28 +23066,28 @@ function SubmissionList({ siteId }) {
22825
23066
  return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 12 }, children: [
22826
23067
  /* @__PURE__ */ jsx("h3", { style: subheadingStyle, children: "Henvendelser" }),
22827
23068
  error ? /* @__PURE__ */ jsx("p", { style: errStyle, children: error }) : null,
22828
- rows.length === 0 ? /* @__PURE__ */ jsx("p", { style: mutedStyle, children: "Ingen henvendelser ennå. Når noen sender inn et skjema på siden, dukker det opp her og i e-posten." }) : /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 6 }, children: rows.map((row) => /* @__PURE__ */ jsx(
23069
+ rows.length === 0 ? /* @__PURE__ */ jsx("p", { style: mutedStyle, children: "Ingen henvendelser ennå. Når noen sender inn et skjema på siden, dukker det opp her og i e-posten." }) : /* @__PURE__ */ jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0, display: "flex", flexDirection: "column", gap: 6 }, children: rows.map((row2) => /* @__PURE__ */ jsx(
22829
23070
  SubmissionItem,
22830
23071
  {
22831
- row,
22832
- open: openId === row.id,
22833
- onToggle: () => setOpenId(openId === row.id ? null : row.id),
22834
- onDelete: () => void remove2(row.id)
23072
+ row: row2,
23073
+ open: openId === row2.id,
23074
+ onToggle: () => setOpenId(openId === row2.id ? null : row2.id),
23075
+ onDelete: () => void remove2(row2.id)
22835
23076
  },
22836
- row.id
23077
+ row2.id
22837
23078
  )) }),
22838
23079
  hasMore ? /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void loadMore(), disabled: loadingMore, style: secondaryBtnStyle, children: loadingMore ? "Laster …" : "Vis eldre" }) : null
22839
23080
  ] });
22840
23081
  }
22841
23082
  function SubmissionItem({
22842
- row,
23083
+ row: row2,
22843
23084
  open,
22844
23085
  onToggle,
22845
23086
  onDelete
22846
23087
  }) {
22847
- const fields = submissionFields(row);
23088
+ const fields = submissionFields(row2);
22848
23089
  const sender = senderOf(fields);
22849
- const title = row.meta.title ?? row.form_id;
23090
+ const title = row2.meta.title ?? row2.form_id;
22850
23091
  return /* @__PURE__ */ jsxs("li", { children: [
22851
23092
  /* @__PURE__ */ jsxs(
22852
23093
  "button",
@@ -22856,7 +23097,7 @@ function SubmissionItem({
22856
23097
  "aria-expanded": open,
22857
23098
  style: { ...rowStyle, width: "100%", textAlign: "left", color: "inherit", border: "none", cursor: "pointer", font: "inherit" },
22858
23099
  children: [
22859
- /* @__PURE__ */ jsx("span", { style: statusDotStyle(row.email_status), title: emailStatusLabel(row) }),
23100
+ /* @__PURE__ */ jsx("span", { style: statusDotStyle(row2.email_status), title: emailStatusLabel(row2) }),
22860
23101
  /* @__PURE__ */ jsxs("span", { style: { flex: 1, fontSize: 13, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: [
22861
23102
  sender ?? /* @__PURE__ */ jsx("span", { style: { color: "#aaa" }, children: "Uten navn" }),
22862
23103
  /* @__PURE__ */ jsxs("span", { style: { color: "#888" }, children: [
@@ -22864,7 +23105,7 @@ function SubmissionItem({
22864
23105
  title
22865
23106
  ] })
22866
23107
  ] }),
22867
- /* @__PURE__ */ jsx("time", { style: { fontSize: 11, color: "#888", flexShrink: 0 }, children: formatWhen(row.created_at) })
23108
+ /* @__PURE__ */ jsx("time", { style: { fontSize: 11, color: "#888", flexShrink: 0 }, children: formatWhen(row2.created_at) })
22868
23109
  ]
22869
23110
  }
22870
23111
  ),
@@ -22874,26 +23115,26 @@ function SubmissionItem({
22874
23115
  /* @__PURE__ */ jsx("dd", { style: { margin: 0, fontSize: 14, whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: f.value === "" ? /* @__PURE__ */ jsx("span", { style: { color: "#666" }, children: "—" }) : f.value })
22875
23116
  ] }, f.name)) }),
22876
23117
  /* @__PURE__ */ jsxs("p", { style: mutedStyle, children: [
22877
- emailStatusLabel(row),
22878
- row.recipients.length > 0 ? ` til ${row.recipients.join(", ")}` : "",
22879
- row.email_error ? ` — ${row.email_error}` : "",
22880
- row.meta.page ? /* @__PURE__ */ jsxs(Fragment, { children: [
23118
+ emailStatusLabel(row2),
23119
+ row2.recipients.length > 0 ? ` til ${row2.recipients.join(", ")}` : "",
23120
+ row2.email_error ? ` — ${row2.email_error}` : "",
23121
+ row2.meta.page ? /* @__PURE__ */ jsxs(Fragment, { children: [
22881
23122
  " · ",
22882
- /* @__PURE__ */ jsx("a", { href: row.meta.page, style: { color: "#bda6ff" }, target: "_blank", rel: "noreferrer", children: "Sendt fra siden" })
23123
+ /* @__PURE__ */ jsx("a", { href: row2.meta.page, style: { color: "#bda6ff" }, target: "_blank", rel: "noreferrer", children: "Sendt fra siden" })
22883
23124
  ] }) : null
22884
23125
  ] }),
22885
23126
  /* @__PURE__ */ jsx("button", { type: "button", onClick: onDelete, style: dangerBtnStyle, children: "Slett henvendelse" })
22886
23127
  ] }) : null
22887
23128
  ] });
22888
23129
  }
22889
- function submissionFields(row) {
23130
+ function submissionFields(row2) {
22890
23131
  const flat = [];
22891
- flatten(row.data, "", flat);
22892
- const rank = new Map((row.field_order ?? []).map((n, i) => [n, i]));
23132
+ flatten(row2.data, "", flat);
23133
+ const rank = new Map((row2.field_order ?? []).map((n, i) => [n, i]));
22893
23134
  const rankOf = (name) => rank.get(name) ?? rank.get(name.split(".")[0]) ?? Number.MAX_SAFE_INTEGER;
22894
23135
  return flat.map((f, i) => ({ f, i })).sort((a, b) => rankOf(a.f.name) - rankOf(b.f.name) || a.i - b.i).map(({ f }) => ({
22895
23136
  name: f.name,
22896
- label: row.labels?.[f.name] ?? row.labels?.[f.name.split(".")[0]] ?? prettify(f.name),
23137
+ label: row2.labels?.[f.name] ?? row2.labels?.[f.name.split(".")[0]] ?? prettify(f.name),
22897
23138
  value: f.value
22898
23139
  }));
22899
23140
  }
@@ -22932,8 +23173,8 @@ function senderOf(fields) {
22932
23173
  const first = fields.find((f) => f.value !== "");
22933
23174
  return first ? first.value.slice(0, 80) : null;
22934
23175
  }
22935
- function emailStatusLabel(row) {
22936
- switch (row.email_status) {
23176
+ function emailStatusLabel(row2) {
23177
+ switch (row2.email_status) {
22937
23178
  case "sent":
22938
23179
  return "E-post sendt";
22939
23180
  case "failed":
@@ -24383,7 +24624,7 @@ const formsModule = {
24383
24624
  label: "Skjemaer",
24384
24625
  AdminView: FormsView
24385
24626
  };
24386
- const SETTO_MODULES = [formsModule];
24627
+ const SETTO_MODULES = [formsModule, domainModule];
24387
24628
  function findModule(id) {
24388
24629
  return id ? SETTO_MODULES.find((m) => m.id === id) : void 0;
24389
24630
  }
@@ -26209,8 +26450,8 @@ function DeploymentsView({
26209
26450
  ] })
26210
26451
  ] });
26211
26452
  }
26212
- function statusLabel(row) {
26213
- switch (row.status) {
26453
+ function statusLabel(row2) {
26454
+ switch (row2.status) {
26214
26455
  case "pending":
26215
26456
  return "Venter";
26216
26457
  case "building":
@@ -26218,7 +26459,7 @@ function statusLabel(row) {
26218
26459
  case "ready":
26219
26460
  return "Publisert";
26220
26461
  case "error":
26221
- return row.error_message?.includes("webhook") ? "Utløpt" : "Feilet";
26462
+ return row2.error_message?.includes("webhook") ? "Utløpt" : "Feilet";
26222
26463
  case "canceled":
26223
26464
  return "Avbrutt";
26224
26465
  }
@@ -26256,7 +26497,9 @@ function SiteList() {
26256
26497
  }
26257
26498
  if (currentSite) {
26258
26499
  redirectAfterSignIn.current = false;
26259
- window.location.replace(siteHomeUrl());
26500
+ window.location.replace(
26501
+ wantsCheckout() ? `${siteHomeUrl()}?${CHECKOUT_INTENT}=1` : siteHomeUrl()
26502
+ );
26260
26503
  return;
26261
26504
  }
26262
26505
  redirectAfterSignIn.current = false;
@@ -26377,20 +26620,20 @@ function nodeChildren(node) {
26377
26620
  }
26378
26621
  }
26379
26622
  const ANIMATION_PRESETS = ["fadeIn", "slideUp", "stagger", "scrollReveal"];
26380
- function validateBlockTree(input) {
26623
+ function validateBlockTree(input2) {
26381
26624
  const issues = [];
26382
- if (!isRecord(input)) {
26625
+ if (!isRecord(input2)) {
26383
26626
  return fail("$", "Block tree must be an object");
26384
26627
  }
26385
- if (input.version !== "1") {
26628
+ if (input2.version !== "1") {
26386
26629
  issues.push({ path: "$.version", message: 'Expected version "1"' });
26387
26630
  }
26388
- if (!Array.isArray(input.root)) {
26631
+ if (!Array.isArray(input2.root)) {
26389
26632
  return fail("$.root", "root must be an array of block nodes");
26390
26633
  }
26391
26634
  const seenIds = /* @__PURE__ */ new Set();
26392
- for (let i = 0; i < input.root.length; i++) {
26393
- validateNode(input.root[i], `root[${i}]`, seenIds, issues);
26635
+ for (let i = 0; i < input2.root.length; i++) {
26636
+ validateNode(input2.root[i], `root[${i}]`, seenIds, issues);
26394
26637
  }
26395
26638
  return issues.length ? { ok: false, issues } : { ok: true };
26396
26639
  }
@@ -26540,14 +26783,14 @@ function isRecord(value) {
26540
26783
  function fail(path, message) {
26541
26784
  return { ok: false, issues: [{ path, message }] };
26542
26785
  }
26543
- function parseBlockTree(input) {
26544
- const result = validateBlockTree(input);
26786
+ function parseBlockTree(input2) {
26787
+ const result = validateBlockTree(input2);
26545
26788
  if (!result.ok) {
26546
26789
  const first = result.issues[0];
26547
26790
  const detail = first ? `${first.path}: ${first.message}` : "unknown";
26548
26791
  throw new Error(`Invalid block tree at ${detail}`);
26549
26792
  }
26550
- return input;
26793
+ return input2;
26551
26794
  }
26552
26795
  const IconRegistryContext = createContext(null);
26553
26796
  const RepeaterScopeContext = createContext(null);