@cmssy/react 0.10.0 → 0.12.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
@@ -485,6 +485,69 @@ function getBlockContentForLanguage(content, locale, defaultLocale = "en", avail
485
485
  const chosen = localeMap[locale] ?? localeMap[defaultLocale] ?? localeMap[fallbackKey];
486
486
  return { ...nonTranslatable, ...chosen };
487
487
  }
488
+
489
+ // src/components/block-attrs.ts
490
+ var PADDING_SCALE = {
491
+ none: "0",
492
+ sm: "0.5rem",
493
+ md: "1rem",
494
+ lg: "2rem",
495
+ xl: "4rem"
496
+ };
497
+ var MAX_WIDTH_SCALE = {
498
+ sm: "640px",
499
+ md: "768px",
500
+ lg: "1024px",
501
+ full: "100%"
502
+ };
503
+ var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right"]);
504
+ function asRecord(value) {
505
+ return value && typeof value === "object" ? value : {};
506
+ }
507
+ function text(value) {
508
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
509
+ }
510
+ function resolveBlockAttrs(blockId, styleBucket, advancedBucket) {
511
+ const s = asRecord(styleBucket);
512
+ const a = asRecord(advancedBucket);
513
+ const style = {};
514
+ const background = text(s.background);
515
+ if (background) style.background = background;
516
+ const padding = text(s.padding);
517
+ if (padding && PADDING_SCALE[padding]) {
518
+ style.paddingTop = PADDING_SCALE[padding];
519
+ style.paddingBottom = PADDING_SCALE[padding];
520
+ }
521
+ const align = text(s.align);
522
+ if (align && TEXT_ALIGN.has(align)) {
523
+ style.textAlign = align;
524
+ }
525
+ const maxWidth = text(s.maxWidth);
526
+ if (maxWidth && MAX_WIDTH_SCALE[maxWidth]) {
527
+ style.maxWidth = MAX_WIDTH_SCALE[maxWidth];
528
+ style.marginLeft = "auto";
529
+ style.marginRight = "auto";
530
+ }
531
+ const selector = `[data-block-id="${blockId.replace(/["\\]/g, "\\$&")}"]`;
532
+ const rules = [];
533
+ const customCss = text(a.customCss);
534
+ if (customCss) {
535
+ const safe = customCss.replace(/[{}]/g, "").replace(/<\/style/gi, "");
536
+ rules.push(`${selector}{${safe}}`);
537
+ }
538
+ if (a.hideOnMobile === true) {
539
+ rules.push(
540
+ `@media (max-width:767px){${selector}{display:none !important}}`
541
+ );
542
+ }
543
+ return {
544
+ style: Object.keys(style).length > 0 ? style : void 0,
545
+ className: text(a.className),
546
+ id: text(a.anchorId),
547
+ hidden: a.visible === false,
548
+ css: rules.length > 0 ? rules.join("") : void 0
549
+ };
550
+ }
488
551
  var WARN_CAP = 256;
489
552
  var warned = /* @__PURE__ */ new Set();
