@developer_tribe/react-builder 1.2.24 → 1.2.26

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 (193) hide show
  1. package/dist/attributes-editor/AttributesEditorFields.d.ts +1 -1
  2. package/dist/attributes-editor/SpecialCategorySection.d.ts +2 -1
  3. package/dist/attributes-editor/attributesEditorModelTypes.d.ts +2 -0
  4. package/dist/build-components/BIcon/BIconProps.generated.d.ts +0 -2
  5. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +0 -2
  6. package/dist/build-components/Button/ButtonProps.generated.d.ts +0 -2
  7. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +0 -2
  8. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +0 -2
  9. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +0 -2
  10. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +0 -2
  11. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +0 -2
  12. package/dist/build-components/CountDown/CountDownProps.generated.d.ts +3 -6
  13. package/dist/build-components/Image/ImageProps.generated.d.ts +0 -2
  14. package/dist/build-components/Main/MainProps.generated.d.ts +0 -2
  15. package/dist/build-components/NavigationBarColor/NavigationBarColorProps.generated.d.ts +0 -2
  16. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +0 -2
  17. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +0 -2
  18. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +0 -2
  19. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +0 -2
  20. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +0 -2
  21. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +0 -2
  22. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +0 -2
  23. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +0 -2
  24. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +0 -2
  25. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +0 -2
  26. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +0 -2
  27. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +0 -2
  28. package/dist/build-components/PaywallOptions/PaywallOptionButton.d.ts +1 -1
  29. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +0 -2
  30. package/dist/build-components/PaywallProvider/PaywallContext.d.ts +1 -2
  31. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +0 -2
  32. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +0 -2
  33. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +0 -2
  34. package/dist/build-components/Separator/SeparatorProps.generated.d.ts +0 -2
  35. package/dist/build-components/StatusBarColor/StatusBarColorProps.generated.d.ts +0 -2
  36. package/dist/build-components/Text/TextProps.generated.d.ts +0 -2
  37. package/dist/build-components/index.d.ts +1 -3
  38. package/dist/build-components/patterns.generated.d.ts +818 -1690
  39. package/dist/index.cjs.js +3 -3
  40. package/dist/index.cjs.js.map +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.esm.js +4 -4
  43. package/dist/index.esm.js.map +1 -1
  44. package/dist/index.web.cjs.js +4 -4
  45. package/dist/index.web.cjs.js.map +1 -1
  46. package/dist/index.web.esm.js +3 -3
  47. package/dist/index.web.esm.js.map +1 -1
  48. package/dist/pages/ProjectPage.d.ts +2 -2
  49. package/dist/pages/projectPageUtils.d.ts +7 -1
  50. package/dist/paywall/hooks/index.d.ts +0 -1
  51. package/dist/styles.css +1 -1
  52. package/dist/types/Project.d.ts +6 -0
  53. package/dist/utils/index.d.ts +1 -0
  54. package/dist/utils/patterns.d.ts +2 -0
  55. package/dist/utils/projectColors.d.ts +7 -0
  56. package/package.json +3 -3
  57. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +11 -2
  58. package/src/AttributesEditor.tsx +15 -4
  59. package/src/DeviceMockFrame.tsx +0 -2
  60. package/src/RenderPage.tsx +0 -9
  61. package/src/assets/.DS_Store +0 -0
  62. package/src/assets/meta.json +1 -1
  63. package/src/assets/samples/paywall-1.json +0 -1
  64. package/src/assets/samples/paywall-2.json +2 -3
  65. package/src/assets/samples/paywall-app-delete-offer.json +2 -4
  66. package/src/assets/samples/paywall-app-open-offer.json +2 -4
  67. package/src/assets/samples/paywall-back-offer.json +2 -4
  68. package/src/assets/samples/paywall-notification-offer.json +2 -4
  69. package/src/assets/samples/simple-2.json +0 -1
  70. package/src/assets/samples/vpn-onboard-1.json +15 -15
  71. package/src/assets/samples/vpn-onboard-2.json +15 -15
  72. package/src/assets/samples/vpn-onboard-3.json +15 -15
  73. package/src/assets/samples/vpn-onboard-4.json +15 -15
  74. package/src/assets/samples/vpn-onboard-5.json +21 -21
  75. package/src/assets/samples/vpn-onboard-6.json +15 -15
  76. package/src/attributes-editor/AttributesEditorFields.tsx +0 -1
  77. package/src/attributes-editor/AttributesEditorView.tsx +43 -38
  78. package/src/attributes-editor/Field.tsx +1 -1
  79. package/src/attributes-editor/SpecialCategorySection.tsx +5 -4
  80. package/src/attributes-editor/attributesEditorModelTypes.ts +2 -0
  81. package/src/attributes-editor/useAttributesEditorModel.ts +24 -8
  82. package/src/build-components/BIcon/BIcon.tsx +1 -1
  83. package/src/build-components/BIcon/BIconProps.generated.ts +0 -2
  84. package/src/build-components/BIcon/pattern.json +2 -2
  85. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +0 -2
  86. package/src/build-components/BackgroundImage/pattern.json +2 -2
  87. package/src/build-components/Button/ButtonProps.generated.ts +0 -2
  88. package/src/build-components/Button/pattern.json +2 -2
  89. package/src/build-components/Carousel/Carousel.tsx +1 -1
  90. package/src/build-components/Carousel/CarouselProps.generated.ts +0 -2
  91. package/src/build-components/Carousel/pattern.json +3 -3
  92. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +0 -2
  93. package/src/build-components/CarouselButtons/pattern.json +2 -2
  94. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +0 -2
  95. package/src/build-components/CarouselDots/pattern.json +2 -2
  96. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +0 -2
  97. package/src/build-components/CarouselItem/pattern.json +3 -5
  98. package/src/build-components/CarouselProvider/CarouselProvider.tsx +1 -1
  99. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +0 -2
  100. package/src/build-components/CarouselProvider/pattern.json +2 -4
  101. package/src/build-components/CountDown/CountDown.tsx +25 -1
  102. package/src/build-components/CountDown/CountDownProps.generated.ts +3 -6
  103. package/src/build-components/CountDown/pattern.json +10 -2
  104. package/src/build-components/Image/ImageProps.generated.ts +0 -2
  105. package/src/build-components/Image/pattern.json +5 -3
  106. package/src/build-components/Main/MainProps.generated.ts +0 -2
  107. package/src/build-components/Main/pattern.json +2 -2
  108. package/src/build-components/NavigationBarColor/NavigationBarColorProps.generated.ts +0 -2
  109. package/src/build-components/NavigationBarColor/pattern.json +2 -2
  110. package/src/build-components/Onboard/OnboardProps.generated.ts +0 -2
  111. package/src/build-components/Onboard/pattern.json +3 -5
  112. package/src/build-components/OnboardButton/OnboardButton.tsx +1 -4
  113. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +0 -2
  114. package/src/build-components/OnboardButton/pattern.json +2 -2
  115. package/src/build-components/OnboardButtons/OnboardButtons.tsx +1 -9
  116. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +0 -2
  117. package/src/build-components/OnboardButtons/pattern.json +2 -2
  118. package/src/build-components/OnboardDot/OnboardDot.tsx +2 -1
  119. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +0 -2
  120. package/src/build-components/OnboardDot/pattern.json +2 -2
  121. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +0 -2
  122. package/src/build-components/OnboardFooter/pattern.json +2 -2
  123. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +0 -2
  124. package/src/build-components/OnboardImage/pattern.json +2 -2
  125. package/src/build-components/OnboardItem/OnboardItem.tsx +1 -1
  126. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +0 -2
  127. package/src/build-components/OnboardItem/pattern.json +2 -2
  128. package/src/build-components/OnboardProvider/OnboardProvider.tsx +0 -1
  129. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +0 -2
  130. package/src/build-components/OnboardProvider/pattern.json +2 -2
  131. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +0 -2
  132. package/src/build-components/OnboardSubtitle/pattern.json +3 -5
  133. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +0 -2
  134. package/src/build-components/OnboardTitle/pattern.json +3 -5
  135. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +0 -2
  136. package/src/build-components/PaywallBackground/pattern.json +2 -4
  137. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +0 -2
  138. package/src/build-components/PaywallCloseButton/pattern.json +3 -5
  139. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +1 -2
  140. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +0 -2
  141. package/src/build-components/PaywallOptions/pattern.json +3 -5
  142. package/src/build-components/PaywallProvider/PaywallContext.ts +1 -1
  143. package/src/build-components/PaywallProvider/PaywallProvider.tsx +0 -10
  144. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +0 -2
  145. package/src/build-components/PaywallProvider/pattern.json +2 -2
  146. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +1 -1
  147. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +0 -2
  148. package/src/build-components/PaywallSubscribeButton/pattern.json +3 -5
  149. package/src/build-components/RadioButton/RadioButton.tsx +1 -1
  150. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +0 -2
  151. package/src/build-components/RadioButton/pattern.json +2 -2
  152. package/src/build-components/RenderNode.generated.tsx +0 -10
  153. package/src/build-components/Separator/SeparatorProps.generated.ts +0 -2
  154. package/src/build-components/Separator/pattern.json +2 -2
  155. package/src/build-components/StatusBarColor/StatusBarColorProps.generated.ts +0 -2
  156. package/src/build-components/StatusBarColor/pattern.json +2 -2
  157. package/src/build-components/Text/TextProps.generated.ts +0 -2
  158. package/src/build-components/Text/pattern.json +2 -3
  159. package/src/build-components/View/pattern.json +2 -0
  160. package/src/build-components/index.ts +0 -10
  161. package/src/build-components/patterns.generated.ts +850 -1759
  162. package/src/components/AttributesEditorPanel.tsx +48 -32
  163. package/src/components/Builder.tsx +9 -1
  164. package/src/components/BuilderProvider.tsx +2 -37
  165. package/src/hooks/useSafeAreaViewStyle.ts +1 -3
  166. package/src/index.ts +1 -1
  167. package/src/mockOS/managers/navigationManager.ts +1 -1
  168. package/src/pages/ProjectPage.tsx +47 -22
  169. package/src/pages/projectPageUtils.ts +15 -1
  170. package/src/pages/tabs/SideTool.tsx +1 -22
  171. package/src/paywall/hooks/index.ts +0 -1
  172. package/src/store.ts +1 -6
  173. package/src/styles/base/_global.scss +2 -0
  174. package/src/types/Project.ts +7 -0
  175. package/src/utils/analyseNodeByPatterns.ts +4 -0
  176. package/src/utils/index.ts +1 -0
  177. package/src/utils/logRenderStore.ts +0 -1
  178. package/src/utils/novaToJson.ts +1 -5
  179. package/src/utils/parseColor.ts +1 -0
  180. package/src/utils/patterns.ts +2 -0
  181. package/src/utils/projectColors.ts +71 -0
  182. package/dist/build-components/Counter/Counter.d.ts +0 -2
  183. package/dist/build-components/Counter/CounterProps.generated.d.ts +0 -63
  184. package/dist/build-components/PaywallCounter/PaywallCounter.d.ts +0 -2
  185. package/dist/build-components/PaywallCounter/PaywallCounterProps.generated.d.ts +0 -63
  186. package/dist/paywall/hooks/useHandleGoBack.d.ts +0 -1
  187. package/src/build-components/Counter/Counter.tsx +0 -44
  188. package/src/build-components/Counter/CounterProps.generated.ts +0 -80
  189. package/src/build-components/Counter/pattern.json +0 -25
  190. package/src/build-components/PaywallCounter/PaywallCounter.tsx +0 -46
  191. package/src/build-components/PaywallCounter/PaywallCounterProps.generated.ts +0 -80
  192. package/src/build-components/PaywallCounter/pattern.json +0 -23
  193. package/src/paywall/hooks/useHandleGoBack.ts +0 -60
