@byscott-io/pagelet 0.2.0 → 0.2.2

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
@@ -1,5 +1,29 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.2 (2026-11-13)
4
+
5
+ - **Theme `fontSize`**: the page's base text size (default `1rem`), as
6
+ `--pagelet-font-size`. It applies to the page, not the menu, so a site can
7
+ use larger body text without a larger menu. The Hero subheading is now sized
8
+ in `em` so it scales with it.
9
+
10
+ ## 0.2.1 (2026-11-13)
11
+
12
+ - **The public renderer no longer imports Puck.** 0.2.0's `PageletPage` used
13
+ `@puckeditor/core/rsc`, which pulls in Tiptap and ProseMirror: about 350 KB
14
+ minified on every public page. pagelet now draws pages with its own renderer
15
+ (`src/render.jsx`), which produces byte-for-byte the same HTML as Puck's (a
16
+ test holds it to that). The renderer bundle is now about 27 KB minified.
17
+ - The build fails if the renderer imports Puck or exceeds a size budget.
18
+ - **Older Puck data with DropZones renders correctly.** A block that draws
19
+ `puck.renderDropZone({ zone })` gets its blocks from `data.zones`, exactly as
20
+ Puck's renderer does (held to Puck's HTML by a test). 0.2.0 ran Puck's
21
+ `migrate()` on public pages, which throws for such a block.
22
+ - The editor converts zones to slots with Puck's `migrate()` when the block
23
+ now has a matching slot field, and opens the data unchanged when it does not
24
+ (`migrate()` throws there), instead of crashing.
25
+ - `upgradeDocument(document)` no longer takes the palette.
26
+
3
27
  ## 0.2.0 (2026-11-13)
4
28
 
5
29
  ### npm `@byscott-io/pagelet`
package/README.md CHANGED
@@ -120,7 +120,7 @@ Any subset of these tokens; the rest use the defaults:
120
120
  {
121
121
  colorText, colorBackground, colorMuted,
122
122
  colorAccent, colorAccentText,
123
- fontBody, fontHeading,
123
+ fontBody, fontHeading, fontSize, // fontSize: the page's base text size, e.g. '1.25rem'
124
124
  radius, maxWidth, space,
125
125
  }
