@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
@@ -0,0 +1,72 @@
1
+ import { __ } from '@wordpress/i18n';
2
+
3
+ import { WebentorConfig } from '../../../../types/_webentor-config';
4
+ import { getGapValues } from '../shared/gap-values';
5
+ import {
6
+ getAlignContentValues,
7
+ getAlignItemsValues,
8
+ getJustifyContentValues,
9
+ } from '../shared/layout-values';
10
+ import { createTwThemeValues } from '../shared/tw-values';
11
+
12
+ export const GRID_PROPERTY_NAMES = [
13
+ 'grid-cols',
14
+ 'grid-rows',
15
+ 'gap',
16
+ 'gap-x',
17
+ 'gap-y',
18
+ 'justify-content',
19
+ 'align-items',
20
+ 'align-content',
21
+ ];
22
+
23
+ export const getGridProperties = (twTheme: WebentorConfig['theme']) => [
24
+ {
25
+ label: __('Grid Template Columns', 'webentor'),
26
+ name: 'grid-cols',
27
+ values: createTwThemeValues(twTheme, 'gridTemplateColumns', 'grid-cols', {
28
+ sort: false,
29
+ labelFormatter: (key) => __('Columns: %s', 'webentor').replace('%s', key),
30
+ }),
31
+ },
32
+ {
33
+ label: __('Grid Template Rows', 'webentor'),
34
+ name: 'grid-rows',
35
+ values: createTwThemeValues(twTheme, 'gridTemplateRows', 'grid-rows', {
36
+ sort: false,
37
+ labelFormatter: (key) => __('Rows: %s', 'webentor').replace('%s', key),
38
+ }),
39
+ },
40
+ {
41
+ label: __('Gap', 'webentor'),
42
+ name: 'gap',
43
+ values: getGapValues('', twTheme),
44
+ },
45
+ {
46
+ label: __('Gap X', 'webentor'),
47
+ name: 'gap-x',
48
+ values: getGapValues('x', twTheme),
49
+ help: __('Overrides Gap value', 'webentor'),
50
+ },
51
+ {
52
+ label: __('Gap Y', 'webentor'),
53
+ name: 'gap-y',
54
+ values: getGapValues('y', twTheme),
55
+ help: __('Overrides Gap value', 'webentor'),
56
+ },
57
+ {
58
+ label: __('Justify Content', 'webentor'),
59
+ name: 'justify-content',
60
+ values: getJustifyContentValues(),
61
+ },
62
+ {
63
+ label: __('Align Items', 'webentor'),
64
+ name: 'align-items',
65
+ values: getAlignItemsValues(),
66
+ },
67
+ {
68
+ label: __('Align Content', 'webentor'),
69
+ name: 'align-content',
70
+ values: getAlignContentValues(),
71
+ },
72
+ ];
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Grid container module registration.
3
+ *
4
+ * panelGroup: displayLayout, order: 40
5
+ * Contextual: only renders when display=grid at the active breakpoint.
6
+ * Support key: 'grid'
7
+ */
8
+ import { getEffectiveDisplayValue } from '../../migration';
9
+ import { registry } from '../../registry';
10
+ import { ClassGenContext } from '../../types';
11
+ import { GRID_PROPERTY_NAMES } from './properties';
12
+ import { GridSettings } from './settings';
13
+
14
+ export const generateGridClasses = (
15
+ attributes: Record<string, any>,
16
+ breakpoint: string,
17
+ context: ClassGenContext,
18
+ ): string[] => {
19
+ const classes: string[] = [];
20
+
21
+ if (!attributes.grid) return classes;
22
+
23
+ // Cascaded display check: grid classes apply when effective display is 'grid'
24
+ const effectiveDisplay = getEffectiveDisplayValue(
25
+ attributes,
26
+ breakpoint,
27
+ context.breakpoints,
28
+ );
29
+ if (effectiveDisplay !== 'grid') return classes;
30
+
31
+ for (const [, prop] of Object.entries(attributes.grid)) {
32
+ const propData = prop as any;
33
+ if (!propData?.value) continue;
34
+ const bpValue = propData.value[breakpoint];
35
+ if (!bpValue) continue;
36
+ if (attributes?.slider?.enabled?.value?.[breakpoint]) continue;
37
+
38
+ const twBreakpoint = breakpoint === 'basic' ? '' : `${breakpoint}:`;
39
+ classes.push(`${twBreakpoint}${bpValue}`);
40
+ }
41
+
42
+ return classes;
43
+ };
44
+
45
+ const hasGridActiveSettings = (
46
+ attributes: Record<string, any>,
47
+ breakpoint: string,
48
+ ): boolean => {
49
+ return GRID_PROPERTY_NAMES.some(
50
+ (propName) => !!attributes?.grid?.[propName]?.value?.[breakpoint],
51
+ );
52
+ };
53
+
54
+ registry.register({
55
+ name: 'grid',
56
+ panelGroup: 'displayLayout',
57
+ order: 40,
58
+ attributeKey: 'grid',
59
+ supportKey: 'grid',
60
+ attributeSchema: {
61
+ grid: { type: 'object', default: {} },
62
+ },
63
+ SettingsComponent: GridSettings,
64
+ generateClasses: generateGridClasses,
65
+ hasActiveSettings: hasGridActiveSettings,
66
+ });
@@ -0,0 +1,78 @@
1
+ /**
2
+ * GridSettings — grid container controls.
3
+ *
4
+ * Only renders when the current block's display is 'grid'.
5
+ * Grid-item settings are now a separate module.
6
+ */
7
+ import { Fragment } from '@wordpress/element';
8
+ import { __ } from '@wordpress/i18n';
9
+
10
+ import { DisabledSliderInfo } from '../../components/DisabledSliderInfo';
11
+ import { InheritedIndicator } from '../../components/InheritedIndicator';
12
+ import { ResponsiveSelectGroup } from '../../components/ResponsiveSelectGroup';
13
+ import {
14
+ getDisplayInheritedFromBreakpoint,
15
+ getEffectiveDisplayValue,
16
+ } from '../../migration';
17
+ import { SettingsComponentProps } from '../../types';
18
+ import { isSliderEnabledForBreakpoint } from '../../utils';
19
+ import { getGridProperties } from './properties';
20
+
21
+ const SECTION_STYLE = {
22
+ marginTop: '16px',
23
+ border: '1px solid #e0e0e0',
24
+ padding: '8px',
25
+ };
26
+
27
+ export const GridSettings = ({
28
+ attributes,
29
+ setAttributes,
30
+ name,
31
+ breakpoint,
32
+ breakpoints,
33
+ twTheme,
34
+ }: SettingsComponentProps) => {
35
+ const effectiveDisplay = getEffectiveDisplayValue(
36
+ attributes,
37
+ breakpoint,
38
+ breakpoints,
39
+ );
40
+ const isCurrentGrid = effectiveDisplay === 'grid';
41
+
42
+ if (!isCurrentGrid || !attributes?.grid) {
43
+ return null;
44
+ }
45
+
46
+ const isSliderEnabled = isSliderEnabledForBreakpoint(
47
+ name,
48
+ attributes,
49
+ breakpoint,
50
+ );
51
+
52
+ const inheritedFrom = getDisplayInheritedFromBreakpoint(
53
+ attributes,
54
+ breakpoint,
55
+ breakpoints,
56
+ );
57
+
58
+ return (
59
+ <Fragment>
60
+ <div style={SECTION_STYLE}>
61
+ <h3 style={{ marginBottom: '8px' }}>
62
+ {__('Grid settings', 'webentor')}
63
+ </h3>
64
+ {inheritedFrom && <InheritedIndicator fromBreakpoint={inheritedFrom} />}
65
+ {isSliderEnabled && <DisabledSliderInfo />}
66
+ <ResponsiveSelectGroup
67
+ attributeKey="grid"
68
+ properties={getGridProperties(twTheme)}
69
+ attributes={attributes}
70
+ setAttributes={setAttributes}
71
+ breakpoint={breakpoint}
72
+ breakpoints={breakpoints}
73
+ disabled={isSliderEnabled}
74
+ />
75
+ </div>
76
+ </Fragment>
77
+ );
78
+ };
@@ -0,0 +1,4 @@
1
+ import './registration';
2
+
3
+ export { GridItemSettings } from './settings';
4
+ export { getGridItemProperties } from './properties';
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Grid-item properties — column span, row span, order.
3
+ *
4
+ * These properties apply to children of a grid container.
5
+ * Re-uses getGridItemProperties from the grid module for DRY.
6
+ */
7
+ import { __ } from '@wordpress/i18n';
8
+
9
+ import { WebentorConfig } from '../../../../types/_webentor-config';
10
+ import { PropertyDefinition } from '../../types';
11
+ import { getOrderValues } from '../shared/layout-values';
12
+ import { createTwThemeValues } from '../shared/tw-values';
13
+
14
+ export const getGridItemProperties = (
15
+ twTheme: WebentorConfig['theme'],
16
+ ): PropertyDefinition[] => [
17
+ {
18
+ label: __('Grid Column Span', 'webentor'),
19
+ name: 'grid-col-span',
20
+ values: createTwThemeValues(twTheme, 'gridColumn', 'col', {
21
+ sort: false,
22
+ labelFormatter: (key) => key,
23
+ }),
24
+ },
25
+ {
26
+ label: __('Grid Row Span', 'webentor'),
27
+ name: 'grid-row-span',
28
+ values: createTwThemeValues(twTheme, 'gridRow', 'row', {
29
+ sort: false,
30
+ labelFormatter: (key) => key,
31
+ }),
32
+ },
33
+ {
34
+ label: __('Order', 'webentor'),
35
+ name: 'order',
36
+ values: getOrderValues(),
37
+ },
38
+ ];
39
+
40
+ export const GRID_ITEM_PROPERTY_NAMES = [
41
+ 'grid-col-span',
42
+ 'grid-row-span',
43
+ 'order',
44
+ ];
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Grid-item module registration.
3
+ *
4
+ * panelGroup: displayLayout, order: 60
5
+ * Contextual: only shows when parent block display=grid.
6
+ * Support key: 'gridItem'
7
+ */
8
+ import { getEffectiveParentDisplayValue } from '../../migration';
9
+ import { registry } from '../../registry';
10
+ import { ClassGenContext } from '../../types';
11
+ import { GRID_ITEM_PROPERTY_NAMES } from './properties';
12
+ import { GridItemSettings } from './settings';
13
+
14
+ export const generateGridItemClasses = (
15
+ attributes: Record<string, any>,
16
+ breakpoint: string,
17
+ context: ClassGenContext,
18
+ ): string[] => {
19
+ const classes: string[] = [];
20
+
21
+ if (!attributes.gridItem) return classes;
22
+
23
+ // Cascaded parent display check
24
+ const effectiveParentDisplay = getEffectiveParentDisplayValue(
25
+ context.parentBlockAttributes,
26
+ breakpoint,
27
+ context.breakpoints,
28
+ );
29
+ if (effectiveParentDisplay !== 'grid') return classes;
30
+
31
+ for (const [, prop] of Object.entries(attributes.gridItem)) {
32
+ const propData = prop as any;
33
+ if (!propData?.value) continue;
34
+ const bpValue = propData.value[breakpoint];
35
+ if (!bpValue) continue;
36
+ if (attributes?.slider?.enabled?.value?.[breakpoint]) continue;
37
+
38
+ const twBreakpoint = breakpoint === 'basic' ? '' : `${breakpoint}:`;
39
+ classes.push(`${twBreakpoint}${bpValue}`);
40
+ }
41
+
42
+ return classes;
43
+ };
44
+
45
+ const hasGridItemActiveSettings = (
46
+ attributes: Record<string, any>,
47
+ breakpoint: string,
48
+ context?: ClassGenContext,
49
+ ): boolean => {
50
+ const effectiveParentDisplay = getEffectiveParentDisplayValue(
51
+ context?.parentBlockAttributes,
52
+ breakpoint,
53
+ context?.breakpoints ?? [],
54
+ );
55
+ if (effectiveParentDisplay !== 'grid') return false;
56
+
57
+ return GRID_ITEM_PROPERTY_NAMES.some(
58
+ (prop) => !!attributes?.gridItem?.[prop]?.value?.[breakpoint],
59
+ );
60
+ };
61
+
62
+ registry.register({
63
+ name: 'gridItem',
64
+ panelGroup: 'displayLayout',
65
+ order: 60,
66
+ attributeKey: 'gridItem',
67
+ supportKey: 'gridItem',
68
+ attributeSchema: {
69
+ gridItem: { type: 'object', default: {} },
70
+ },
71
+ SettingsComponent: GridItemSettings,
72
+ generateClasses: generateGridItemClasses,
73
+ hasActiveSettings: hasGridItemActiveSettings,
74
+ });
@@ -0,0 +1,87 @@
1
+ /**
2
+ * GridItemSettings — grid child controls (column span, row span, order).
3
+ *
4
+ * Contextual: only shows when the parent block's display is 'grid'.
5
+ */
6
+ import { Fragment } from '@wordpress/element';
7
+ import { __ } from '@wordpress/i18n';
8
+
9
+ import { useBlockParent } from '../../../../blocks-utils/_use-block-parent';
10
+ import { DisabledSliderInfo } from '../../components/DisabledSliderInfo';
11
+ import { InheritedIndicator } from '../../components/InheritedIndicator';
12
+ import { ResponsiveSelectGroup } from '../../components/ResponsiveSelectGroup';
13
+ import {
14
+ getDisplayInheritedFromBreakpoint,
15
+ getEffectiveParentDisplayValue,
16
+ } from '../../migration';
17
+ import { SettingsComponentProps } from '../../types';
18
+ import { isSliderEnabledForBreakpoint } from '../../utils';
19
+ import { getGridItemProperties } from './properties';
20
+
21
+ const SECTION_STYLE = {
22
+ marginTop: '16px',
23
+ border: '1px solid #e0e0e0',
24
+ padding: '8px',
25
+ };
26
+
27
+ export const GridItemSettings = ({
28
+ attributes,
29
+ setAttributes,
30
+ name,
31
+ breakpoint,
32
+ breakpoints,
33
+ twTheme,
34
+ }: SettingsComponentProps) => {
35
+ const parentBlock = useBlockParent();
36
+ const effectiveParentDisplay = getEffectiveParentDisplayValue(
37
+ parentBlock?.attributes,
38
+ breakpoint,
39
+ breakpoints,
40
+ );
41
+
42
+ if (effectiveParentDisplay !== 'grid') return null;
43
+ if (!attributes?.gridItem) return null;
44
+
45
+ const isSliderEnabled = isSliderEnabledForBreakpoint(
46
+ name,
47
+ attributes,
48
+ breakpoint,
49
+ );
50
+
51
+ const parentInheritedFrom = parentBlock?.attributes
52
+ ? getDisplayInheritedFromBreakpoint(
53
+ parentBlock.attributes,
54
+ breakpoint,
55
+ breakpoints,
56
+ )
57
+ : null;
58
+
59
+ return (
60
+ <Fragment>
61
+ <div style={SECTION_STYLE}>
62
+ <h3 style={{ marginBottom: '8px' }}>
63
+ {__('Grid Item settings', 'webentor')}
64
+ </h3>
65
+ {parentInheritedFrom && (
66
+ <InheritedIndicator fromBreakpoint={parentInheritedFrom} />
67
+ )}
68
+ <div style={{ marginBottom: '8px', fontSize: '12px' }}>
69
+ {__(
70
+ 'Parent block display setting is set to `Grid`, so current block also acts as grid item.',
71
+ 'webentor',
72
+ )}
73
+ </div>
74
+ {isSliderEnabled && <DisabledSliderInfo />}
75
+ <ResponsiveSelectGroup
76
+ attributeKey="gridItem"
77
+ properties={getGridItemProperties(twTheme)}
78
+ attributes={attributes}
79
+ setAttributes={setAttributes}
80
+ breakpoint={breakpoint}
81
+ breakpoints={breakpoints}
82
+ disabled={isSliderEnabled}
83
+ />
84
+ </div>
85
+ </Fragment>
86
+ );
87
+ };
@@ -0,0 +1,4 @@
1
+ import './registration';
2
+
3
+ export { LayoutSettings } from './settings';
4
+ export { getLayoutProperties } from './properties';
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Layout properties — display mode and visibility.
3
+ *
4
+ * Separated from the old display/properties.ts which lumped sizing
5
+ * properties together with display mode. This module only handles
6
+ * the CSS `display` property itself.
7
+ */
8
+ import { applyFilters } from '@wordpress/hooks';
9
+ import { __ } from '@wordpress/i18n';
10
+
11
+ import { WebentorConfig } from '../../../../types/_webentor-config';
12
+ import { PropertyDefinition } from '../../types';
13
+
14
+ const getDisplayValues = () => [
15
+ { label: 'None selected', value: '' },
16
+ { label: 'Block', value: 'block' },
17
+ { label: 'Hidden', value: 'hidden' },
18
+ { label: 'Flex', value: 'flex' },
19
+ { label: 'Grid', value: 'grid' },
20
+ { label: 'Inline Block', value: 'inline-block' },
21
+ { label: 'Inline', value: 'inline' },
22
+ ];
23
+
24
+ export const getLayoutProperties = (
25
+ blockName: string,
26
+ _twTheme: WebentorConfig['theme'],
27
+ ): PropertyDefinition[] =>
28
+ applyFilters(
29
+ 'webentor-theme-layout-settings',
30
+ [
31
+ {
32
+ label: __('Display', 'webentor'),
33
+ name: 'display',
34
+ help: __('Initial value is "Flex"', 'webentor'),
35
+ values: getDisplayValues(),
36
+ },
37
+ ],
38
+ blockName,
39
+ ) as PropertyDefinition[];
40
+
41
+ /** Property names for active-settings detection */
42
+ export const LAYOUT_PROPERTY_NAMES = ['display'];
43
+
44
+ export const hasLayoutSettingsForBreakpoint = (
45
+ attributes: Record<string, any>,
46
+ breakpoint: string,
47
+ ): boolean => {
48
+ return LAYOUT_PROPERTY_NAMES.some(
49
+ (prop) => !!attributes?.layout?.[prop]?.value?.[breakpoint],
50
+ );
51
+ };
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Layout module registration.
3
+ *
4
+ * panelGroup: displayLayout, order: 10
5
+ * Handles the CSS display property (block/flex/grid/hidden/etc).
6
+ * Support key: 'layout'
7
+ */
8
+ import { getDisplayValue, getEffectiveDisplayValue } from '../../migration';
9
+ import { registry } from '../../registry';
10
+ import { ClassGenContext } from '../../types';
11
+ import { hasLayoutSettingsForBreakpoint } from './properties';
12
+ import { LayoutSettings } from './settings';
13
+
14
+ const generateLayoutClasses = (
15
+ attributes: Record<string, any>,
16
+ breakpoint: string,
17
+ context: ClassGenContext,
18
+ ): string[] => {
19
+ const classes: string[] = [];
20
+ const displayValue = getDisplayValue(attributes, breakpoint);
21
+
22
+ if (!displayValue) return classes;
23
+
24
+ // Skip when slider is enabled at this breakpoint
25
+ if (attributes?.slider?.enabled?.value?.[breakpoint]) return classes;
26
+
27
+ const twBreakpoint = breakpoint === 'basic' ? '' : `${breakpoint}:`;
28
+
29
+ // 'hidden' maps to opacity-30 in the editor (visual indicator rather than true hide)
30
+ if (displayValue === 'hidden') {
31
+ classes.push(`${twBreakpoint}opacity-30`);
32
+ } else {
33
+ classes.push(`${twBreakpoint}${displayValue}`);
34
+
35
+ // Reset opacity when transitioning from hidden to visible across breakpoints.
36
+ // Without this, opacity-30 from a lower breakpoint would persist even after
37
+ // the display is overridden to a non-hidden value at a higher breakpoint.
38
+ const bpIndex = context.breakpoints.indexOf(breakpoint);
39
+ if (bpIndex > 0) {
40
+ const prevBp = context.breakpoints[bpIndex - 1];
41
+ const prevEffective = getEffectiveDisplayValue(
42
+ attributes,
43
+ prevBp,
44
+ context.breakpoints,
45
+ );
46
+ if (prevEffective === 'hidden') {
47
+ classes.push(`${twBreakpoint}opacity-100`);
48
+ }
49
+ }
50
+ }
51
+
52
+ return classes;
53
+ };
54
+
55
+ registry.register({
56
+ name: 'layout',
57
+ panelGroup: 'displayLayout',
58
+ order: 10,
59
+ attributeKey: 'layout',
60
+ supportKey: 'layout',
61
+ attributeSchema: {
62
+ layout: { type: 'object', default: {} },
63
+ },
64
+ initAttributes: (settings, _name) => {
65
+ const webentorSupport = settings?.supports?.webentor;
66
+ const displaySupport =
67
+ webentorSupport?.layout === true ||
68
+ webentorSupport?.layout?.display === true;
69
+
70
+ if (displaySupport) {
71
+ const defaultValue = {
72
+ display: {
73
+ value: {
74
+ basic: 'flex',
75
+ ...settings?.attributes?.layout?.default?.display?.value,
76
+ },
77
+ },
78
+ };
79
+
80
+ settings.attributes = {
81
+ ...settings.attributes,
82
+ layout: {
83
+ type: 'object',
84
+ default: {
85
+ ...settings?.attributes?.layout?.default,
86
+ ...defaultValue,
87
+ },
88
+ },
89
+ };
90
+ }
91
+ return settings;
92
+ },
93
+ SettingsComponent: LayoutSettings,
94
+ generateClasses: generateLayoutClasses,
95
+ hasActiveSettings: hasLayoutSettingsForBreakpoint,
96
+ });
@@ -0,0 +1,64 @@
1
+ /**
2
+ * LayoutSettings — display mode selector.
3
+ *
4
+ * Rendered inside the DisplayLayoutPanel at order: 10.
5
+ */
6
+ import { getBlockSupport } from '@wordpress/blocks';
7
+ import { Fragment } from '@wordpress/element';
8
+
9
+ import { camelize } from '../../../../_utils';
10
+ import { DisabledSliderInfo } from '../../components/DisabledSliderInfo';
11
+ import { ResponsiveSelectGroup } from '../../components/ResponsiveSelectGroup';
12
+ import { PropertyDefinition, SettingsComponentProps } from '../../types';
13
+ import { isSliderEnabledForBreakpoint } from '../../utils';
14
+ import { getLayoutProperties } from './properties';
15
+
16
+ export const LayoutSettings = ({
17
+ attributes,
18
+ setAttributes,
19
+ name,
20
+ breakpoint,
21
+ breakpoints,
22
+ twTheme,
23
+ }: SettingsComponentProps) => {
24
+ if (!attributes?.layout) {
25
+ return null;
26
+ }
27
+
28
+ const isSliderEnabled = isSliderEnabledForBreakpoint(
29
+ name,
30
+ attributes,
31
+ breakpoint,
32
+ );
33
+ const layoutProperties = getLayoutProperties(name, twTheme);
34
+
35
+ const webentorSupports = getBlockSupport(name, 'webentor') as
36
+ | Record<string, any>
37
+ | undefined;
38
+ const supports = webentorSupports?.layout;
39
+
40
+ const isPropertyVisible = (property: PropertyDefinition) => {
41
+ if (supports === true) return true;
42
+ return supports?.[camelize(property.name)] === true;
43
+ };
44
+
45
+ const attributeKey = 'layout';
46
+
47
+ return (
48
+ <Fragment>
49
+ <div style={{ marginTop: '16px' }}>
50
+ {isSliderEnabled && <DisabledSliderInfo />}
51
+ <ResponsiveSelectGroup
52
+ attributeKey={attributeKey}
53
+ properties={layoutProperties}
54
+ attributes={attributes}
55
+ setAttributes={setAttributes}
56
+ breakpoint={breakpoint}
57
+ breakpoints={breakpoints}
58
+ disabled={isSliderEnabled}
59
+ isPropertyVisible={isPropertyVisible}
60
+ />
61
+ </div>
62
+ </Fragment>
63
+ );
64
+ };
@@ -0,0 +1,4 @@
1
+ import './registration';
2
+
3
+ export { PresetSettings } from './settings';
4
+ export { getLayoutPresets, layoutPresets } from './presets';