490
553
  function UnknownBlock({ type }) {
@@ -506,17 +569,24 @@ function CmssyBlock({
506
569
  context
507
570
  }) {
508
571
  const Component = Object.hasOwn(blockMap, block.type) ? blockMap[block.type] : void 0;
572
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
573
+ if (attrs.hidden && !editable) return null;
509
574
  const base = getBlockContentForLanguage(block.content, locale, defaultLocale);
510
575
  const content = patchedContent ? { ...base, ...patchedContent } : base;
511
- return /* @__PURE__ */ jsxRuntime.jsx(
576
+ return /* @__PURE__ */ jsxRuntime.jsxs(
512
577
  "div",
513
578
  {
514
579
  "data-block-id": block.id,
515
580
  "data-block-type": block.type,
516
581
  "data-layout-position": layoutPosition,
517
582
  draggable: editable || void 0,
518
- style: Component ? void 0 : { display: "none" },
519
- children: Component ? react.createElement(Component, { content, context }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
583
+ id: attrs.id,
584
+ className: attrs.className,
585
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
586
+ children: [
587
+ attrs.css ? /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
588
+ Component ? react.createElement(Component, { content, context }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
589
+ ]
520
590
  }
521
591
  );
522
592
  }
package/dist/client.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-DXT2RQlm.cjs';
3
- export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-DXT2RQlm.cjs';
2
+ import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-ClCU8FZN.cjs';
3
+ export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-ClCU8FZN.cjs';
4
4
  import { ReactNode } from 'react';
5
5
  import '@cmssy/types';
6
6
 
package/dist/client.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-DXT2RQlm.js';
3
- export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-DXT2RQlm.js';
2
+ import { B as BlockSchema, a as BlockMeta, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, d as CmssyLayoutGroup, e as CmssyLocaleContext, f as CmssyCart, g as CmssyOrder, h as CmssyProduct } from './commerce-queries-ClCU8FZN.js';
3
+ export { i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, l as CmssyOrderItem, m as CmssyProductVariant } from './commerce-queries-ClCU8FZN.js';
4
4
  import { ReactNode } from 'react';
5
5
  import '@cmssy/types';
6
6
 
package/dist/client.js CHANGED
@@ -483,6 +483,69 @@ function getBlockContentForLanguage(content, locale, defaultLocale = "en", avail
483
483
  const chosen = localeMap[locale] ?? localeMap[defaultLocale] ?? localeMap[fallbackKey];
484
484
  return { ...nonTranslatable, ...chosen };
485
485
  }
486
+
487
+ // src/components/block-attrs.ts
488
+ var PADDING_SCALE = {
489
+ none: "0",
490
+ sm: "0.5rem",
491
+ md: "1rem",
492
+ lg: "2rem",
493
+ xl: "4rem"
494
+ };
495
+ var MAX_WIDTH_SCALE = {
496
+ sm: "640px",
497
+ md: "768px",
498
+ lg: "1024px",
499
+ full: "100%"
500
+ };
501
+ var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right"]);
502
+ function asRecord(value) {
503
+ return value && typeof value === "object" ? value : {};
504
+ }
505
+ function text(value) {
506
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
507
+ }
508
+ function resolveBlockAttrs(blockId, styleBucket, advancedBucket) {
509
+ const s = asRecord(styleBucket);
510
+ const a = asRecord(advancedBucket);
511
+ const style = {};
512
+ const background = text(s.background);
513
+ if (background) style.background = background;
514
+ const padding = text(s.padding);
515
+ if (padding && PADDING_SCALE[padding]) {
516
+ style.paddingTop = PADDING_SCALE[padding];
517
+ style.paddingBottom = PADDING_SCALE[padding];
518
+ }
519
+ const align = text(s.align);
520
+ if (align && TEXT_ALIGN.has(align)) {
521
+ style.textAlign = align;
522
+ }
523
+ const maxWidth = text(s.maxWidth);
524
+ if (maxWidth && MAX_WIDTH_SCALE[maxWidth]) {
525
+ style.maxWidth = MAX_WIDTH_SCALE[maxWidth];
526
+ style.marginLeft = "auto";
527
+ style.marginRight = "auto";
528
+ }
529
+ const selector = `[data-block-id="${blockId.replace(/["\\]/g, "\\$&")}"]`;
530
+ const rules = [];
531
+ const customCss = text(a.customCss);
532
+ if (customCss) {
533
+ const safe = customCss.replace(/[{}]/g, "").replace(/<\/style/gi, "");
534
+ rules.push(`${selector}{${safe}}`);
535
+ }
536
+ if (a.hideOnMobile === true) {
537
+ rules.push(
538
+ `@media (max-width:767px){${selector}{display:none !important}}`
539
+ );
540
+ }
541
+ return {
542
+ style: Object.keys(style).length > 0 ? style : void 0,
543
+ className: text(a.className),
544
+ id: text(a.anchorId),
545
+ hidden: a.visible === false,
546
+ css: rules.length > 0 ? rules.join("") : void 0
547
+ };
548
+ }
486
549
  var WARN_CAP = 256;
487
550
  var warned = /* @__PURE__ */ new Set();
488
551
  function UnknownBlock({ type }) {
@@ -504,17 +567,24 @@ function CmssyBlock({
504
567
  context
505
568
  }) {
506
569
  const Component = Object.hasOwn(blockMap, block.type) ? blockMap[block.type] : void 0;
570
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
571
+ if (attrs.hidden && !editable) return null;
507
572
  const base = getBlockContentForLanguage(block.content, locale, defaultLocale);
508
573
  const content = patchedContent ? { ...base, ...patchedContent } : base;
509
- return /* @__PURE__ */ jsx(
574
+ return /* @__PURE__ */ jsxs(
510
575
  "div",
511
576
  {
512
577
  "data-block-id": block.id,
513
578
  "data-block-type": block.type,
514
579
  "data-layout-position": layoutPosition,
515
580
  draggable: editable || void 0,
516
- style: Component ? void 0 : { display: "none" },
517
- children: Component ? createElement(Component, { content, context }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
581
+ id: attrs.id,
582
+ className: attrs.className,
583
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
584
+ children: [
585
+ attrs.css ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
586
+ Component ? createElement(Component, { content, context }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
587
+ ]
518
588
  }
519
589
  );
520
590
  }
@@ -36,6 +36,8 @@ interface RawBlock {
36
36
  id: string;
37
37
  type: string;
38
38
  content: unknown;
39
+ style?: unknown;
40
+ advanced?: unknown;
39
41
  }
40
42
  interface CmssyPageData {
41
43
  id: string;
@@ -45,6 +47,8 @@ interface RawLayoutBlock {
45
47
  id: string;
46
48
  type: string;
47
49
  content: unknown;
50
+ style?: unknown;
51
+ advanced?: unknown;
48
52
  order: number;
49
53
  isActive: boolean;
50
54
  }
@@ -36,6 +36,8 @@ interface RawBlock {
36
36
  id: string;
37
37
  type: string;
38
38
  content: unknown;
39
+ style?: unknown;
40
+ advanced?: unknown;
39
41
  }
40
42
  interface CmssyPageData {
41
43
  id: string;
@@ -45,6 +47,8 @@ interface RawLayoutBlock {
45
47
  id: string;
46
48
  type: string;
47
49
  content: unknown;
50
+ style?: unknown;
51
+ advanced?: unknown;
48
52
  order: number;
49
53
  isActive: boolean;
50
54
  }
package/dist/index.cjs CHANGED
@@ -116,6 +116,69 @@ function buildBlockContext(locale, defaultLocale, enabledLocales, isPreview, for
116
116
  ...extra?.workspace ? { workspace: extra.workspace } : {}
117
117
  };
118
118
  }
119
+
120
+ // src/components/block-attrs.ts
121
+ var PADDING_SCALE = {
122
+ none: "0",
123
+ sm: "0.5rem",
124
+ md: "1rem",
125
+ lg: "2rem",
126
+ xl: "4rem"
127
+ };
128
+ var MAX_WIDTH_SCALE = {
129
+ sm: "640px",
130
+ md: "768px",
131
+ lg: "1024px",
132
+ full: "100%"
133
+ };
134
+ var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right"]);
135
+ function asRecord(value) {
136
+ return value && typeof value === "object" ? value : {};
137
+ }
138
+ function text(value) {
139
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
140
+ }
141
+ function resolveBlockAttrs(blockId, styleBucket, advancedBucket) {
142
+ const s = asRecord(styleBucket);
143
+ const a = asRecord(advancedBucket);
144
+ const style = {};
145
+ const background = text(s.background);
146
+ if (background) style.background = background;
147
+ const padding = text(s.padding);
148
+ if (padding && PADDING_SCALE[padding]) {
149
+ style.paddingTop = PADDING_SCALE[padding];
150
+ style.paddingBottom = PADDING_SCALE[padding];
151
+ }
152
+ const align = text(s.align);
153
+ if (align && TEXT_ALIGN.has(align)) {
154
+ style.textAlign = align;
155
+ }
156
+ const maxWidth = text(s.maxWidth);
157
+ if (maxWidth && MAX_WIDTH_SCALE[maxWidth]) {
158
+ style.maxWidth = MAX_WIDTH_SCALE[maxWidth];
159
+ style.marginLeft = "auto";
160
+ style.marginRight = "auto";
161
+ }
162
+ const selector = `[data-block-id="${blockId.replace(/["\\]/g, "\\$&")}"]`;
163
+ const rules = [];
164
+ const customCss = text(a.customCss);
165
+ if (customCss) {
166
+ const safe = customCss.replace(/[{}]/g, "").replace(/<\/style/gi, "");
167
+ rules.push(`${selector}{${safe}}`);
168
+ }
169
+ if (a.hideOnMobile === true) {
170
+ rules.push(
171
+ `@media (max-width:767px){${selector}{display:none !important}}`
172
+ );
173
+ }
174
+ return {
175
+ style: Object.keys(style).length > 0 ? style : void 0,
176
+ className: text(a.className),
177
+ id: text(a.anchorId),
178
+ hidden: a.visible === false,
179
+ css: rules.length > 0 ? rules.join("") : void 0
180
+ };
181
+ }
119
182
  var WARN_CAP = 256;
120
183
  var warned = /* @__PURE__ */ new Set();
121
184
  function UnknownBlock({ type }) {
@@ -129,19 +192,26 @@ function UnknownBlock({ type }) {
129
192
  function renderResolvedBlock(block, map, locale, defaultLocale, options = {}) {
130
193
  const { context, data, resolvedContent, enabledLocales } = options;
131
194
  const Component = Object.hasOwn(map, block.type) ? map[block.type] : void 0;
195
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
196
+ if (attrs.hidden) return null;
132
197
  const content = resolvedContent ?? getBlockContentForLanguage(
133
198
  block.content,
134
199
  locale,
135
200
  defaultLocale,
136
201
  enabledLocales?.length ? enabledLocales : void 0
137
202
  );
138
- return /* @__PURE__ */ jsxRuntime.jsx(
203
+ return /* @__PURE__ */ jsxRuntime.jsxs(
139
204
  "div",
140
205
  {
141
206
  "data-block-id": block.id,
142
207
  "data-block-type": block.type,
143
- style: Component ? void 0 : { display: "none" },
144
- children: Component ? react.createElement(Component, { content, context, data }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
208
+ id: attrs.id,
209
+ className: attrs.className,
210
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
211
+ children: [
212
+ attrs.css ? /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
213
+ Component ? react.createElement(Component, { content, context, data }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
214
+ ]
145
215
  },
146
216
  block.id
147
217
  );
@@ -312,8 +382,8 @@ var PUBLIC_PAGE_QUERY = `query PublicPage($workspaceSlug: String!, $slug: String
312
382
  page {
313
383
  get(workspaceSlug: $workspaceSlug, slug: $slug, previewSecret: $previewSecret) {
314
384
  id
315
- blocks { id type content }
316
- publishedBlocks { id type content }
385
+ blocks { id type content style advanced }
386
+ publishedBlocks { id type content style advanced }
317
387
  }
318
388
  }
319
389
  }
@@ -323,8 +393,8 @@ var PUBLIC_PAGE_DEV_QUERY = `query PublicPage($workspaceSlug: String!, $slug: St
323
393
  page {
324
394
  get(workspaceSlug: $workspaceSlug, slug: $slug, previewSecret: $previewSecret, devPreview: $devPreview) {
325
395
  id
326
- blocks { id type content }
327
- publishedBlocks { id type content }
396
+ blocks { id type content style advanced }
397
+ publishedBlocks { id type content style advanced }
328
398
  }
329
399
  }
330
400
  }
@@ -334,7 +404,7 @@ var PUBLIC_PAGE_BY_ID_QUERY = `query PublicPageById($workspaceSlug: String!, $pa
334
404
  page {
335
405
  getById(workspaceSlug: $workspaceSlug, pageId: $pageId) {
336
406
  id
337
- publishedBlocks { id type content }
407
+ publishedBlocks { id type content style advanced }
338
408
  }
339
409
  }
340
410
  }
@@ -369,7 +439,7 @@ var PUBLIC_PAGE_LAYOUTS_QUERY = `query PublicPageLayouts($workspaceSlug: String!
369
439
  page {
370
440
  layouts(workspaceSlug: $workspaceSlug, pageSlug: $pageSlug, previewSecret: $previewSecret) {
371
441
  position
372
- blocks { id type content order isActive }
442
+ blocks { id type content style advanced order isActive }
373
443
  }
374
444
  }
375
445
  }
@@ -888,17 +958,24 @@ function CmssyBlock({
888
958
  context
889
959
  }) {
890
960
  const Component = Object.hasOwn(blockMap, block.type) ? blockMap[block.type] : void 0;
961
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
962
+ if (attrs.hidden && !editable) return null;
891
963
  const base = getBlockContentForLanguage(block.content, locale, defaultLocale);
892
964
  const content = patchedContent ? { ...base, ...patchedContent } : base;
893
- return /* @__PURE__ */ jsxRuntime.jsx(
965
+ return /* @__PURE__ */ jsxRuntime.jsxs(
894
966
  "div",
895
967
  {
896
968
  "data-block-id": block.id,
897
969
  "data-block-type": block.type,
898
970
  "data-layout-position": layoutPosition,
899
971
  draggable: editable || void 0,
900
- style: Component ? void 0 : { display: "none" },
901
- children: Component ? react.createElement(Component, { content, context }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
972
+ id: attrs.id,
973
+ className: attrs.className,
974
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
975
+ children: [
976
+ attrs.css ? /* @__PURE__ */ jsxRuntime.jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
977
+ Component ? react.createElement(Component, { content, context }) : /* @__PURE__ */ jsxRuntime.jsx(UnknownBlock, { type: block.type })
978
+ ]
902
979
  }
903
980
  );
904
981
  }
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, n as CmssyBlockAuthContext, o as CmssyBlockWorkspace, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, p as FetchLike, q as CmssyClientConfig, r as CmssySiteConfig, R as RawBlock, e as CmssyLocaleContext, s as BlockMap, t as CmssyBlockContext } from './commerce-queries-DXT2RQlm.cjs';
2
- export { a as BlockMeta, u as BlockRect, B as BlockSchema, v as BoundsMessage, w as BuildBlockContextExtra, x as ClickMessage, y as CmssyBlockMember, z as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, D as CmssyFormField, G as CmssyFormSettings, H as CmssyFormSubmitResponse, I as CmssyLocalizedValue, J as CmssyModelDefinition, K as CmssyModelRecord, g as CmssyOrder, L as CmssyPageMeta, M as CmssyPageSummary, h as CmssyProduct, m as CmssyProductVariant, N as CmssyRecordList, O as DEFAULT_CMSSY_API_URL, P as FORM_QUERY, Q as FetchLikeResponse, S as FetchPageOptions, T as MODEL_DEFINITIONS_QUERY, U as MODEL_RECORDS_QUERY, V as PROTOCOL_VERSION, W as ParentReadyMessage, X as PatchMessage, Y as RawLayoutBlock, Z as ReadyMessage, _ as SITE_CONFIG_QUERY, $ as SUBMIT_FORM_MUTATION, a0 as SelectMessage, a1 as SubmitFormInput, a2 as blocksToMeta, a3 as blocksToSchemas, a4 as buildBlockContext, a5 as buildBlockMap, a6 as defineBlock, a7 as fetchLayouts, a8 as fetchPage, a9 as fetchPageById, aa as fetchPageMeta, ab as fetchPages, ac as isProtocolCompatible, ad as normalizeSlug, ae as resolveApiUrl } from './commerce-queries-DXT2RQlm.cjs';
1
+ import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, n as CmssyBlockAuthContext, o as CmssyBlockWorkspace, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, p as FetchLike, q as CmssyClientConfig, r as CmssySiteConfig, R as RawBlock, e as CmssyLocaleContext, s as BlockMap, t as CmssyBlockContext } from './commerce-queries-ClCU8FZN.cjs';
2
+ export { a as BlockMeta, u as BlockRect, B as BlockSchema, v as BoundsMessage, w as BuildBlockContextExtra, x as ClickMessage, y as CmssyBlockMember, z as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, D as CmssyFormField, G as CmssyFormSettings, H as CmssyFormSubmitResponse, I as CmssyLocalizedValue, J as CmssyModelDefinition, K as CmssyModelRecord, g as CmssyOrder, L as CmssyPageMeta, M as CmssyPageSummary, h as CmssyProduct, m as CmssyProductVariant, N as CmssyRecordList, O as DEFAULT_CMSSY_API_URL, P as FORM_QUERY, Q as FetchLikeResponse, S as FetchPageOptions, T as MODEL_DEFINITIONS_QUERY, U as MODEL_RECORDS_QUERY, V as PROTOCOL_VERSION, W as ParentReadyMessage, X as PatchMessage, Y as RawLayoutBlock, Z as ReadyMessage, _ as SITE_CONFIG_QUERY, $ as SUBMIT_FORM_MUTATION, a0 as SelectMessage, a1 as SubmitFormInput, a2 as blocksToMeta, a3 as blocksToSchemas, a4 as buildBlockContext, a5 as buildBlockMap, a6 as defineBlock, a7 as fetchLayouts, a8 as fetchPage, a9 as fetchPageById, aa as fetchPageMeta, ab as fetchPages, ac as isProtocolCompatible, ad as normalizeSlug, ae as resolveApiUrl } from './commerce-queries-ClCU8FZN.cjs';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  export { FieldCondition, FieldConditionGroup, FieldConditionLogic, FieldType, evaluateFieldConditionGroup } from '@cmssy/types';
5
5
  import 'react';
@@ -133,7 +133,7 @@ interface CmssyBlockProps {
133
133
  layoutPosition?: string;
134
134
  context?: CmssyBlockContext;
135
135
  }
136
- declare function CmssyBlock({ block, locale, defaultLocale, blockMap, patchedContent, editable, layoutPosition, context, }: CmssyBlockProps): react_jsx_runtime.JSX.Element;
136
+ declare function CmssyBlock({ block, locale, defaultLocale, blockMap, patchedContent, editable, layoutPosition, context, }: CmssyBlockProps): react_jsx_runtime.JSX.Element | null;
137
137
 
138
138
  interface UnknownBlockProps {
139
139
  type: string;
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, n as CmssyBlockAuthContext, o as CmssyBlockWorkspace, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, p as FetchLike, q as CmssyClientConfig, r as CmssySiteConfig, R as RawBlock, e as CmssyLocaleContext, s as BlockMap, t as CmssyBlockContext } from './commerce-queries-DXT2RQlm.js';
2
- export { a as BlockMeta, u as BlockRect, B as BlockSchema, v as BoundsMessage, w as BuildBlockContextExtra, x as ClickMessage, y as CmssyBlockMember, z as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, D as CmssyFormField, G as CmssyFormSettings, H as CmssyFormSubmitResponse, I as CmssyLocalizedValue, J as CmssyModelDefinition, K as CmssyModelRecord, g as CmssyOrder, L as CmssyPageMeta, M as CmssyPageSummary, h as CmssyProduct, m as CmssyProductVariant, N as CmssyRecordList, O as DEFAULT_CMSSY_API_URL, P as FORM_QUERY, Q as FetchLikeResponse, S as FetchPageOptions, T as MODEL_DEFINITIONS_QUERY, U as MODEL_RECORDS_QUERY, V as PROTOCOL_VERSION, W as ParentReadyMessage, X as PatchMessage, Y as RawLayoutBlock, Z as ReadyMessage, _ as SITE_CONFIG_QUERY, $ as SUBMIT_FORM_MUTATION, a0 as SelectMessage, a1 as SubmitFormInput, a2 as blocksToMeta, a3 as blocksToSchemas, a4 as buildBlockContext, a5 as buildBlockMap, a6 as defineBlock, a7 as fetchLayouts, a8 as fetchPage, a9 as fetchPageById, aa as fetchPageMeta, ab as fetchPages, ac as isProtocolCompatible, ad as normalizeSlug, ae as resolveApiUrl } from './commerce-queries-DXT2RQlm.js';
1
+ import { F as FieldDefinition, C as CmssyPageData, b as BlockDefinition, c as CmssyFormDefinition, n as CmssyBlockAuthContext, o as CmssyBlockWorkspace, d as CmssyLayoutGroup, E as EditorToAppMessage, A as AppToEditorMessage, p as FetchLike, q as CmssyClientConfig, r as CmssySiteConfig, R as RawBlock, e as CmssyLocaleContext, s as BlockMap, t as CmssyBlockContext } from './commerce-queries-ClCU8FZN.js';
2
+ export { a as BlockMeta, u as BlockRect, B as BlockSchema, v as BoundsMessage, w as BuildBlockContextExtra, x as ClickMessage, y as CmssyBlockMember, z as CmssyBranding, f as CmssyCart, i as CmssyCartDiscount, j as CmssyCartItem, k as CmssyCartItemSnapshot, D as CmssyFormField, G as CmssyFormSettings, H as CmssyFormSubmitResponse, I as CmssyLocalizedValue, J as CmssyModelDefinition, K as CmssyModelRecord, g as CmssyOrder, L as CmssyPageMeta, M as CmssyPageSummary, h as CmssyProduct, m as CmssyProductVariant, N as CmssyRecordList, O as DEFAULT_CMSSY_API_URL, P as FORM_QUERY, Q as FetchLikeResponse, S as FetchPageOptions, T as MODEL_DEFINITIONS_QUERY, U as MODEL_RECORDS_QUERY, V as PROTOCOL_VERSION, W as ParentReadyMessage, X as PatchMessage, Y as RawLayoutBlock, Z as ReadyMessage, _ as SITE_CONFIG_QUERY, $ as SUBMIT_FORM_MUTATION, a0 as SelectMessage, a1 as SubmitFormInput, a2 as blocksToMeta, a3 as blocksToSchemas, a4 as buildBlockContext, a5 as buildBlockMap, a6 as defineBlock, a7 as fetchLayouts, a8 as fetchPage, a9 as fetchPageById, aa as fetchPageMeta, ab as fetchPages, ac as isProtocolCompatible, ad as normalizeSlug, ae as resolveApiUrl } from './commerce-queries-ClCU8FZN.js';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  export { FieldCondition, FieldConditionGroup, FieldConditionLogic, FieldType, evaluateFieldConditionGroup } from '@cmssy/types';
5
5
  import 'react';
@@ -133,7 +133,7 @@ interface CmssyBlockProps {
133
133
  layoutPosition?: string;
134
134
  context?: CmssyBlockContext;
135
135
  }
136
- declare function CmssyBlock({ block, locale, defaultLocale, blockMap, patchedContent, editable, layoutPosition, context, }: CmssyBlockProps): react_jsx_runtime.JSX.Element;
136
+ declare function CmssyBlock({ block, locale, defaultLocale, blockMap, patchedContent, editable, layoutPosition, context, }: CmssyBlockProps): react_jsx_runtime.JSX.Element | null;
137
137
 
138
138
  interface UnknownBlockProps {
139
139
  type: string;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createElement } from 'react';
2
- import { jsx, Fragment } from 'react/jsx-runtime';
2
+ import { jsx, Fragment, jsxs } from 'react/jsx-runtime';
3
3
  export { evaluateFieldConditionGroup } from '@cmssy/types';
4
4
 
5
5
  // src/fields.ts
@@ -114,6 +114,69 @@ function buildBlockContext(locale, defaultLocale, enabledLocales, isPreview, for
114
114
  ...extra?.workspace ? { workspace: extra.workspace } : {}
115
115
  };
116
116
  }
117
+
118
+ // src/components/block-attrs.ts
119
+ var PADDING_SCALE = {
120
+ none: "0",
121
+ sm: "0.5rem",
122
+ md: "1rem",
123
+ lg: "2rem",
124
+ xl: "4rem"
125
+ };
126
+ var MAX_WIDTH_SCALE = {
127
+ sm: "640px",
128
+ md: "768px",
129
+ lg: "1024px",
130
+ full: "100%"
131
+ };
132
+ var TEXT_ALIGN = /* @__PURE__ */ new Set(["left", "center", "right"]);
133
+ function asRecord(value) {
134
+ return value && typeof value === "object" ? value : {};
135
+ }
136
+ function text(value) {
137
+ return typeof value === "string" && value.trim() !== "" ? value : void 0;
138
+ }
139
+ function resolveBlockAttrs(blockId, styleBucket, advancedBucket) {
140
+ const s = asRecord(styleBucket);
141
+ const a = asRecord(advancedBucket);
142
+ const style = {};
143
+ const background = text(s.background);
144
+ if (background) style.background = background;
145
+ const padding = text(s.padding);
146
+ if (padding && PADDING_SCALE[padding]) {
147
+ style.paddingTop = PADDING_SCALE[padding];
148
+ style.paddingBottom = PADDING_SCALE[padding];
149
+ }
150
+ const align = text(s.align);
151
+ if (align && TEXT_ALIGN.has(align)) {
152
+ style.textAlign = align;
153
+ }
154
+ const maxWidth = text(s.maxWidth);
155
+ if (maxWidth && MAX_WIDTH_SCALE[maxWidth]) {
156
+ style.maxWidth = MAX_WIDTH_SCALE[maxWidth];
157
+ style.marginLeft = "auto";
158
+ style.marginRight = "auto";
159
+ }
160
+ const selector = `[data-block-id="${blockId.replace(/["\\]/g, "\\$&")}"]`;
161
+ const rules = [];
162
+ const customCss = text(a.customCss);
163
+ if (customCss) {
164
+ const safe = customCss.replace(/[{}]/g, "").replace(/<\/style/gi, "");
165
+ rules.push(`${selector}{${safe}}`);
166
+ }
167
+ if (a.hideOnMobile === true) {
168
+ rules.push(
169
+ `@media (max-width:767px){${selector}{display:none !important}}`
170
+ );
171
+ }
172
+ return {
173
+ style: Object.keys(style).length > 0 ? style : void 0,
174
+ className: text(a.className),
175
+ id: text(a.anchorId),
176
+ hidden: a.visible === false,
177
+ css: rules.length > 0 ? rules.join("") : void 0
178
+ };
179
+ }
117
180
  var WARN_CAP = 256;
118
181
  var warned = /* @__PURE__ */ new Set();
119
182
  function UnknownBlock({ type }) {
@@ -127,19 +190,26 @@ function UnknownBlock({ type }) {
127
190
  function renderResolvedBlock(block, map, locale, defaultLocale, options = {}) {
128
191
  const { context, data, resolvedContent, enabledLocales } = options;
129
192
  const Component = Object.hasOwn(map, block.type) ? map[block.type] : void 0;
193
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
194
+ if (attrs.hidden) return null;
130
195
  const content = resolvedContent ?? getBlockContentForLanguage(
131
196
  block.content,
132
197
  locale,
133
198
  defaultLocale,
134
199
  enabledLocales?.length ? enabledLocales : void 0
135
200
  );
136
- return /* @__PURE__ */ jsx(
201
+ return /* @__PURE__ */ jsxs(
137
202
  "div",
138
203
  {
139
204
  "data-block-id": block.id,
140
205
  "data-block-type": block.type,
141
- style: Component ? void 0 : { display: "none" },
142
- children: Component ? createElement(Component, { content, context, data }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
206
+ id: attrs.id,
207
+ className: attrs.className,
208
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
209
+ children: [
210
+ attrs.css ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
211
+ Component ? createElement(Component, { content, context, data }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
212
+ ]
143
213
  },
144
214
  block.id
145
215
  );
@@ -310,8 +380,8 @@ var PUBLIC_PAGE_QUERY = `query PublicPage($workspaceSlug: String!, $slug: String
310
380
  page {
311
381
  get(workspaceSlug: $workspaceSlug, slug: $slug, previewSecret: $previewSecret) {
312
382
  id
313
- blocks { id type content }
314
- publishedBlocks { id type content }
383
+ blocks { id type content style advanced }
384
+ publishedBlocks { id type content style advanced }
315
385
  }
316
386
  }
317
387
  }
@@ -321,8 +391,8 @@ var PUBLIC_PAGE_DEV_QUERY = `query PublicPage($workspaceSlug: String!, $slug: St
321
391
  page {
322
392
  get(workspaceSlug: $workspaceSlug, slug: $slug, previewSecret: $previewSecret, devPreview: $devPreview) {
323
393
  id
324
- blocks { id type content }
325
- publishedBlocks { id type content }
394
+ blocks { id type content style advanced }
395
+ publishedBlocks { id type content style advanced }
326
396
  }
327
397
  }
328
398
  }
@@ -332,7 +402,7 @@ var PUBLIC_PAGE_BY_ID_QUERY = `query PublicPageById($workspaceSlug: String!, $pa
332
402
  page {
333
403
  getById(workspaceSlug: $workspaceSlug, pageId: $pageId) {
334
404
  id
335
- publishedBlocks { id type content }
405
+ publishedBlocks { id type content style advanced }
336
406
  }
337
407
  }
338
408
  }
@@ -367,7 +437,7 @@ var PUBLIC_PAGE_LAYOUTS_QUERY = `query PublicPageLayouts($workspaceSlug: String!
367
437
  page {
368
438
  layouts(workspaceSlug: $workspaceSlug, pageSlug: $pageSlug, previewSecret: $previewSecret) {
369
439
  position
370
- blocks { id type content order isActive }
440
+ blocks { id type content style advanced order isActive }
371
441
  }
372
442
  }
373
443
  }
@@ -886,17 +956,24 @@ function CmssyBlock({
886
956
  context
887
957
  }) {
888
958
  const Component = Object.hasOwn(blockMap, block.type) ? blockMap[block.type] : void 0;
959
+ const attrs = resolveBlockAttrs(block.id, block.style, block.advanced);
960
+ if (attrs.hidden && !editable) return null;
889
961
  const base = getBlockContentForLanguage(block.content, locale, defaultLocale);
890
962
  const content = patchedContent ? { ...base, ...patchedContent } : base;
891
- return /* @__PURE__ */ jsx(
963
+ return /* @__PURE__ */ jsxs(
892
964
  "div",
893
965
  {
894
966
  "data-block-id": block.id,
895
967
  "data-block-type": block.type,
896
968
  "data-layout-position": layoutPosition,
897
969
  draggable: editable || void 0,
898
- style: Component ? void 0 : { display: "none" },
899
- children: Component ? createElement(Component, { content, context }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
970
+ id: attrs.id,
971
+ className: attrs.className,
972
+ style: Component ? attrs.style : { ...attrs.style, display: "none" },
973
+ children: [
974
+ attrs.css ? /* @__PURE__ */ jsx("style", { dangerouslySetInnerHTML: { __html: attrs.css } }) : null,
975
+ Component ? createElement(Component, { content, context }) : /* @__PURE__ */ jsx(UnknownBlock, { type: block.type })
976
+ ]
900
977
  }
901
978
  );
902
979
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cmssy/react",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
4
4
  "description": "React blocks, renderers, data client and editor bridge for cmssy headless sites",
5
5
  "keywords": [
6
6
  "cmssy",