@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,61 @@
1
+ /**
2
+ * BorderPanel — Thin panel wrapper for panelGroup='border'.
3
+ *
4
+ * Renders border + border-radius settings within a single PanelBody
5
+ * with responsive breakpoint tabs.
6
+ */
7
+ import { PanelBody } from '@wordpress/components';
8
+ import { __ } from '@wordpress/i18n';
9
+
10
+ import { BreakpointResetButton } from '../components/BreakpointResetButton';
11
+ import { ResponsiveTabPanel } from '../components/ResponsiveTabPanel';
12
+ import { registry } from '../registry';
13
+ import { BlockPanelProps } from '../types';
14
+
15
+ export const BorderPanel = (props: BlockPanelProps) => {
16
+ const { attributes, setAttributes, breakpoints } = props;
17
+ const modules = registry.getByPanelGroup('border');
18
+
19
+ const hasAnyAttributes = modules.some((def) =>
20
+ Object.keys(def.attributeSchema).some((key) => !!attributes?.[key]),
21
+ );
22
+
23
+ if (!hasAnyAttributes) return null;
24
+
25
+ const hasActiveSettings = (breakpoint: string): boolean => {
26
+ return modules.some((def) => def.hasActiveSettings(attributes, breakpoint));
27
+ };
28
+
29
+ const hasNonDefaults = breakpoints.some((bp) => hasActiveSettings(bp));
30
+
31
+ return (
32
+ <PanelBody
33
+ title={__('Border Settings', 'webentor') + (hasNonDefaults ? ' *' : '')}
34
+ initialOpen={false}
35
+ >
36
+ <ResponsiveTabPanel
37
+ breakpoints={breakpoints}
38
+ hasActiveSettings={hasActiveSettings}
39
+ screens={props.twTheme?.screens as Record<string, any>}
40
+ >
41
+ {(breakpoint) => (
42
+ <>
43
+ <BreakpointResetButton
44
+ panelGroup="border"
45
+ breakpoint={breakpoint}
46
+ attributes={attributes}
47
+ setAttributes={setAttributes}
48
+ />
49
+ {modules.map((def) => (
50
+ <def.SettingsComponent
51
+ key={def.name}
52
+ {...props}
53
+ breakpoint={breakpoint}
54
+ />
55
+ ))}
56
+ </>
57
+ )}
58
+ </ResponsiveTabPanel>
59
+ </PanelBody>
60
+ );
61
+ };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * DisplayLayoutPanel — Thin panel wrapper for panelGroup='displayLayout'.
3
+ *
4
+ * Groups presets, layout, sizing, flexbox, grid, flex-item, and grid-item
5
+ * into a single "Display & Layout Settings" panel. Each module renders
6
+ * conditionally (e.g. flexbox only shows when display=flex).
7
+ *
8
+ * The panel also supports a filter hook for injecting content before tabs
9
+ * (e.g. preset buttons or block-specific UI).
10
+ */
11
+ import { PanelBody } from '@wordpress/components';
12
+ import { applyFilters } from '@wordpress/hooks';
13
+ import { __ } from '@wordpress/i18n';
14
+
15
+ import { useBlockParent } from '../../../blocks-utils/_use-block-parent';
16
+ import { BreakpointResetButton } from '../components/BreakpointResetButton';
17
+ import { ResponsiveTabPanel } from '../components/ResponsiveTabPanel';
18
+ import { registry } from '../registry';
19
+ import { PresetSettings } from '../settings/presets/settings';
20
+ import { BlockPanelProps, ClassGenContext } from '../types';
21
+
22
+ export const DisplayLayoutPanel = (props: BlockPanelProps) => {
23
+ const { attributes, setAttributes, breakpoints } = props;
24
+ const modules = registry.getByPanelGroup('displayLayout');
25
+
26
+ const parentBlock = useBlockParent();
27
+
28
+ const hasAnyAttributes = modules.some((def) =>
29
+ Object.keys(def.attributeSchema).some((key) => !!attributes?.[key]),
30
+ );
31
+
32
+ if (!hasAnyAttributes) return null;
33
+
34
+ const context: ClassGenContext = {
35
+ blockName: props.name,
36
+ supports: {},
37
+ parentBlockAttributes: parentBlock?.attributes,
38
+ };
39
+
40
+ const hasActiveSettings = (breakpoint: string): boolean => {
41
+ return modules.some((def) =>
42
+ def.hasActiveSettings(attributes, breakpoint, context),
43
+ );
44
+ };
45
+
46
+ const hasNonDefaults = breakpoints.some((bp) => hasActiveSettings(bp));
47
+
48
+ const beforeTabsContent = applyFilters(
49
+ 'webentor.displayLayoutPanel.beforeTabs',
50
+ null,
51
+ props,
52
+ );
53
+
54
+ // Show presets above tabs (they apply globally, not per-breakpoint)
55
+ const showPresets = !!attributes?._preset || attributes?._preset === '';
56
+
57
+ return (
58
+ <PanelBody
59
+ title={
60
+ __('Display & Layout Settings', 'webentor') +
61
+ (hasNonDefaults ? ' *' : '')
62
+ }
63
+ initialOpen={true}
64
+ >
65
+ {showPresets && <PresetSettings {...props} />}
66
+ {beforeTabsContent}
67
+ <ResponsiveTabPanel
68
+ breakpoints={breakpoints}
69
+ hasActiveSettings={hasActiveSettings}
70
+ screens={props.twTheme?.screens as Record<string, any>}
71
+ >
72
+ {(breakpoint) => (
73
+ <>
74
+ <BreakpointResetButton
75
+ panelGroup="displayLayout"
76
+ breakpoint={breakpoint}
77
+ attributes={attributes}
78
+ setAttributes={setAttributes}
79
+ />
80
+ {modules.map((def) => (
81
+ <def.SettingsComponent
82
+ key={def.name}
83
+ {...props}
84
+ breakpoint={breakpoint}
85
+ />
86
+ ))}
87
+ </>
88
+ )}
89
+ </ResponsiveTabPanel>
90
+ </PanelBody>
91
+ );
92
+ };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * SpacingPanel — Thin panel wrapper for panelGroup='spacing'.
3
+ *
4
+ * Renders a single PanelBody with responsive breakpoint tabs,
5
+ * then loops over all setting modules registered to the 'spacing'
6
+ * panel group and renders each one's SettingsComponent inline.
7
+ */
8
+ import { PanelBody } from '@wordpress/components';
9
+ import { __ } from '@wordpress/i18n';
10
+
11
+ import { BreakpointResetButton } from '../components/BreakpointResetButton';
12
+ import { ResponsiveTabPanel } from '../components/ResponsiveTabPanel';
13
+ import { registry } from '../registry';
14
+ import { BlockPanelProps } from '../types';
15
+
16
+ export const SpacingPanel = (props: BlockPanelProps) => {
17
+ const { attributes, setAttributes, breakpoints } = props;
18
+ const modules = registry.getByPanelGroup('spacing');
19
+
20
+ const hasAnyAttributes = modules.some((def) =>
21
+ Object.keys(def.attributeSchema).some((key) => !!attributes?.[key]),
22
+ );
23
+
24
+ if (!hasAnyAttributes) return null;
25
+
26
+ const hasActiveSettings = (breakpoint: string): boolean => {
27
+ return modules.some((def) => def.hasActiveSettings(attributes, breakpoint));
28
+ };
29
+
30
+ // Panel-level check: any breakpoint has non-default values
31
+ const hasNonDefaults = breakpoints.some((bp) => hasActiveSettings(bp));
32
+
33
+ return (
34
+ <PanelBody
35
+ title={__('Spacing Settings', 'webentor') + (hasNonDefaults ? ' *' : '')}
36
+ initialOpen={false}
37
+ >
38
+ <ResponsiveTabPanel
39
+ breakpoints={breakpoints}
40
+ hasActiveSettings={hasActiveSettings}
41
+ screens={props.twTheme?.screens as Record<string, any>}
42
+ >
43
+ {(breakpoint) => (
44
+ <>
45
+ <BreakpointResetButton
46
+ panelGroup="spacing"
47
+ breakpoint={breakpoint}
48
+ attributes={attributes}
49
+ setAttributes={setAttributes}
50
+ />
51
+ {modules.map((def) => (
52
+ <def.SettingsComponent
53
+ key={def.name}
54
+ {...props}
55
+ breakpoint={breakpoint}
56
+ />
57
+ ))}
58
+ </>
59
+ )}
60
+ </ResponsiveTabPanel>
61
+ </PanelBody>
62
+ );
63
+ };
@@ -0,0 +1,4 @@
1
+ export { SpacingPanel } from './SpacingPanel';
2
+ export { DisplayLayoutPanel } from './DisplayLayoutPanel';
3
+ export { BorderPanel } from './BorderPanel';
4
+ export { BlockLinkPanel } from './BlockLinkPanel';
@@ -0,0 +1,88 @@
1
+ /**
2
+ * SettingsRegistry — Central registry for responsive setting modules.
3
+ *
4
+ * Each setting module (layout, sizing, flexbox, etc.) self-registers via
5
+ * its registration.ts side-effect import. The registry provides lookup
6
+ * by name and by panelGroup for panel components to query.
7
+ *
8
+ * Architecture: Setting modules declare a panelGroup ('spacing' | 'displayLayout' | 'border')
9
+ * which determines which panel wrapper renders them. The panel wrapper
10
+ * queries getByPanelGroup() and renders each module's SettingsComponent
11
+ * in order.
12
+ */
13
+
14
+ import { ClassGenContext, PanelGroup, SettingDefinition } from './types';
15
+
16
+ export type { ClassGenContext, PanelGroup, SettingDefinition };
17
+
18
+ // Re-export PropertyDefinition for backward compat with existing imports
19
+ export type { PropertyDefinition } from './types';
20
+
21
+ class SettingsRegistry {
22
+ private settings = new Map<string, SettingDefinition>();
23
+
24
+ /**
25
+ * Register a setting module. Called as a side-effect in each module's
26
+ * registration.ts file. Duplicate names will overwrite (useful for
27
+ * theme/plugin overrides).
28
+ */
29
+ register(def: SettingDefinition): void {
30
+ this.settings.set(def.name, def);
31
+ }
32
+
33
+ /** All registered settings sorted by panelGroup priority then order */
34
+ getAll(): SettingDefinition[] {
35
+ return Array.from(this.settings.values()).sort((a, b) => a.order - b.order);
36
+ }
37
+
38
+ /** Get a specific setting by name */
39
+ getByName(name: string): SettingDefinition | undefined {
40
+ return this.settings.get(name);
41
+ }
42
+
43
+ /**
44
+ * Get all settings for a given panel group, sorted by order.
45
+ * Panel components use this to discover which modules to render.
46
+ */
47
+ getByPanelGroup(group: PanelGroup): SettingDefinition[] {
48
+ return this.getAll().filter((def) => def.panelGroup === group);
49
+ }
50
+
51
+ /** Merge all attribute schemas into a single object */
52
+ getAllAttributeSchemas(): Record<string, any> {
53
+ const schemas: Record<string, any> = {};
54
+ for (const def of this.settings.values()) {
55
+ Object.assign(schemas, def.attributeSchema);
56
+ }
57
+ return schemas;
58
+ }
59
+
60
+ /**
61
+ * Check if a block supports a setting by matching its supportKey
62
+ * against the block's supports.webentor config.
63
+ */
64
+ isSupported(
65
+ supports: Record<string, any> | undefined,
66
+ def: SettingDefinition,
67
+ ): boolean {
68
+ const keys = Array.isArray(def.supportKey)
69
+ ? def.supportKey
70
+ : [def.supportKey];
71
+ return keys.some((key) => !!supports?.webentor?.[key]);
72
+ }
73
+
74
+ /**
75
+ * Get unique panel groups that have at least one registered setting.
76
+ * Useful for determining which panels to render.
77
+ */
78
+ getActivePanelGroups(): PanelGroup[] {
79
+ const groups = new Set<PanelGroup>();
80
+ for (const def of this.settings.values()) {
81
+ groups.add(def.panelGroup);
82
+ }
83
+ return Array.from(groups);
84
+ }
85
+ }
86
+
87
+ /** Singleton registry instance shared across all modules */
88
+ export const registry = new SettingsRegistry();
@@ -1 +1,4 @@
1
+ // Side-effect: registers with SettingsRegistry
2
+ import './registration';
3
+
1
4
  export { BlockLinkPanel } from './panel';
