@cmssy/react 12.5.0 → 12.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/client.cjs CHANGED
@@ -65,6 +65,122 @@ function resolveShortcutAction(event, isMac, isTyping) {
65
65
  return null;
66
66
  }
67
67
 
68
+ // src/bridge/invisible-blocks.ts
69
+ var TRANSPARENT = 0.01;
70
+ var PAINTS_WITHOUT_TEXT = "img,svg,video,canvas,picture,iframe";
71
+ function effectiveOpacity(node) {
72
+ let value = 1;
73
+ let current = node;
74
+ while (current) {
75
+ const style = getComputedStyle(current);
76
+ if (style.display === "none" || style.visibility === "hidden") return 0;
77
+ const own = Number.parseFloat(style.opacity);
78
+ if (Number.isFinite(own)) value *= own;
79
+ if (value <= TRANSPARENT) return 0;
80
+ if (current === document.documentElement) break;
81
+ current = current.parentElement;
82
+ }
83
+ return value;
84
+ }
85
+ function paintsSomething(el) {
86
+ if (el.matches(PAINTS_WITHOUT_TEXT)) return true;
87
+ for (const node of el.childNodes) {
88
+ if (node.nodeType === 3 && node.textContent?.trim()) return true;
89
+ }
90
+ return false;
91
+ }
92
+ function isBlockPainted(block) {
93
+ const candidates = [];
94
+ if (paintsSomething(block)) candidates.push(block);
95
+ for (const el of block.querySelectorAll("*")) {
96
+ if (paintsSomething(el)) candidates.push(el);
97
+ }
98
+ if (candidates.length === 0) return true;
99
+ return candidates.some((el) => effectiveOpacity(el) > TRANSPARENT);
100
+ }
101
+
102
+ // src/bridge/use-invisible-blocks.ts
103
+ var DWELL_MS = 1500;
104
+ var VISIBLE_FRACTION = 0.35;
105
+ var SWEEP_MS = 2e3;
106
+ function useInvisibleBlocks(enabled, blocksKey, report) {
107
+ const reportRef = react.useRef(report);
108
+ reportRef.current = report;
109
+ react.useEffect(() => {
110
+ if (!enabled) return;
111
+ if (typeof document === "undefined") return;
112
+ if (typeof IntersectionObserver === "undefined") return;
113
+ const timers = /* @__PURE__ */ new Map();
114
+ const observed = /* @__PURE__ */ new WeakSet();
115
+ const invisible = /* @__PURE__ */ new Map();
116
+ let reported = "";
117
+ const flush = () => {
118
+ const blocks = [...invisible.values()];
119
+ const key = blocks.map((block) => `${block.blockId}:${block.blockType}`).sort().join("|");
120
+ if (key === reported) return;
121
+ reported = key;
122
+ reportRef.current(blocks);
123
+ };
124
+ const judge = (el) => {
125
+ const blockId = el.getAttribute("data-block-id");
126
+ const blockType = el.getAttribute("data-block-type");
127
+ if (!blockId || !blockType) return;
128
+ if (isBlockPainted(el)) invisible.delete(blockId);
129
+ else invisible.set(blockId, { blockId, blockType });
130
+ flush();
131
+ };
132
+ const observer = new IntersectionObserver(
133
+ (entries) => {
134
+ for (const entry of entries) {
135
+ const pending = timers.get(entry.target);
136
+ if (!entry.isIntersecting || entry.intersectionRatio < VISIBLE_FRACTION) {
137
+ if (pending) {
138
+ clearTimeout(pending);
139
+ timers.delete(entry.target);
140
+ }
141
+ continue;
142
+ }
143
+ if (pending) continue;
144
+ timers.set(
145
+ entry.target,
146
+ setTimeout(() => {
147
+ timers.delete(entry.target);
148
+ judge(entry.target);
149
+ }, DWELL_MS)
150
+ );
151
+ }
152
+ },
153
+ { threshold: VISIBLE_FRACTION }
154
+ );
155
+ const sweep = () => {
156
+ const present = /* @__PURE__ */ new Set();
157
+ for (const el of document.querySelectorAll("[data-block-id]")) {
158
+ if (!observed.has(el)) {
159
+ observed.add(el);
160
+ observer.observe(el);
161
+ }
162
+ const blockId = el.getAttribute("data-block-id");
163
+ if (!blockId) continue;
164
+ present.add(blockId);
165
+ if (invisible.has(blockId) && isBlockPainted(el)) {
166
+ invisible.delete(blockId);
167
+ }
168
+ }
169
+ for (const blockId of [...invisible.keys()]) {
170
+ if (!present.has(blockId)) invisible.delete(blockId);
171
+ }
172
+ flush();
173
+ };
174
+ sweep();
175
+ const interval = setInterval(sweep, SWEEP_MS);
176
+ return () => {
177
+ observer.disconnect();
178
+ for (const timer of timers.values()) clearTimeout(timer);
179
+ clearInterval(interval);
180
+ };
181
+ }, [enabled, blocksKey]);
182
+ }
183
+
68
184
  // src/bridge/use-edit-bridge.tsx
