@webikon/webentor-core 0.9.13 → 0.10.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.
Files changed (126) hide show
  1. package/CHANGELOG.md +24 -1
  2. package/README.md +41 -0
  3. package/core-js/_alpine.ts +6 -0
  4. package/core-js/_slider.ts +22 -11
  5. package/core-js/blocks-components/button.tsx +50 -33
  6. package/core-js/blocks-components/custom-image-sizes-panel.tsx +3 -1
  7. package/core-js/blocks-components/typography-picker-select.tsx +16 -1
  8. package/core-js/blocks-filters/_filter-core-typography.tsx +11 -1
  9. package/core-js/blocks-filters/_slider-settings.tsx +1 -1
  10. package/core-js/blocks-filters/_wrap-with-container.tsx +104 -0
  11. package/core-js/blocks-filters/responsive-settings/AGENTS.md +255 -0
  12. package/core-js/blocks-filters/responsive-settings/components/AppliedClassesViewer.tsx +189 -0
  13. package/core-js/blocks-filters/responsive-settings/components/BoxModelControl.tsx +346 -0
  14. package/core-js/blocks-filters/responsive-settings/components/BreakpointResetButton.tsx +94 -0
  15. package/core-js/blocks-filters/responsive-settings/components/DebugPanel.tsx +67 -0
  16. package/core-js/blocks-filters/responsive-settings/components/InheritedIndicator.tsx +32 -0
  17. package/core-js/blocks-filters/responsive-settings/components/LinkedValuesControl.tsx +55 -0
  18. package/core-js/blocks-filters/responsive-settings/components/ResponsiveSelectGroup.tsx +185 -0
  19. package/core-js/blocks-filters/responsive-settings/components/ResponsiveTabPanel.tsx +106 -0
  20. package/core-js/blocks-filters/responsive-settings/index.tsx +97 -148
  21. package/core-js/blocks-filters/responsive-settings/migration.ts +86 -0
  22. package/core-js/blocks-filters/responsive-settings/panels/BlockLinkPanel.tsx +38 -0
  23. package/core-js/blocks-filters/responsive-settings/panels/BorderPanel.tsx +61 -0
  24. package/core-js/blocks-filters/responsive-settings/panels/DisplayLayoutPanel.tsx +92 -0
  25. package/core-js/blocks-filters/responsive-settings/panels/SpacingPanel.tsx +63 -0
  26. package/core-js/blocks-filters/responsive-settings/panels/index.ts +4 -0
  27. package/core-js/blocks-filters/responsive-settings/registry.ts +88 -0
  28. package/core-js/blocks-filters/responsive-settings/settings/block-link/index.ts +3 -0
  29. package/core-js/blocks-filters/responsive-settings/settings/block-link/panel.tsx +6 -6
  30. package/core-js/blocks-filters/responsive-settings/settings/block-link/registration.ts +35 -0
  31. package/core-js/blocks-filters/responsive-settings/settings/border/border/properties.ts +1 -2
  32. package/core-js/blocks-filters/responsive-settings/settings/border/border/settings.tsx +21 -3
  33. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/index.tsx +2 -1
  34. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/properties.ts +6 -29
  35. package/core-js/blocks-filters/responsive-settings/settings/border/border-radius/settings.tsx +79 -6
  36. package/core-js/blocks-filters/responsive-settings/settings/border/index.ts +5 -1
  37. package/core-js/blocks-filters/responsive-settings/settings/border/panel.tsx +5 -54
  38. package/core-js/blocks-filters/responsive-settings/settings/border/registration.ts +84 -0
  39. package/core-js/blocks-filters/responsive-settings/settings/border/settings.tsx +21 -0
  40. package/core-js/blocks-filters/responsive-settings/settings/flex-item/index.ts +4 -0
  41. package/core-js/blocks-filters/responsive-settings/settings/flex-item/properties.ts +60 -0
  42. package/core-js/blocks-filters/responsive-settings/settings/flex-item/registration.ts +78 -0
  43. package/core-js/blocks-filters/responsive-settings/settings/flex-item/settings.tsx +90 -0
  44. package/core-js/blocks-filters/responsive-settings/settings/flexbox/index.ts +4 -0
  45. package/core-js/blocks-filters/responsive-settings/settings/flexbox/properties.ts +80 -0
  46. package/core-js/blocks-filters/responsive-settings/settings/flexbox/registration.ts +66 -0
  47. package/core-js/blocks-filters/responsive-settings/settings/flexbox/settings.tsx +78 -0
  48. package/core-js/blocks-filters/responsive-settings/settings/grid/index.ts +4 -0
  49. package/core-js/blocks-filters/responsive-settings/settings/grid/properties.ts +72 -0
  50. package/core-js/blocks-filters/responsive-settings/settings/grid/registration.ts +66 -0
  51. package/core-js/blocks-filters/responsive-settings/settings/grid/settings.tsx +78 -0
  52. package/core-js/blocks-filters/responsive-settings/settings/grid-item/index.ts +4 -0
  53. package/core-js/blocks-filters/responsive-settings/settings/grid-item/properties.ts +44 -0
  54. package/core-js/blocks-filters/responsive-settings/settings/grid-item/registration.ts +74 -0
  55. package/core-js/blocks-filters/responsive-settings/settings/grid-item/settings.tsx +87 -0
  56. package/core-js/blocks-filters/responsive-settings/settings/layout/index.ts +4 -0
  57. package/core-js/blocks-filters/responsive-settings/settings/layout/properties.ts +51 -0
  58. package/core-js/blocks-filters/responsive-settings/settings/layout/registration.ts +96 -0
  59. package/core-js/blocks-filters/responsive-settings/settings/layout/settings.tsx +64 -0
  60. package/core-js/blocks-filters/responsive-settings/settings/presets/index.ts +4 -0
  61. package/core-js/blocks-filters/responsive-settings/settings/presets/presets.ts +52 -0
  62. package/core-js/blocks-filters/responsive-settings/settings/presets/registration.ts +53 -0
  63. package/core-js/blocks-filters/responsive-settings/settings/presets/settings.tsx +100 -0
  64. package/core-js/blocks-filters/responsive-settings/settings/shared/gap-values.ts +16 -0
  65. package/core-js/blocks-filters/responsive-settings/settings/shared/layout-values.ts +56 -0
  66. package/core-js/blocks-filters/responsive-settings/settings/shared/tw-values.ts +107 -0
  67. package/core-js/blocks-filters/responsive-settings/settings/sizing/index.ts +4 -0
  68. package/core-js/blocks-filters/responsive-settings/settings/sizing/properties.ts +71 -0
  69. package/core-js/blocks-filters/responsive-settings/settings/sizing/registration.ts +52 -0
  70. package/core-js/blocks-filters/responsive-settings/settings/sizing/settings.tsx +96 -0
  71. package/core-js/blocks-filters/responsive-settings/settings/spacing/index.ts +7 -2
  72. package/core-js/blocks-filters/responsive-settings/settings/spacing/panel.tsx +5 -45
  73. package/core-js/blocks-filters/responsive-settings/settings/spacing/properties.ts +51 -29
  74. package/core-js/blocks-filters/responsive-settings/settings/spacing/registration.ts +53 -0
  75. package/core-js/blocks-filters/responsive-settings/settings/spacing/settings.tsx +26 -55
  76. package/core-js/blocks-filters/responsive-settings/types/index.ts +174 -28
  77. package/core-js/blocks-filters/responsive-settings/utils.ts +247 -216
  78. package/core-js/config/index.ts +6 -0
  79. package/core-js/config/webentor-config.ts +44 -2
  80. package/core-js/index.ts +8 -10
  81. package/core-js/types/index.ts +6 -0
  82. package/package.json +116 -6
  83. package/public/build/assets/_utils-CzK6Vfiv.js +2 -0
  84. package/public/build/assets/{_utils-PDaZ1Dn1.js.map → _utils-CzK6Vfiv.js.map} +1 -1
  85. package/public/build/assets/coreAppStyles-Bvp3emQy.css +1 -0
  86. package/public/build/assets/coreEditorJs-DYd3ZopL.js +366 -0
  87. package/public/build/assets/coreEditorJs-DYd3ZopL.js.map +1 -0
  88. package/public/build/assets/coreEditorStyles-BzlB6eA_.css +1 -0
  89. package/public/build/assets/resources/blocks/e-table/{script-BIchbcPK.js → script-C_Z50hjm.js} +2 -2
  90. package/public/build/assets/resources/blocks/e-table/{script-BIchbcPK.js.map → script-C_Z50hjm.js.map} +1 -1
  91. package/public/build/assets/{sliderJs-Ch69_tVA.js → sliderJs-CyGnrv0Q.js} +3 -3
  92. package/public/build/assets/{sliderJs-Ch69_tVA.js.map → sliderJs-CyGnrv0Q.js.map} +1 -1
  93. package/public/build/manifest.json +10 -10
  94. package/resources/blocks/e-accordion-group/block.json +6 -4
  95. package/resources/blocks/e-gallery/block.json +2 -2
  96. package/resources/blocks/e-gallery/e-gallery.block.tsx +4 -0
  97. package/resources/blocks/e-image/e-image.block.tsx +4 -0
  98. package/resources/blocks/e-slider/block.json +3 -2
  99. package/resources/blocks/e-tab-container/block.json +2 -1
  100. package/resources/blocks/e-tabs/block.json +2 -1
  101. package/resources/blocks/l-flexible-container/block.json +3 -2
  102. package/resources/blocks/l-mobile-nav/block.json +2 -1
  103. package/resources/blocks/l-nav-menu/block.json +2 -1
  104. package/resources/blocks/l-nav-menu/l-nav-menu.block.tsx +2 -0
  105. package/resources/blocks/l-section/block.json +7 -5
  106. package/resources/blocks/l-section/l-section.block.tsx +40 -31
  107. package/resources/scripts/editor.ts +2 -0
  108. package/resources/styles/common/_editor.css +22 -0
  109. package/resources/styles/common/_utilities.css +210 -0
  110. package/core-js/blocks-filters/responsive-settings/constants.ts +0 -11
  111. package/core-js/blocks-filters/responsive-settings/settings/container/display/index.ts +0 -2
  112. package/core-js/blocks-filters/responsive-settings/settings/container/display/properties.ts +0 -167
  113. package/core-js/blocks-filters/responsive-settings/settings/container/display/settings.tsx +0 -73
  114. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/index.ts +0 -2
  115. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/properties.ts +0 -187
  116. package/core-js/blocks-filters/responsive-settings/settings/container/flexbox/settings.tsx +0 -131
  117. package/core-js/blocks-filters/responsive-settings/settings/container/grid/index.ts +0 -2
  118. package/core-js/blocks-filters/responsive-settings/settings/container/grid/properties.ts +0 -187
  119. package/core-js/blocks-filters/responsive-settings/settings/container/grid/settings.tsx +0 -132
  120. package/core-js/blocks-filters/responsive-settings/settings/container/index.ts +0 -4
  121. package/core-js/blocks-filters/responsive-settings/settings/container/panel.tsx +0 -92
  122. package/public/build/assets/_utils-PDaZ1Dn1.js +0 -2
  123. package/public/build/assets/coreAppStyles-Dp0WYk4N.css +0 -1
  124. package/public/build/assets/coreEditorJs-Cyc87wTo.js +0 -366
  125. package/public/build/assets/coreEditorJs-Cyc87wTo.js.map +0 -1
  126. package/public/build/assets/coreEditorStyles-D8-nNpQG.css +0 -1
