@sudajs/theme-engine 0.0.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.
Files changed (153) hide show
  1. package/dist/ai/slots.d.ts +33 -0
  2. package/dist/ai/slots.d.ts.map +1 -0
  3. package/dist/ai/slots.js +139 -0
  4. package/dist/ai/slots.js.map +1 -0
  5. package/dist/assets.d.ts +42 -0
  6. package/dist/assets.d.ts.map +1 -0
  7. package/dist/assets.js +36 -0
  8. package/dist/assets.js.map +1 -0
  9. package/dist/cms/apply-bindings.d.ts +9 -0
  10. package/dist/cms/apply-bindings.d.ts.map +1 -0
  11. package/dist/cms/apply-bindings.js +128 -0
  12. package/dist/cms/apply-bindings.js.map +1 -0
  13. package/dist/cms/get-context.d.ts +9 -0
  14. package/dist/cms/get-context.d.ts.map +1 -0
  15. package/dist/cms/get-context.js +13 -0
  16. package/dist/cms/get-context.js.map +1 -0
  17. package/dist/cms/index.d.ts +4 -0
  18. package/dist/cms/index.d.ts.map +1 -0
  19. package/dist/cms/index.js +4 -0
  20. package/dist/cms/index.js.map +1 -0
  21. package/dist/cms/types.d.ts +116 -0
  22. package/dist/cms/types.d.ts.map +1 -0
  23. package/dist/cms/types.js +2 -0
  24. package/dist/cms/types.js.map +1 -0
  25. package/dist/components/base-blocks.d.ts +13 -0
  26. package/dist/components/base-blocks.d.ts.map +1 -0
  27. package/dist/components/base-blocks.js +157 -0
  28. package/dist/components/base-blocks.js.map +1 -0
  29. package/dist/components/containers.d.ts +8 -0
  30. package/dist/components/containers.d.ts.map +1 -0
  31. package/dist/components/containers.js +142 -0
  32. package/dist/components/containers.js.map +1 -0
  33. package/dist/components/index.d.ts +11 -0
  34. package/dist/components/index.d.ts.map +1 -0
  35. package/dist/components/index.js +17 -0
  36. package/dist/components/index.js.map +1 -0
  37. package/dist/components/interactive.client.d.ts +12 -0
  38. package/dist/components/interactive.client.d.ts.map +1 -0
  39. package/dist/components/interactive.client.js +43 -0
  40. package/dist/components/interactive.client.js.map +1 -0
  41. package/dist/components/metadata.d.ts +20 -0
  42. package/dist/components/metadata.d.ts.map +1 -0
  43. package/dist/components/metadata.js +9 -0
  44. package/dist/components/metadata.js.map +1 -0
  45. package/dist/components/shared-fields.d.ts +11 -0
  46. package/dist/components/shared-fields.d.ts.map +1 -0
  47. package/dist/components/shared-fields.js +37 -0
  48. package/dist/components/shared-fields.js.map +1 -0
  49. package/dist/editor/context.d.ts +79 -0
  50. package/dist/editor/context.d.ts.map +1 -0
  51. package/dist/editor/context.js +12 -0
  52. package/dist/editor/context.js.map +1 -0
  53. package/dist/editor/index.d.ts +5 -0
  54. package/dist/editor/index.d.ts.map +1 -0
  55. package/dist/editor/index.js +5 -0
  56. package/dist/editor/index.js.map +1 -0
  57. package/dist/editor/overrides.d.ts +3 -0
  58. package/dist/editor/overrides.d.ts.map +1 -0
  59. package/dist/editor/overrides.js +379 -0
  60. package/dist/editor/overrides.js.map +1 -0
  61. package/dist/editor/theme-editor.d.ts +46 -0
  62. package/dist/editor/theme-editor.d.ts.map +1 -0
  63. package/dist/editor/theme-editor.js +169 -0
  64. package/dist/editor/theme-editor.js.map +1 -0
  65. package/dist/editor/unified-editor.d.ts +25 -0
  66. package/dist/editor/unified-editor.d.ts.map +1 -0
  67. package/dist/editor/unified-editor.js +229 -0
  68. package/dist/editor/unified-editor.js.map +1 -0
  69. package/dist/editor/use-theme-runtime.d.ts +8 -0
  70. package/dist/editor/use-theme-runtime.d.ts.map +1 -0
  71. package/dist/editor/use-theme-runtime.js +77 -0
  72. package/dist/editor/use-theme-runtime.js.map +1 -0
  73. package/dist/fields/basic-fields.d.ts +14 -0
  74. package/dist/fields/basic-fields.d.ts.map +1 -0
  75. package/dist/fields/basic-fields.js +46 -0
  76. package/dist/fields/basic-fields.js.map +1 -0
  77. package/dist/fields/color-field.d.ts +3 -0
  78. package/dist/fields/color-field.d.ts.map +1 -0
  79. package/dist/fields/color-field.js +97 -0
  80. package/dist/fields/color-field.js.map +1 -0
  81. package/dist/fields/color-scheme-field.d.ts +81 -0
  82. package/dist/fields/color-scheme-field.d.ts.map +1 -0
  83. package/dist/fields/color-scheme-field.js +234 -0
  84. package/dist/fields/color-scheme-field.js.map +1 -0
  85. package/dist/fields/index.d.ts +6 -0
  86. package/dist/fields/index.d.ts.map +1 -0
  87. package/dist/fields/index.js +4 -0
  88. package/dist/fields/index.js.map +1 -0
  89. package/dist/fields/media-field.d.ts +10 -0
  90. package/dist/fields/media-field.d.ts.map +1 -0
  91. package/dist/fields/media-field.js +495 -0
  92. package/dist/fields/media-field.js.map +1 -0
  93. package/dist/fields/normalize-config.d.ts +3 -0
  94. package/dist/fields/normalize-config.d.ts.map +1 -0
  95. package/dist/fields/normalize-config.js +81 -0
  96. package/dist/fields/normalize-config.js.map +1 -0
  97. package/dist/fields/range-field.d.ts +9 -0
  98. package/dist/fields/range-field.d.ts.map +1 -0
  99. package/dist/fields/range-field.js +53 -0
  100. package/dist/fields/range-field.js.map +1 -0
  101. package/dist/fields/spacing-field.d.ts +7 -0
  102. package/dist/fields/spacing-field.d.ts.map +1 -0
  103. package/dist/fields/spacing-field.js +40 -0
  104. package/dist/fields/spacing-field.js.map +1 -0
  105. package/dist/fields/suda-fields.d.ts +45 -0
  106. package/dist/fields/suda-fields.d.ts.map +1 -0
  107. package/dist/fields/suda-fields.js +91 -0
  108. package/dist/fields/suda-fields.js.map +1 -0
  109. package/dist/index.d.ts +12 -0
  110. package/dist/index.d.ts.map +1 -0
  111. package/dist/index.js +15 -0
  112. package/dist/index.js.map +1 -0
  113. package/dist/manifest.d.ts +47 -0
  114. package/dist/manifest.d.ts.map +1 -0
  115. package/dist/manifest.js +39 -0
  116. package/dist/manifest.js.map +1 -0
  117. package/dist/registry/filesystem.d.ts +27 -0
  118. package/dist/registry/filesystem.d.ts.map +1 -0
  119. package/dist/registry/filesystem.js +162 -0
  120. package/dist/registry/filesystem.js.map +1 -0
  121. package/dist/registry.d.ts +13 -0
  122. package/dist/registry.d.ts.map +1 -0
  123. package/dist/registry.js +2 -0
  124. package/dist/registry.js.map +1 -0
  125. package/dist/render/chrome.d.ts +18 -0
  126. package/dist/render/chrome.d.ts.map +1 -0
  127. package/dist/render/chrome.js +36 -0
  128. package/dist/render/chrome.js.map +1 -0
  129. package/dist/render/index.d.ts +4 -0
  130. package/dist/render/index.d.ts.map +1 -0
  131. package/dist/render/index.js +4 -0
  132. package/dist/render/index.js.map +1 -0
  133. package/dist/render/render.d.ts +21 -0
  134. package/dist/render/render.d.ts.map +1 -0
  135. package/dist/render/render.js +50 -0
  136. package/dist/render/render.js.map +1 -0
  137. package/dist/render/slot.d.ts +14 -0
  138. package/dist/render/slot.d.ts.map +1 -0
  139. package/dist/render/slot.js +14 -0
  140. package/dist/render/slot.js.map +1 -0
  141. package/dist/runtime.d.ts +8 -0
  142. package/dist/runtime.d.ts.map +1 -0
  143. package/dist/runtime.js +10 -0
  144. package/dist/runtime.js.map +1 -0
  145. package/dist/server.d.ts +13 -0
  146. package/dist/server.d.ts.map +1 -0
  147. package/dist/server.js +16 -0
  148. package/dist/server.js.map +1 -0
  149. package/dist/types.d.ts +171 -0
  150. package/dist/types.d.ts.map +1 -0
  151. package/dist/types.js +2 -0
  152. package/dist/types.js.map +1 -0
  153. package/package.json +68 -0