69
185
  var ZERO_RECT = { x: 0, y: 0, width: 0, height: 0 };
70
186
  function collectRects() {
@@ -88,6 +204,9 @@ function findBlockEl(blockId) {
88
204
  return null;
89
205
  }
90
206
  }
207
+ function canDetectInvisibleBlocks() {
208
+ return typeof document !== "undefined" && typeof IntersectionObserver !== "undefined";
209
+ }
91
210
  function prefersReducedMotion() {
92
211
  return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
93
212
  }
@@ -126,6 +245,7 @@ function useEditBridge(page, config) {
126
245
  });
127
246
  const { id: pageId, blocks } = page;
128
247
  const blocksKey = blocks.map((b) => `${b.id}:${b.type}`).join("|");
248
+ const framed = typeof window !== "undefined" && window.parent !== window;
129
249
  react.useEffect(() => {
130
250
  setPatches({});
131
251
  setPatchesStyle({});
@@ -172,7 +292,7 @@ function useEditBridge(page, config) {
172
292
  ],
173
293
  schemas: config.schemas ?? /* @__PURE__ */ Object.create(null),
174
294
  blockMeta: config.blockMeta ?? /* @__PURE__ */ Object.create(null),
175
- capabilities: ["shortcuts"]
295
+ capabilities: canDetectInvisibleBlocks() ? ["shortcuts", "invisible-blocks"] : ["shortcuts"]
176
296
  });
177
297
  } catch (error) {
178
298
  if (typeof console !== "undefined") {
@@ -322,6 +442,13 @@ function useEditBridge(page, config) {
322
442
  window.removeEventListener("resize", emitSelectedBounds);
323
443
  };
324
444
  }, [config.editorOrigin, pageId, blocksKey]);
445
+ useInvisibleBlocks(framed, blocksKey, (invisibleBlocks) => {
446
+ postSafeRef.current({
447
+ type: "cmssy:invisible-blocks",
448
+ protocolVersion: core.PROTOCOL_VERSION,
449
+ blocks: invisibleBlocks
450
+ });
451
+ });
325
452
  react.useEffect(() => {
326
453
  emitBoundsRef.current();
327
454
  });