@@ -1,24 +1,15 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
 
3
- import { WebentorConfig } from '@webentorCore/types/_webentor-config';
3
+ import { WebentorConfig } from '../../../../types/_webentor-config';
4
+ import { createTwThemeValues, spacingLabel } from '../shared/tw-values';
4
5
 
5
- const getSpacingValues = (property = '', twTheme: WebentorConfig['theme']) => {
6
- const values = Object.keys(twTheme?.spacing)
7
- .sort((a, b) => Number(a) - Number(b))
8
- .map((key) => ({
9
- label: `${Number(key) * 4}px`,
10
- value: `${property}-${key}`,
11
- }));
12
-
13
- values.unshift({
14
- label: __('None selected', 'webentor'),
15
- value: '',
6
+ const getSpacingValues = (property: string, twTheme: WebentorConfig['theme']) =>
7
+ createTwThemeValues(twTheme, 'spacing', property, {
8
+ labelFormatter: spacingLabel,
16
9
  });
17
10
 
18
- return values;
19
- };
20
-
21
- export const getSpacingProperties = (twTheme: WebentorConfig['theme']) => [
11
+ /** Margin sides for BoxModelControl (includes Auto option) */
12
+ export const getMarginSides = (twTheme: WebentorConfig['theme']) => [
22
13
  {
23
14
  label: __('Margin Top', 'webentor'),
24
15
  name: 'margin-top',
@@ -27,14 +18,6 @@ export const getSpacingProperties = (twTheme: WebentorConfig['theme']) => [
27
18
  { label: 'Auto', value: 'mt-auto' },
28
19
  ],
29
20
  },
30
- {
31
- label: __('Margin Left', 'webentor'),
32
- name: 'margin-left',
33
- values: [
34
- ...getSpacingValues('ml', twTheme),
35
- { label: 'Auto', value: 'ml-auto' },
36
- ],
37
- },
38
21
  {
39
22
  label: __('Margin Right', 'webentor'),
40
23
  name: 'margin-right',
@@ -51,16 +34,23 @@ export const getSpacingProperties = (twTheme: WebentorConfig['theme']) => [
51
34
  { label: 'Auto', value: 'mb-auto' },
52
35
  ],
53
36
  },
37
+ {
38
+ label: __('Margin Left', 'webentor'),
39
+ name: 'margin-left',
40
+ values: [
41
+ ...getSpacingValues('ml', twTheme),
42
+ { label: 'Auto', value: 'ml-auto' },
43
+ ],
44
+ },
45
+ ];
46
+
47
+ /** Padding sides for BoxModelControl */
48
+ export const getPaddingSides = (twTheme: WebentorConfig['theme']) => [
54
49
  {
55
50
  label: __('Padding Top', 'webentor'),
56
51
  name: 'padding-top',
57
52
  values: getSpacingValues('pt', twTheme),
58
53
  },
59
- {
60
- label: __('Padding Left', 'webentor'),
61
- name: 'padding-left',
62
- values: getSpacingValues('pl', twTheme),
63
- },
64
54
  {
65
55
  label: __('Padding Right', 'webentor'),
66
56
  name: 'padding-right',
@@ -71,4 +61,36 @@ export const getSpacingProperties = (twTheme: WebentorConfig['theme']) => [
71
61
  name: 'padding-bottom',
72
62
  values: getSpacingValues('pb', twTheme),
73
63
  },
64
+ {
65
+ label: __('Padding Left', 'webentor'),
66
+ name: 'padding-left',
67
+ values: getSpacingValues('pl', twTheme),
68
+ },
69
+ ];
70
+
71
+ /** Flat list of all spacing properties (backward compat for getSpacingProperties) */
72
+ export const getSpacingProperties = (twTheme: WebentorConfig['theme']) => [
73
+ ...getMarginSides(twTheme),
74
+ ...getPaddingSides(twTheme),
74
75
  ];
76
+
77
+ const SPACING_PROPERTY_NAMES = [
78
+ 'margin-top',
79
+ 'margin-bottom',
80
+ 'margin-left',
81
+ 'margin-right',
82
+ 'padding-top',
83
+ 'padding-bottom',
84
+ 'padding-left',
85
+ 'padding-right',
86
+ ];
87
+
88
+ /** Check if any spacing value is set for a given breakpoint */
89
+ export const hasSpacingSettingsForBreakpoint = (
90
+ attributes: Record<string, any>,
91
+ breakpoint: string,
92
+ ): boolean => {
93
+ return SPACING_PROPERTY_NAMES.some(
94
+ (prop) => !!attributes?.spacing?.[prop]?.value?.[breakpoint],
95
+ );
96
+ };
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Spacing module registration.
3
+ *
4
+ * panelGroup: spacing, order: 10
5
+ * Handles margin and padding properties.
6
+ * Unchanged between v1 and v2 — attribute key 'spacing' stays the same.
7
+ */
8
+ import { registry } from '../../registry';
9
+ import { ClassGenContext } from '../../types';
10
+ import { hasSpacingSettingsForBreakpoint } from './properties';
11
+ import { SpacingSettings } from './settings';
12
+
13
+ const generateSpacingClasses = (
14
+ attributes: Record<string, any>,
15
+ breakpoint: string,
16
+ _context: ClassGenContext,
17
+ ): string[] => {
18
+ const classes: string[] = [];
19
+
20
+ if (!attributes.spacing) return classes;
21
+
22
+ for (const [propName, prop] of Object.entries(attributes.spacing)) {
23
+ if (propName.startsWith('_')) continue;
24
+ const propData = prop as any;
25
+ if (!propData?.value) continue;
26
+ const bpValue = propData.value[breakpoint];
27
+ if (!bpValue) continue;
28
+
29
+ if (attributes?.slider?.enabled?.value?.[breakpoint]) continue;
30
+
31
+ const twBreakpoint = breakpoint === 'basic' ? '' : `${breakpoint}:`;
32
+ classes.push(`${twBreakpoint}${bpValue}`);
33
+ }
34
+
35
+ return classes;
36
+ };
37
+
38
+ registry.register({
39
+ name: 'spacing',
40
+ panelGroup: 'spacing',
41
+ order: 10,
42
+ attributeKey: 'spacing',
43
+ supportKey: 'spacing',
44
+ attributeSchema: {
45
+ spacing: {
46
+ type: 'object',
47
+ default: {},
48
+ },
49
+ },
50
+ SettingsComponent: SpacingSettings,
51
+ generateClasses: generateSpacingClasses,
52
+ hasActiveSettings: hasSpacingSettingsForBreakpoint,
53
+ });
@@ -1,11 +1,8 @@
1
- import { SelectControl } from '@wordpress/components';
2
-
3
- import { setImmutably } from '@webentorCore/_utils';
4
- import { BlockPanelProps } from '@webentorCore/block-filters/responsive-settings/types';
5
-
1
+ import { BoxModelControl } from '../../components/BoxModelControl';
6
2
  import { DisabledSliderInfo } from '../../components/DisabledSliderInfo';
3
+ import { BlockPanelProps } from '../../types';
7
4
  import { isSliderEnabledForBreakpoint } from '../../utils';
8
- import { getSpacingProperties } from './properties';
5
+ import { getMarginSides, getPaddingSides } from './properties';
9
6
 
10
7
  interface SpacingSettingsProps extends BlockPanelProps {
11
8
  breakpoint: string;
@@ -16,6 +13,7 @@ export const SpacingSettings = ({
16
13
  setAttributes,
17
14
  name,
18
15
  breakpoint,
16
+ breakpoints,
19
17
  twTheme,
20
18
  }: SpacingSettingsProps) => {
21
19
  if (!attributes?.spacing) {
@@ -28,58 +26,31 @@ export const SpacingSettings = ({
28
26
  breakpoint,
29
27
  );
30
28
 
31
- const spacingProperties = getSpacingProperties(twTheme);
32
-
33
29
  return (
34
- <div
35
- style={{
36
- marginTop: '16px',
37
- display: 'flex',
38
- flexWrap: 'wrap',
39
- justifyContent: 'center',
40
- gap: '16px',
41
- }}
42
- >
30
+ <div style={{ marginTop: '16px' }}>
43
31
  {isSliderEnabled && <DisabledSliderInfo />}
44
32
 
45
- {spacingProperties.map((property) => (
46
- <div
47
- key={property.name + breakpoint}
48
- style={{
49
- margin:
50
- property.name.includes('top') || property.name.includes('bottom')
51
- ? '0 auto'
52
- : undefined,
53
- width:
54
- property.name.includes('top') || property.name.includes('bottom')
55
- ? '75%'
56
- : property.name.includes('left') ||
57
- property.name.includes('right')
58
- ? '40%'
59
- : undefined,
60
- }}
61
- >
62
- <SelectControl
63
- label={property.label}
64
- value={attributes.spacing?.[property.name]?.value?.[breakpoint]}
65
- help={property?.help}
66
- disabled={isSliderEnabled}
67
- options={property.values}
68
- onChange={(selected) =>
69
- setAttributes(
70
- setImmutably(
71
- attributes,
72
- ['spacing', property.name, 'value', breakpoint],
73
- selected,
74
- ),
75
- )
76
- }
77
- />
78
-
79
- {/* Horizontal line between margin & padding settings */}
80
- {property.name.includes('margin-bottom') && <hr />}
81
- </div>
82
- ))}
33
+ <BoxModelControl
34
+ type="margin"
35
+ sides={getMarginSides(twTheme)}
36
+ attributes={attributes}
37
+ setAttributes={setAttributes}
38
+ attributeKey="spacing"
39
+ breakpoint={breakpoint}
40
+ breakpoints={breakpoints}
41
+ disabled={isSliderEnabled}
42
+ />
43
+
44
+ <BoxModelControl
45
+ type="padding"
46
+ sides={getPaddingSides(twTheme)}
47
+ attributes={attributes}
48
+ setAttributes={setAttributes}
49
+ attributeKey="spacing"
50
+ breakpoint={breakpoint}
51
+ breakpoints={breakpoints}
52
+ disabled={isSliderEnabled}
53
+ />
83
54
  </div>
84
55
  );
85
56
  };
@@ -1,68 +1,214 @@
1
- import { WebentorConfig } from '@webentorCore/types/_webentor-config';
1
+ import { WebentorConfig } from '../../../types/_webentor-config';
2
+
3
+ // ─── Panel groups ────────────────────────────────────────────────────
4
+ // Each setting module declares which panel group it renders in.
5
+ // The panel components query the registry by this key.
6
+ export type PanelGroup = 'spacing' | 'displayLayout' | 'border' | 'blockLink';
7
+
8
+ // ─── Primitive value types ───────────────────────────────────────────
2
9
 
3
10
  export interface SelectOption {
4
11
  label: string;
5
12
  value: string;
6
13
  }
7
14
 
15
+ /**
16
+ * A single responsive property value.
17
+ * Keys are breakpoint names ('basic', 'sm', 'md', 'lg', 'xl', '2xl').
18
+ */
8
19
  export interface ResponsiveValue {
9
20
  value: {
10
- [key: string]: string;
21
+ [breakpoint: string]: string;
11
22
  };
12
23
  }
13
24
 
25
+ /**
26
+ * A group of responsive properties keyed by CSS property name.
27
+ * e.g. { 'margin-top': { value: { basic: 'mt-4', md: 'md:mt-8' } } }
28
+ */
14
29
  export interface ResponsiveAttribute {
15
- [key: string]: ResponsiveValue;
30
+ [propertyName: string]: ResponsiveValue;
31
+ }
32
+
33
+ // ─── Border-specific value types ─────────────────────────────────────
34
+
35
+ export interface BorderSideValue {
36
+ width: string;
37
+ color: string;
38
+ style: string;
16
39
  }
17
40
 
18
41
  export interface BorderValue {
19
- top: {
20
- width: string;
21
- color: string;
22
- style: string;
23
- };
24
- right: {
25
- width: string;
26
- color: string;
27
- style: string;
28
- };
29
- bottom: {
30
- width: string;
31
- color: string;
32
- style: string;
33
- };
34
- left: {
35
- width: string;
36
- color: string;
37
- style: string;
38
- };
42
+ top: BorderSideValue;
43
+ right: BorderSideValue;
44
+ bottom: BorderSideValue;
45
+ left: BorderSideValue;
46
+ linked?: boolean;
39
47
  }
40
48
 
41
49
  export interface ResponsiveBorderValue {
42
50
  value: {
43
- [key: string]: BorderValue;
51
+ [breakpoint: string]: BorderValue;
52
+ };
53
+ }
54
+
55
+ export interface BorderRadiusValue {
56
+ topLeft: string;
57
+ topRight: string;
58
+ bottomRight: string;
59
+ bottomLeft: string;
60
+ linked?: boolean;
61
+ }
62
+
63
+ export interface ResponsiveBorderRadiusValue {
64
+ value: {
65
+ [breakpoint: string]: BorderRadiusValue;
44
66
  };
45
67
  }
46
68
 
69
+ export interface BorderAttribute {
70
+ border?: ResponsiveBorderValue;
71
+ borderRadius?: ResponsiveBorderRadiusValue;
72
+ }
73
+
74
+ // ─── Grouped select options ──────────────────────────────────────────
75
+
76
+ export interface SelectOptionGroup {
77
+ label: string;
78
+ options: SelectOption[];
79
+ }
80
+
81
+ // ─── Property definition ─────────────────────────────────────────────
82
+
83
+ export interface PropertyDefinition {
84
+ label: string;
85
+ name: string;
86
+ help?: string;
87
+ values: SelectOption[];
88
+ /** When true, values are split into optgroups (numeric vs keyword) in the select */
89
+ groupedValues?: boolean;
90
+ }
91
+
92
+ // ─── Block attributes & panel props ──────────────────────────────────
93
+
94
+ /**
95
+ * Block attributes shape for responsive settings.
96
+ */
47
97
  export interface BlockAttributes {
48
98
  blockLink?: any;
49
99
  spacing?: ResponsiveAttribute;
50
- display?: ResponsiveAttribute;
100
+ layout?: ResponsiveAttribute;
101
+ sizing?: ResponsiveAttribute;
102
+ flexItem?: ResponsiveAttribute;
51
103
  grid?: ResponsiveAttribute;
52
104
  gridItem?: ResponsiveAttribute;
53
105
  flexbox?: ResponsiveAttribute;
54
- flexboxItem?: ResponsiveAttribute;
55
- border?: ResponsiveBorderValue;
106
+ border?: BorderAttribute;
56
107
  slider?: {
57
108
  enabled?: ResponsiveValue;
58
109
  };
110
+ _preset?: string;
111
+ _presetClasses?: string[];
59
112
  }
60
113
 
61
114
  export interface BlockPanelProps {
62
115
  attributes: BlockAttributes;
63
- setAttributes: (attributes: BlockAttributes) => void;
116
+ setAttributes: (attributes: Partial<BlockAttributes>) => void;
64
117
  name: string;
65
118
  clientId: string;
66
119
  breakpoints: string[];
67
120
  twTheme: WebentorConfig['theme'];
68
121
  }
122
+
123
+ // ─── Class generation context ────────────────────────────────────────
124
+
125
+ /**
126
+ * Context passed to generateClasses() so modules can inspect
127
+ * parent block state, slider status, and support flags.
128
+ */
129
+ export interface ClassGenContext {
130
+ blockName: string;
131
+ supports: Record<string, any>;
132
+ parentBlockAttributes?: Record<string, any>;
133
+ /** Ordered breakpoint names for cascade resolution (min-width inheritance) */
134
+ breakpoints: string[];
135
+ }
136
+
137
+ // ─── Setting definition (registry contract) ──────────────────────────
138
+
139
+ /**
140
+ * Each setting module implements this interface and registers itself
141
+ * with the SettingsRegistry. The panelGroup determines which panel
142
+ * wrapper renders it; order determines render sequence within the panel.
143
+ */
144
+ export interface SettingDefinition {
145
+ /** Unique identifier, e.g. 'layout', 'sizing', 'flexbox' */
146
+ name: string;
147
+ /** Which UI panel this setting renders in */
148
+ panelGroup: PanelGroup;
149
+ /** Render order within the panel group (lower = higher) */
150
+ order: number;
151
+ /** WP block attribute key(s) this module reads/writes */
152
+ attributeKey: string;
153
+ /** webentor.* support flag(s) checked against block.json supports */
154
+ supportKey: string | string[];
155
+ /** Attribute schema merged into blocks.registerBlockType */
156
+ attributeSchema: Record<string, any>;
157
+ /** Optional custom attribute initialiser (e.g. display flex default) */
158
+ initAttributes?: (
159
+ settings: Record<string, any>,
160
+ name: string,
161
+ ) => Record<string, any>;
162
+ /** React component rendered inline within the panel (NOT a PanelBody) */
163
+ SettingsComponent: React.FC<SettingsComponentProps>;
164
+ /** Generates Tailwind class array for a given breakpoint */
165
+ generateClasses: (
166
+ attributes: Record<string, any>,
167
+ breakpoint: string,
168
+ context: ClassGenContext,
169
+ ) => string[];
170
+ /** Returns true when at least one value is set for the breakpoint (tab indicator) */
171
+ hasActiveSettings: (
172
+ attributes: Record<string, any>,
173
+ breakpoint: string,
174
+ context?: ClassGenContext,
175
+ ) => boolean;
176
+ /** Optional v1→v2 migration for this module's attributes */
177
+ migrateFromV1?: (oldAttrs: Record<string, any>) => Record<string, any>;
178
+ }
179
+
180
+ /**
181
+ * Props passed to each setting module's SettingsComponent.
182
+ * The panel wrapper provides these after resolving the active breakpoint.
183
+ */
184
+ export interface SettingsComponentProps extends BlockPanelProps {
185
+ breakpoint: string;
186
+ }
187
+
188
+ // ─── Layout preset ───────────────────────────────────────────────────
189
+
190
+ /**
191
+ * A preset provides one-click layout configuration.
192
+ * Selecting a preset fills in the underlying attribute values
193
+ * and optionally attaches custom CSS classes for edge cases.
194
+ */
195
+ export interface LayoutPresetValue {
196
+ value: Record<string, unknown>;
197
+ }
198
+
199
+ export interface LayoutPresetApplies {
200
+ [attributeKey: string]: {
201
+ [propertyName: string]: LayoutPresetValue;
202
+ };
203
+ }
204
+
205
+ export interface LayoutPreset {
206
+ id: string;
207
+ label: string;
208
+ icon?: string;
209
+ description: string;
210
+ /** Attribute values keyed by module attribute key, then property name */
211
+ applies: LayoutPresetApplies;
212
+ /** Non-TW custom classes for edge cases (e.g. flex-wrap + gap calc) */
213
+ customClasses?: string[];
214
+ }