@@ -314,7 +314,7 @@
314
314
  "styles": {
315
315
  "width": "100%",
316
316
  "height": 2,
317
- "backgroundColor": "STATIC_COLORS.SEPARATOR_COLOR"
317
+ "backgroundColor": "STATIC_COLORS.ONBOARD_SEPARATOR_COLOR"
318
318
  }
319
319
  }
320
320
  },
@@ -337,7 +337,7 @@
337
337
  "type": "OnboardButton",
338
338
  "attributes": {
339
339
  "labelKey": "onboard.skip.one-page",
340
- "button_text_color": "THEME_COLORS.BUTTON_SECONDARY_TEXT",
340
+ "button_text_color": "THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT",
341
341
  "button_background_color": "THEME_COLORS.TEXT",
342
342
  "events": [
343
343
  {
@@ -355,8 +355,8 @@
355
355
  "type": "OnboardButton",
356
356
  "attributes": {
357
357
  "labelKey": "onboard.next.one-page",
358
- "button_text_color": "STATIC_COLORS.BUTTON_PRIMARY_TEXT",
359
- "button_background_color": "STATIC_COLORS.BUTTON_PRIMARY_BACKGROUND",
358
+ "button_text_color": "STATIC_COLORS.WHITE",
359
+ "button_background_color": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
360
360
  "events": [
361
361
  {
362
362
  "type": "Navigate",
@@ -390,7 +390,7 @@
390
390
  "type": "OnboardButton",
391
391
  "attributes": {
392
392
  "labelKey": "onboard.skip.two-page",
393
- "button_text_color": "THEME_COLORS.BUTTON_SECONDARY_TEXT",
393
+ "button_text_color": "THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT",
394
394
  "button_background_color": "THEME_COLORS.TEXT",
395
395
  "events": [
396
396
  {
@@ -408,8 +408,8 @@
408
408
  "type": "OnboardButton",
409
409
  "attributes": {
410
410
  "labelKey": "onboard.next.two-page",
411
- "button_text_color": "STATIC_COLORS.BUTTON_PRIMARY_TEXT",
412
- "button_background_color": "STATIC_COLORS.BUTTON_PRIMARY_BACKGROUND",
411
+ "button_text_color": "STATIC_COLORS.WHITE",
412
+ "button_background_color": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
413
413
  "events": [
414
414
  {
415
415
  "type": "Navigate",
@@ -443,7 +443,7 @@
443
443
  "type": "OnboardButton",
444
444
  "attributes": {
445
445
  "labelKey": "onboard.skip.three-page",
446
- "button_text_color": "THEME_COLORS.BUTTON_SECONDARY_TEXT",
446
+ "button_text_color": "THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT",
447
447
  "button_background_color": "THEME_COLORS.TEXT",
448
448
  "events": [
449
449
  {
@@ -461,8 +461,8 @@
461
461
  "type": "OnboardButton",
462
462
  "attributes": {
463
463
  "labelKey": "onboard.next.three-page",
464
- "button_text_color": "STATIC_COLORS.BUTTON_PRIMARY_TEXT",
465
- "button_background_color": "STATIC_COLORS.BUTTON_PRIMARY_BACKGROUND",
464
+ "button_text_color": "STATIC_COLORS.WHITE",
465
+ "button_background_color": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
466
466
  "events": [
467
467
  {
468
468
  "type": "Permission",
@@ -500,8 +500,8 @@
500
500
  "type": "OnboardButton",
501
501
  "attributes": {
502
502
  "labelKey": "onboard.allow.four-page",
503
- "button_text_color": "STATIC_COLORS.BUTTON_PRIMARY_TEXT",
504
- "button_background_color": "STATIC_COLORS.BUTTON_PRIMARY_BACKGROUND",
503
+ "button_text_color": "STATIC_COLORS.WHITE",
504
+ "button_background_color": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
505
505
  "events": [
506
506
  {
507
507
  "type": "Permission",
@@ -535,14 +535,14 @@
535
535
  "attributes": {
536
536
  "textLocalizationKey": "view.onboarding.footer.description",
537
537
  "linkedWordFirstLocalizationKey": "view.onboarding.btnPrivacy",
538
- "linkedWordFirstColor": "STATIC_COLORS.LINK_COLOR",
538
+ "linkedWordFirstColor": "STATIC_COLORS.ONBOARD_LINK_COLOR",
539
539
  "linkedWordFirstPage": "privacy",
540
540
  "linkedWordSecondLocalizationKey": "view.onboarding.btnTerms",
541
- "linkedWordSecondColor": "STATIC_COLORS.LINK_COLOR",
541
+ "linkedWordSecondColor": "STATIC_COLORS.ONBOARD_LINK_COLOR",
542
542
  "linkedWordSecondPage": "terms",
543
543
  "styles": {
544
544
  "gap": 8,
545
- "color": "THEME_COLORS.FOOTER_TEXT"
545
+ "color": "THEME_COLORS.ONBOARD_FOOTER_TEXT"
546
546
  }
547
547
  }
548
548
  }
@@ -14,7 +14,6 @@ type IconTypePickerFieldProps = {
14
14
  };
15
15
 
16
16
  export function IconTypePickerField({
17
- name,
18
17
  value,
19
18
  onChange,
20
19
  }: IconTypePickerFieldProps) {
@@ -13,7 +13,6 @@ import type {
13
13
  AttributesEditorModel,
14
14
  AttributesEditorSpecialSection,
15
15
  } from './attributesEditorModelTypes';
16
- import type { NodeDefaultAttribute } from '../types/Node';
17
16
 
18
17
  type AttributesEditorViewProps = AttributesEditorModel;
19
18
 
@@ -63,6 +62,8 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
63
62
  firstAvailableTab,
64
63
  activeEntries,
65
64
  activeSpecialSections,
65
+ hasTitleField,
66
+ hasDescriptionField,
66
67
  hasStringChildren,
67
68
  childrenValue,
68
69
  handleChildrenChange,
@@ -73,7 +74,6 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
73
74
  projectColorsForPicker,
74
75
  layoutContext,
75
76
  viewAttributes,
76
- styleBag,
77
77
  attributes,
78
78
  projectFonts,
79
79
  loadedFonts,
@@ -94,37 +94,46 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
94
94
 
95
95
  const titleValue = getAttributeValue('title');
96
96
  const descriptionValue = getAttributeValue('description');
97
- const topFieldsSection = !isInvalidNode ? (
97
+ const showTopFields =
98
+ !isInvalidNode && (hasTitleField || hasDescriptionField);
99
+ const topFieldsSection = showTopFields ? (
98
100
  <section className="attributes-editor__top-fields">
99
- <div className="attributes-editor__field-wrapper">
100
- <label className="attributes-editor__field-label" htmlFor="title">
101
- Title (max 20 characters for display purposes)
102
- </label>
103
- <input
104
- id="title"
105
- className="input"
106
- type="text"
107
- maxLength={20}
108
- value={typeof titleValue === 'string' ? titleValue : ''}
109
- onChange={(event) =>
110
- handleAttributeChange('title', event.target.value)
111
- }
112
- />
113
- </div>
114
- <div className="attributes-editor__field-wrapper">
115
- <label className="attributes-editor__field-label" htmlFor="description">
116
- Description (for display purposes)
117
- </label>
118
- <input
119
- id="description"
120
- className="input"
121
- type="text"
122
- value={typeof descriptionValue === 'string' ? descriptionValue : ''}
123
- onChange={(event) =>
124
- handleAttributeChange('description', event.target.value)
125
- }
126
- />
127
- </div>
101
+ {hasTitleField ? (
102
+ <div className="attributes-editor__field-wrapper">
103
+ <label className="attributes-editor__field-label" htmlFor="title">
104
+ Title (max 20 characters for display purposes)
105
+ </label>
106
+ <input
107
+ id="title"
108
+ className="input"
109
+ type="text"
110
+ maxLength={20}
111
+ value={typeof titleValue === 'string' ? titleValue : ''}
112
+ onChange={(event) =>
113
+ handleAttributeChange('title', event.target.value)
114
+ }
115
+ />
116
+ </div>
117
+ ) : null}
118
+ {hasDescriptionField ? (
119
+ <div className="attributes-editor__field-wrapper">
120
+ <label
121
+ className="attributes-editor__field-label"
122
+ htmlFor="description"
123
+ >
124
+ Description (for display purposes)
125
+ </label>
126
+ <input
127
+ id="description"
128
+ className="input"
129
+ type="text"
130
+ value={typeof descriptionValue === 'string' ? descriptionValue : ''}
131
+ onChange={(event) =>
132
+ handleAttributeChange('description', event.target.value)
133
+ }
134
+ />
135
+ </div>
136
+ ) : null}
128
137
  </section>
129
138
  ) : null;
130
139
 
@@ -346,18 +355,14 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
346
355
  );
347
356
  }
348
357
 
349
- const sectionAttributes =
350
- section.meta?.category === 'style'
351
- ? ((styleBag ?? {}) as unknown as NodeDefaultAttribute)
352
- : attributes;
353
-
354
358
  return (
355
359
  <SpecialCategorySection
356
360
  key={section.key}
357
361
  category={section.key}
358
362
  entries={section.entries}
359
363
  attributeMeta={attributeMeta}
360
- attributes={sectionAttributes}
364
+ attributes={attributes}
365
+ getAttributeValue={getAttributeValue}
361
366
  onAttributeChange={handleAttributeChange}
362
367
  componentType={data?.type}
363
368
  projectColors={projectColorsForPicker}
@@ -1,4 +1,4 @@
1
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
1
+ import React, { useMemo, useState } from 'react';
2
2
  import type { ViewPropsGenerated } from '../build-components/View/ViewProps.generated';
3
3
  import { ColorModal, resolveProjectColorValue } from '../modals/ColorModal';
4
4
  import type { ProjectColors } from '../types/Project';
@@ -16,6 +16,7 @@ type SpecialCategorySectionProps = {
16
16
  entries: SchemaEntry[];
17
17
  attributeMeta?: AttributeMetaMap;
18
18
  attributes: NodeDefaultAttribute;
19
+ getAttributeValue: (name: string) => unknown;
19
20
  onAttributeChange: (name: string, value: unknown) => void;
20
21
  componentType?: string;
21
22
  projectColors?: ProjectColors;
@@ -40,7 +41,7 @@ export function SpecialCategorySection({
40
41
  category,
41
42
  entries,
42
43
  attributeMeta,
43
- attributes,
44
+ getAttributeValue,
44
45
  onAttributeChange,
45
46
  componentType,
46
47
  projectColors,
@@ -96,7 +97,7 @@ export function SpecialCategorySection({
96
97
  const preferredScale = toPreferredScale(
97
98
  attributeMeta?.[name]?.preferedScale,
98
99
  );
99
- const currentValue = (attributes as Record<string, unknown>)[name];
100
+ const currentValue = getAttributeValue(name);
100
101
  const isBoolean = isBooleanFieldType(type);
101
102
  const fieldSlot = detectFieldSlot(name);
102
103
  const wrapperClassNames = [
@@ -175,7 +176,7 @@ export function SpecialCategorySection({
175
176
  const preferredScale = toPreferredScale(
176
177
  attributeMeta?.[name]?.preferedScale,
177
178
  );
178
- const currentValue = (attributes as Record<string, unknown>)[name];
179
+ const currentValue = getAttributeValue(name);
179
180
  const isBoolean = isBooleanFieldType(type);
180
181
  const fieldSlot = detectFieldSlot(name);
181
182
  const wrapperClassNames = [
@@ -220,7 +221,7 @@ export function SpecialCategorySection({
220
221
  const preferredScale = toPreferredScale(
221
222
  attributeMeta?.[name]?.preferedScale,
222
223
  );
223
- const currentValue = (attributes as Record<string, unknown>)[name];
224
+ const currentValue = getAttributeValue(name);
224
225
  const isBoolean = isBooleanFieldType(type);
225
226
  const wrapperClassNames = [
226
227
  'attributes-editor__field-wrapper',
@@ -81,6 +81,8 @@ export type AttributesEditorModel = {
81
81
  mockableFeatureKeys: string[];
82
82
  activeMockableFeature: string | null;
83
83
  setActiveMockableFeature: (next: string | null) => void;
84
+ hasTitleField: boolean;
85
+ hasDescriptionField: boolean;
84
86
  hasStringChildren: boolean;
85
87
  childrenValue: string;
86
88
  };
@@ -83,9 +83,14 @@ export function useAttributesEditorModel({
83
83
  projectColors,
84
84
  }: AttributesEditorProps): AttributesEditorModel {
85
85
  const isInvalidNode = !node || isNodeString(node);
86
- const baseData: NodeData<NodeDefaultAttribute> = isInvalidNode
87
- ? { type: 'View', children: null, attributes: {} }
88
- : (node as NodeData<NodeDefaultAttribute>);
86
+ // Memoize baseData to prevent it from changing on every render
87
+ const baseData = useMemo<NodeData<NodeDefaultAttribute>>(
88
+ () =>
89
+ isInvalidNode
90
+ ? { type: 'View', children: null, attributes: {} }
91
+ : (node as NodeData<NodeDefaultAttribute>),
92
+ [isInvalidNode, node],
93
+ );
89
94
 
90
95
  const data = useNode(baseData);
91
96
  const {
@@ -102,12 +107,17 @@ export function useAttributesEditorModel({
102
107
  addError: state.addError,
103
108
  }));
104
109
 
105
- const schema = (getAttributeSchema(data?.type) ?? {}) as Record<
106
- string,
107
- unknown
108
- >;
110
+ // Memoize schema to prevent it from changing on every render
111
+ const schema = useMemo(
112
+ () => (getAttributeSchema(data?.type) ?? {}) as Record<string, unknown>,
113
+ [data?.type],
114
+ );
109
115
  const attributeMeta = getAttributeMeta(data?.type);
110
- const attributes = (data?.attributes ?? {}) as NodeDefaultAttribute;
116
+ // Memoize attributes to prevent it from changing on every render
117
+ const attributes = useMemo(
118
+ () => (data?.attributes ?? {}) as NodeDefaultAttribute,
119
+ [data?.attributes],
120
+ );
111
121
 
112
122
  const styleAttributeKeys = useMemo(() => getStyleAttributeKeySet(), []);
113
123
  const styleBagInfo = useMemo(
@@ -217,6 +227,10 @@ export function useAttributesEditorModel({
217
227
  const componentTitle = componentMeta?.label ?? data?.type ?? 'Component';
218
228
  const componentDescription = componentMeta?.description;
219
229
 
230
+ const hasTitleField = patternForType?.pattern?.title === 'title';
231
+ const hasDescriptionField =
232
+ patternForType?.pattern?.description === 'description';
233
+
220
234
  const entries = useMemo(() => {
221
235
  return buildAttributesEditorEntries(schema, attributeMeta).filter(
222
236
  ({ type }) => (typeof type === 'string' ? type !== 'never' : true),
@@ -477,6 +491,8 @@ export function useAttributesEditorModel({
477
491
  mockableFeatureKeys,
478
492
  activeMockableFeature,
479
493
  setActiveMockableFeature,
494
+ hasTitleField,
495
+ hasDescriptionField,
480
496
  hasStringChildren,
481
497
  childrenValue,
482
498
  };
@@ -1,4 +1,4 @@
1
- import React, { useId, useMemo } from 'react';
1
+ import React, { useId } from 'react';
2
2
  import type { BIconComponentProps } from './BIconProps.generated';
3
3
  import useNode from '../useNode';
4
4
  import { useBuilderParams } from '../../components/BuilderProvider';
@@ -66,8 +66,6 @@ export interface BIconPropsGenerated {
66
66
  child: string;
67
67
  attributes: {
68
68
  style?: BIconStyleGenerated;
69
- title?: string;
70
- description?: string;
71
69
  adjustsFontSizeToFit?: boolean;
72
70
  showEllipsis?: boolean;
73
71
  scrollable?: boolean;
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "BIcon",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "never",
6
8
  "extends": "Text",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "iconType": "iconType",
11
11
  "size": "number",
12
12
  "strokeWidth": "number"
@@ -62,8 +62,6 @@ export interface BackgroundImagePropsGenerated {
62
62
  attributes: {
63
63
  style?: BackgroundImageStyleGenerated;
64
64
  scrollable?: boolean;
65
- title?: string;
66
- description?: string;
67
65
  src?: string;
68
66
  resizeMode?: ResizeModeOptionType;
69
67
  };
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "BackgroundImage",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "never",
6
8
  "extends": "View",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "src": "string",
11
11
  "resizeMode": ["cover", "contain", "stretch", "center"]
12
12
  },
@@ -76,8 +76,6 @@ export interface ButtonPropsGenerated {
76
76
  attributes: {
77
77
  style?: ButtonStyleGenerated;
78
78
  scrollable?: boolean;
79
- title?: string;
80
- description?: string;
81
79
  };
82
80
  }
83
81
 
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "Button",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "string",
6
8
  "extends": "View",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "style": {
11
11
  "color": "color",
12
12
  "fontSize": "size",
@@ -1,4 +1,4 @@
1
- import React, { useId, useMemo } from 'react';
1
+ import React, { useId } from 'react';
2
2
  import type { CarouselComponentProps } from './CarouselProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import { isCarouselItem } from '../../utils/isCarousel';
@@ -62,8 +62,6 @@ export interface CarouselPropsGenerated {
62
62
  attributes: {
63
63
  style?: CarouselStyleGenerated;
64
64
  scrollable?: boolean;
65
- title?: string;
66
- description?: string;
67
65
  loop?: boolean;
68
66
  dragFree?: boolean;
69
67
  align?: AlignOptionType;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
- "extends": "View",
5
4
  "type": "Carousel",
5
+ "title": "title",
6
+ "description": "description",
7
+ "extends": "View",
6
8
  "children": "node",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "loop": "boolean",
11
11
  "dragFree": "boolean",
12
12
  "align": ["start", "center", "end"]
@@ -65,8 +65,6 @@ export interface CarouselButtonsPropsGenerated {
65
65
  attributes: {
66
66
  style?: CarouselButtonsStyleGenerated;
67
67
  scrollable?: boolean;
68
- title?: string;
69
- description?: string;
70
68
  buttonType?: ButtonTypeOptionType;
71
69
  skipNumber?: number;
72
70
  };
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "CarouselButtons",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "never",
6
8
  "extends": "View",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "buttonType": ["previous_button", "next_button", "skip_button"],
11
11
  "skipNumber": "number"
12
12
  }
@@ -68,8 +68,6 @@ export interface CarouselDotsPropsGenerated {
68
68
  attributes: {
69
69
  style?: CarouselDotsStyleGenerated;
70
70
  scrollable?: boolean;
71
- title?: string;
72
- description?: string;
73
71
  dotType?: DotTypeOptionType;
74
72
  };
75
73
  }
@@ -2,11 +2,11 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "CarouselDots",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "never",
6
8
  "extends": "View",
7
9
  "attributes": {
8
- "title": "title",
9
- "description": "description",
10
10
  "dotType": [
11
11
  "expanding_dot",
12
12
  "normal_dot",
@@ -61,8 +61,6 @@ export interface CarouselItemPropsGenerated {
61
61
  attributes: {
62
62
  style?: CarouselItemStyleGenerated;
63
63
  scrollable?: boolean;
64
- title?: string;
65
- description?: string;
66
64
  };
67
65
  }
68
66
 
@@ -2,12 +2,10 @@
2
2
  "schemaVersion": 2,
3
3
  "pattern": {
4
4
  "type": "CarouselItem",
5
+ "title": "title",
6
+ "description": "description",
5
7
  "children": "node",
6
- "extends": "View",
7
- "attributes": {
8
- "title": "title",
9
- "description": "description"
10
- }
8
+ "extends": "View"
11
9
  },
12
10
  "meta": {
13
11
  "desiredParent": ["=Carousel"],
@@ -1,4 +1,4 @@
1
- import React, { createContext, useId, useMemo } from 'react';
1
+ import React, { createContext, useId } from 'react';
2
2
  import type { CarouselProviderComponentProps } from './CarouselProviderProps.generated';
3
3
  import RenderNode from '../RenderNode.generated';
4
4
  import useEmblaCarousel from 'embla-carousel-react';
@@ -61,8 +61,6 @@ export interface CarouselProviderPropsGenerated {
61
61
  attributes: {
62
62
  style?: CarouselProviderStyleGenerated;
63
63
  scrollable?: boolean;
64
- title?: string;
65
- description?: string;
66
64
  };
67
65
  }
68
66
 
@@ -3,12 +3,10 @@
3
3
  "allowUnknownAttributes": false,
4
4
  "pattern": {
5
5
  "type": "CarouselProvider",
6
+ "title": "title",
7
+ "description": "description",
6
8
  "children": "node",
7
9
  "extends": "View",
8
- "attributes": {
9
- "title": "title",
10
- "description": "description"
11
- },
12
10
  "defaults": {
13
11
  "style": {
14
12
  "width": "100%",
@@ -69,11 +69,35 @@ export function CountDown({ node }: CountDownComponentProps) {
69
69
  };
70
70
  }, [delayMs]);
71
71
 
72
+ const fontSize =
73
+ typeof style?.fontSize === 'number'
74
+ ? style.fontSize
75
+ : typeof style?.fontSize === 'string'
76
+ ? parseFloat(style.fontSize)
77
+ : 16;
78
+
79
+ const letterSpacing =
80
+ typeof style?.letterSpacing === 'number'
81
+ ? style.letterSpacing
82
+ : typeof style?.letterSpacing === 'string'
83
+ ? parseFloat(style.letterSpacing)
84
+ : 0;
85
+
86
+ // "00:00" format needs ~5 characters width
87
+ const charCount = 5;
88
+ const width = fontSize * charCount * 0.6 + letterSpacing * (charCount - 1);
89
+
72
90
  return (
73
91
  <p
74
92
  attribute-name={attributeName}
75
93
  attribute-key={attributeKey}
76
- style={style}
94
+ style={{
95
+ ...style,
96
+ width,
97
+ textAlign: 'left',
98
+ alignItems: 'left',
99
+ alignSelf: 'center',
100
+ }}
77
101
  >
78
102
  {time}
79
103
  </p>
@@ -2,7 +2,6 @@
2
2
 
3
3
  import type { NodeData } from '../../types/Node';
4
4
 
5
- export type TextAlignOptionType = 'left' | 'center' | 'right' | 'justify';
6
5
  export type FlexDirectionOptionType = 'row' | 'column';
7
6
  export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
8
7
  export type AlignItemsOptionType =
@@ -25,7 +24,7 @@ export interface CountDownStyleGenerated {
25
24
  fontSize?: string;
26
25
  fontFamily?: string;
27
26
  fontWeight?: string;
28
- textAlign?: TextAlignOptionType;
27
+ textAlign?: never;
29
28
  flexDirection?: FlexDirectionOptionType;
30
29
  flexWrap?: FlexWrapOptionType;
31
30
  alignItems?: AlignItemsOptionType;
@@ -47,7 +46,7 @@ export interface CountDownStyleGenerated {
47
46
  marginRight?: string;
48
47
  backgroundColor?: string;
49
48
  borderRadius?: string;
50
- width?: string;
49
+ width?: never;
51
50
  minWidth?: string;
52
51
  maxWidth?: string;
53
52
  height?: string;
@@ -66,12 +65,10 @@ export interface CountDownPropsGenerated {
66
65
  child: string;
67
66
  attributes: {
68
67
  style?: CountDownStyleGenerated;
69
- count?: number;
70
- title?: string;
71
- description?: string;
72
68
  adjustsFontSizeToFit?: boolean;
73
69
  showEllipsis?: boolean;
74
70
  scrollable?: boolean;
71
+ count?: number;
75
72
  };
76
73
  }
77
74