@@ -639,7 +766,7 @@ function CmssyBlock({
639
766
  }
640
767
  const base = resolvedContent ? { ...resolvedContent } : internal.getBlockContentForLanguage(block.content, locale, defaultLocale);
641
768
  const content = patchedContent ? { ...base, ...patchedContent } : base;
642
- if (schema) internal.normalizeRelationContent(content, schema, resolvedContent);
769
+ if (schema) internal.normalizeBlockContent(content, schema, resolvedContent);
643
770
  const style = patchedStyle ? { ...internal.asBucket(block.style), ...patchedStyle } : internal.asBucket(block.style);
644
771
  const advanced = patchedAdvanced ? { ...internal.asBucket(block.advanced), ...patchedAdvanced } : internal.asBucket(block.advanced);
645
772
  return wrap(
package/dist/client.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { BlockSchema, BlockMeta, CmssyPageData, CmssyFormDefinition, CmssyLayoutGroup } from '@cmssy/core';
3
- import { B as BlockDefinition } from './registry-fguZApc8.cjs';
3
+ import { B as BlockDefinition } from './registry-CwJ2cby4.cjs';
4
4
  import 'react';
5
5
 
6
6
  interface EditBridgeConfig {
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { BlockSchema, BlockMeta, CmssyPageData, CmssyFormDefinition, CmssyLayoutGroup } from '@cmssy/core';
3
- import { B as BlockDefinition } from './registry-fguZApc8.js';
3
+ import { B as BlockDefinition } from './registry-CwJ2cby4.js';
4
4
  import 'react';
5
5
 
6
6
  interface EditBridgeConfig {
package/dist/client.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { useState, useRef, useEffect, useMemo, createElement } from 'react';
3
3
  import { postToEditor, PROTOCOL_VERSION, parseEditorMessage } from '@cmssy/core';
4
- import { resolveInitialTarget, buildBlockContext, getBlockContentForLanguage, normalizeRelationContent, asBucket } from '@cmssy/core/internal';
4
+ import { resolveInitialTarget, buildBlockContext, getBlockContentForLanguage, normalizeBlockContent, asBucket } from '@cmssy/core/internal';
5
5
  import { BlockErrorBoundary } from '@cmssy/react/block-error-boundary';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
@@ -63,6 +63,122 @@ function resolveShortcutAction(event, isMac, isTyping) {
63
63
  return null;
64
64
  }
65
65
 
66
+ // src/bridge/invisible-blocks.ts
67
+ var TRANSPARENT = 0.01;
68
+ var PAINTS_WITHOUT_TEXT = "img,svg,video,canvas,picture,iframe";
69
+ function effectiveOpacity(node) {
70
+ let value = 1;
71
+ let current = node;
72
+ while (current) {
73
+ const style = getComputedStyle(current);
74
+ if (style.display === "none" || style.visibility === "hidden") return 0;
75
+ const own = Number.parseFloat(style.opacity);
76
+ if (Number.isFinite(own)) value *= own;
77
+ if (value <= TRANSPARENT) return 0;
78
+ if (current === document.documentElement) break;
79
+ current = current.parentElement;
80
+ }
81
+ return value;
82
+ }
83
+ function paintsSomething(el) {
84
+ if (el.matches(PAINTS_WITHOUT_TEXT)) return true;
85
+ for (const node of el.childNodes) {
86
+ if (node.nodeType === 3 && node.textContent?.trim()) return true;
87
+ }
88
+ return false;
89
+ }
90
+ function isBlockPainted(block) {
91
+ const candidates = [];
92
+ if (paintsSomething(block)) candidates.push(block);
93
+ for (const el of block.querySelectorAll("*")) {
94
+ if (paintsSomething(el)) candidates.push(el);
95
+ }
96
+ if (candidates.length === 0) return true;
97
+ return candidates.some((el) => effectiveOpacity(el) > TRANSPARENT);
98
+ }
99
+
100
+ // src/bridge/use-invisible-blocks.ts
101
+ var DWELL_MS = 1500;
102
+ var VISIBLE_FRACTION = 0.35;
103
+ var SWEEP_MS = 2e3;
104
+ function useInvisibleBlocks(enabled, blocksKey, report) {
105
+ const reportRef = useRef(report);
106
+ reportRef.current = report;
107
+ useEffect(() => {
108
+ if (!enabled) return;
109
+ if (typeof document === "undefined") return;
110
+ if (typeof IntersectionObserver === "undefined") return;
111
+ const timers = /* @__PURE__ */ new Map();
112
+ const observed = /* @__PURE__ */ new WeakSet();
113
+ const invisible = /* @__PURE__ */ new Map();
114
+ let reported = "";
115
+ const flush = () => {
116
+ const blocks = [...invisible.values()];
117
+ const key = blocks.map((block) => `${block.blockId}:${block.blockType}`).sort().join("|");
118
+ if (key === reported) return;
119
+ reported = key;
120
+ reportRef.current(blocks);
121
+ };
122
+ const judge = (el) => {
123
+ const blockId = el.getAttribute("data-block-id");
124
+ const blockType = el.getAttribute("data-block-type");
125
+ if (!blockId || !blockType) return;
126
+ if (isBlockPainted(el)) invisible.delete(blockId);
127
+ else invisible.set(blockId, { blockId, blockType });
128
+ flush();
129
+ };
130
+ const observer = new IntersectionObserver(
131
+ (entries) => {
132
+ for (const entry of entries) {
133
+ const pending = timers.get(entry.target);
134
+ if (!entry.isIntersecting || entry.intersectionRatio < VISIBLE_FRACTION) {
135
+ if (pending) {
136
+ clearTimeout(pending);
137
+ timers.delete(entry.target);
138
+ }
139
+ continue;
140
+ }
141
+ if (pending) continue;
142
+ timers.set(
143
+ entry.target,
144
+ setTimeout(() => {
145
+ timers.delete(entry.target);
146
+ judge(entry.target);
147
+ }, DWELL_MS)
148
+ );
149
+ }
150
+ },
151
+ { threshold: VISIBLE_FRACTION }
152
+ );
153
+ const sweep = () => {
154
+ const present = /* @__PURE__ */ new Set();
155
+ for (const el of document.querySelectorAll("[data-block-id]")) {
156
+ if (!observed.has(el)) {
157
+ observed.add(el);
158
+ observer.observe(el);
159
+ }
160
+ const blockId = el.getAttribute("data-block-id");
161
+ if (!blockId) continue;
162
+ present.add(blockId);
163
+ if (invisible.has(blockId) && isBlockPainted(el)) {
164
+ invisible.delete(blockId);
165
+ }
166
+ }
167
+ for (const blockId of [...invisible.keys()]) {
168
+ if (!present.has(blockId)) invisible.delete(blockId);
169
+ }
170
+ flush();
171
+ };
172
+ sweep();
173
+ const interval = setInterval(sweep, SWEEP_MS);
174
+ return () => {
175
+ observer.disconnect();
176
+ for (const timer of timers.values()) clearTimeout(timer);
177
+ clearInterval(interval);
178
+ };
179
+ }, [enabled, blocksKey]);
180
+ }
181
+
66
182
  // src/bridge/use-edit-bridge.tsx
67
183
  var ZERO_RECT = { x: 0, y: 0, width: 0, height: 0 };
68
184
  function collectRects() {
@@ -86,6 +202,9 @@ function findBlockEl(blockId) {
86
202
  return null;
87
203
  }
88
204
  }
205
+ function canDetectInvisibleBlocks() {
206
+ return typeof document !== "undefined" && typeof IntersectionObserver !== "undefined";
207
+ }
89
208
  function prefersReducedMotion() {
90
209
  return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
91
210
  }
@@ -124,6 +243,7 @@ function useEditBridge(page, config) {
124
243
  });
125
244
  const { id: pageId, blocks } = page;
126
245
  const blocksKey = blocks.map((b) => `${b.id}:${b.type}`).join("|");
246
+ const framed = typeof window !== "undefined" && window.parent !== window;
127
247
  useEffect(() => {
128
248
  setPatches({});
129
249
  setPatchesStyle({});
@@ -170,7 +290,7 @@ function useEditBridge(page, config) {
170
290
  ],
171
291
  schemas: config.schemas ?? /* @__PURE__ */ Object.create(null),
172
292
  blockMeta: config.blockMeta ?? /* @__PURE__ */ Object.create(null),
173
- capabilities: ["shortcuts"]
293
+ capabilities: canDetectInvisibleBlocks() ? ["shortcuts", "invisible-blocks"] : ["shortcuts"]
174
294
  });
175
295
  } catch (error) {
176
296
  if (typeof console !== "undefined") {
@@ -320,6 +440,13 @@ function useEditBridge(page, config) {
320
440
  window.removeEventListener("resize", emitSelectedBounds);
321
441
  };
322
442
  }, [config.editorOrigin, pageId, blocksKey]);
443
+ useInvisibleBlocks(framed, blocksKey, (invisibleBlocks) => {
444
+ postSafeRef.current({
445
+ type: "cmssy:invisible-blocks",
446
+ protocolVersion: PROTOCOL_VERSION,
447
+ blocks: invisibleBlocks
448
+ });
449
+ });
323
450
  useEffect(() => {
324
451
  emitBoundsRef.current();
325
452
  });
@@ -637,7 +764,7 @@ function CmssyBlock({
637
764
  }
638
765
  const base = resolvedContent ? { ...resolvedContent } : getBlockContentForLanguage(block.content, locale, defaultLocale);
639
766
  const content = patchedContent ? { ...base, ...patchedContent } : base;
640
- if (schema) normalizeRelationContent(content, schema, resolvedContent);
767
+ if (schema) normalizeBlockContent(content, schema, resolvedContent);
641
768
  const style = patchedStyle ? { ...asBucket(block.style), ...patchedStyle } : asBucket(block.style);
642
769
  const advanced = patchedAdvanced ? { ...asBucket(block.advanced), ...patchedAdvanced } : asBucket(block.advanced);
643
770
  return wrap(
package/dist/index.cjs CHANGED
@@ -195,14 +195,21 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
195
195
  enabledLocales?.length ? enabledLocales : void 0
196
196
  )
197
197
  );
198
- if (options?.config && options.schemas) {
199
- await internal.resolveRelationContent(
200
- options.config,
201
- blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
202
- options.schemas,
203
- locale,
204
- options.workspaceId ? { workspaceId: options.workspaceId } : {}
205
- );
198
+ const schemas = options?.schemas;
199
+ if (schemas) {
200
+ if (options?.config) {
201
+ await internal.resolveRelationContent(
202
+ options.config,
203
+ blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
204
+ schemas,
205
+ locale,
206
+ options.workspaceId ? { workspaceId: options.workspaceId } : {}
207
+ );
208
+ }
209
+ blocks.forEach((block, i) => {
210
+ const schema = schemas[block.type];
211
+ if (schema) internal.normalizeBlockContent(contents[i], schema);
212
+ });
206
213
  }
207
214
  return Promise.all(
208
215
  blocks.map(async (block, i) => {
@@ -540,7 +547,7 @@ function CmssyBlock({
540
547
  }
541
548
  const base = resolvedContent ? { ...resolvedContent } : internal.getBlockContentForLanguage(block.content, locale, defaultLocale);
542
549
  const content = patchedContent ? { ...base, ...patchedContent } : base;
543
- if (schema) internal.normalizeRelationContent(content, schema, resolvedContent);
550
+ if (schema) internal.normalizeBlockContent(content, schema, resolvedContent);
544
551
  const style = patchedStyle ? { ...internal.asBucket(block.style), ...patchedStyle } : internal.asBucket(block.style);
545
552
  const advanced = patchedAdvanced ? { ...internal.asBucket(block.advanced), ...patchedAdvanced } : internal.asBucket(block.advanced);
546
553
  return wrap(
package/dist/index.d.cts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { CmssyPageData, CmssyClientConfig, CmssyFormDefinition, CmssyBlockAuthContext, CmssyBlockWorkspace, CmssyLayoutGroup, CmssyConfig, RawBlock, CmssyBlockContext } from '@cmssy/core';
2
2
  export { AppToEditorMessage, BlockMeta, BlockPropsSchema, BlockRect, BlockSchema, BoundsMessage, BuildBlockContextExtra, ClickMessage, CmssyBlockAuthContext, CmssyBlockContext, CmssyBlockMember, CmssyBlockPage, CmssyBlockWorkspace, CmssyBranding, CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyFormField, CmssyFormSettings, CmssyFormSubmitResponse, CmssyLayoutGroup, CmssyLayoutSettings, CmssyLocaleContext, CmssyLocalizedValue, CmssyModelDefinition, CmssyModelRecord, CmssyPageData, CmssyPageMeta, CmssyPageSummary, CmssyRecordList, CmssyRequestError, CmssySiteConfig, CmssyTypedDocument, EditorToAppMessage, FetchLike, FetchLikeResponse, FetchPageOptions, FieldControl, FieldDefinition, FieldType, GraphqlRequestOptions, InferBlockContent, LayoutPosition, MediaLike, PROTOCOL_VERSION, ParentReadyMessage, PatchMessage, PostTarget, QueryScopedOptions, RawBlock, RawLayoutBlock, ReadyMessage, RetryPolicy, SelectMessage, SubmitFormInput, TypedField, createCmssyClient, fields, graphqlRequest, isProtocolCompatible, layoutPositionValues, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor } from '@cmssy/core';
3
- import { B as BlockDefinition, a as BlockMap } from './registry-fguZApc8.cjs';
4
- export { b as BlockProps, c as buildBlockMap, d as defineBlock } from './registry-fguZApc8.cjs';
3
+ import { B as BlockDefinition, a as BlockMap } from './registry-CwJ2cby4.cjs';
4
+ export { b as BlockProps, c as buildBlockMap, d as defineBlock } from './registry-CwJ2cby4.cjs';
5
5
  import { FieldDefinition } from '@cmssy/types';
6
6
  export { FieldCondition, FieldConditionGroup, FieldConditionLogic } from '@cmssy/types';
7
7
  export { buildBlockContext } from '@cmssy/core/internal';
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { CmssyPageData, CmssyClientConfig, CmssyFormDefinition, CmssyBlockAuthContext, CmssyBlockWorkspace, CmssyLayoutGroup, CmssyConfig, RawBlock, CmssyBlockContext } from '@cmssy/core';
2
2
  export { AppToEditorMessage, BlockMeta, BlockPropsSchema, BlockRect, BlockSchema, BoundsMessage, BuildBlockContextExtra, ClickMessage, CmssyBlockAuthContext, CmssyBlockContext, CmssyBlockMember, CmssyBlockPage, CmssyBlockWorkspace, CmssyBranding, CmssyClient, CmssyClientConfig, CmssyFormDefinition, CmssyFormField, CmssyFormSettings, CmssyFormSubmitResponse, CmssyLayoutGroup, CmssyLayoutSettings, CmssyLocaleContext, CmssyLocalizedValue, CmssyModelDefinition, CmssyModelRecord, CmssyPageData, CmssyPageMeta, CmssyPageSummary, CmssyRecordList, CmssyRequestError, CmssySiteConfig, CmssyTypedDocument, EditorToAppMessage, FetchLike, FetchLikeResponse, FetchPageOptions, FieldControl, FieldDefinition, FieldType, GraphqlRequestOptions, InferBlockContent, LayoutPosition, MediaLike, PROTOCOL_VERSION, ParentReadyMessage, PatchMessage, PostTarget, QueryScopedOptions, RawBlock, RawLayoutBlock, ReadyMessage, RetryPolicy, SelectMessage, SubmitFormInput, TypedField, createCmssyClient, fields, graphqlRequest, isProtocolCompatible, layoutPositionValues, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor } from '@cmssy/core';
3
- import { B as BlockDefinition, a as BlockMap } from './registry-fguZApc8.js';
4
- export { b as BlockProps, c as buildBlockMap, d as defineBlock } from './registry-fguZApc8.js';
3
+ import { B as BlockDefinition, a as BlockMap } from './registry-CwJ2cby4.js';
4
+ export { b as BlockProps, c as buildBlockMap, d as defineBlock } from './registry-CwJ2cby4.js';
5
5
  import { FieldDefinition } from '@cmssy/types';
6
6
  export { FieldCondition, FieldConditionGroup, FieldConditionLogic } from '@cmssy/types';
7
7
  export { buildBlockContext } from '@cmssy/core/internal';
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { resolveEditorOrigin } from '@cmssy/core';
2
2
  export { CmssyRequestError, PROTOCOL_VERSION, createCmssyClient, fields, graphqlRequest, isProtocolCompatible, layoutPositionValues, mediaAlt, mediaUrl, mediaUrls, normalizeOrigin, parseEditorMessage, postToEditor } from '@cmssy/core';
3
- import { buildBlockContext, fetchLayouts, getBlockContentForLanguage, normalizeRelationContent, asBucket, resolveSiteLocales as resolveSiteLocales$1, resolveRelationContent } from '@cmssy/core/internal';
3
+ import { buildBlockContext, fetchLayouts, getBlockContentForLanguage, normalizeBlockContent, asBucket, resolveSiteLocales as resolveSiteLocales$1, resolveRelationContent } from '@cmssy/core/internal';
4
4
  export { buildBlockContext } from '@cmssy/core/internal';
5
5
  import { createElement } from 'react';
6
6
  import { BlockErrorBoundary } from '@cmssy/react/block-error-boundary';
@@ -195,14 +195,21 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
195
195
  enabledLocales?.length ? enabledLocales : void 0
196
196
  )
197
197
  );
198
- if (options?.config && options.schemas) {
199
- await resolveRelationContent(
200
- options.config,
201
- blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
202
- options.schemas,
203
- locale,
204
- options.workspaceId ? { workspaceId: options.workspaceId } : {}
205
- );
198
+ const schemas = options?.schemas;
199
+ if (schemas) {
200
+ if (options?.config) {
201
+ await resolveRelationContent(
202
+ options.config,
203
+ blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
204
+ schemas,
205
+ locale,
206
+ options.workspaceId ? { workspaceId: options.workspaceId } : {}
207
+ );
208
+ }
209
+ blocks.forEach((block, i) => {
210
+ const schema = schemas[block.type];
211
+ if (schema) normalizeBlockContent(contents[i], schema);
212
+ });
206
213
  }
207
214
  return Promise.all(
208
215
  blocks.map(async (block, i) => {
@@ -540,7 +547,7 @@ function CmssyBlock({
540
547
  }
541
548
  const base = resolvedContent ? { ...resolvedContent } : getBlockContentForLanguage(block.content, locale, defaultLocale);
542
549
  const content = patchedContent ? { ...base, ...patchedContent } : base;
543
- if (schema) normalizeRelationContent(content, schema, resolvedContent);
550
+ if (schema) normalizeBlockContent(content, schema, resolvedContent);
544
551
  const style = patchedStyle ? { ...asBucket(block.style), ...patchedStyle } : asBucket(block.style);
545
552
  const advanced = patchedAdvanced ? { ...asBucket(block.advanced), ...patchedAdvanced } : asBucket(block.advanced);
546
553
  return wrap(
@@ -41,14 +41,21 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
41
41
  enabledLocales?.length ? enabledLocales : void 0
42
42
  )
43
43
  );
44
- if (options?.config && options.schemas) {
45
- await internal.resolveRelationContent(
46
- options.config,
47
- blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
48
- options.schemas,
49
- locale,
50
- options.workspaceId ? { workspaceId: options.workspaceId } : {}
51
- );
44
+ const schemas = options?.schemas;
45
+ if (schemas) {
46
+ if (options?.config) {
47
+ await internal.resolveRelationContent(
48
+ options.config,
49
+ blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
50
+ schemas,
51
+ locale,
52
+ options.workspaceId ? { workspaceId: options.workspaceId } : {}
53
+ );
54
+ }
55
+ blocks.forEach((block, i) => {
56
+ const schema = schemas[block.type];
57
+ if (schema) internal.normalizeBlockContent(contents[i], schema);
58
+ });
52
59
  }
53
60
  return Promise.all(
54
61
  blocks.map(async (block, i) => {
@@ -164,6 +171,7 @@ async function resolveLayoutBlockData(options) {
164
171
  return (await resolveEditorLayoutBlockData(options)).data;
165
172
  }
166
173
 
174
+ exports.blocksToSchemas = blocksToSchemas;
167
175
  exports.resolveBlockData = resolveBlockData;
168
176
  exports.resolveEditorBlockData = resolveEditorBlockData;
169
177
  exports.resolveEditorLayoutBlockData = resolveEditorLayoutBlockData;
@@ -1,5 +1,6 @@
1
1
  import { CmssyPageData, CmssyFormDefinition, CmssyClientConfig, CmssyLayoutGroup } from '@cmssy/core';
2
- import { B as BlockDefinition } from './registry-fguZApc8.cjs';
2
+ import { B as BlockDefinition } from './registry-CwJ2cby4.cjs';
3
+ export { e as blocksToSchemas } from './registry-CwJ2cby4.cjs';
3
4
  import 'react';
4
5
 
5
6
  interface EditorBlockData {
@@ -1,5 +1,6 @@
1
1
  import { CmssyPageData, CmssyFormDefinition, CmssyClientConfig, CmssyLayoutGroup } from '@cmssy/core';
2
- import { B as BlockDefinition } from './registry-fguZApc8.js';
2
+ import { B as BlockDefinition } from './registry-CwJ2cby4.js';
3
+ export { e as blocksToSchemas } from './registry-CwJ2cby4.js';
3
4
  import 'react';
4
5
 
5
6
  interface EditorBlockData {
@@ -1,4 +1,4 @@
1
- import { buildBlockContext, getBlockContentForLanguage, resolveRelationContent } from '@cmssy/core/internal';
1
+ import { buildBlockContext, getBlockContentForLanguage, resolveRelationContent, normalizeBlockContent } from '@cmssy/core/internal';
2
2
 
3
3
  // src/components/resolve-block-data.ts
4
4
 
@@ -39,14 +39,21 @@ async function resolveBlocks(blocks, loaderMap, locale, defaultLocale, context,
39
39
  enabledLocales?.length ? enabledLocales : void 0
40
40
  )
41
41
  );
42
- if (options?.config && options.schemas) {
43
- await resolveRelationContent(
44
- options.config,
45
- blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
46
- options.schemas,
47
- locale,
48
- options.workspaceId ? { workspaceId: options.workspaceId } : {}
49
- );
42
+ const schemas = options?.schemas;
43
+ if (schemas) {
44
+ if (options?.config) {
45
+ await resolveRelationContent(
46
+ options.config,
47
+ blocks.map((block, i) => ({ type: block.type, content: contents[i] })),
48
+ schemas,
49
+ locale,
50
+ options.workspaceId ? { workspaceId: options.workspaceId } : {}
51
+ );
52
+ }
53
+ blocks.forEach((block, i) => {
54
+ const schema = schemas[block.type];
55
+ if (schema) normalizeBlockContent(contents[i], schema);
56
+ });
50
57
  }
51
58
  return Promise.all(
52
59
  blocks.map(async (block, i) => {
@@ -162,4 +169,4 @@ async function resolveLayoutBlockData(options) {
162
169
  return (await resolveEditorLayoutBlockData(options)).data;
163
170
  }
164
171
 
165
- export { resolveBlockData, resolveEditorBlockData, resolveEditorLayoutBlockData, resolveLayoutBlockData };
172
+ export { blocksToSchemas, resolveBlockData, resolveEditorBlockData, resolveEditorLayoutBlockData, resolveLayoutBlockData };
@@ -1,5 +1,5 @@
1
1
  import { ComponentType } from 'react';
2
- import { FieldDefinition, CmssyBlockContext, BlockPropsSchema, InferBlockContent } from '@cmssy/core';
2
+ import { FieldDefinition, CmssyBlockContext, BlockPropsSchema, InferBlockContent, BlockSchema } from '@cmssy/core';
3
3
 
4
4
  interface BlockProps<P extends BlockPropsSchema, D = unknown> {
5
5
  content: InferBlockContent<P>;
@@ -65,5 +65,6 @@ type BlockMap = Record<string, ComponentType<{
65
65
  data?: unknown;
66
66
  }>>;
67
67
  declare function buildBlockMap(blocks: BlockDefinition[]): BlockMap;
68
+ declare function blocksToSchemas(blocks: BlockDefinition[]): Record<string, BlockSchema>;
68
69
 
69
- export { type BlockDefinition as B, type BlockMap as a, type BlockProps as b, buildBlockMap as c, defineBlock as d };
70
+ export { type BlockDefinition as B, type BlockMap as a, type BlockProps as b, buildBlockMap as c, defineBlock as d, blocksToSchemas as e };
@@ -1,5 +1,5 @@
1
1
  import { ComponentType } from 'react';
2
- import { FieldDefinition, CmssyBlockContext, BlockPropsSchema, InferBlockContent } from '@cmssy/core';
2
+ import { FieldDefinition, CmssyBlockContext, BlockPropsSchema, InferBlockContent, BlockSchema } from '@cmssy/core';
3
3
 
4
4
  interface BlockProps<P extends BlockPropsSchema, D = unknown> {
5
5
  content: InferBlockContent<P>;
@@ -65,5 +65,6 @@ type BlockMap = Record<string, ComponentType<{
65
65
  data?: unknown;
66
66
  }>>;
67
67
  declare function buildBlockMap(blocks: BlockDefinition[]): BlockMap;
68
+ declare function blocksToSchemas(blocks: BlockDefinition[]): Record<string, BlockSchema>;
68
69
 
69
- export { type BlockDefinition as B, type BlockMap as a, type BlockProps as b, buildBlockMap as c, defineBlock as d };
70
+ export { type BlockDefinition as B, type BlockMap as a, type BlockProps as b, buildBlockMap as c, defineBlock as d, blocksToSchemas as e };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/react",
3
- "version": "12.5.0",
3
+ "version": "12.7.0",
4
4
  "description": "React blocks, renderers, data client and editor bridge for cmssy headless sites",
5
5
  "keywords": [
6
6
  "cmssy",
@@ -97,7 +97,7 @@
97
97
  },
98
98
  "dependencies": {
99
99
  "@cmssy/types": "0.35.0",
100
- "@cmssy/core": "12.5.0"
100
+ "@cmssy/core": "12.7.0"
101
101
  },
102
102
  "scripts": {
103
103
  "build": "tsup",