@bygghammar/cms-platform 0.90.0-m7.1 → 0.90.0-m7.3

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/CHANGELOG.md CHANGED
@@ -8,6 +8,26 @@ matches `package.json` exactly. See
8
8
  Versions 0.1.0 through 0.78.0 predate this repository and were reconstructed
9
9
  from the published npm tarballs.
10
10
 
11
+ ## 0.90.0-m7.3
12
+
13
+ - Popup exclusions are derived from the configured `backofficePath`, so a site
14
+ that mounts its office at `/admin` or `/cms/backoffice` is covered without
15
+ naming it twice. Both the tree and its landing page are excluded: `/admin/**`
16
+ does not match `/admin`.
17
+ - `registerPopupPublicHost` accepts `excludedPaths` for a site's own private
18
+ routes — a checkout, a members' area. The CMS adds to that list and never
19
+ replaces it, and drops duplicates rather than repeating a path.
20
+ - Requires `@bygghammar/lightweight-popup@>=0.2.0-m7.3`, whose defaults no
21
+ longer name anyone's backoffice.
22
+
23
+ ## 0.90.0-m7.2
24
+
25
+ - `backofficePaths` gains `popups` and `popupDestinations`, and both popup
26
+ mount points supply them to the package's navigation. The destinations screen
27
+ was reachable only by typing its address.
28
+ - Requires `@bygghammar/lightweight-popup@>=0.2.0-m7.2`, which is where the
29
+ navigation itself lives.
30
+
11
31
  ## 0.90.0-m7.1
12
32
 
13
33
  First version published to npm rather than vendored as a tarball. Same code as
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bygghammar/cms-platform",
3
- "version": "0.90.0-m7.1",
3
+ "version": "0.90.0-m7.3",
4
4
  "description": "Shared CMS platform: blocks, block types, i18n core, UI primitives and design-token contract used by every Bygghammar/Voyara site.",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -263,7 +263,7 @@
263
263
  "@dnd-kit/sortable": ">=3",
264
264
  "@dnd-kit/utilities": ">=3",
265
265
  "zod": ">=3",
266
- "@bygghammar/lightweight-popup": ">=0.2.0-m7.1"
266
+ "@bygghammar/lightweight-popup": ">=0.2.0-m7.3"
267
267
  },