126
126
  ```
package/dist/editor.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var core = require('@puckeditor/core');
5
- var rsc = require('@puckeditor/core/rsc');
6
5
 
7
6
  const DOCUMENT_VERSION = 1;
8
7
  function emptyData() {
@@ -11,7 +10,7 @@ function emptyData() {
11
10
  function createDocument(data = emptyData()) {
12
11
  return { pagelet: DOCUMENT_VERSION, data };
13
12
  }
14
- function upgradeDocument(document, palette) {
13
+ function upgradeDocument(document) {
15
14
  if (document == null) return createDocument();
16
15
  if (typeof document !== "object") {
17
16
  throw new TypeError("pagelet: a page document must be an object");
@@ -29,7 +28,12 @@ function upgradeDocument(document, palette) {
29
28
  );
30
29
  }
31
30
  const data = { ...emptyData(), ...doc.data };
32
- return createDocument(palette && needsPuckMigration(data) ? rsc.migrate(data, palette.config) : data);
31
+ return createDocument({ ...data, root: upgradeRoot(data.root) });
32
+ }
33
+ function upgradeRoot(root = {}) {
34
+ const { props = {}, readOnly, ...legacy } = root;
35
+ if (Object.keys(legacy).length === 0) return root;
36
+ return { ...readOnly ? { readOnly } : {}, props: { ...legacy, ...props } };
33
37
  }
34
38
  function needsPuckMigration(data) {
35
39
  const zones = data.zones ?? {};
@@ -40,7 +44,7 @@ function needsPuckMigration(data) {
40
44
 
41
45
  function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {
42
46
  if (!palette) throw new Error("pagelet: <PageletEditor> needs a palette (see createPalette)");
43
- const { data } = upgradeDocument(document, palette);
47
+ const data = editorData(document, palette);
44
48
  return /* @__PURE__ */ jsxRuntime.jsx(
45
49
  core.Puck,
46
50
  {
@@ -54,6 +58,15 @@ function PageletEditor({ document, palette, theme, onPublish, onChange, headerTi
54
58
  }
55
59
  );
56
60
  }
61
+ function editorData(document, palette) {
62
+ const data = upgradeDocument(document).data;
63
+ if (!needsPuckMigration(document?.data ?? document ?? {})) return data;
64
+ try {
65
+ return core.migrate(data, palette.config);
66
+ } catch {
67
+ return data;
68
+ }
69
+ }
57
70
 
58
71
  exports.PageletEditor = PageletEditor;
59
72
  //# sourceMappingURL=editor.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.cjs","sources":["../src/document.js","../src/PageletEditor.jsx"],"sourcesContent":["import { migrate } from '@puckeditor/core/rsc';\n\n// What an app stores for a page: Puck's data inside an envelope that carries\n// pagelet's own format version. The version lets a stored page be upgraded when\n// pagelet or Puck changes shape, so apps never hold raw Puck data whose format\n// they do not control.\nexport const DOCUMENT_VERSION = 1;\n\nexport function emptyData() {\n return { root: { props: {} }, content: [] };\n}\n\nexport function createDocument(data = emptyData()) {\n return { pagelet: DOCUMENT_VERSION, data };\n}\n\n// Bring a stored document up to the current format.\n//\n// Accepts bare Puck data too, since an app adopting pagelet may already hold\n// some. Passing the palette also runs Puck's own migrate(), which converts\n// older Puck structures (DropZone zones) into the current one (slots).\nexport function upgradeDocument(document, palette) {\n if (document == null) return createDocument();\n if (typeof document !== 'object') {\n throw new TypeError('pagelet: a page document must be an object');\n }\n\n let doc = document;\n if (!('pagelet' in doc)) {\n if (!('content' in doc) && !('root' in doc)) {\n throw new TypeError('pagelet: not a page document (no \"pagelet\" version and no Puck data)');\n }\n doc = createDocument(doc);\n }\n\n if (doc.pagelet > DOCUMENT_VERSION) {\n throw new Error(\n `pagelet: this page was saved by a newer pagelet (format ${doc.pagelet}); ` +\n `this version reads up to format ${DOCUMENT_VERSION}. Upgrade @byscott-io/pagelet.`,\n );\n }\n\n // Format migrations go here, one step per version:\n // if (doc.pagelet === 1) doc = migrateV1toV2(doc);\n\n const data = { ...emptyData(), ...doc.data };\n return createDocument(palette && needsPuckMigration(data) ? migrate(data, palette.config) : data);\n}\n\n// Puck's migrate() logs to the console every time it is given a config, even\n// when there is nothing to convert. On a public page that would be a log line\n// per page view, so only call it for data in an older Puck shape: DropZone\n// zones holding content, or a root whose fields sit outside `props`.\nexport function needsPuckMigration(data) {\n const zones = data.zones ?? {};\n if (Object.values(zones).some((content) => Array.isArray(content) && content.length > 0)) return true;\n const root = data.root ?? {};\n return Object.keys(root).some((key) => key !== 'props' && key !== 'readOnly');\n}\n\n// A page's own settings (title, background), for the app to use outside the\n// page body, e.g. the browser title.\nexport function pageSettings(document) {\n const props = upgradeDocument(document)?.data?.root?.props ?? {};\n return { title: props.title || '', background: props.background ?? 'site' };\n}\n","import { Puck } from '@puckeditor/core';\nimport { createDocument, upgradeDocument } from './document.js';\n\n// The visual editor. Import from \"@byscott-io/pagelet/editor\" (and its\n// stylesheet from \"@byscott-io/pagelet/editor.css\") in admin screens only.\n//\n// onPublish and onChange receive a pagelet document, ready to store as-is.\nexport function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {\n if (!palette) throw new Error('pagelet: <PageletEditor> needs a palette (see createPalette)');\n const { data } = upgradeDocument(document, palette);\n return (\n <Puck\n {...rest}\n config={palette.config}\n data={data}\n metadata={{ pageletTheme: theme }}\n headerTitle={headerTitle}\n onPublish={onPublish ? (next) => onPublish(createDocument(next)) : undefined}\n onChange={onChange ? (next) => onChange(createDocument(next)) : undefined}\n />\n );\n}\n"],"names":["migrate","jsx","Puck"],"mappings":";;;;;;AAMO,MAAM,gBAAA,GAAmB,CAAA;AAEzB,SAAS,SAAA,GAAY;AAC1B,EAAA,OAAO,EAAE,MAAM,EAAE,KAAA,EAAO,EAAC,EAAE,EAAG,OAAA,EAAS,EAAC,EAAE;AAC5C;AAEO,SAAS,cAAA,CAAe,IAAA,GAAO,SAAA,EAAU,EAAG;AACjD,EAAA,OAAO,EAAE,OAAA,EAAS,gBAAA,EAAkB,IAAA,EAAK;AAC3C;AAOO,SAAS,eAAA,CAAgB,UAAU,OAAA,EAAS;AACjD,EAAA,IAAI,QAAA,IAAY,IAAA,EAAM,OAAO,cAAA,EAAe;AAC5C,EAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,IAAA,MAAM,IAAI,UAAU,4CAA4C,CAAA;AAAA,EAClE;AAEA,EAAA,IAAI,GAAA,GAAM,QAAA;AACV,EAAA,IAAI,EAAE,aAAa,GAAA,CAAA,EAAM;AACvB,IAAA,IAAI,EAAE,SAAA,IAAa,GAAA,CAAA,IAAQ,EAAE,UAAU,GAAA,CAAA,EAAM;AAC3C,MAAA,MAAM,IAAI,UAAU,sEAAsE,CAAA;AAAA,IAC5F;AACA,IAAA,GAAA,GAAM,eAAe,GAAG,CAAA;AAAA,EAC1B;AAEA,EAAA,IAAI,GAAA,CAAI,UAAU,gBAAA,EAAkB;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wDAAA,EAA2D,GAAA,CAAI,OAAO,CAAA,mCAAA,EACjC,gBAAgB,CAAA,8BAAA;AAAA,KACvD;AAAA,EACF;AAKA,EAAA,MAAM,OAAO,EAAE,GAAG,WAAU,EAAG,GAAG,IAAI,IAAA,EAAK;AAC3C,EAAA,OAAO,cAAA,CAAe,OAAA,IAAW,kBAAA,CAAmB,IAAI,CAAA,GAAIA,YAAQ,IAAA,EAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,IAAI,CAAA;AAClG;AAMO,SAAS,mBAAmB,IAAA,EAAM;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAC7B,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,KAAK,CAAC,OAAA,KAAY,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,MAAA,GAAS,CAAC,GAAG,OAAO,IAAA;AACjG,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC3B,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,KAAQ,OAAA,IAAW,GAAA,KAAQ,UAAU,CAAA;AAC9E;;ACnDO,SAAS,aAAA,CAAc,EAAE,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,WAAW,QAAA,EAAU,WAAA,EAAa,GAAG,IAAA,EAAK,EAAG;AACrG,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAC5F,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,eAAA,CAAgB,UAAU,OAAO,CAAA;AAClD,EAAA,uBACEC,cAAA;AAAA,IAACC,SAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,IAAA;AAAA,MACA,QAAA,EAAU,EAAE,YAAA,EAAc,KAAA,EAAM;AAAA,MAChC,WAAA;AAAA,MACA,SAAA,EAAW,YAAY,CAAC,IAAA,KAAS,UAAU,cAAA,CAAe,IAAI,CAAC,CAAA,GAAI,MAAA;AAAA,MACnE,QAAA,EAAU,WAAW,CAAC,IAAA,KAAS,SAAS,cAAA,CAAe,IAAI,CAAC,CAAA,GAAI;AAAA;AAAA,GAClE;AAEJ;;"}
1
+ {"version":3,"file":"editor.cjs","sources":["../src/document.js","../src/PageletEditor.jsx"],"sourcesContent":["// What an app stores for a page: Puck's data inside an envelope that carries\n// pagelet's own format version. The version lets a stored page be upgraded when\n// pagelet or Puck changes shape, so apps never hold raw Puck data whose format\n// they do not control.\nexport const DOCUMENT_VERSION = 1;\n\nexport function emptyData() {\n return { root: { props: {} }, content: [] };\n}\n\nexport function createDocument(data = emptyData()) {\n return { pagelet: DOCUMENT_VERSION, data };\n}\n\n// Bring a stored document up to the current format.\n//\n// Accepts bare Puck data too, since an app adopting pagelet may already hold\n// some. Imports nothing from Puck, because the public renderer uses this: an\n// old root shape (fields beside \"props\") is converted here, and DropZone zones,\n// which pagelet never wrote, are converted by the editor (needsPuckMigration).\nexport function upgradeDocument(document) {\n if (document == null) return createDocument();\n if (typeof document !== 'object') {\n throw new TypeError('pagelet: a page document must be an object');\n }\n\n let doc = document;\n if (!('pagelet' in doc)) {\n if (!('content' in doc) && !('root' in doc)) {\n throw new TypeError('pagelet: not a page document (no \"pagelet\" version and no Puck data)');\n }\n doc = createDocument(doc);\n }\n\n if (doc.pagelet > DOCUMENT_VERSION) {\n throw new Error(\n `pagelet: this page was saved by a newer pagelet (format ${doc.pagelet}); ` +\n `this version reads up to format ${DOCUMENT_VERSION}. Upgrade @byscott-io/pagelet.`,\n );\n }\n\n // Format migrations go here, one step per version:\n // if (doc.pagelet === 1) doc = migrateV1toV2(doc);\n\n const data = { ...emptyData(), ...doc.data };\n return createDocument({ ...data, root: upgradeRoot(data.root) });\n}\n\n// Puck once kept root fields beside \"props\" ({ title } rather than\n// { props: { title } }). Move any such fields into props.\nfunction upgradeRoot(root = {}) {\n const { props = {}, readOnly, ...legacy } = root;\n if (Object.keys(legacy).length === 0) return root;\n return { ...(readOnly ? { readOnly } : {}), props: { ...legacy, ...props } };\n}\n\n// Data in an older Puck shape: DropZone zones holding content, or a root whose\n// fields sit outside props. The editor runs Puck's migrate() only then, because\n// migrate() logs to the console every time it is called.\nexport function needsPuckMigration(data) {\n const zones = data.zones ?? {};\n if (Object.values(zones).some((content) => Array.isArray(content) && content.length > 0)) return true;\n const root = data.root ?? {};\n return Object.keys(root).some((key) => key !== 'props' && key !== 'readOnly');\n}\n\n// A page's own settings (title, background), for the app to use outside the\n// page body, e.g. the browser title.\nexport function pageSettings(document) {\n const props = upgradeDocument(document)?.data?.root?.props ?? {};\n return { title: props.title || '', background: props.background ?? 'site' };\n}\n","import { Puck, migrate } from '@puckeditor/core';\nimport { createDocument, needsPuckMigration, upgradeDocument } from './document.js';\n\n// The visual editor. Import from \"@byscott-io/pagelet/editor\" (and its\n// stylesheet from \"@byscott-io/pagelet/editor.css\") in admin screens only.\n//\n// onPublish and onChange receive a pagelet document, ready to store as-is.\nexport function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {\n if (!palette) throw new Error('pagelet: <PageletEditor> needs a palette (see createPalette)');\n const data = editorData(document, palette);\n return (\n <Puck\n {...rest}\n config={palette.config}\n data={data}\n metadata={{ pageletTheme: theme }}\n headerTitle={headerTitle}\n onPublish={onPublish ? (next) => onPublish(createDocument(next)) : undefined}\n onChange={onChange ? (next) => onChange(createDocument(next)) : undefined}\n />\n );\n}\n\n// Older Puck data (DropZone zones) is converted to slots here, in the editor,\n// where Puck is loaded anyway; the public renderer never imports Puck.\n//\n// Puck's migrate() only converts a zone whose block now has a slot field of the\n// same name, and THROWS otherwise. A block that still draws a DropZone is fine\n// as it is (Puck's editor and pagelet's renderer both draw zones), so then the\n// data opens unconverted rather than crashing the editor.\nfunction editorData(document, palette) {\n const data = upgradeDocument(document).data;\n if (!needsPuckMigration(document?.data ?? document ?? {})) return data;\n try {\n return migrate(data, palette.config);\n } catch {\n return data;\n }\n}\n"],"names":["jsx","Puck","migrate"],"mappings":"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"}
package/dist/editor.js CHANGED
@@ -1,6 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { Puck } from '@puckeditor/core';
3
- import { migrate } from '@puckeditor/core/rsc';
2
+ import { Puck, migrate } from '@puckeditor/core';
4
3
 
5
4
  const DOCUMENT_VERSION = 1;
6
5
  function emptyData() {
@@ -9,7 +8,7 @@ function emptyData() {
9
8
  function createDocument(data = emptyData()) {
10
9
  return { pagelet: DOCUMENT_VERSION, data };
11
10
  }
12
- function upgradeDocument(document, palette) {
11
+ function upgradeDocument(document) {
13
12
  if (document == null) return createDocument();
14
13
  if (typeof document !== "object") {
15
14
  throw new TypeError("pagelet: a page document must be an object");
@@ -27,7 +26,12 @@ function upgradeDocument(document, palette) {
27
26
  );
28
27
  }
29
28
  const data = { ...emptyData(), ...doc.data };
30
- return createDocument(palette && needsPuckMigration(data) ? migrate(data, palette.config) : data);
29
+ return createDocument({ ...data, root: upgradeRoot(data.root) });
30
+ }
31
+ function upgradeRoot(root = {}) {
32
+ const { props = {}, readOnly, ...legacy } = root;
33
+ if (Object.keys(legacy).length === 0) return root;
34
+ return { ...readOnly ? { readOnly } : {}, props: { ...legacy, ...props } };
31
35
  }
32
36
  function needsPuckMigration(data) {
33
37
  const zones = data.zones ?? {};
@@ -38,7 +42,7 @@ function needsPuckMigration(data) {
38
42
 
39
43
  function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {
40
44
  if (!palette) throw new Error("pagelet: <PageletEditor> needs a palette (see createPalette)");
41
- const { data } = upgradeDocument(document, palette);
45
+ const data = editorData(document, palette);
42
46
  return /* @__PURE__ */ jsx(
43
47
  Puck,
44
48
  {
@@ -52,6 +56,15 @@ function PageletEditor({ document, palette, theme, onPublish, onChange, headerTi
52
56
  }
53
57
  );
54
58
  }
59
+ function editorData(document, palette) {
60
+ const data = upgradeDocument(document).data;
61
+ if (!needsPuckMigration(document?.data ?? document ?? {})) return data;
62
+ try {
63
+ return migrate(data, palette.config);
64
+ } catch {
65
+ return data;
66
+ }
67
+ }
55
68
 
56
69
  export { PageletEditor };
57
70
  //# sourceMappingURL=editor.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"editor.js","sources":["../src/document.js","../src/PageletEditor.jsx"],"sourcesContent":["import { migrate } from '@puckeditor/core/rsc';\n\n// What an app stores for a page: Puck's data inside an envelope that carries\n// pagelet's own format version. The version lets a stored page be upgraded when\n// pagelet or Puck changes shape, so apps never hold raw Puck data whose format\n// they do not control.\nexport const DOCUMENT_VERSION = 1;\n\nexport function emptyData() {\n return { root: { props: {} }, content: [] };\n}\n\nexport function createDocument(data = emptyData()) {\n return { pagelet: DOCUMENT_VERSION, data };\n}\n\n// Bring a stored document up to the current format.\n//\n// Accepts bare Puck data too, since an app adopting pagelet may already hold\n// some. Passing the palette also runs Puck's own migrate(), which converts\n// older Puck structures (DropZone zones) into the current one (slots).\nexport function upgradeDocument(document, palette) {\n if (document == null) return createDocument();\n if (typeof document !== 'object') {\n throw new TypeError('pagelet: a page document must be an object');\n }\n\n let doc = document;\n if (!('pagelet' in doc)) {\n if (!('content' in doc) && !('root' in doc)) {\n throw new TypeError('pagelet: not a page document (no \"pagelet\" version and no Puck data)');\n }\n doc = createDocument(doc);\n }\n\n if (doc.pagelet > DOCUMENT_VERSION) {\n throw new Error(\n `pagelet: this page was saved by a newer pagelet (format ${doc.pagelet}); ` +\n `this version reads up to format ${DOCUMENT_VERSION}. Upgrade @byscott-io/pagelet.`,\n );\n }\n\n // Format migrations go here, one step per version:\n // if (doc.pagelet === 1) doc = migrateV1toV2(doc);\n\n const data = { ...emptyData(), ...doc.data };\n return createDocument(palette && needsPuckMigration(data) ? migrate(data, palette.config) : data);\n}\n\n// Puck's migrate() logs to the console every time it is given a config, even\n// when there is nothing to convert. On a public page that would be a log line\n// per page view, so only call it for data in an older Puck shape: DropZone\n// zones holding content, or a root whose fields sit outside `props`.\nexport function needsPuckMigration(data) {\n const zones = data.zones ?? {};\n if (Object.values(zones).some((content) => Array.isArray(content) && content.length > 0)) return true;\n const root = data.root ?? {};\n return Object.keys(root).some((key) => key !== 'props' && key !== 'readOnly');\n}\n\n// A page's own settings (title, background), for the app to use outside the\n// page body, e.g. the browser title.\nexport function pageSettings(document) {\n const props = upgradeDocument(document)?.data?.root?.props ?? {};\n return { title: props.title || '', background: props.background ?? 'site' };\n}\n","import { Puck } from '@puckeditor/core';\nimport { createDocument, upgradeDocument } from './document.js';\n\n// The visual editor. Import from \"@byscott-io/pagelet/editor\" (and its\n// stylesheet from \"@byscott-io/pagelet/editor.css\") in admin screens only.\n//\n// onPublish and onChange receive a pagelet document, ready to store as-is.\nexport function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {\n if (!palette) throw new Error('pagelet: <PageletEditor> needs a palette (see createPalette)');\n const { data } = upgradeDocument(document, palette);\n return (\n <Puck\n {...rest}\n config={palette.config}\n data={data}\n metadata={{ pageletTheme: theme }}\n headerTitle={headerTitle}\n onPublish={onPublish ? (next) => onPublish(createDocument(next)) : undefined}\n onChange={onChange ? (next) => onChange(createDocument(next)) : undefined}\n />\n );\n}\n"],"names":[],"mappings":";;;;AAMO,MAAM,gBAAA,GAAmB,CAAA;AAEzB,SAAS,SAAA,GAAY;AAC1B,EAAA,OAAO,EAAE,MAAM,EAAE,KAAA,EAAO,EAAC,EAAE,EAAG,OAAA,EAAS,EAAC,EAAE;AAC5C;AAEO,SAAS,cAAA,CAAe,IAAA,GAAO,SAAA,EAAU,EAAG;AACjD,EAAA,OAAO,EAAE,OAAA,EAAS,gBAAA,EAAkB,IAAA,EAAK;AAC3C;AAOO,SAAS,eAAA,CAAgB,UAAU,OAAA,EAAS;AACjD,EAAA,IAAI,QAAA,IAAY,IAAA,EAAM,OAAO,cAAA,EAAe;AAC5C,EAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,IAAA,MAAM,IAAI,UAAU,4CAA4C,CAAA;AAAA,EAClE;AAEA,EAAA,IAAI,GAAA,GAAM,QAAA;AACV,EAAA,IAAI,EAAE,aAAa,GAAA,CAAA,EAAM;AACvB,IAAA,IAAI,EAAE,SAAA,IAAa,GAAA,CAAA,IAAQ,EAAE,UAAU,GAAA,CAAA,EAAM;AAC3C,MAAA,MAAM,IAAI,UAAU,sEAAsE,CAAA;AAAA,IAC5F;AACA,IAAA,GAAA,GAAM,eAAe,GAAG,CAAA;AAAA,EAC1B;AAEA,EAAA,IAAI,GAAA,CAAI,UAAU,gBAAA,EAAkB;AAClC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,wDAAA,EAA2D,GAAA,CAAI,OAAO,CAAA,mCAAA,EACjC,gBAAgB,CAAA,8BAAA;AAAA,KACvD;AAAA,EACF;AAKA,EAAA,MAAM,OAAO,EAAE,GAAG,WAAU,EAAG,GAAG,IAAI,IAAA,EAAK;AAC3C,EAAA,OAAO,cAAA,CAAe,OAAA,IAAW,kBAAA,CAAmB,IAAI,CAAA,GAAI,QAAQ,IAAA,EAAM,OAAA,CAAQ,MAAM,CAAA,GAAI,IAAI,CAAA;AAClG;AAMO,SAAS,mBAAmB,IAAA,EAAM;AACvC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,IAAS,EAAC;AAC7B,EAAA,IAAI,MAAA,CAAO,MAAA,CAAO,KAAK,CAAA,CAAE,KAAK,CAAC,OAAA,KAAY,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,IAAK,OAAA,CAAQ,MAAA,GAAS,CAAC,GAAG,OAAO,IAAA;AACjG,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,IAAQ,EAAC;AAC3B,EAAA,OAAO,MAAA,CAAO,IAAA,CAAK,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,GAAA,KAAQ,GAAA,KAAQ,OAAA,IAAW,GAAA,KAAQ,UAAU,CAAA;AAC9E;;ACnDO,SAAS,aAAA,CAAc,EAAE,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,WAAW,QAAA,EAAU,WAAA,EAAa,GAAG,IAAA,EAAK,EAAG;AACrG,EAAA,IAAI,CAAC,OAAA,EAAS,MAAM,IAAI,MAAM,8DAA8D,CAAA;AAC5F,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,eAAA,CAAgB,UAAU,OAAO,CAAA;AAClD,EAAA,uBACE,GAAA;AAAA,IAAC,IAAA;AAAA,IAAA;AAAA,MACE,GAAG,IAAA;AAAA,MACJ,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,IAAA;AAAA,MACA,QAAA,EAAU,EAAE,YAAA,EAAc,KAAA,EAAM;AAAA,MAChC,WAAA;AAAA,MACA,SAAA,EAAW,YAAY,CAAC,IAAA,KAAS,UAAU,cAAA,CAAe,IAAI,CAAC,CAAA,GAAI,MAAA;AAAA,MACnE,QAAA,EAAU,WAAW,CAAC,IAAA,KAAS,SAAS,cAAA,CAAe,IAAI,CAAC,CAAA,GAAI;AAAA;AAAA,GAClE;AAEJ;;"}
1
+ {"version":3,"file":"editor.js","sources":["../src/document.js","../src/PageletEditor.jsx"],"sourcesContent":["// What an app stores for a page: Puck's data inside an envelope that carries\n// pagelet's own format version. The version lets a stored page be upgraded when\n// pagelet or Puck changes shape, so apps never hold raw Puck data whose format\n// they do not control.\nexport const DOCUMENT_VERSION = 1;\n\nexport function emptyData() {\n return { root: { props: {} }, content: [] };\n}\n\nexport function createDocument(data = emptyData()) {\n return { pagelet: DOCUMENT_VERSION, data };\n}\n\n// Bring a stored document up to the current format.\n//\n// Accepts bare Puck data too, since an app adopting pagelet may already hold\n// some. Imports nothing from Puck, because the public renderer uses this: an\n// old root shape (fields beside \"props\") is converted here, and DropZone zones,\n// which pagelet never wrote, are converted by the editor (needsPuckMigration).\nexport function upgradeDocument(document) {\n if (document == null) return createDocument();\n if (typeof document !== 'object') {\n throw new TypeError('pagelet: a page document must be an object');\n }\n\n let doc = document;\n if (!('pagelet' in doc)) {\n if (!('content' in doc) && !('root' in doc)) {\n throw new TypeError('pagelet: not a page document (no \"pagelet\" version and no Puck data)');\n }\n doc = createDocument(doc);\n }\n\n if (doc.pagelet > DOCUMENT_VERSION) {\n throw new Error(\n `pagelet: this page was saved by a newer pagelet (format ${doc.pagelet}); ` +\n `this version reads up to format ${DOCUMENT_VERSION}. Upgrade @byscott-io/pagelet.`,\n );\n }\n\n // Format migrations go here, one step per version:\n // if (doc.pagelet === 1) doc = migrateV1toV2(doc);\n\n const data = { ...emptyData(), ...doc.data };\n return createDocument({ ...data, root: upgradeRoot(data.root) });\n}\n\n// Puck once kept root fields beside \"props\" ({ title } rather than\n// { props: { title } }). Move any such fields into props.\nfunction upgradeRoot(root = {}) {\n const { props = {}, readOnly, ...legacy } = root;\n if (Object.keys(legacy).length === 0) return root;\n return { ...(readOnly ? { readOnly } : {}), props: { ...legacy, ...props } };\n}\n\n// Data in an older Puck shape: DropZone zones holding content, or a root whose\n// fields sit outside props. The editor runs Puck's migrate() only then, because\n// migrate() logs to the console every time it is called.\nexport function needsPuckMigration(data) {\n const zones = data.zones ?? {};\n if (Object.values(zones).some((content) => Array.isArray(content) && content.length > 0)) return true;\n const root = data.root ?? {};\n return Object.keys(root).some((key) => key !== 'props' && key !== 'readOnly');\n}\n\n// A page's own settings (title, background), for the app to use outside the\n// page body, e.g. the browser title.\nexport function pageSettings(document) {\n const props = upgradeDocument(document)?.data?.root?.props ?? {};\n return { title: props.title || '', background: props.background ?? 'site' };\n}\n","import { Puck, migrate } from '@puckeditor/core';\nimport { createDocument, needsPuckMigration, upgradeDocument } from './document.js';\n\n// The visual editor. Import from \"@byscott-io/pagelet/editor\" (and its\n// stylesheet from \"@byscott-io/pagelet/editor.css\") in admin screens only.\n//\n// onPublish and onChange receive a pagelet document, ready to store as-is.\nexport function PageletEditor({ document, palette, theme, onPublish, onChange, headerTitle, ...rest }) {\n if (!palette) throw new Error('pagelet: <PageletEditor> needs a palette (see createPalette)');\n const data = editorData(document, palette);\n return (\n <Puck\n {...rest}\n config={palette.config}\n data={data}\n metadata={{ pageletTheme: theme }}\n headerTitle={headerTitle}\n onPublish={onPublish ? (next) => onPublish(createDocument(next)) : undefined}\n onChange={onChange ? (next) => onChange(createDocument(next)) : undefined}\n />\n );\n}\n\n// Older Puck data (DropZone zones) is converted to slots here, in the editor,\n// where Puck is loaded anyway; the public renderer never imports Puck.\n//\n// Puck's migrate() only converts a zone whose block now has a slot field of the\n// same name, and THROWS otherwise. A block that still draws a DropZone is fine\n// as it is (Puck's editor and pagelet's renderer both draw zones), so then the\n// data opens unconverted rather than crashing the editor.\nfunction editorData(document, palette) {\n const data = upgradeDocument(document).data;\n if (!needsPuckMigration(document?.data ?? document ?? {})) return data;\n try {\n return migrate(data, palette.config);\n } catch {\n return data;\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/index.cjs CHANGED
@@ -1,7 +1,6 @@
1
1
  'use strict';
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
- var rsc = require('@puckeditor/core/rsc');
5
4
  var react = require('react');
6
5
 
7
6
  const DOCUMENT_VERSION = 1;
@@ -11,7 +10,7 @@ function emptyData() {
11
10
  function createDocument(data = emptyData()) {
12
11
  return { pagelet: DOCUMENT_VERSION, data };
13
12
  }
14
- function upgradeDocument(document, palette) {
13
+ function upgradeDocument(document) {
15
14
  if (document == null) return createDocument();
16
15
  if (typeof document !== "object") {
17
16
  throw new TypeError("pagelet: a page document must be an object");
@@ -29,23 +28,64 @@ function upgradeDocument(document, palette) {
29
28
  );
30
29
  }
31
30
  const data = { ...emptyData(), ...doc.data };
32
- return createDocument(palette && needsPuckMigration(data) ? rsc.migrate(data, palette.config) : data);
31
+ return createDocument({ ...data, root: upgradeRoot(data.root) });
33
32
  }
34
- function needsPuckMigration(data) {
35
- const zones = data.zones ?? {};
36
- if (Object.values(zones).some((content) => Array.isArray(content) && content.length > 0)) return true;
37
- const root = data.root ?? {};
38
- return Object.keys(root).some((key) => key !== "props" && key !== "readOnly");
33
+ function upgradeRoot(root = {}) {
34
+ const { props = {}, readOnly, ...legacy } = root;
35
+ if (Object.keys(legacy).length === 0) return root;
36
+ return { ...readOnly ? { readOnly } : {}, props: { ...legacy, ...props } };
39
37
  }
40
38
  function pageSettings(document) {
41
39
  const props = upgradeDocument(document)?.data?.root?.props ?? {};
42
40
  return { title: props.title || "", background: props.background ?? "site" };
43
41
  }
44
42
 
43
+ const ROOT_ZONE = "root:default-zone";
44
+ function slotNames(component) {
45
+ return Object.entries(component.fields ?? {}).filter(([, field]) => field?.type === "slot").map(([name]) => name);
46
+ }
47
+ function renderItems(items, context) {
48
+ return (Array.isArray(items) ? items : []).map((item, index) => /* @__PURE__ */ jsxRuntime.jsx(react.Fragment, { children: renderItem(item, context) }, item?.props?.id ?? index));
49
+ }
50
+ function puckFor(areaId, context) {
51
+ return {
52
+ isEditing: false,
53
+ metadata: context.metadata,
54
+ dragRef: null,
55
+ renderDropZone: ({ zone }) => {
56
+ const compound = `${areaId}:${zone}`;
57
+ const items = compound === ROOT_ZONE ? context.data.content : context.data.zones?.[compound];
58
+ return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: renderItems(items, context) });
59
+ }
60
+ };
61
+ }
62
+ function renderItem(item, context) {
63
+ const component = item && context.config.components[item.type];
64
+ if (!component) return null;
65
+ const props = { ...item.props, puck: puckFor(item.props?.id, context) };
66
+ for (const name of slotNames(component)) {
67
+ const children = item.props?.[name];
68
+ props[name] = function Slot({ className, style }) {
69
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className, style, children: renderItems(children, context) });
70
+ };
71
+ }
72
+ const Render = component.render;
73
+ return /* @__PURE__ */ jsxRuntime.jsx(Render, { ...props });
74
+ }
75
+ function renderPage({ config, data, metadata = {} }) {
76
+ const context = { config, data: data ?? {}, metadata };
77
+ const puck = puckFor("root", context);
78
+ const rootProps = data?.root?.props ?? {};
79
+ const content = renderItems(data?.content, context);
80
+ const RootRender = config.root?.render;
81
+ if (!RootRender) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: content });
82
+ return /* @__PURE__ */ jsxRuntime.jsx(RootRender, { ...rootProps, title: rootProps.title || "", editMode: false, id: "puck-root", puck, children: content });
83
+ }
84
+
45
85
  function PageletPage({ document, palette, theme }) {
46
86
  if (!palette) throw new Error("pagelet: <PageletPage> needs a palette (see createPalette)");
47
- const { data } = upgradeDocument(document, palette);
48
- return /* @__PURE__ */ jsxRuntime.jsx(rsc.Render, { config: palette.config, data, metadata: { pageletTheme: theme } });
87
+ const { data } = upgradeDocument(document);
88
+ return renderPage({ config: palette.config, data, metadata: { pageletTheme: theme } });
49
89
  }
50
90
 
51
91
  const outline = { fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
@@ -131,6 +171,9 @@ const defaultTheme = {
131
171
  colorAccentText: "#ffffff",
132
172
  fontBody: 'system-ui, -apple-system, "Segoe UI", Roboto, sans-serif',
133
173
  fontHeading: "inherit",
174
+ // The page's base text size. Block text is sized in em from it, so text,
175
+ // lists, schedules and quotes all scale together; the menu keeps its own.
176
+ fontSize: "1rem",
134
177
  radius: "8px",
135
178
  maxWidth: "1100px",
136
179
  space: "24px"
@@ -264,7 +307,7 @@ const Hero = {
264
307
  },
265
308
  children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { maxWidth: "760px", margin: "0 auto" }, children: [
266
309
  /* @__PURE__ */ jsxRuntime.jsx("h1", { style: { fontFamily: tokenVar("fontHeading"), fontSize: "clamp(2rem, 5vw, 3.25rem)", margin: "0 0 0.4em", textWrap: "balance" }, children: heading }),
267
- /* @__PURE__ */ jsxRuntime.jsx(Paragraphs, { text: subheading, style: { fontSize: "1.15rem" } }),
310
+ /* @__PURE__ */ jsxRuntime.jsx(Paragraphs, { text: subheading, style: { fontSize: "1.15em" } }),
268
311
  /* @__PURE__ */ jsxRuntime.jsx(ButtonLink, { label: buttonLabel, href: buttonHref, variant: "outline" })
269
312
  ] })
270
313
  }
@@ -693,7 +736,7 @@ function resolveBackground(theme = {}, page = {}) {
693
736
  function ThemeRoot({ theme, page, children }) {
694
737
  const background = resolveBackground(theme ?? {}, page ?? {});
695
738
  if (!background) {
696
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet", style: themeToStyle(theme), children });
739
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet", style: { ...themeToStyle(theme), fontSize: tokenVar("fontSize") }, children });
697
740
  }
698
741
  const radius = background.rounded ? "var(--pagelet-radius)" : 0;
699
742
  const panel = { background: overlayColor(background.overlayColor, background.overlayOpacity), padding: "calc(var(--pagelet-space) * 2)" };
@@ -701,7 +744,7 @@ function ThemeRoot({ theme, page, children }) {
701
744
  /* @__PURE__ */ jsxRuntime.jsx("img", { src: background.imageUrl, alt: "", "aria-hidden": "true", style: { gridArea: "1 / 1", width: "100%", height: "100%", objectFit: "cover", display: "block" } }),
702
745
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet-panel", style: { gridArea: "1 / 1", ...panel }, children })
703
746
  ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet-background", style: { background: `${background.image} center / cover`, borderRadius: radius, overflow: "hidden" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet-panel", style: { ...panel, minHeight: "60vh" }, children }) });
704
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet", style: themeToStyle(theme), children: background.frame === "card" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet-frame", style: { border: "1px solid rgba(0, 0, 0, 0.15)", borderRadius: radius, padding: "var(--pagelet-space)", background: "var(--pagelet-color-background)" }, children: area }) : area });
747
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet", style: { ...themeToStyle(theme), fontSize: tokenVar("fontSize") }, children: background.frame === "card" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pagelet-frame", style: { border: "1px solid rgba(0, 0, 0, 0.15)", borderRadius: radius, padding: "var(--pagelet-space)", background: "var(--pagelet-color-background)" }, children: area }) : area });
705
748
  }
706
749
 
707
750
  const pageFields = {