@brilo/base-blocks 0.1.51 → 0.1.54
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/career/job-position-group/JobPositionsSelectModal.d.ts.map +1 -1
- package/build/blocks/career/job-position-group/JobPositionsSelectModal.js +1 -1
- package/build/blocks/document/documents-grid/DocumentsSelectModal.d.ts.map +1 -1
- package/build/blocks/document/documents-grid/DocumentsSelectModal.js +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/components/EntitySelectModal/EntitySelectModal.d.ts +1 -1
- package/build/components/EntitySelectModal/EntitySelectModal.d.ts.map +1 -1
- package/build/components/EntitySelectModal/EntitySelectModal.js +1 -1
- package/build/components/LazyDataViews/LazyDataViews.d.ts +8 -0
- package/build/components/LazyDataViews/LazyDataViews.d.ts.map +1 -0
- package/build/components/LazyDataViews/LazyDataViews.js +11 -0
- 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/career/job-position-group/JobPositionsSelectModal.tsx +2 -1
- package/src/blocks/document/documents-grid/DocumentsSelectModal.tsx +2 -1
- 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/components/EntitySelectModal/EntitySelectModal.tsx +2 -1
- package/src/components/LazyDataViews/LazyDataViews.tsx +17 -0
- 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
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import apiFetch from '@wordpress/api-fetch'
|
|
2
2
|
import {Button, Card, CardBody, __experimentalHStack as HStack, Modal, __experimentalVStack as VStack} from '@wordpress/components'
|
|
3
|
-
import
|
|
3
|
+
import type {Field, View} from '@wordpress/dataviews/wp'
|
|
4
|
+
import {LazyDataViews as DataViews} from '~/components/LazyDataViews/LazyDataViews'
|
|
4
5
|
import {__} from '@wordpress/i18n'
|
|
5
6
|
import {arrowDown, arrowUp, close, plusCircle} from '@wordpress/icons'
|
|
6
7
|
// biome-ignore lint/correctness/noUnusedImports: required in scope for classic JSX transform
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import {Spinner} from '@wordpress/components'
|
|
2
|
+
import type {DataViews as DataViewsComponent} from '@wordpress/dataviews/wp'
|
|
3
|
+
// biome-ignore lint/correctness/noUnusedImports: required in scope for classic JSX transform
|
|
4
|
+
import React, {type ComponentProps, lazy, Suspense} from 'react'
|
|
5
|
+
|
|
6
|
+
const DataViews = lazy(() => import('@wordpress/dataviews/wp').then((module) => ({default: module.DataViews})))
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `@wordpress/dataviews/wp` is a ~2 MB prebundle that WP core doesn't expose as a script handle,
|
|
10
|
+
* so a static import gets copied into every block entry that uses it. Loading it via `import()`
|
|
11
|
+
* lets webpack emit a single shared async chunk, fetched only once a picker modal is opened.
|
|
12
|
+
*/
|
|
13
|
+
export const LazyDataViews = ((props: ComponentProps<typeof DataViewsComponent>) => (
|
|
14
|
+
<Suspense fallback={<Spinner />}>
|
|
15
|
+
<DataViews {...props} />
|
|
16
|
+
</Suspense>
|
|
17
|
+
)) as typeof DataViewsComponent
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BaseControl,
|
|
3
|
+
ColorPalette,
|
|
4
|
+
PanelBody,
|
|
5
|
+
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
6
|
+
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
7
|
+
} from '@wordpress/components'
|
|
8
|
+
import {__} from '@wordpress/i18n'
|
|
9
|
+
import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Shadow presets shared by every "surface" block (accordion, faq, ...). The
|
|
13
|
+
* `DEFAULT_` prefix marks it as tenant-overridable — pass your own array as
|
|
14
|
+
* `options.shadows` and the factory/edit resolve it with `??`.
|
|
15
|
+
*/
|
|
16
|
+
export const DEFAULT_SURFACE_SHADOWS = [
|
|
17
|
+
{value: 'none', label: __('Žádný', 'brilo-blocks')},
|
|
18
|
+
{value: 'sm', label: __('Malý', 'brilo-blocks')},
|
|
19
|
+
{value: 'md', label: __('Střední', 'brilo-blocks')},
|
|
20
|
+
] as const
|
|
21
|
+
|
|
22
|
+
export type SurfaceShadow = (typeof DEFAULT_SURFACE_SHADOWS)[number]['value']
|
|
23
|
+
|
|
24
|
+
export interface SurfaceShadowOption {
|
|
25
|
+
value: string
|
|
26
|
+
label: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The shadow + colour quartet that group blocks hand down to their items. Kept
|
|
31
|
+
* as one named type so the shape lives in a single place across TS, PHP and twig.
|
|
32
|
+
*/
|
|
33
|
+
export interface SurfaceStyle<TShadow extends string = SurfaceShadow> {
|
|
34
|
+
shadow: TShadow
|
|
35
|
+
borderColor: string
|
|
36
|
+
backgroundColor: string
|
|
37
|
+
textColor: string
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** Attribute default for a `style` object holding a {@link SurfaceStyle}. */
|
|
41
|
+
export function surfaceStyleAttribute(shadows: readonly SurfaceShadowOption[] = DEFAULT_SURFACE_SHADOWS) {
|
|
42
|
+
return {
|
|
43
|
+
type: 'object',
|
|
44
|
+
default: {
|
|
45
|
+
shadow: shadows[0]?.value ?? 'none',
|
|
46
|
+
borderColor: '',
|
|
47
|
+
backgroundColor: '',
|
|
48
|
+
textColor: '',
|
|
49
|
+
},
|
|
50
|
+
} as const
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Inspector panel for {@link SurfaceStyle}. `idPrefix` keeps the `BaseControl`
|
|
55
|
+
* ids unique per block (`faq-group`, `accordion-group`, ...).
|
|
56
|
+
*/
|
|
57
|
+
export function SurfaceStylePanel<TStyle extends SurfaceStyle<string>>({
|
|
58
|
+
style,
|
|
59
|
+
onChange,
|
|
60
|
+
idPrefix,
|
|
61
|
+
shadows = DEFAULT_SURFACE_SHADOWS,
|
|
62
|
+
title = __('Styl', 'brilo-blocks'),
|
|
63
|
+
children,
|
|
64
|
+
}: {
|
|
65
|
+
style: TStyle
|
|
66
|
+
onChange: (style: TStyle) => void
|
|
67
|
+
idPrefix: string
|
|
68
|
+
shadows?: readonly SurfaceShadowOption[]
|
|
69
|
+
title?: string
|
|
70
|
+
children?: React.ReactNode
|
|
71
|
+
}) {
|
|
72
|
+
const {paletteColors} = useTenantColorPalette()
|
|
73
|
+
|
|
74
|
+
return (
|
|
75
|
+
<PanelBody title={title}>
|
|
76
|
+
<ToggleGroupControl
|
|
77
|
+
isBlock
|
|
78
|
+
label={__('Stín', 'brilo-blocks')}
|
|
79
|
+
value={style.shadow}
|
|
80
|
+
onChange={(value) => onChange({...style, shadow: value as TStyle['shadow']})}
|
|
81
|
+
>
|
|
82
|
+
{shadows.map((shadow) => (
|
|
83
|
+
<ToggleGroupControlOption key={shadow.value} value={shadow.value} label={shadow.label} />
|
|
84
|
+
))}
|
|
85
|
+
</ToggleGroupControl>
|
|
86
|
+
<BaseControl
|
|
87
|
+
label={__('Barva okraje', 'brilo-blocks')}
|
|
88
|
+
help={__('Bez vybrané barvy se okraj nevykreslí.', 'brilo-blocks')}
|
|
89
|
+
id={`${idPrefix}-border-color`}
|
|
90
|
+
>
|
|
91
|
+
<ColorPalette
|
|
92
|
+
colors={paletteColors}
|
|
93
|
+
value={style.borderColor || undefined}
|
|
94
|
+
onChange={(value) => onChange({...style, borderColor: value ?? ''})}
|
|
95
|
+
/>
|
|
96
|
+
</BaseControl>
|
|
97
|
+
<BaseControl label={__('Barva pozadí', 'brilo-blocks')} id={`${idPrefix}-background-color`}>
|
|
98
|
+
<ColorPalette
|
|
99
|
+
colors={paletteColors}
|
|
100
|
+
value={style.backgroundColor || undefined}
|
|
101
|
+
onChange={(value) => onChange({...style, backgroundColor: value ?? ''})}
|
|
102
|
+
/>
|
|
103
|
+
</BaseControl>
|
|
104
|
+
<BaseControl label={__('Barva textu', 'brilo-blocks')} id={`${idPrefix}-text-color`}>
|
|
105
|
+
<ColorPalette
|
|
106
|
+
colors={paletteColors}
|
|
107
|
+
value={style.textColor || undefined}
|
|
108
|
+
onChange={(value) => onChange({...style, textColor: value ?? ''})}
|
|
109
|
+
/>
|
|
110
|
+
</BaseControl>
|
|
111
|
+
{children}
|
|
112
|
+
</PanelBody>
|
|
113
|
+
)
|
|
114
|
+
}
|