@@ -0,0 +1,33 @@
1
+ import type { AiSlotDescriptor, PageData } from "../types";
2
+ /**
3
+ * A concrete AI-editable slot located inside a page document, produced by
4
+ * {@link extractAiSlots}. Identifies the component instance plus the prop path
5
+ * and current value, so the assistant can propose edits scoped to safe fields.
6
+ */
7
+ export interface ResolvedAiSlot {
8
+ /** Puck component instance id (`props.id`). */
9
+ componentId: string;
10
+ /** Puck component type. */
11
+ type: string;
12
+ descriptor: AiSlotDescriptor;
13
+ value: unknown;
14
+ }
15
+ /** A single edit the assistant wants to apply. */
16
+ export interface AiSlotEdit {
17
+ componentId: string;
18
+ path: string;
19
+ value: unknown;
20
+ }
21
+ /**
22
+ * Walks a page document and returns every AI-editable slot declared by the
23
+ * theme's `aiSlots` map (keyed by component type).
24
+ */
25
+ export declare function extractAiSlots(data: PageData, aiSlots: Record<string, AiSlotDescriptor[]> | undefined): ResolvedAiSlot[];
26
+ /**
27
+ * Applies a batch of AI edits to a page document, scoped strictly to the
28
+ * declared `aiSlots` for each component type. Edits targeting unknown
29
+ * components or paths outside the allow-list are ignored. Returns a new
30
+ * document; the input is not mutated.
31
+ */
32
+ export declare function applyAiValues(data: PageData, aiSlots: Record<string, AiSlotDescriptor[]> | undefined, edits: AiSlotEdit[]): PageData;
33
+ //# sourceMappingURL=slots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.d.ts","sourceRoot":"","sources":["../../src/ai/slots.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAE3D;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,+CAA+C;IAC/C,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,gBAAgB,CAAC;IAC7B,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,OAAO,CAAC;CAChB;AA6FD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,GAAG,SAAS,GACtD,cAAc,EAAE,CAqBlB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,EAAE,CAAC,GAAG,SAAS,EACvD,KAAK,EAAE,UAAU,EAAE,GAClB,QAAQ,CAgCV"}
@@ -0,0 +1,139 @@
1
+ function getContent(data) {
2
+ const content = data.content;
3
+ if (!Array.isArray(content)) {
4
+ return [];
5
+ }
6
+ return content.filter((item) => typeof item === "object" &&
7
+ item !== null &&
8
+ typeof item.type === "string" &&
9
+ typeof item.props === "object" &&
10
+ item.props !== null);
11
+ }
12
+ /** Splits a dot/bracket path into segments: `blocks[0].heading` -> ["blocks","0","heading"]. */
13
+ function parsePath(path) {
14
+ return path
15
+ .replace(/\[(\w+)\]/g, ".$1")
16
+ .split(".")
17
+ .filter((segment) => segment.length > 0);
18
+ }
19
+ function getAtPath(root, path) {
20
+ let current = root;
21
+ for (const segment of parsePath(path)) {
22
+ if (current === null || current === undefined) {
23
+ return undefined;
24
+ }
25
+ if (Array.isArray(current)) {
26
+ const index = Number(segment);
27
+ if (!Number.isInteger(index)) {
28
+ return undefined;
29
+ }
30
+ current = current[index];
31
+ }
32
+ else if (typeof current === "object") {
33
+ current = current[segment];
34
+ }
35
+ else {
36
+ return undefined;
37
+ }
38
+ }
39
+ return current;
40
+ }
41
+ /**
42
+ * Immutably sets `value` at `path` within `root`, creating intermediate
43
+ * objects/arrays as needed. Returns a shallow-cloned copy; the original is not
44
+ * mutated.
45
+ */
46
+ function setAtPath(root, path, value) {
47
+ const segments = parsePath(path);
48
+ if (segments.length === 0) {
49
+ return root;
50
+ }
51
+ const clone = (node, nextSegment) => {
52
+ if (Array.isArray(node)) {
53
+ return [...node];
54
+ }
55
+ if (node && typeof node === "object") {
56
+ return { ...node };
57
+ }
58
+ // Decide container shape from the next key.
59
+ return Number.isInteger(Number(nextSegment)) ? [] : {};
60
+ };
61
+ const result = clone(root, segments[0]);
62
+ let cursor = result;
63
+ for (let i = 0; i < segments.length - 1; i += 1) {
64
+ const segment = segments[i];
65
+ const nextSegment = segments[i + 1];
66
+ const key = Array.isArray(cursor) ? Number(segment) : segment;
67
+ const existing = cursor[key];
68
+ const child = clone(existing, nextSegment);
69
+ cursor[key] = child;
70
+ cursor = child;
71
+ }
72
+ const lastSegment = segments[segments.length - 1];
73
+ const lastKey = Array.isArray(cursor) ? Number(lastSegment) : lastSegment;
74
+ cursor[lastKey] = value;
75
+ return result;
76
+ }
77
+ /**
78
+ * Walks a page document and returns every AI-editable slot declared by the
79
+ * theme's `aiSlots` map (keyed by component type).
80
+ */
81
+ export function extractAiSlots(data, aiSlots) {
82
+ if (!aiSlots) {
83
+ return [];
84
+ }
85
+ const slots = [];
86
+ for (const item of getContent(data)) {
87
+ const descriptors = aiSlots[item.type];
88
+ if (!descriptors) {
89
+ continue;
90
+ }
91
+ const componentId = typeof item.props.id === "string" ? item.props.id : "";
92
+ for (const descriptor of descriptors) {
93
+ slots.push({
94
+ componentId,
95
+ type: item.type,
96
+ descriptor,
97
+ value: getAtPath(item.props, descriptor.path),
98
+ });
99
+ }
100
+ }
101
+ return slots;
102
+ }
103
+ /**
104
+ * Applies a batch of AI edits to a page document, scoped strictly to the
105
+ * declared `aiSlots` for each component type. Edits targeting unknown
106
+ * components or paths outside the allow-list are ignored. Returns a new
107
+ * document; the input is not mutated.
108
+ */
109
+ export function applyAiValues(data, aiSlots, edits) {
110
+ if (!aiSlots || edits.length === 0) {
111
+ return data;
112
+ }
113
+ const editsByComponent = new Map();
114
+ for (const edit of edits) {
115
+ const list = editsByComponent.get(edit.componentId) ?? [];
116
+ list.push(edit);
117
+ editsByComponent.set(edit.componentId, list);
118
+ }
119
+ const content = getContent(data);
120
+ const nextContent = content.map((item) => {
121
+ const componentId = typeof item.props.id === "string" ? item.props.id : "";
122
+ const componentEdits = editsByComponent.get(componentId);
123
+ const descriptors = aiSlots[item.type];
124
+ if (!componentEdits || !descriptors) {
125
+ return item;
126
+ }
127
+ const allowedPaths = new Set(descriptors.map((d) => d.path));
128
+ let props = item.props;
129
+ for (const edit of componentEdits) {
130
+ if (!allowedPaths.has(edit.path)) {
131
+ continue;
132
+ }
133
+ props = setAtPath(props, edit.path, edit.value);
134
+ }
135
+ return props === item.props ? item : { ...item, props };
136
+ });
137
+ return { ...data, content: nextContent };
138
+ }
139
+ //# sourceMappingURL=slots.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slots.js","sourceRoot":"","sources":["../../src/ai/slots.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ export interface ThemeAssetSummary {
2
+ id: string;
3
+ kind?: "image" | "video" | "file";
4
+ source?: "UPLOAD" | "AI";
5
+ /**
6
+ * Canonical asset path exposed to fields. Server-side detail (such as
7
+ * `Media.objectKey`) is mapped to this path before reaching the field layer.
8
+ */
9
+ path: string;
10
+ url: string;
11
+ filename: string;
12
+ contentType?: string;
13
+ sizeBytes?: number;
14
+ }
15
+ export interface ThemeUnsplashAssetSummary {
16
+ id: string;
17
+ cdnUrl: string;
18
+ thumbUrl?: string;
19
+ alt?: string;
20
+ description?: string | null;
21
+ authorName?: string;
22
+ }
23
+ export type ResolveAssetPathOptions = {
24
+ assetBaseUrl?: string;
25
+ legacyResolve?: (path: string) => string | undefined;
26
+ };
27
+ /**
28
+ * Resolves an asset field value (path string or absolute URL) to a usable URL.
29
+ *
30
+ * - Empty / undefined values return `undefined`.
31
+ * - Absolute URLs (http/https/protocol-relative/data) are returned as-is.
32
+ * - Otherwise the value is treated as a canonical asset path and joined with
33
+ * `assetBaseUrl`; if no base url is configured, `legacyResolve` is consulted.
34
+ */
35
+ export declare function resolveAssetPath(value: string | undefined, options?: ResolveAssetPathOptions): string | undefined;
36
+ /**
37
+ * Build the canonical asset path for a theme-bundled asset. Mirrors the
38
+ * `themes/<themeKey>/<version>/<relativePath>` layout used by the Suda CLI and
39
+ * the registry storage prefix.
40
+ */
41
+ export declare function createThemeAssetPath(themeKey: string, version: string, relativePath: string): string;
42
+ //# sourceMappingURL=assets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,MAAM,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IACzB;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,yBAAyB;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACtD,CAAC;AAUF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,OAAO,GAAE,uBAA4B,GACpC,MAAM,GAAG,SAAS,CAWpB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,GACnB,MAAM,CAGR"}
package/dist/assets.js ADDED
@@ -0,0 +1,36 @@
1
+ function isAbsoluteUrl(value) {
2
+ return /^(?:[a-z][a-z0-9+\-.]*:)?\/\//i.test(value) || value.indexOf("data:") === 0;
3
+ }
4
+ function joinAssetUrl(baseUrl, key) {
5
+ return `${baseUrl.replace(/\/$/, "")}/${key.replace(/^\/+/, "")}`;
6
+ }
7
+ /**
8
+ * Resolves an asset field value (path string or absolute URL) to a usable URL.
9
+ *
10
+ * - Empty / undefined values return `undefined`.
11
+ * - Absolute URLs (http/https/protocol-relative/data) are returned as-is.
12
+ * - Otherwise the value is treated as a canonical asset path and joined with
13
+ * `assetBaseUrl`; if no base url is configured, `legacyResolve` is consulted.
14
+ */
15
+ export function resolveAssetPath(value, options = {}) {
16
+ if (!value || typeof value !== "string") {
17
+ return undefined;
18
+ }
19
+ if (isAbsoluteUrl(value)) {
20
+ return value;
21
+ }
22
+ if (options.assetBaseUrl) {
23
+ return joinAssetUrl(options.assetBaseUrl, value);
24
+ }
25
+ return options.legacyResolve?.(value) ?? value;
26
+ }
27
+ /**
28
+ * Build the canonical asset path for a theme-bundled asset. Mirrors the
29
+ * `themes/<themeKey>/<version>/<relativePath>` layout used by the Suda CLI and
30
+ * the registry storage prefix.
31
+ */
32
+ export function createThemeAssetPath(themeKey, version, relativePath) {
33
+ const normalizedRelative = relativePath.replace(/^\/+/, "");
34
+ return `themes/${themeKey}/${version}/${normalizedRelative}`;
35
+ }
36
+ //# sourceMappingURL=assets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets.js","sourceRoot":"","sources":["../src/assets.ts"],"names":[],"mappings":"AA6BA,SAAS,aAAa,CAAC,KAAa;IAClC,OAAO,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AACtF,CAAC;AAED,SAAS,YAAY,CAAC,OAAe,EAAE,GAAW;IAChD,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;AACpE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAyB,EACzB,UAAmC,EAAE;IAErC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;QACzB,OAAO,YAAY,CAAC,OAAO,CAAC,YAAY,EAAE,KAAK,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,OAAO,CAAC,aAAa,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAgB,EAChB,OAAe,EACf,YAAoB;IAEpB,MAAM,kBAAkB,GAAG,YAAY,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5D,OAAO,UAAU,QAAQ,IAAI,OAAO,IAAI,kBAAkB,EAAE,CAAC;AAC/D,CAAC"}
@@ -0,0 +1,9 @@
1
+ import type { PageData } from "../types";
2
+ import type { CmsContext } from "./types";
3
+ /**
4
+ * Pure function: project `cms` data onto components in `pageData` whose props
5
+ * declare a `cmsBinding`. Returns the original `pageData` reference when no
6
+ * binding matches the context, so React reconciliation stays stable.
7
+ */
8
+ export declare function applyCmsBindings(pageData: PageData, cms: CmsContext | null): PageData;
9
+ //# sourceMappingURL=apply-bindings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-bindings.d.ts","sourceRoot":"","sources":["../../src/cms/apply-bindings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAEzC,OAAO,KAAK,EAEV,UAAU,EAKX,MAAM,SAAS,CAAC;AA4IjB;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,GAAG,IAAI,GAAG,QAAQ,CAerF"}
@@ -0,0 +1,128 @@
1
+ function isPlainObject(value) {
2
+ return typeof value === "object" && value !== null && !Array.isArray(value);
3
+ }
4
+ function asNode(value) {
5
+ if (!isPlainObject(value))
6
+ return null;
7
+ if (typeof value.type !== "string")
8
+ return null;
9
+ if (!isPlainObject(value.props))
10
+ return null;
11
+ // Return the original reference so we preserve Puck's BaseData fields
12
+ // (e.g. `readOnly`) alongside `type` / `props`.
13
+ return value;
14
+ }
15
+ function asBinding(value) {
16
+ if (!isPlainObject(value))
17
+ return null;
18
+ const source = value.source;
19
+ if (source !== "cms.posts" &&
20
+ source !== "cms.post" &&
21
+ source !== "cms.tags" &&
22
+ source !== "cms.tag") {
23
+ return null;
24
+ }
25
+ // We don't deep-validate optional fields like `limit`; downstream components
26
+ // tolerate extra/missing data.
27
+ return value;
28
+ }
29
+ function projectPostsBinding(props, binding, payload) {
30
+ if (!payload)
31
+ return props;
32
+ const items = typeof binding.limit === "number" && binding.limit >= 0
33
+ ? payload.items.slice(0, binding.limit)
34
+ : payload.items;
35
+ return {
36
+ ...props,
37
+ items,
38
+ pagination: payload.pagination,
39
+ };
40
+ }
41
+ function projectPostBinding(props, payload) {
42
+ if (payload === undefined)
43
+ return props;
44
+ return {
45
+ ...props,
46
+ post: payload,
47
+ };
48
+ }
49
+ function projectTagsBinding(props, binding, payload) {
50
+ if (!payload)
51
+ return props;
52
+ const tags = typeof binding.limit === "number" && binding.limit >= 0
53
+ ? payload.slice(0, binding.limit)
54
+ : payload;
55
+ return { ...props, tags };
56
+ }
57
+ function projectTagBinding(props, payload) {
58
+ if (payload === undefined)
59
+ return props;
60
+ return { ...props, tag: payload };
61
+ }
62
+ function projectProps(props, cms) {
63
+ const binding = asBinding(props.cmsBinding);
64
+ if (!binding)
65
+ return props;
66
+ switch (binding.source) {
67
+ case "cms.posts":
68
+ return projectPostsBinding(props, binding, cms.posts);
69
+ case "cms.post":
70
+ return projectPostBinding(props, cms.post);
71
+ case "cms.tags":
72
+ return projectTagsBinding(props, binding, cms.tags);
73
+ case "cms.tag":
74
+ return projectTagBinding(props, cms.tag);
75
+ default:
76
+ return props;
77
+ }
78
+ }
79
+ function projectNode(node, cms) {
80
+ let nextProps = projectProps(node.props, cms);
81
+ let childChanged = false;
82
+ // Recurse into slot children (any prop value that is an array of nodes).
83
+ for (const [key, value] of Object.entries(nextProps)) {
84
+ if (!Array.isArray(value))
85
+ continue;
86
+ const children = value
87
+ .map(asNode)
88
+ .filter((n) => n !== null);
89
+ if (children.length !== value.length)
90
+ continue;
91
+ const projected = children.map((child) => projectNode(child, cms));
92
+ if (projected.some((next, i) => next !== children[i])) {
93
+ if (!childChanged) {
94
+ nextProps = { ...nextProps };
95
+ childChanged = true;
96
+ }
97
+ nextProps[key] = projected;
98
+ }
99
+ }
100
+ if (nextProps === node.props && !childChanged)
101
+ return node;
102
+ return { ...node, props: nextProps };
103
+ }
104
+ /**
105
+ * Pure function: project `cms` data onto components in `pageData` whose props
106
+ * declare a `cmsBinding`. Returns the original `pageData` reference when no
107
+ * binding matches the context, so React reconciliation stays stable.
108
+ */
109
+ export function applyCmsBindings(pageData, cms) {
110
+ if (!cms)
111
+ return pageData;
112
+ if (!Array.isArray(pageData.content))
113
+ return pageData;
114
+ const nodes = pageData.content
115
+ .map(asNode)
116
+ .filter((n) => n !== null);
117
+ if (nodes.length !== pageData.content.length)
118
+ return pageData;
119
+ const projected = nodes.map((node) => projectNode(node, cms));
120
+ if (projected.every((next, i) => next === nodes[i])) {
121
+ return pageData;
122
+ }
123
+ return {
124
+ ...pageData,
125
+ content: projected,
126
+ };
127
+ }
128
+ //# sourceMappingURL=apply-bindings.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply-bindings.js","sourceRoot":"","sources":["../../src/cms/apply-bindings.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { ThemeRenderMetadata } from "../components/metadata";
2
+ import type { CmsContext } from "./types";
3
+ /**
4
+ * Read the CMS render context from Puck metadata. Use this from "raw"
5
+ * components that need richer access than the default `cmsBinding`
6
+ * projection (e.g. pagination links, tag clouds).
7
+ */
8
+ export declare function getCmsContext(metadata: ThemeRenderMetadata | undefined): CmsContext | null;
9
+ //# sourceMappingURL=get-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-context.d.ts","sourceRoot":"","sources":["../../src/cms/get-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE1C;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAM1F"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Read the CMS render context from Puck metadata. Use this from "raw"
3
+ * components that need richer access than the default `cmsBinding`
4
+ * projection (e.g. pagination links, tag clouds).
5
+ */
6
+ export function getCmsContext(metadata) {
7
+ const cms = metadata?.cms;
8
+ if (!cms || typeof cms !== "object" || Array.isArray(cms)) {
9
+ return null;
10
+ }
11
+ return cms;
12
+ }
13
+ //# sourceMappingURL=get-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-context.js","sourceRoot":"","sources":["../../src/cms/get-context.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,QAAyC;IACrE,MAAM,GAAG,GAAG,QAAQ,EAAE,GAAG,CAAC;IAC1B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,GAAiB,CAAC;AAC3B,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export { applyCmsBindings } from "./apply-bindings";
3
+ export { getCmsContext } from "./get-context";
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cms/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,4 @@
1
+ export * from "./types";
2
+ export { applyCmsBindings } from "./apply-bindings";
3
+ export { getCmsContext } from "./get-context";
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cms/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,116 @@
1
+ export type CmsViewKind = "post.index" | "post.detail" | "tag.index" | "tag.detail";
2
+ export type CmsSort = "newest" | "oldest" | "featured";
3
+ export interface NormalizedCmsParams {
4
+ tag?: string;
5
+ q?: string;
6
+ featured?: boolean;
7
+ page: number;
8
+ pageSize: number;
9
+ sort: CmsSort;
10
+ from?: string;
11
+ to?: string;
12
+ }
13
+ /**
14
+ * Lightweight summary of a published post used in CMS list rendering.
15
+ * Theme-render-only; never persisted directly.
16
+ */
17
+ export interface CmsPostSummary {
18
+ id: string;
19
+ title: string;
20
+ slug: string;
21
+ excerpt: string | null;
22
+ featured: boolean;
23
+ publishedAt: string | null;
24
+ url: string;
25
+ coverImageUrl?: string;
26
+ tags: Array<{
27
+ slug: string;
28
+ name: string;
29
+ }>;
30
+ }
31
+ export interface CmsPostDetail extends CmsPostSummary {
32
+ body: string;
33
+ seo: unknown;
34
+ }
35
+ export interface CmsTagSummary {
36
+ id: string;
37
+ name: string;
38
+ slug: string;
39
+ description: string | null;
40
+ url: string;
41
+ postCount: number;
42
+ }
43
+ export interface CmsTagDetail extends CmsTagSummary {
44
+ seo: unknown;
45
+ }
46
+ export interface CmsPagination {
47
+ page: number;
48
+ pageSize: number;
49
+ total: number;
50
+ pageCount: number;
51
+ /** Absolute or path-relative URL for the previous page, when available. */
52
+ prevUrl?: string;
53
+ /** Absolute or path-relative URL for the next page, when available. */
54
+ nextUrl?: string;
55
+ }
56
+ export interface CmsPostListPayload {
57
+ items: CmsPostSummary[];
58
+ pagination: CmsPagination;
59
+ }
60
+ /**
61
+ * Render-time CMS context carried via Puck `metadata.cms`. Built by the site
62
+ * layer after querying the database; consumed by theme components either
63
+ * indirectly (via `cmsBinding` props projection) or directly via
64
+ * `getCmsContext`.
65
+ */
66
+ export interface CmsContext {
67
+ view: CmsViewKind | null;
68
+ params: NormalizedCmsParams;
69
+ posts?: CmsPostListPayload;
70
+ post?: CmsPostDetail | null;
71
+ tags?: CmsTagSummary[];
72
+ tag?: CmsTagDetail | null;
73
+ }
74
+ /**
75
+ * Component-level data binding declarations. A component author adds an
76
+ * optional `cmsBinding` prop; the engine projects matching CMS data onto the
77
+ * component's existing static props (`items`, `post`, `tag`, `tags`,
78
+ * `pagination`) at render time, so the component itself stays unaware of CMS.
79
+ */
80
+ export type CmsBinding = {
81
+ source: "cms.posts";
82
+ /** Optional limit applied client-side (component may render fewer items). */
83
+ limit?: number;
84
+ } | {
85
+ source: "cms.post";
86
+ } | {
87
+ source: "cms.tags";
88
+ limit?: number;
89
+ } | {
90
+ source: "cms.tag";
91
+ };
92
+ /** Theme-level CMS view binding declaration. */
93
+ export interface CmsViewBinding {
94
+ /** Path of the index page, e.g. "/articles". */
95
+ indexPath?: string;
96
+ /**
97
+ * Path of the detail page root. The slug is appended directly, e.g.
98
+ * `detailPath: "/articles"` resolves `/articles/<slug>`.
99
+ */
100
+ detailPath?: string;
101
+ /** URL parameter keys this view officially supports. */
102
+ supportedParams?: Array<keyof NormalizedCmsParams>;
103
+ }
104
+ export interface ThemeContentCapabilities {
105
+ /** Bumped if `metadata.cms` shape ever evolves. */
106
+ cmsContextVersion: 1;
107
+ posts?: {
108
+ index?: CmsViewBinding;
109
+ detail?: CmsViewBinding;
110
+ };
111
+ tags?: {
112
+ index?: CmsViewBinding;
113
+ detail?: CmsViewBinding;
114
+ };
115
+ }
116
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cms/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cms/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,13 @@
1
+ import type { ComponentConfig } from "@puckeditor/core";
2
+ /**
3
+ * The whitelist of base "block" component types that may be inserted into
4
+ * container slots. Containers reference this list in their slot `allow`.
5
+ */
6
+ export declare const BASE_BLOCK_TYPES: readonly ["Text", "Heading", "RichText", "Image", "Button", "Spacer"];
7
+ export type BaseBlockType = (typeof BASE_BLOCK_TYPES)[number];
8
+ /**
9
+ * Returns the base block components keyed by type. These are the only
10
+ * components allowed inside container slots (see {@link BASE_BLOCK_TYPES}).
11
+ */
12
+ export declare function createBaseBlocks(): Record<string, ComponentConfig>;
13
+ //# sourceMappingURL=base-blocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-blocks.d.ts","sourceRoot":"","sources":["../../src/components/base-blocks.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAQxD;;;GAGG;AACH,eAAO,MAAM,gBAAgB,uEAOnB,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAuM9D;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CASlE"}