@@ -1,8 +1,11 @@
1
- import { __experimentalLinkControl as LinkControl } from '@wordpress/block-editor';
1
+ import * as BlockEditor from '@wordpress/block-editor';
2
2
  import { __ } from '@wordpress/i18n';
3
3
 
4
- import { setImmutably } from '@webentorCore/_utils';
5
- import { BlockPanelProps } from '@webentorCore/block-filters/responsive-settings/types';
4
+ import { setImmutably } from '../../../../_utils';
5
+ import { BlockPanelProps } from '../../types';
6
+
7
+ // WordPress ships this control, but the package typings still expose it as experimental.
8
+ const LinkControl = (BlockEditor as any).__experimentalLinkControl;
6
9
 
7
10
  export const BlockLinkPanel = ({
8
11
  attributes,
@@ -14,9 +17,6 @@ export const BlockLinkPanel = ({
14
17
 
15
18
  return (
16
19
  <div className="w-link-settings" style={{ marginBottom: '16px' }}>
17
- <h3 style={{ padding: '16px', paddingBottom: '0px' }}>
18
- {__('Block Link', 'webentor')}
19
- </h3>
20
20
  <div style={{ padding: '16px', paddingTop: '0px', fontSize: '12px' }}>
21
21
  {__('This whole block can act like a link', 'webentor')}
22
22
  </div>
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Block link module registration.
3
+ *
4
+ * Block link is non-responsive and doesn't generate Tailwind classes.
5
+ * Uses its own panelGroup 'blockLink' with a standalone panel wrapper
6
+ * (panels/BlockLinkPanel.tsx) that renders without breakpoint tabs.
7
+ */
8
+ import { registry } from '../../registry';
9
+ import { ClassGenContext } from '../../types';
10
+ import { BlockLinkPanel } from './panel';
11
+
12
+ registry.register({
13
+ name: 'blockLink',
14
+ panelGroup: 'blockLink',
15
+ order: 100,
16
+ attributeKey: 'blockLink',
17
+ supportKey: 'blockLink',
18
+ attributeSchema: {
19
+ blockLink: { type: 'object', default: {} },
20
+ },
21
+ SettingsComponent: BlockLinkPanel,
22
+ generateClasses: (
23
+ _attributes: Record<string, any>,
24
+ _breakpoint: string,
25
+ _context: ClassGenContext,
26
+ ): string[] => {
27
+ return [];
28
+ },
29
+ hasActiveSettings: (
30
+ attributes: Record<string, any>,
31
+ _breakpoint: string,
32
+ ): boolean => {
33
+ return !!attributes?.blockLink?.url;
34
+ },
35
+ });
@@ -1,7 +1,6 @@
1
1
  import { __ } from '@wordpress/i18n';
2
2
 
3
- import { WebentorConfig } from '@webentorCore/types/_webentor-config';
4
-
3
+ import { WebentorConfig } from '../../../../../types/_webentor-config';
5
4
  import { getPixelFromRemValue } from '../../../utils';
6
5
 
7
6
  export const getBorderProperties = (twTheme: WebentorConfig['theme']) => [
@@ -15,10 +15,13 @@ import {
15
15
  getColorSlugByColor,
16
16
  isEmpty,
17
17
  setImmutably,
18
- } from '@webentorCore/_utils';
19
-
18
+ } from '../../../../../_utils';
19
+ import { InheritedIndicator } from '../../../components/InheritedIndicator';
20
20
  import { BlockPanelProps } from '../../../types';
21
- import { prepareTailwindBorderClassesFromSettings } from '../../../utils';
21
+ import {
22
+ getObjectInheritedFromBreakpoint,
23
+ prepareTailwindBorderClassesFromSettings,
24
+ } from '../../../utils';
22
25
  import { getBorderProperties } from './properties';
23
26
 
24
27
  interface BorderSettingsProps extends BlockPanelProps {
@@ -78,6 +81,7 @@ const WebentorBorderControl = ({
78
81
  label={property.label}
79
82
  value={value?.[property.name]}
80
83
  options={property.values}
84
+ __nextHasNoMarginBottom
81
85
  onChange={(selectValue) =>
82
86
  onChange({ ...value, [property.name]: selectValue })
83
87
  }
@@ -111,6 +115,7 @@ export const BorderSettings = ({
111
115
  setAttributes,
112
116
  name,
113
117
  breakpoint,
118
+ breakpoints,
114
119
  twTheme,
115
120
  }: BorderSettingsProps) => {
116
121
  if (!attributes?.border) {
@@ -220,9 +225,22 @@ export const BorderSettings = ({
220
225
  justifyItems: 'center',
221
226
  };
222
227
 
228
+ const borderInheritedFrom = breakpoints?.length
229
+ ? getObjectInheritedFromBreakpoint(
230
+ attributes,
231
+ 'border',
232
+ 'border',
233
+ breakpoint,
234
+ breakpoints,
235
+ )
236
+ : null;
237
+
223
238
  return (
224
239
  <div className="wbtr:my-2 wbtr:flex wbtr:flex-col wbtr:gap-2 wbtr:border wbtr:border-editor-border wbtr:p-2">
225
240
  <p className="wbtr:text-12 wbtr:uppercase">{__('Border', 'webentor')}</p>
241
+ {borderInheritedFrom && (
242
+ <InheritedIndicator fromBreakpoint={borderInheritedFrom} />
243
+ )}
226
244
 
227
245
  <div style={containerStyle}>
228
246
  {isLinked ? (
@@ -1 +1,2 @@
1
- export { BorderRadiusPanel } from './panel';
1
+ export { BorderRadiusSettings } from './settings';
2
+ export { getBorderRadiusValues } from './properties';
@@ -1,31 +1,8 @@
1
- import { __ } from '@wordpress/i18n';
1
+ import { WebentorConfig } from '../../../../../types/_webentor-config';
2
+ import { createTwThemeValues } from '../../shared/tw-values';
2
3
 
3
- import { WebentorConfig } from '@webentorCore/types/_webentor-config';
4
-
5
- export const getBorderRadiusValues = (twTheme: WebentorConfig['theme']) => {
6
- const values = Object.keys(twTheme?.borderRadius).map((key) => ({
7
- label: `${key} (${twTheme?.borderRadius[key]})`,
8
- value: key,
9
- }));
10
-
11
- values.unshift({
12
- label: __('None selected', 'webentor'),
13
- value: '',
4
+ export const getBorderRadiusValues = (twTheme: WebentorConfig['theme']) =>
5
+ createTwThemeValues(twTheme, 'borderRadius', '', {
6
+ sort: false,
7
+ labelFormatter: (key, rawValue) => `${key} (${rawValue})`,
14
8
  });
15
-
16
- return values;
17
- };
18
-
19
- // export const getBorderRadiusProperties = (twTheme: WebentorConfig['theme']) => [
20
- // {
21
- // name: 'radius',
22
- // label: __('Radius', 'webentor'),
23
- // values: [
24
- // { label: __('None selected', 'webentor'), value: '' },
25
- // ...Object.keys(twTheme?.borderRadius || {}).map((key) => ({
26
- // label: key,
27
- // value: key,
28
- // })),
29
- // ],
30
- // },
31
- // ];
@@ -1,11 +1,15 @@
1
1
  import { getBlockType } from '@wordpress/blocks';
2
2
  import { Button, SelectControl } from '@wordpress/components';
3
- import { __ } from '@wordpress/i18n';
3
+ import { __, sprintf } from '@wordpress/i18n';
4
4
  import { link, linkOff } from '@wordpress/icons';
5
5
 
6
- import { isEmpty, setImmutably } from '@webentorCore/_utils';
7
-
6
+ import { isEmpty, setImmutably } from '../../../../../_utils';
7
+ import { InheritedIndicator } from '../../../components/InheritedIndicator';
8
8
  import { BlockPanelProps } from '../../../types';
9
+ import {
10
+ getEffectiveObjectValue,
11
+ getObjectInheritedFromBreakpoint,
12
+ } from '../../../utils';
9
13
  import { getBorderRadiusValues } from './properties';
10
14
 
11
15
  interface BorderRadiusSettingsProps extends BlockPanelProps {
@@ -20,26 +24,53 @@ interface BorderRadiusValue {
20
24
  linked?: boolean;
21
25
  }
22
26
 
27
+ type CornerKey = 'topLeft' | 'topRight' | 'bottomRight' | 'bottomLeft';
28
+
23
29
  const WebentorBorderRadiusControl = ({
24
30
  label,
25
31
  value,
26
32
  onChange,
27
33
  twTheme,
34
+ inheritedValue,
35
+ inheritedFrom,
28
36
  }: {
29
37
  label?: string;
30
38
  value?: string;
31
39
  onChange: (value: string) => void;
32
40
  twTheme: any;
41
+ inheritedValue?: string;
42
+ inheritedFrom?: string | null;
33
43
  }) => {
34
- const values = getBorderRadiusValues(twTheme);
44
+ const allValues = getBorderRadiusValues(twTheme);
45
+ const isInherited = !value && !!inheritedValue && !!inheritedFrom;
46
+ const selectClassName = `wbtr:w-24${isInherited ? ' wbtr-inherited-value' : ''}`;
47
+
48
+ let options = allValues;
49
+ if (isInherited) {
50
+ const inheritedLabel =
51
+ allValues.find((o) => o.value === inheritedValue)?.label ??
52
+ inheritedValue;
53
+ options = [
54
+ {
55
+ label: sprintf(
56
+ __('%s (from %s)', 'webentor'),
57
+ inheritedLabel,
58
+ inheritedFrom,
59
+ ),
60
+ value: '',
61
+ },
62
+ ...allValues.filter((o) => o.value !== ''),
63
+ ];
64
+ }
35
65
 
36
66
  return (
37
67
  <SelectControl
38
68
  label={label}
39
69
  value={value ?? ''}
40
- options={values}
70
+ options={options}
71
+ __nextHasNoMarginBottom
41
72
  onChange={onChange}
42
- className="wbtr:w-24"
73
+ className={selectClassName}
43
74
  />
44
75
  );
45
76
  };
@@ -49,6 +80,7 @@ export const BorderRadiusSettings = ({
49
80
  setAttributes,
50
81
  name,
51
82
  breakpoint,
83
+ breakpoints,
52
84
  twTheme,
53
85
  }: BorderRadiusSettingsProps) => {
54
86
  if (!attributes?.border) {
@@ -129,11 +161,42 @@ export const BorderRadiusSettings = ({
129
161
  justifyItems: 'center',
130
162
  };
131
163
 
164
+ const radiusInheritedFrom = breakpoints?.length
165
+ ? getObjectInheritedFromBreakpoint(
166
+ attributes,
167
+ 'border',
168
+ 'borderRadius',
169
+ breakpoint,
170
+ breakpoints,
171
+ )
172
+ : null;
173
+
174
+ // Resolve inherited per-corner values for placeholder display
175
+ const effectiveRadius = breakpoints?.length
176
+ ? getEffectiveObjectValue<BorderRadiusValue>(
177
+ attributes,
178
+ 'border',
179
+ 'borderRadius',
180
+ breakpoint,
181
+ breakpoints,
182
+ )
183
+ : undefined;
184
+
185
+ const getCornerInherited = (corner: CornerKey) => {
186
+ const explicitVal = currentBorderRadius?.[corner];
187
+ if (explicitVal) return { value: undefined, from: null };
188
+ const inherited = effectiveRadius?.[corner];
189
+ return { value: inherited || undefined, from: radiusInheritedFrom };
190
+ };
191
+
132
192
  return (
133
193
  <div className="wbtr:my-2 wbtr:flex wbtr:flex-col wbtr:gap-2 wbtr:border wbtr:border-editor-border wbtr:p-2">
134
194
  <p className="wbtr:text-12 wbtr:uppercase">
135
195
  {__('Border Radius', 'webentor')}
136
196
  </p>
197
+ {radiusInheritedFrom && (
198
+ <InheritedIndicator fromBreakpoint={radiusInheritedFrom} />
199
+ )}
137
200
 
138
201
  <div style={containerStyle}>
139
202
  {isLinked ? (
@@ -144,6 +207,8 @@ export const BorderRadiusSettings = ({
144
207
  value={currentBorderRadius?.topLeft}
145
208
  onChange={(value) => onChange(value, 'topLeft')}
146
209
  twTheme={twTheme}
210
+ inheritedValue={getCornerInherited('topLeft').value}
211
+ inheritedFrom={getCornerInherited('topLeft').from}
147
212
  />
148
213
  </div>
149
214
  </>
@@ -155,6 +220,8 @@ export const BorderRadiusSettings = ({
155
220
  value={currentBorderRadius?.topLeft}
156
221
  onChange={(value) => onChange(value, 'topLeft')}
157
222
  twTheme={twTheme}
223
+ inheritedValue={getCornerInherited('topLeft').value}
224
+ inheritedFrom={getCornerInherited('topLeft').from}
158
225
  />
159
226
  </div>
160
227
  <div style={{ gridColumn: '2', gridRow: '1' }}>
@@ -163,6 +230,8 @@ export const BorderRadiusSettings = ({
163
230
  value={currentBorderRadius?.topRight}
164
231
  onChange={(value) => onChange(value, 'topRight')}
165
232
  twTheme={twTheme}
233
+ inheritedValue={getCornerInherited('topRight').value}
234
+ inheritedFrom={getCornerInherited('topRight').from}
166
235
  />
167
236
  </div>
168
237
  <div style={{ gridColumn: '2', gridRow: '2' }}>
@@ -171,6 +240,8 @@ export const BorderRadiusSettings = ({
171
240
  value={currentBorderRadius?.bottomRight}
172
241
  onChange={(value) => onChange(value, 'bottomRight')}
173
242
  twTheme={twTheme}
243
+ inheritedValue={getCornerInherited('bottomRight').value}
244
+ inheritedFrom={getCornerInherited('bottomRight').from}
174
245
  />
175
246
  </div>
176
247
  <div style={{ gridColumn: '1', gridRow: '2' }}>
@@ -179,6 +250,8 @@ export const BorderRadiusSettings = ({
179
250
  value={currentBorderRadius?.bottomLeft}
180
251
  onChange={(value) => onChange(value, 'bottomLeft')}
181
252
  twTheme={twTheme}
253
+ inheritedValue={getCornerInherited('bottomLeft').value}
254
+ inheritedFrom={getCornerInherited('bottomLeft').from}
182
255
  />
183
256
  </div>
184
257
  </>
@@ -1 +1,5 @@
1
- export { BorderPanel } from './panel';
1
+ import './registration';
2
+
3
+ export { BorderAndRadiusSettings } from './settings';
4
+ export { BorderSettings } from './border/settings';
5
+ export { BorderRadiusSettings } from './border-radius/settings';