268
268
  "peerDependenciesMeta": {
269
269
  "@supabase/supabase-js": {
@@ -328,7 +328,7 @@
328
328
  "check": "bun run typecheck && bun run test && bun run verify:pack"
329
329
  },
330
330
  "devDependencies": {
331
- "@bygghammar/lightweight-popup": "file:./vendor/bygghammar-lightweight-popup-0.1.0-dev.9.tgz",
331
+ "@bygghammar/lightweight-popup": "file:./vendor/bygghammar-lightweight-popup-0.2.0-m7.3.tgz",
332
332
  "@dnd-kit/core": "^6.3.1",
333
333
  "@dnd-kit/sortable": "^10.0.0",
334
334
  "@dnd-kit/utilities": "^3.2.2",
@@ -317,6 +317,8 @@ export function backofficePaths(host: BackofficeHost = backofficeHost()) {
317
317
  formDeliveries: `${base}/forms/deliveries`,
318
318
  pagesBuilder: `${base}/pages-builder`,
319
319
  resetPassword: `${base}/reset-password`,
320
+ popups: `${base}/popups`,
321
+ popupDestinations: `${base}/popups/destinations`,
320
322
  };
321
323
  }
322
324
 
@@ -22,6 +22,7 @@ import "@bygghammar/lightweight-popup/admin.css";
22
22
  import type { AdminAdapters } from "@bygghammar/lightweight-popup/adapters";
23
23
 
24
24
  import { useFeatureGate } from "../backoffice/shell/use-resolved-config";
25
+ import { cmsPopupNavigation } from "./cms-bridges";
25
26
  import { cmsMediaPicker } from "./media-bridge";
26
27
  import { ManagedForm } from "../forms/FormRenderer";
27
28
  import {
@@ -49,6 +50,7 @@ function PopupsRouteInner(): ReactNode {
49
50
  // popup editor falls back to typing an address, which is what an
50
51
  // administrator was left with before.
51
52
  media: cmsMediaPicker(),
53
+ navigation: cmsPopupNavigation("popups"),
52
54
  forms: {
53
55
  // The builder preview renders the site's real form, so what an editor
54
56
  // checks is what a visitor will see.
@@ -7,6 +7,8 @@
7
7
  * this itself.
8
8
  */
9
9
  import type {
10
+ AdminNavigationPort,
11
+ AdminScreen,
10
12
  FormDirectoryPort,
11
13
  HostFormField,
12
14
  HostFormSchema,
@@ -16,6 +18,7 @@ import type {
16
18
  PageDirectoryPort,
17
19
  } from "@bygghammar/lightweight-popup/adapters";
18
20
  import { fieldTypes } from "../forms/field-sets";
21
+ import { backofficePaths } from "../backoffice/routes/host";
19
22
  import { DEFAULT_LOCALE, t } from "../i18n";
20
23
  import { backofficeHost } from "../backoffice/routes/host";
21
24
 
@@ -198,3 +201,20 @@ export function cmsOptInDestinations(): OptInDestinationPort {
198
201
  },
199
202
  };
200
203
  }
204
+
205
+
206
+ /**
207
+ * Where this site mounted the popup screens.
208
+ *
209
+ * Derived from the backoffice base the site configured, like every other
210
+ * backoffice path — so a site that moves its backoffice moves these with it,
211
+ * and the popup package never learns either address.
212
+ */
213
+ export function cmsPopupNavigation(current: AdminScreen): AdminNavigationPort {
214
+ const paths = backofficePaths();
215
+ return {
216
+ popupsHref: paths.popups,
217
+ destinationsHref: paths.popupDestinations,
218
+ current,
219
+ };
220
+ }
@@ -23,6 +23,7 @@ import type {
23
23
  } from "@bygghammar/lightweight-popup/adapters";
24
24
 
25
25
  import { backofficeHost } from "../backoffice/routes/host";
26
+ import { cmsPopupNavigation } from "./cms-bridges";
26
27
 
27
28
  /* eslint-disable @typescript-eslint/no-explicit-any */
28
29
  type Fn = (...args: any[]) => Promise<any>;
@@ -135,7 +136,12 @@ export function cmsDestinationAdmin(): OptInDestinationAdminPort {
135
136
 
136
137
  /** The screen, ready to mount on a route. */
137
138
  export function PopupDestinationsView(): ReactNode {
138
- return <DestinationsAdmin destinations={cmsDestinationAdmin()} />;
139
+ return (
140
+ <DestinationsAdmin
141
+ destinations={cmsDestinationAdmin()}
142
+ navigation={cmsPopupNavigation("destinations")}
143
+ />
144
+ );
139
145
  }
140
146
 
141
147
  export default PopupDestinationsView;
@@ -19,6 +19,15 @@ import type {
19
19
  export type PopupPublicHost = {
20
20
  readonly configs: PopupConfigRepository;
21
21
  readonly analytics: AnalyticsEventRepository;
22
+ /**
23
+ * Paths of the site's own that no popup may appear on.
24
+ *
25
+ * The backoffice is added for every site already, from the configured
26
+ * `backofficePath` — this is for the rest: a checkout, a members' area, a
27
+ * page a site simply wants left alone. Patterns are the popup package's:
28
+ * `/checkout` for one page, `/checkout/**` for everything beneath it.
29
+ */
30
+ readonly excludedPaths?: readonly string[];
22
31
  };
23
32
 
24
33
  /**
@@ -13,12 +13,16 @@
13
13
  import { useCallback, useEffect, useMemo, useRef } from "react";
14
14
  import type { ReactNode } from "react";
15
15
  import { useRouterState } from "@tanstack/react-router";
16
- import { PopupRuntime } from "@bygghammar/lightweight-popup/runtime";
16
+ import {
17
+ PopupRuntime,
18
+ withExcludedBase,
19
+ } from "@bygghammar/lightweight-popup/runtime";
17
20
  import type { RuntimeAdapters } from "@bygghammar/lightweight-popup/adapters";
18
21
 
19
22
  import { ManagedForm } from "../forms/FormRenderer";
20
23
  import { onFormSubmissionSuccess } from "../forms/success-listeners";
21
24
  import { siteConfig } from "../config/site-config";
25
+ import type { PopupPublicHost } from "./host";
22
26
  import { popupPublicHost } from "./host";
23
27
 
24
28
  /**
@@ -52,13 +56,26 @@ function PopupForm({
52
56
  /**
53
57
  * Paths the runtime never displays on.
54
58
  *
55
- * Derived from the site's configured backoffice path rather than a hardcoded
56
- * `/kontoret`, plus the CMS preview routes — a popup over the editor's own
57
- * live preview would end up in screenshots.
59
+ * Three sources, in one list. The site's own exclusions come first and are
60
+ * kept whole — this only ever adds to them. `/preview/**` is the platform's:
61
+ * a popup over the editor's live preview ends up in screenshots. The
62
+ * backoffice comes from the site's configured `backofficePath`, the same
63
+ * value `backofficePaths()` builds every backoffice address from, so a site
64
+ * that mounts its office at `/admin` or `/cms/backoffice` is covered without
65
+ * telling anyone twice.
66
+ *
67
+ * The popup package deliberately excludes nothing by itself. It cannot know
68
+ * which of a site's paths are private, and when it used to guess, every site
69
+ * whose office was named differently got popups over its own admin screens.
58
70
  */
59
- function excludedPaths(): readonly string[] {
60
- const base = siteConfig().backofficePath.replace(/\/+$/, "");
61
- return [`${base}/**`, base, "/preview/**"];
71
+ export function popupExcludedPaths(
72
+ host: Pick<PopupPublicHost, "excludedPaths">,
73
+ backofficePath: string,
74
+ ): readonly string[] {
75
+ return withExcludedBase(
76
+ [...(host.excludedPaths ?? []), "/preview/**"],
77
+ backofficePath,
78
+ );
62
79
  }
63
80
 
64
81
  export function PopupModuleRuntime(): ReactNode {
@@ -85,7 +102,7 @@ export function PopupModuleRuntime(): ReactNode {
85
102
  <PopupRuntime
86
103
  path={path}
87
104
  adapters={adapters}
88
- excludedPaths={excludedPaths()}
105
+ excludedPaths={popupExcludedPaths(host, siteConfig().backofficePath)}
89
106
  />
90
107
  );
91
108
  }