@brilo/base-blocks 0.1.50 → 0.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/.tsbuildinfo +1 -1
- package/build/blocks/accordion/accordion-group/edit.d.ts.map +1 -1
- package/build/blocks/accordion/accordion-group/edit.js +8 -2
- package/build/blocks/accordion/accordion-group/factory.d.ts.map +1 -1
- package/build/blocks/accordion/accordion-group/factory.js +20 -11
- package/build/blocks/accordion/accordion-group/index.d.ts +2 -1
- package/build/blocks/accordion/accordion-group/index.d.ts.map +1 -1
- package/build/blocks/accordion/accordion-group/index.js +1 -0
- package/build/blocks/accordion/accordion-group/types.d.ts +8 -0
- package/build/blocks/accordion/accordion-group/types.d.ts.map +1 -1
- package/build/blocks/contact/contact-group/factory.d.ts.map +1 -1
- package/build/blocks/contact/contact-group/types.d.ts.map +1 -1
- package/build/blocks/contact/contact-item/edit.d.ts.map +1 -1
- package/build/blocks/faq/faq-group/constants.d.ts +0 -10
- package/build/blocks/faq/faq-group/constants.d.ts.map +1 -1
- package/build/blocks/faq/faq-group/constants.js +0 -5
- package/build/blocks/faq/faq-group/edit.d.ts.map +1 -1
- package/build/blocks/faq/faq-group/edit.js +6 -4
- package/build/blocks/faq/faq-group/factory.d.ts.map +1 -1
- package/build/blocks/faq/faq-group/factory.js +9 -10
- package/build/blocks/faq/faq-group/types.d.ts +6 -7
- package/build/blocks/faq/faq-group/types.d.ts.map +1 -1
- package/build/blocks/layout/box/constants.d.ts +12 -0
- package/build/blocks/layout/box/constants.d.ts.map +1 -0
- package/build/blocks/layout/box/constants.js +15 -0
- package/build/blocks/layout/box/controls.d.ts.map +1 -1
- package/build/blocks/layout/box/controls.js +6 -5
- package/build/blocks/layout/box/deprecated.d.ts +71 -0
- package/build/blocks/layout/box/deprecated.d.ts.map +1 -0
- package/build/blocks/layout/box/deprecated.js +100 -0
- package/build/blocks/layout/box/edit.d.ts.map +1 -1
- package/build/blocks/layout/box/edit.js +14 -18
- package/build/blocks/layout/box/factory.d.ts.map +1 -1
- package/build/blocks/layout/box/factory.js +4 -2
- package/build/blocks/layout/box/index.d.ts +1 -1
- package/build/blocks/layout/box/index.d.ts.map +1 -1
- package/build/blocks/layout/box/types.d.ts +5 -14
- package/build/blocks/layout/box/types.d.ts.map +1 -1
- package/build/blocks/sections/base-section/controls.d.ts.map +1 -1
- package/build/blocks/sections/base-section/controls.js +4 -3
- package/build/blocks/sections/base-section/types.d.ts +1 -0
- package/build/blocks/sections/base-section/types.d.ts.map +1 -1
- package/build/blocks/step/step-group/edit.d.ts.map +1 -1
- package/build/components/SurfaceStyleControl/index.d.ts +53 -0
- package/build/components/SurfaceStyleControl/index.d.ts.map +1 -0
- package/build/components/SurfaceStyleControl/index.js +36 -0
- package/build/index.d.ts +5 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +2 -1
- package/package.json +1 -1
- package/src/blocks/accordion/accordion-group/edit.tsx +16 -1
- package/src/blocks/accordion/accordion-group/factory.tsx +19 -7
- package/src/blocks/accordion/accordion-group/index.ts +8 -1
- package/src/blocks/accordion/accordion-group/types.ts +11 -1
- package/src/blocks/contact/contact-group/factory.tsx +1 -6
- package/src/blocks/contact/contact-group/types.ts +1 -7
- package/src/blocks/contact/contact-item/edit.tsx +1 -4
- package/src/blocks/faq/faq-group/constants.ts +0 -6
- package/src/blocks/faq/faq-group/edit.tsx +11 -56
- package/src/blocks/faq/faq-group/factory.tsx +6 -6
- package/src/blocks/faq/faq-group/types.ts +6 -7
- package/src/blocks/layout/box/constants.ts +19 -0
- package/src/blocks/layout/box/controls.tsx +42 -21
- package/src/blocks/layout/box/deprecated.tsx +146 -0
- package/src/blocks/layout/box/edit.tsx +15 -18
- package/src/blocks/layout/box/factory.tsx +4 -2
- package/src/blocks/layout/box/index.ts +1 -1
- package/src/blocks/layout/box/types.ts +5 -14
- package/src/blocks/sections/base-section/controls.tsx +10 -1
- package/src/blocks/sections/base-section/types.ts +1 -0
- package/src/blocks/step/step-group/edit.tsx +11 -11
- package/src/components/SurfaceStyleControl/index.tsx +114 -0
- package/src/index.ts +11 -3
|
@@ -1,27 +1,12 @@
|
|
|
1
1
|
import {InspectorControls} from '@wordpress/block-editor'
|
|
2
|
-
import {
|
|
3
|
-
BaseControl,
|
|
4
|
-
Button,
|
|
5
|
-
ColorPalette,
|
|
6
|
-
PanelBody,
|
|
7
|
-
RangeControl,
|
|
8
|
-
SelectControl,
|
|
9
|
-
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
10
|
-
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
11
|
-
} from '@wordpress/components'
|
|
2
|
+
import {BaseControl, Button, ColorPalette, PanelBody, RangeControl, SelectControl} from '@wordpress/components'
|
|
12
3
|
import {__} from '@wordpress/i18n'
|
|
13
4
|
import {ItemSpacingPanel, itemSpacingStyle} from '~/components/ItemSpacingControl'
|
|
5
|
+
import {DEFAULT_SURFACE_SHADOWS, SurfaceStylePanel} from '~/components/SurfaceStyleControl'
|
|
14
6
|
import {useGroupBlock} from '~/hooks/useGroupBlock'
|
|
15
7
|
import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
|
|
16
|
-
import {
|
|
17
|
-
|
|
18
|
-
DEFAULT_ICON_VARIANTS,
|
|
19
|
-
DEFAULT_SHADOWS,
|
|
20
|
-
FAQ_HEADING_LEVELS,
|
|
21
|
-
ICON_SIZE_MAX,
|
|
22
|
-
ICON_SIZE_MIN,
|
|
23
|
-
} from './constants'
|
|
24
|
-
import type {FaqGroupAttributes, FaqGroupOptions, FaqHeadingLevel, FaqIconVariant, FaqShadow, FaqSizePreset} from './types'
|
|
8
|
+
import {DEFAULT_ICON_SIZE_PRESETS, DEFAULT_ICON_VARIANTS, FAQ_HEADING_LEVELS, ICON_SIZE_MAX, ICON_SIZE_MIN} from './constants'
|
|
9
|
+
import type {FaqGroupAttributes, FaqGroupOptions, FaqHeadingLevel, FaqIconVariant, FaqSizePreset} from './types'
|
|
25
10
|
|
|
26
11
|
function PresetSizeControl({
|
|
27
12
|
label,
|
|
@@ -56,6 +41,7 @@ export function createFaqGroupEdit(options: FaqGroupOptions) {
|
|
|
56
41
|
const ICON_VARIANTS = options.iconVariants ?? DEFAULT_ICON_VARIANTS
|
|
57
42
|
const ICON_SIZE_PRESETS = options.iconSizePresets ?? DEFAULT_ICON_SIZE_PRESETS
|
|
58
43
|
const exclude = options.exclude ?? []
|
|
44
|
+
const shadows = options.shadows ?? DEFAULT_SURFACE_SHADOWS
|
|
59
45
|
|
|
60
46
|
return function Edit({
|
|
61
47
|
attributes,
|
|
@@ -123,43 +109,12 @@ export function createFaqGroupEdit(options: FaqGroupOptions) {
|
|
|
123
109
|
)}
|
|
124
110
|
</PanelBody>
|
|
125
111
|
{!exclude.includes('colors') && style && (
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
>
|
|
133
|
-
{DEFAULT_SHADOWS.map((s) => (
|
|
134
|
-
<ToggleGroupControlOption key={s.value} value={s.value} label={s.label} />
|
|
135
|
-
))}
|
|
136
|
-
</ToggleGroupControl>
|
|
137
|
-
<BaseControl
|
|
138
|
-
label={__('Barva okraje', 'brilo-blocks')}
|
|
139
|
-
help={__('Bez vybrané barvy se okraj nevykreslí.', 'brilo-blocks')}
|
|
140
|
-
id="faq-group-border-color"
|
|
141
|
-
>
|
|
142
|
-
<ColorPalette
|
|
143
|
-
colors={paletteColors}
|
|
144
|
-
value={style.borderColor || undefined}
|
|
145
|
-
onChange={(value) => setAttributes({style: {...style, borderColor: value ?? ''}})}
|
|
146
|
-
/>
|
|
147
|
-
</BaseControl>
|
|
148
|
-
<BaseControl label={__('Barva pozadí', 'brilo-blocks')} id="faq-group-background-color">
|
|
149
|
-
<ColorPalette
|
|
150
|
-
colors={paletteColors}
|
|
151
|
-
value={style.backgroundColor || undefined}
|
|
152
|
-
onChange={(value) => setAttributes({style: {...style, backgroundColor: value ?? ''}})}
|
|
153
|
-
/>
|
|
154
|
-
</BaseControl>
|
|
155
|
-
<BaseControl label={__('Barva textu', 'brilo-blocks')} id="faq-group-text-color">
|
|
156
|
-
<ColorPalette
|
|
157
|
-
colors={paletteColors}
|
|
158
|
-
value={style.textColor || undefined}
|
|
159
|
-
onChange={(value) => setAttributes({style: {...style, textColor: value ?? ''}})}
|
|
160
|
-
/>
|
|
161
|
-
</BaseControl>
|
|
162
|
-
</PanelBody>
|
|
112
|
+
<SurfaceStylePanel
|
|
113
|
+
style={style}
|
|
114
|
+
shadows={shadows}
|
|
115
|
+
idPrefix="faq-group"
|
|
116
|
+
onChange={(next) => setAttributes({style: {...style, ...next}})}
|
|
117
|
+
/>
|
|
163
118
|
)}
|
|
164
119
|
<ItemSpacingPanel spacing={spacing} onChange={(v) => setAttributes({spacing: v})} />
|
|
165
120
|
</InspectorControls>
|
|
@@ -3,7 +3,8 @@ import type {BlockConfiguration} from '@wordpress/blocks'
|
|
|
3
3
|
import {__} from '@wordpress/i18n'
|
|
4
4
|
import {ITEM_SPACING_ATTRIBUTE} from '~/components/ItemSpacingControl'
|
|
5
5
|
import type {OptionArray} from '~/types'
|
|
6
|
-
import {
|
|
6
|
+
import {DEFAULT_SURFACE_SHADOWS, surfaceStyleAttribute} from '~/components/SurfaceStyleControl'
|
|
7
|
+
import {DEFAULT_ICON_SIZE, DEFAULT_ICON_VARIANTS, FAQ_HEADING_LEVELS} from './constants'
|
|
7
8
|
import {createFaqGroupEdit} from './edit'
|
|
8
9
|
import type {FaqGroupAttributes, FaqGroupOptions} from './types'
|
|
9
10
|
|
|
@@ -30,13 +31,12 @@ export function createFaqGroupBlock<TIconVariants extends OptionArray = typeof D
|
|
|
30
31
|
}
|
|
31
32
|
|
|
32
33
|
if (!exclude.includes('colors')) {
|
|
34
|
+
const surfaceStyle = surfaceStyleAttribute(options.shadows ?? DEFAULT_SURFACE_SHADOWS)
|
|
35
|
+
|
|
33
36
|
attributes.style = {
|
|
34
|
-
|
|
37
|
+
...surfaceStyle,
|
|
35
38
|
default: {
|
|
36
|
-
|
|
37
|
-
borderColor: '',
|
|
38
|
-
backgroundColor: '',
|
|
39
|
-
textColor: '',
|
|
39
|
+
...surfaceStyle.default,
|
|
40
40
|
icon: {
|
|
41
41
|
color: '',
|
|
42
42
|
background: '',
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import type {SurfaceShadowOption, SurfaceStyle} from '~/components/SurfaceStyleControl'
|
|
1
2
|
import type {BriloBlockType, OptionArray} from '~/types'
|
|
2
|
-
import type {DEFAULT_ICON_VARIANTS,
|
|
3
|
+
import type {DEFAULT_ICON_VARIANTS, FAQ_HEADING_LEVELS} from './constants'
|
|
3
4
|
|
|
4
5
|
export type FaqHeadingLevel = (typeof FAQ_HEADING_LEVELS)[number]
|
|
5
6
|
export type FaqIconVariant = (typeof DEFAULT_ICON_VARIANTS)[number]['value']
|
|
6
|
-
export type FaqShadow =
|
|
7
|
+
export type FaqShadow = SurfaceStyle['shadow']
|
|
7
8
|
|
|
8
9
|
export type ExcludableFaqAttr = 'colors'
|
|
9
10
|
|
|
@@ -15,11 +16,7 @@ export interface FaqSizePreset {
|
|
|
15
16
|
export interface FaqGroupAttributes<TIconVariant extends string = FaqIconVariant> extends Record<string, unknown> {
|
|
16
17
|
headingLevel: FaqHeadingLevel
|
|
17
18
|
iconVariant: TIconVariant
|
|
18
|
-
style: {
|
|
19
|
-
shadow: FaqShadow
|
|
20
|
-
borderColor: string
|
|
21
|
-
backgroundColor: string
|
|
22
|
-
textColor: string
|
|
19
|
+
style: SurfaceStyle<string> & {
|
|
23
20
|
icon: {
|
|
24
21
|
color: string
|
|
25
22
|
background: string
|
|
@@ -33,4 +30,6 @@ export interface FaqGroupOptions<TIconVariants extends OptionArray = typeof DEFA
|
|
|
33
30
|
iconVariants?: TIconVariants
|
|
34
31
|
iconSizePresets?: readonly FaqSizePreset[]
|
|
35
32
|
exclude?: ExcludableFaqAttr[]
|
|
33
|
+
/** Overrides the shared shadow presets — see `DEFAULT_SURFACE_SHADOWS`. */
|
|
34
|
+
shadows?: readonly SurfaceShadowOption[]
|
|
36
35
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import {__} from '@wordpress/i18n'
|
|
2
|
+
import {justifyBottom, justifyLeft, justifyRight, justifyTop} from '@wordpress/icons'
|
|
3
|
+
import type {ReactElement} from 'react'
|
|
4
|
+
import type {BoxSpacingSide} from './types'
|
|
5
|
+
|
|
6
|
+
/** Sides shared by the padding and margin panels, in CSS shorthand order. */
|
|
7
|
+
export const BOX_SPACING_SIDES: readonly {value: BoxSpacingSide; label: string; icon: ReactElement}[] = [
|
|
8
|
+
{value: 'top', label: __('Nahoře', 'brilo-blocks'), icon: justifyTop},
|
|
9
|
+
{value: 'right', label: __('Vpravo', 'brilo-blocks'), icon: justifyRight},
|
|
10
|
+
{value: 'bottom', label: __('Dole', 'brilo-blocks'), icon: justifyBottom},
|
|
11
|
+
{value: 'left', label: __('Vlevo', 'brilo-blocks'), icon: justifyLeft},
|
|
12
|
+
] as const
|
|
13
|
+
|
|
14
|
+
// All box lengths are plain pixel numbers — the same convention as the shared
|
|
15
|
+
// `spacing` attribute — so the editor needs no unit picker and the template
|
|
16
|
+
// appends the unit.
|
|
17
|
+
export const BOX_SPACING_MAX = 120
|
|
18
|
+
export const BOX_BORDER_WIDTH_MAX = 20
|
|
19
|
+
export const BOX_BORDER_RADIUS_MAX = 64
|
|
@@ -1,43 +1,55 @@
|
|
|
1
|
-
import * as blockEditor from '@wordpress/block-editor'
|
|
2
1
|
import {ColorPalette, ContrastChecker} from '@wordpress/block-editor'
|
|
3
|
-
import {
|
|
2
|
+
import {PanelBody, RangeControl} from '@wordpress/components'
|
|
4
3
|
import {__} from '@wordpress/i18n'
|
|
5
|
-
import type {ComponentType} from 'react'
|
|
6
4
|
import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
// `__experimentalBorderRadiusControl` is a real runtime export of @wordpress/block-editor (see
|
|
10
|
-
// packages/block-editor/src/components/border-radius-control) but isn't covered by the community
|
|
11
|
-
// @types/wordpress__block-editor typings, so it's pulled off the namespace import and cast by hand.
|
|
12
|
-
interface BorderRadiusControlProps {
|
|
13
|
-
values?: string | BoxBorderRadius
|
|
14
|
-
onChange: (next: string | BoxBorderRadius | undefined) => void
|
|
15
|
-
}
|
|
16
|
-
const BorderRadiusControl = (blockEditor as unknown as {__experimentalBorderRadiusControl: ComponentType<BorderRadiusControlProps>})
|
|
17
|
-
.__experimentalBorderRadiusControl
|
|
5
|
+
import {BOX_BORDER_RADIUS_MAX, BOX_BORDER_WIDTH_MAX, BOX_SPACING_MAX, BOX_SPACING_SIDES} from './constants'
|
|
6
|
+
import type {BoxAttributes, BoxSpacing} from './types'
|
|
18
7
|
|
|
19
8
|
interface BoxControlsProps {
|
|
20
9
|
attributes: BoxAttributes
|
|
21
10
|
setAttributes: (attrs: Partial<BoxAttributes>) => void
|
|
22
11
|
}
|
|
23
12
|
|
|
13
|
+
function SpacingPanel({title, values, onChange}: {title: string; values: BoxSpacing; onChange: (next: BoxSpacing) => void}) {
|
|
14
|
+
return (
|
|
15
|
+
<PanelBody title={title}>
|
|
16
|
+
{BOX_SPACING_SIDES.map((side) => (
|
|
17
|
+
<RangeControl
|
|
18
|
+
key={side.value}
|
|
19
|
+
label={side.label}
|
|
20
|
+
beforeIcon={side.icon}
|
|
21
|
+
value={values?.[side.value]}
|
|
22
|
+
onChange={(v) => onChange({...values, [side.value]: v})}
|
|
23
|
+
min={0}
|
|
24
|
+
max={BOX_SPACING_MAX}
|
|
25
|
+
step={1}
|
|
26
|
+
allowReset
|
|
27
|
+
withInputField
|
|
28
|
+
/>
|
|
29
|
+
))}
|
|
30
|
+
</PanelBody>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
24
34
|
export function BoxControls({attributes, setAttributes}: BoxControlsProps) {
|
|
25
35
|
const {padding, margin, borderRadius, borderWidth, borderColor, background, textColor} = attributes
|
|
26
36
|
const {paletteColors, resolveHex} = useTenantColorPalette()
|
|
27
37
|
|
|
28
38
|
return (
|
|
29
39
|
<>
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
<BoxControl label={__('Margin', 'brilo-blocks')} values={margin} onChange={(next) => setAttributes({margin: next})} />
|
|
33
|
-
</PanelBody>
|
|
40
|
+
<SpacingPanel title={__('Padding', 'brilo-blocks')} values={padding} onChange={(next) => setAttributes({padding: next})} />
|
|
41
|
+
<SpacingPanel title={__('Margin', 'brilo-blocks')} values={margin} onChange={(next) => setAttributes({margin: next})} />
|
|
34
42
|
|
|
35
43
|
<PanelBody title={__('Ohraničení', 'brilo-blocks')}>
|
|
36
|
-
<
|
|
44
|
+
<RangeControl
|
|
37
45
|
label={__('Šířka okraje', 'brilo-blocks')}
|
|
38
46
|
value={borderWidth}
|
|
47
|
+
onChange={(v) => setAttributes({borderWidth: v ?? 0})}
|
|
39
48
|
min={0}
|
|
40
|
-
|
|
49
|
+
max={BOX_BORDER_WIDTH_MAX}
|
|
50
|
+
step={1}
|
|
51
|
+
allowReset
|
|
52
|
+
withInputField
|
|
41
53
|
/>
|
|
42
54
|
<p>{__('Barva okraje', 'brilo-blocks')}</p>
|
|
43
55
|
<ColorPalette
|
|
@@ -45,7 +57,16 @@ export function BoxControls({attributes, setAttributes}: BoxControlsProps) {
|
|
|
45
57
|
value={borderColor || undefined}
|
|
46
58
|
onChange={(value) => setAttributes({borderColor: value ?? ''})}
|
|
47
59
|
/>
|
|
48
|
-
<
|
|
60
|
+
<RangeControl
|
|
61
|
+
label={__('Zaoblení rohů', 'brilo-blocks')}
|
|
62
|
+
value={borderRadius}
|
|
63
|
+
onChange={(v) => setAttributes({borderRadius: v ?? 0})}
|
|
64
|
+
min={0}
|
|
65
|
+
max={BOX_BORDER_RADIUS_MAX}
|
|
66
|
+
step={1}
|
|
67
|
+
allowReset
|
|
68
|
+
withInputField
|
|
69
|
+
/>
|
|
49
70
|
</PanelBody>
|
|
50
71
|
|
|
51
72
|
<PanelBody title={__('Barvy', 'brilo-blocks')}>
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {InnerBlocks} from '@wordpress/block-editor'
|
|
2
|
+
import type {BoxSpacing, BoxSpacingSide} from './types'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* v1 stored every length as a CSS string (`"16px"`, `"1rem"`) and allowed a
|
|
6
|
+
* per-corner `borderRadius` object. v2 stores plain pixel numbers, so posts
|
|
7
|
+
* saved by v1 have to be migrated — the save output is unchanged
|
|
8
|
+
* (`<InnerBlocks.Content />`), which means block validation never fails and
|
|
9
|
+
* would otherwise leave the legacy values in place, silently rendering
|
|
10
|
+
* `16pxpx`. `isEligible` is what forces the migration.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const BOX_SIDES: readonly BoxSpacingSide[] = ['top', 'right', 'bottom', 'left']
|
|
14
|
+
|
|
15
|
+
interface LegacySpacing {
|
|
16
|
+
top?: string
|
|
17
|
+
right?: string
|
|
18
|
+
bottom?: string
|
|
19
|
+
left?: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface LegacyBorderRadius {
|
|
23
|
+
topLeft?: string
|
|
24
|
+
topRight?: string
|
|
25
|
+
bottomLeft?: string
|
|
26
|
+
bottomRight?: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface LegacyBoxAttributes extends Record<string, unknown> {
|
|
30
|
+
padding: LegacySpacing
|
|
31
|
+
margin: LegacySpacing
|
|
32
|
+
borderRadius: string | LegacyBorderRadius
|
|
33
|
+
borderWidth: string
|
|
34
|
+
borderColor: string
|
|
35
|
+
background: string
|
|
36
|
+
textColor: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Parses a v1 CSS length into pixels. `rem`/`em` are approximated at the
|
|
41
|
+
* 16px browser default; anything else unitless-or-px is taken at face value.
|
|
42
|
+
* Unparseable values become 0, which renders as "no declaration".
|
|
43
|
+
*/
|
|
44
|
+
function toPixels(value: unknown): number {
|
|
45
|
+
if (typeof value === 'number') {
|
|
46
|
+
return Number.isFinite(value) ? value : 0
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (typeof value !== 'string') {
|
|
50
|
+
return 0
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const match = value.trim().match(/^(-?\d*\.?\d+)\s*(px|rem|em)?$/)
|
|
54
|
+
|
|
55
|
+
if (!match) {
|
|
56
|
+
return 0
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const amount = Number.parseFloat(match[1])
|
|
60
|
+
|
|
61
|
+
if (!Number.isFinite(amount)) {
|
|
62
|
+
return 0
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return match[2] === 'rem' || match[2] === 'em' ? Math.round(amount * 16) : Math.round(amount)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function migrateSpacing(spacing: LegacySpacing | undefined): BoxSpacing {
|
|
69
|
+
const next: BoxSpacing = {}
|
|
70
|
+
|
|
71
|
+
for (const side of BOX_SIDES) {
|
|
72
|
+
const pixels = toPixels(spacing?.[side])
|
|
73
|
+
|
|
74
|
+
if (pixels !== 0) {
|
|
75
|
+
next[side] = pixels
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return next
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* v1 could set each corner separately; v2 has a single radius. The first
|
|
84
|
+
* non-zero corner wins — lossy by design, and only for content that actually
|
|
85
|
+
* used per-corner radii.
|
|
86
|
+
*/
|
|
87
|
+
function migrateBorderRadius(radius: string | LegacyBorderRadius | undefined): number {
|
|
88
|
+
if (radius && typeof radius === 'object') {
|
|
89
|
+
for (const corner of ['topLeft', 'topRight', 'bottomRight', 'bottomLeft'] as const) {
|
|
90
|
+
const pixels = toPixels(radius[corner])
|
|
91
|
+
|
|
92
|
+
if (pixels !== 0) {
|
|
93
|
+
return pixels
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return 0
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return toPixels(radius)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** A v1 value still needing conversion: a non-empty string, or a corner object. */
|
|
104
|
+
function isLegacyLength(value: unknown): boolean {
|
|
105
|
+
return (typeof value === 'string' && value !== '') || (!!value && typeof value === 'object')
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function hasLegacyLengths(attributes: LegacyBoxAttributes): boolean {
|
|
109
|
+
for (const spacing of [attributes.padding, attributes.margin]) {
|
|
110
|
+
for (const side of BOX_SIDES) {
|
|
111
|
+
if (isLegacyLength(spacing?.[side])) {
|
|
112
|
+
return true
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return isLegacyLength(attributes.borderWidth) || isLegacyLength(attributes.borderRadius)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export const boxDeprecated = [
|
|
121
|
+
{
|
|
122
|
+
attributes: {
|
|
123
|
+
padding: {type: 'object', default: {}},
|
|
124
|
+
margin: {type: 'object', default: {}},
|
|
125
|
+
borderRadius: {type: ['string', 'object'], default: ''},
|
|
126
|
+
borderWidth: {type: 'string', default: ''},
|
|
127
|
+
borderColor: {type: 'string', default: ''},
|
|
128
|
+
background: {type: 'string', default: ''},
|
|
129
|
+
textColor: {type: 'string', default: ''},
|
|
130
|
+
},
|
|
131
|
+
supports: {html: false, customClassName: false},
|
|
132
|
+
isEligible: (attributes: Record<string, unknown>) => hasLegacyLengths(attributes as LegacyBoxAttributes),
|
|
133
|
+
migrate: (attributes: Record<string, unknown>) => {
|
|
134
|
+
const legacy = attributes as LegacyBoxAttributes
|
|
135
|
+
|
|
136
|
+
return {
|
|
137
|
+
...legacy,
|
|
138
|
+
padding: migrateSpacing(legacy.padding),
|
|
139
|
+
margin: migrateSpacing(legacy.margin),
|
|
140
|
+
borderRadius: migrateBorderRadius(legacy.borderRadius),
|
|
141
|
+
borderWidth: toPixels(legacy.borderWidth),
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
save: () => <InnerBlocks.Content />,
|
|
145
|
+
},
|
|
146
|
+
]
|
|
@@ -4,29 +4,26 @@ import type {CSSProperties} from 'react'
|
|
|
4
4
|
import {BoxControls} from './controls'
|
|
5
5
|
import type {BoxAttributes, BoxOptions} from './types'
|
|
6
6
|
|
|
7
|
+
/** Lengths are stored as plain pixel numbers; the unit is added on render. */
|
|
8
|
+
function px(value: number | undefined): string | undefined {
|
|
9
|
+
return typeof value === 'number' && value !== 0 ? `${value}px` : undefined
|
|
10
|
+
}
|
|
11
|
+
|
|
7
12
|
export function createBoxEdit(options: BoxOptions) {
|
|
8
13
|
return function Edit({attributes, setAttributes}: BlockEditProps<BoxAttributes>) {
|
|
9
14
|
const {padding, margin, borderRadius, borderWidth, borderColor, background, textColor} = attributes
|
|
10
15
|
|
|
11
16
|
const style: CSSProperties = {
|
|
12
|
-
...(padding?.top && {paddingTop: padding
|
|
13
|
-
...(padding?.right && {paddingRight: padding
|
|
14
|
-
...(padding?.bottom && {paddingBottom: padding
|
|
15
|
-
...(padding?.left && {paddingLeft: padding
|
|
16
|
-
...(margin?.top && {marginTop: margin
|
|
17
|
-
...(margin?.right && {marginRight: margin
|
|
18
|
-
...(margin?.bottom && {marginBottom: margin
|
|
19
|
-
...(margin?.left && {marginLeft: margin
|
|
20
|
-
...(
|
|
21
|
-
...(
|
|
22
|
-
? {
|
|
23
|
-
...(borderRadius.topLeft && {borderTopLeftRadius: borderRadius.topLeft}),
|
|
24
|
-
...(borderRadius.topRight && {borderTopRightRadius: borderRadius.topRight}),
|
|
25
|
-
...(borderRadius.bottomLeft && {borderBottomLeftRadius: borderRadius.bottomLeft}),
|
|
26
|
-
...(borderRadius.bottomRight && {borderBottomRightRadius: borderRadius.bottomRight}),
|
|
27
|
-
}
|
|
28
|
-
: {}),
|
|
29
|
-
...(borderWidth && {borderWidth, borderStyle: 'solid' as CSSProperties['borderStyle']}),
|
|
17
|
+
...(px(padding?.top) && {paddingTop: px(padding?.top)}),
|
|
18
|
+
...(px(padding?.right) && {paddingRight: px(padding?.right)}),
|
|
19
|
+
...(px(padding?.bottom) && {paddingBottom: px(padding?.bottom)}),
|
|
20
|
+
...(px(padding?.left) && {paddingLeft: px(padding?.left)}),
|
|
21
|
+
...(px(margin?.top) && {marginTop: px(margin?.top)}),
|
|
22
|
+
...(px(margin?.right) && {marginRight: px(margin?.right)}),
|
|
23
|
+
...(px(margin?.bottom) && {marginBottom: px(margin?.bottom)}),
|
|
24
|
+
...(px(margin?.left) && {marginLeft: px(margin?.left)}),
|
|
25
|
+
...(px(borderRadius) && {borderRadius: px(borderRadius)}),
|
|
26
|
+
...(px(borderWidth) && {borderWidth: px(borderWidth), borderStyle: 'solid' as CSSProperties['borderStyle']}),
|
|
30
27
|
...(borderColor && {borderColor}),
|
|
31
28
|
...(background && {backgroundColor: background}),
|
|
32
29
|
...(textColor && {color: textColor}),
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {InnerBlocks} from '@wordpress/block-editor'
|
|
2
2
|
import type {BlockConfiguration} from '@wordpress/blocks'
|
|
3
3
|
import {__} from '@wordpress/i18n'
|
|
4
|
+
import {boxDeprecated} from './deprecated'
|
|
4
5
|
import {createBoxEdit} from './edit'
|
|
5
6
|
import {icon as defaultIcon} from './icon'
|
|
6
7
|
import type {BoxAttributes, BoxOptions} from './types'
|
|
@@ -19,12 +20,13 @@ export function createBoxBlock(options: BoxOptions): BlockConfiguration<BoxAttri
|
|
|
19
20
|
attributes: {
|
|
20
21
|
padding: {type: 'object', default: {}},
|
|
21
22
|
margin: {type: 'object', default: {}},
|
|
22
|
-
borderRadius: {type:
|
|
23
|
-
borderWidth: {type: '
|
|
23
|
+
borderRadius: {type: 'number', default: 0},
|
|
24
|
+
borderWidth: {type: 'number', default: 0},
|
|
24
25
|
borderColor: {type: 'string', default: ''},
|
|
25
26
|
background: {type: 'string', default: ''},
|
|
26
27
|
textColor: {type: 'string', default: ''},
|
|
27
28
|
},
|
|
29
|
+
deprecated: boxDeprecated,
|
|
28
30
|
edit: createBoxEdit(options),
|
|
29
31
|
save: () => <InnerBlocks.Content />,
|
|
30
32
|
} as BlockConfiguration<BoxAttributes>
|
|
@@ -1,24 +1,15 @@
|
|
|
1
1
|
import type {BriloBlockType} from '~/types'
|
|
2
2
|
|
|
3
|
-
export
|
|
4
|
-
top?: string
|
|
5
|
-
right?: string
|
|
6
|
-
bottom?: string
|
|
7
|
-
left?: string
|
|
8
|
-
}
|
|
3
|
+
export type BoxSpacingSide = 'top' | 'right' | 'bottom' | 'left'
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
topRight?: string
|
|
13
|
-
bottomLeft?: string
|
|
14
|
-
bottomRight?: string
|
|
15
|
-
}
|
|
5
|
+
/** Per-side spacing in pixels. An unset side means "no declaration". */
|
|
6
|
+
export type BoxSpacing = Partial<Record<BoxSpacingSide, number>>
|
|
16
7
|
|
|
17
8
|
export interface BoxAttributes extends Record<string, unknown> {
|
|
18
9
|
padding: BoxSpacing
|
|
19
10
|
margin: BoxSpacing
|
|
20
|
-
borderRadius:
|
|
21
|
-
borderWidth:
|
|
11
|
+
borderRadius: number
|
|
12
|
+
borderWidth: number
|
|
22
13
|
borderColor: string
|
|
23
14
|
background: string
|
|
24
15
|
textColor: string
|
|
@@ -76,8 +76,9 @@ function FluidDecorationControl({label, placement, value, onChange}: FluidDecora
|
|
|
76
76
|
// overriding the frontend once the editor actually writes an explicit value.
|
|
77
77
|
const bgPosition = value?.bgPosition ?? (placement === 'bottom' ? 'left bottom' : 'left top')
|
|
78
78
|
const repeat = value?.repeat ?? 'repeat-x'
|
|
79
|
+
const opacity = value?.opacity ?? BACKGROUND_IMAGE_OPACITY_DEFAULT
|
|
79
80
|
|
|
80
|
-
const update = (patch: Partial<FluidDecoration>) => onChange(mergeUpdate({img, height, fit, bgPosition, repeat}, value, patch))
|
|
81
|
+
const update = (patch: Partial<FluidDecoration>) => onChange(mergeUpdate({img, height, fit, bgPosition, repeat, opacity}, value, patch))
|
|
81
82
|
|
|
82
83
|
const handleSelect = (media: {id: number; url: string; alt: string; width?: number; height?: number}) => {
|
|
83
84
|
const nextImg: FluidDecorationImage = {id: media.id, src: media.url, alt: media.alt ?? '', width: media.width, height: media.height}
|
|
@@ -158,6 +159,14 @@ function FluidDecorationControl({label, placement, value, onChange}: FluidDecora
|
|
|
158
159
|
options={[...BACKGROUND_IMAGE_REPEATS]}
|
|
159
160
|
onChange={(next) => update({repeat: next as BackgroundImageRepeat})}
|
|
160
161
|
/>
|
|
162
|
+
|
|
163
|
+
<RangeControl
|
|
164
|
+
label={__('Průhlednost obrázku', 'brilo-blocks')}
|
|
165
|
+
value={opacity}
|
|
166
|
+
min={0}
|
|
167
|
+
max={100}
|
|
168
|
+
onChange={(next) => update({opacity: next ?? BACKGROUND_IMAGE_OPACITY_DEFAULT})}
|
|
169
|
+
/>
|
|
161
170
|
</>
|
|
162
171
|
)}
|
|
163
172
|
</BaseControl>
|
|
@@ -19,6 +19,7 @@ export interface FluidDecoration {
|
|
|
19
19
|
// key as "position" on top of this object, which would silently clobber a same-named field.
|
|
20
20
|
bgPosition?: BackgroundImagePosition
|
|
21
21
|
repeat?: BackgroundImageRepeat
|
|
22
|
+
opacity?: number
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export type DecorationImage = FluidDecorationImage
|
|
@@ -51,14 +51,14 @@ function normaliseStyle(saved: Partial<StepGroupAttributes['style']> | undefined
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
function PresetSizeControl({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
54
|
+
label,
|
|
55
|
+
id,
|
|
56
|
+
value,
|
|
57
|
+
presets,
|
|
58
|
+
min,
|
|
59
|
+
max,
|
|
60
|
+
onChange,
|
|
61
|
+
}: {
|
|
62
62
|
label: string
|
|
63
63
|
id: string
|
|
64
64
|
value: number
|
|
@@ -85,9 +85,9 @@ export function createStepGroupEdit<TVariants extends OptionArray = typeof DEFAU
|
|
|
85
85
|
const VARIANTS = options.variants ?? DEFAULT_VARIANTS
|
|
86
86
|
|
|
87
87
|
return function Edit({
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
attributes,
|
|
89
|
+
setAttributes,
|
|
90
|
+
}: {
|
|
91
91
|
attributes: StepGroupAttributes
|
|
92
92
|
setAttributes: (a: Partial<StepGroupAttributes>) => void
|
|
93
93
|
}) {
|