@brilo/base-blocks 0.1.47 → 0.1.49

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 (35) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/blocks/contact/contact-group/constants.d.ts +71 -0
  3. package/build/blocks/contact/contact-group/constants.d.ts.map +1 -1
  4. package/build/blocks/contact/contact-group/constants.js +35 -0
  5. package/build/blocks/contact/contact-group/edit.d.ts.map +1 -1
  6. package/build/blocks/contact/contact-group/edit.js +40 -8
  7. package/build/blocks/contact/contact-group/factory.d.ts +3 -3
  8. package/build/blocks/contact/contact-group/factory.d.ts.map +1 -1
  9. package/build/blocks/contact/contact-group/factory.js +33 -8
  10. package/build/blocks/contact/contact-group/index.d.ts +2 -2
  11. package/build/blocks/contact/contact-group/index.d.ts.map +1 -1
  12. package/build/blocks/contact/contact-group/index.js +1 -1
  13. package/build/blocks/contact/contact-group/types.d.ts +29 -6
  14. package/build/blocks/contact/contact-group/types.d.ts.map +1 -1
  15. package/build/blocks/contact/contact-item/buildPreviewStyle.d.ts +24 -0
  16. package/build/blocks/contact/contact-item/buildPreviewStyle.d.ts.map +1 -0
  17. package/build/blocks/contact/contact-item/buildPreviewStyle.js +31 -0
  18. package/build/blocks/contact/contact-item/edit.d.ts.map +1 -1
  19. package/build/blocks/contact/contact-item/edit.js +10 -8
  20. package/build/blocks/contact/contact-item/factory.js +2 -2
  21. package/build/index.d.ts +2 -2
  22. package/build/index.d.ts.map +1 -1
  23. package/build/index.js +1 -1
  24. package/package.json +1 -1
  25. package/src/blocks/contact/contact-group/constants.ts +42 -0
  26. package/src/blocks/contact/contact-group/edit.tsx +200 -20
  27. package/src/blocks/contact/contact-group/editor.scss +19 -0
  28. package/src/blocks/contact/contact-group/factory.tsx +61 -8
  29. package/src/blocks/contact/contact-group/index.ts +10 -2
  30. package/src/blocks/contact/contact-group/types.ts +48 -6
  31. package/src/blocks/contact/contact-item/buildPreviewStyle.ts +69 -0
  32. package/src/blocks/contact/contact-item/edit.tsx +17 -30
  33. package/src/blocks/contact/contact-item/editor.scss +136 -7
  34. package/src/blocks/contact/contact-item/factory.tsx +2 -2
  35. package/src/index.ts +5 -0
package/build/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { ANCHOR_ALIGNMENTS, ANCHOR_COLUMNS, anchorGroupDefaults, createAnchorGroupBlock } from './blocks/anchor/anchor-group';
2
2
  export { ANCHOR_ICON_SIZE_DEFAULT, ANCHOR_ICON_SIZE_RANGE, ANCHOR_ICON_TYPES, anchorItemDefaults, createAnchorItemBlock, createAnchorItemEdit, } from './blocks/anchor/anchor-item';
3
- export { CONTACT_COLUMNS, CONTACT_COLUMNS_CONTEXT, contactGroupDefaults, createContactGroupBlock, } from './blocks/contact/contact-group';
3
+ export { CONTACT_COLUMNS, CONTACT_COLUMNS_CONTEXT, CONTACT_STYLE_CONTEXT, contactGroupDefaults, createContactGroupBlock, } from './blocks/contact/contact-group';
4
4
  export { CONTACT_ICON_SIZE_RANGE, CONTACT_ICON_SIZES, CONTACT_ICON_TYPES, contactItemDefaults, createContactItemBlock, createContactItemEdit, } from './blocks/contact/contact-item';
5
5
  export { accordionItemDefaults, createAccordionItemBlock } from './blocks/accordion/accordion-item';
6
6
  export { accordionGroupDefaults, createAccordionGroupBlock } from './blocks/accordion/accordion-group';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@brilo/base-blocks",
3
- "version": "0.1.47",
3
+ "version": "0.1.49",
4
4
  "author": "Brilo",
5
5
  "main": "./build/index.js",
6
6
  "types": "./build/index.d.ts",
@@ -4,13 +4,55 @@ export const CONTACT_COLUMNS = [2, 3] as const
4
4
 
5
5
  export const CONTACT_COLUMNS_CONTEXT = 'brilo/contact-columns'
6
6
 
7
+ export const CONTACT_STYLE_CONTEXT = 'brilo/contact-style'
8
+
7
9
  export const DEFAULT_SHADOWS = [
8
10
  {value: 'none', label: __('Žádný', 'brilo-blocks')},
9
11
  {value: 'sm', label: __('Malý', 'brilo-blocks')},
10
12
  {value: 'md', label: __('Střední', 'brilo-blocks')},
11
13
  ] as const
12
14
 
15
+ export const DEFAULT_DIRECTIONS = [
16
+ {value: 'vertical', label: __('Vertikální', 'brilo-blocks')},
17
+ {value: 'horizontal', label: __('Horizontální', 'brilo-blocks')},
18
+ ] as const
19
+
13
20
  export const TEXT_ALIGNS = [
14
21
  {value: 'left', label: __('Vlevo', 'brilo-blocks')},
15
22
  {value: 'center', label: __('Na střed', 'brilo-blocks')},
16
23
  ] as const
24
+
25
+ export const DEFAULT_ICON_SIZE = 88
26
+ export const ICON_SIZE_MIN = 4
27
+ export const ICON_SIZE_MAX = 128
28
+
29
+ export const DEFAULT_ICON_SIZE_PRESETS = [
30
+ {value: 8, label: __('XS', 'brilo-blocks')},
31
+ {value: 16, label: __('SM', 'brilo-blocks')},
32
+ {value: 24, label: __('MD', 'brilo-blocks')},
33
+ {value: 32, label: __('LG', 'brilo-blocks')},
34
+ {value: 48, label: __('XL', 'brilo-blocks')},
35
+ ] as const
36
+
37
+ export const DEFAULT_ICON_BACKGROUND_SIZE = 88
38
+ export const ICON_BACKGROUND_SIZE_MIN = 16
39
+ export const ICON_BACKGROUND_SIZE_MAX = 240
40
+
41
+ export const DEFAULT_ICON_BACKGROUND_SIZE_PRESETS = [
42
+ {value: 48, label: __('XS', 'brilo-blocks')},
43
+ {value: 64, label: __('SM', 'brilo-blocks')},
44
+ {value: 88, label: __('Výchozí', 'brilo-blocks')},
45
+ {value: 104, label: __('LG', 'brilo-blocks')},
46
+ {value: 128, label: __('XL', 'brilo-blocks')},
47
+ ] as const
48
+
49
+ export const DEFAULT_ICON_BACKGROUND_SHAPES = [
50
+ {value: 'none', label: __('Žádný', 'brilo-blocks')},
51
+ {value: 'circle', label: __('Kruh', 'brilo-blocks')},
52
+ {value: 'triangle', label: __('Trojúhelník', 'brilo-blocks')},
53
+ {value: 'rhombus', label: __('Kosočtverec', 'brilo-blocks')},
54
+ {value: 'octagon', label: __('Osmiúhelník', 'brilo-blocks')},
55
+ {value: 'bevel', label: __('Zkosený', 'brilo-blocks')},
56
+ {value: 'rabbet', label: __('Drážkovaný', 'brilo-blocks')},
57
+ {value: 'parallelogram', label: __('Rovnoběžník', 'brilo-blocks')},
58
+ ] as const
@@ -1,20 +1,82 @@
1
1
  import {InspectorControls} from '@wordpress/block-editor'
2
2
  import {
3
3
  BaseControl,
4
+ Button,
4
5
  ColorPalette,
5
6
  PanelBody,
7
+ RangeControl,
8
+ SelectControl,
6
9
  __experimentalToggleGroupControl as ToggleGroupControl,
7
10
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
8
11
  } from '@wordpress/components'
9
12
  import {__} from '@wordpress/i18n'
10
13
  import clsx from 'clsx'
14
+ import type {CSSProperties} from 'react'
15
+ import {ItemSpacingPanel, itemSpacingStyle} from '~/components/ItemSpacingControl'
11
16
  import {useGroupBlock} from '~/hooks/useGroupBlock'
12
17
  import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
13
- import {CONTACT_COLUMNS, DEFAULT_SHADOWS, TEXT_ALIGNS} from './constants'
14
- import type {ContactColumns, ContactGroupAttributes, ContactGroupOptions, ContactShadow, ContactTextAlign} from './types'
18
+ import {
19
+ CONTACT_COLUMNS,
20
+ DEFAULT_DIRECTIONS,
21
+ DEFAULT_ICON_BACKGROUND_SHAPES,
22
+ DEFAULT_ICON_BACKGROUND_SIZE,
23
+ DEFAULT_ICON_BACKGROUND_SIZE_PRESETS,
24
+ DEFAULT_ICON_SIZE,
25
+ DEFAULT_ICON_SIZE_PRESETS,
26
+ DEFAULT_SHADOWS,
27
+ ICON_BACKGROUND_SIZE_MAX,
28
+ ICON_BACKGROUND_SIZE_MIN,
29
+ ICON_SIZE_MAX,
30
+ ICON_SIZE_MIN,
31
+ TEXT_ALIGNS,
32
+ } from './constants'
33
+ import type {
34
+ ContactColumns,
35
+ ContactDirection,
36
+ ContactGroupAttributes,
37
+ ContactGroupOptions,
38
+ ContactIconBackgroundShape,
39
+ ContactShadow,
40
+ ContactSizePreset,
41
+ ContactTextAlign,
42
+ } from './types'
43
+
44
+ function PresetSizeControl({
45
+ label,
46
+ value,
47
+ presets,
48
+ min,
49
+ max,
50
+ onChange,
51
+ }: {
52
+ label: string
53
+ value: number
54
+ presets: readonly ContactSizePreset[]
55
+ min: number
56
+ max: number
57
+ onChange: (v: number) => void
58
+ }) {
59
+ return (
60
+ <BaseControl label={label} id={`contact-group-size-${label}`}>
61
+ <div style={{display: 'flex', gap: 4, marginBottom: 8, flexWrap: 'wrap'}}>
62
+ {presets.map((p) => (
63
+ <Button key={p.label} variant={value === p.value ? 'primary' : 'secondary'} size="small" onClick={() => onChange(p.value)}>
64
+ {p.label}
65
+ </Button>
66
+ ))}
67
+ </div>
68
+ <RangeControl value={value} onChange={(v) => onChange(v ?? min)} min={min} max={max} step={1} withInputField />
69
+ </BaseControl>
70
+ )
71
+ }
15
72
 
16
73
  export function createContactGroupEdit(options: ContactGroupOptions) {
17
74
  const COLUMNS = options.columns ?? CONTACT_COLUMNS
75
+ const DIRECTIONS = options.directions ?? DEFAULT_DIRECTIONS
76
+ const SHADOWS = options.shadows ?? DEFAULT_SHADOWS
77
+ const ICON_SIZE_PRESETS = options.iconSizePresets ?? DEFAULT_ICON_SIZE_PRESETS
78
+ const ICON_BACKGROUND_SIZE_PRESETS = options.iconBackgroundSizePresets ?? DEFAULT_ICON_BACKGROUND_SIZE_PRESETS
79
+ const ICON_BACKGROUND_SHAPES = options.iconBackgroundShapes ?? DEFAULT_ICON_BACKGROUND_SHAPES
18
80
 
19
81
  return function Edit({
20
82
  attributes,
@@ -23,19 +85,51 @@ export function createContactGroupEdit(options: ContactGroupOptions) {
23
85
  attributes: ContactGroupAttributes
24
86
  setAttributes: (a: Partial<ContactGroupAttributes>) => void
25
87
  }) {
26
- const {columns, style} = attributes
27
- const {paletteColors} = useTenantColorPalette()
88
+ const {columns, groupBackgroundColor, spacing} = attributes
89
+ const {paletteColors, resolveHex} = useTenantColorPalette()
90
+
91
+ const savedStyle = attributes.style as Partial<ContactGroupAttributes['style']> | undefined
92
+ const style: ContactGroupAttributes['style'] = {
93
+ shadow: SHADOWS[0].value,
94
+ direction: DIRECTIONS[0].value,
95
+ textAlign: 'left',
96
+ borderColor: '',
97
+ backgroundColor: '',
98
+ textColor: '',
99
+ ...savedStyle,
100
+ icon: {
101
+ size: DEFAULT_ICON_SIZE,
102
+ color: '',
103
+ background: '',
104
+ backgroundSize: DEFAULT_ICON_BACKGROUND_SIZE,
105
+ backgroundShape: ICON_BACKGROUND_SHAPES[0].value,
106
+ borderColor: '',
107
+ borderWidth: 1,
108
+ ...savedStyle?.icon,
109
+ },
110
+ }
28
111
 
29
112
  const {blockProps, innerBlocksProps} = useGroupBlock({
30
- blockClassName: clsx(options.blockClassName ?? 'g-contact wp-block-section'),
113
+ blockClassName: clsx(
114
+ options.blockClassName ?? 'g-contact wp-block-section',
115
+ `--direction-${style.direction}`,
116
+ groupBackgroundColor && '--group-background',
117
+ spacing === 0 && '--connected',
118
+ ),
31
119
  containerClassName: [options.containerClassName ?? 'g-contact__items', `--cols-${columns}`],
32
- containerStyle: {'--grid-max-col-count': columns},
120
+ containerStyle: {'--grid-max-col-count': columns, ...itemSpacingStyle(spacing)},
33
121
  allowedBlocks: options.allowedBlocks,
34
122
  orientation: 'horizontal',
35
123
  template: options.template,
36
124
  layout: {type: 'default'},
37
125
  })
38
126
 
127
+ const groupStyle = (
128
+ groupBackgroundColor
129
+ ? {...(blockProps.style as CSSProperties), '--group-background-color': resolveHex(groupBackgroundColor)}
130
+ : (blockProps.style as CSSProperties)
131
+ ) as CSSProperties
132
+
39
133
  return (
40
134
  <>
41
135
  <InspectorControls>
@@ -50,20 +144,52 @@ export function createContactGroupEdit(options: ContactGroupOptions) {
50
144
  <ToggleGroupControlOption key={c} value={String(c)} label={String(c)} />
51
145
  ))}
52
146
  </ToggleGroupControl>
147
+ <ToggleGroupControl
148
+ isBlock
149
+ label={__('Směr', 'brilo-blocks')}
150
+ value={style.direction}
151
+ onChange={(v) => setAttributes({style: {...style, direction: v as ContactDirection}})}
152
+ >
153
+ {DIRECTIONS.map((d) => (
154
+ <ToggleGroupControlOption key={d.value} value={d.value} label={d.label} />
155
+ ))}
156
+ </ToggleGroupControl>
157
+ <ToggleGroupControl
158
+ isBlock
159
+ label={__('Zarovnání', 'brilo-blocks')}
160
+ help={__('Zarovná text i ikonu položky.', 'brilo-blocks')}
161
+ value={style.textAlign}
162
+ onChange={(v) => setAttributes({style: {...style, textAlign: v as ContactTextAlign}})}
163
+ >
164
+ {TEXT_ALIGNS.map((a) => (
165
+ <ToggleGroupControlOption key={a.value} value={a.value} label={a.label} />
166
+ ))}
167
+ </ToggleGroupControl>
53
168
  </PanelBody>
54
169
  <PanelBody title={__('Styl', 'brilo-blocks')}>
170
+ <BaseControl
171
+ label={__('Barva pozadí skupiny', 'brilo-blocks')}
172
+ help={__('Souvislé pozadí za všemi položkami. Vhodné s nulovou mezerou.', 'brilo-blocks')}
173
+ id="contact-group-group-background-color"
174
+ >
175
+ <ColorPalette
176
+ colors={paletteColors}
177
+ value={groupBackgroundColor || undefined}
178
+ onChange={(value) => setAttributes({groupBackgroundColor: value ?? ''})}
179
+ />
180
+ </BaseControl>
55
181
  <ToggleGroupControl
56
182
  isBlock
57
- label={__('Stín', 'brilo-blocks')}
183
+ label={__('Stín položek', 'brilo-blocks')}
58
184
  value={style.shadow}
59
185
  onChange={(v) => setAttributes({style: {...style, shadow: v as ContactShadow}})}
60
186
  >
61
- {DEFAULT_SHADOWS.map((s) => (
187
+ {SHADOWS.map((s) => (
62
188
  <ToggleGroupControlOption key={s.value} value={s.value} label={s.label} />
63
189
  ))}
64
190
  </ToggleGroupControl>
65
191
  <BaseControl
66
- label={__('Barva okraje', 'brilo-blocks')}
192
+ label={__('Barva okraje položek', 'brilo-blocks')}
67
193
  help={__('Bez vybrané barvy se okraj nevykreslí.', 'brilo-blocks')}
68
194
  id="contact-group-border-color"
69
195
  >
@@ -73,7 +199,7 @@ export function createContactGroupEdit(options: ContactGroupOptions) {
73
199
  onChange={(value) => setAttributes({style: {...style, borderColor: value ?? ''}})}
74
200
  />
75
201
  </BaseControl>
76
- <BaseControl label={__('Barva pozadí', 'brilo-blocks')} id="contact-group-background-color">
202
+ <BaseControl label={__('Barva pozadí položek', 'brilo-blocks')} id="contact-group-background-color">
77
203
  <ColorPalette
78
204
  colors={paletteColors}
79
205
  value={style.backgroundColor || undefined}
@@ -87,19 +213,73 @@ export function createContactGroupEdit(options: ContactGroupOptions) {
87
213
  onChange={(value) => setAttributes({style: {...style, textColor: value ?? ''}})}
88
214
  />
89
215
  </BaseControl>
90
- <ToggleGroupControl
91
- isBlock
92
- label={__('Zarovnání textu', 'brilo-blocks')}
93
- value={style.textAlign}
94
- onChange={(v) => setAttributes({style: {...style, textAlign: v as ContactTextAlign}})}
216
+ </PanelBody>
217
+ <PanelBody title={__('Ikona', 'brilo-blocks')} initialOpen={false}>
218
+ <PresetSizeControl
219
+ label={__('Velikost', 'brilo-blocks')}
220
+ value={style.icon.size}
221
+ presets={ICON_SIZE_PRESETS}
222
+ min={ICON_SIZE_MIN}
223
+ max={ICON_SIZE_MAX}
224
+ onChange={(v) => setAttributes({style: {...style, icon: {...style.icon, size: v}}})}
225
+ />
226
+ <BaseControl label={__('Barva', 'brilo-blocks')} id="contact-group-icon-color">
227
+ <ColorPalette
228
+ colors={paletteColors}
229
+ value={style.icon.color || undefined}
230
+ onChange={(value) => setAttributes({style: {...style, icon: {...style.icon, color: value ?? ''}}})}
231
+ />
232
+ </BaseControl>
233
+ <BaseControl label={__('Pozadí', 'brilo-blocks')} id="contact-group-icon-background-color">
234
+ <ColorPalette
235
+ colors={paletteColors}
236
+ value={style.icon.background || undefined}
237
+ onChange={(value) => setAttributes({style: {...style, icon: {...style.icon, background: value ?? ''}}})}
238
+ />
239
+ </BaseControl>
240
+ <PresetSizeControl
241
+ label={__('Velikost pozadí', 'brilo-blocks')}
242
+ value={style.icon.backgroundSize}
243
+ presets={ICON_BACKGROUND_SIZE_PRESETS}
244
+ min={ICON_BACKGROUND_SIZE_MIN}
245
+ max={ICON_BACKGROUND_SIZE_MAX}
246
+ onChange={(v) => setAttributes({style: {...style, icon: {...style.icon, backgroundSize: v}}})}
247
+ />
248
+ {style.icon.background && (
249
+ <SelectControl<string>
250
+ label={__('Tvar pozadí', 'brilo-blocks')}
251
+ value={style.icon.backgroundShape}
252
+ options={[...ICON_BACKGROUND_SHAPES]}
253
+ onChange={(v) =>
254
+ setAttributes({style: {...style, icon: {...style.icon, backgroundShape: v as ContactIconBackgroundShape}}})
255
+ }
256
+ />
257
+ )}
258
+ <BaseControl
259
+ label={__('Barva ohraničení', 'brilo-blocks')}
260
+ help={__('Bez vybrané barvy se okraj nevykreslí.', 'brilo-blocks')}
261
+ id="contact-group-icon-border-color"
95
262
  >
96
- {TEXT_ALIGNS.map((a) => (
97
- <ToggleGroupControlOption key={a.value} value={a.value} label={a.label} />
98
- ))}
99
- </ToggleGroupControl>
263
+ <ColorPalette
264
+ colors={paletteColors}
265
+ value={style.icon.borderColor || undefined}
266
+ onChange={(value) => setAttributes({style: {...style, icon: {...style.icon, borderColor: value ?? ''}}})}
267
+ />
268
+ </BaseControl>
269
+ {style.icon.borderColor && (
270
+ <RangeControl
271
+ label={__('Šířka ohraničení (px)', 'brilo-blocks')}
272
+ value={style.icon.borderWidth}
273
+ onChange={(v) => setAttributes({style: {...style, icon: {...style.icon, borderWidth: v ?? 0}}})}
274
+ min={0}
275
+ max={10}
276
+ step={1}
277
+ />
278
+ )}
100
279
  </PanelBody>
280
+ <ItemSpacingPanel spacing={spacing} onChange={(v) => setAttributes({spacing: v})} />
101
281
  </InspectorControls>
102
- <div {...blockProps}>
282
+ <div {...blockProps} style={groupStyle}>
103
283
  <div {...innerBlocksProps} />
104
284
  </div>
105
285
  </>
@@ -6,6 +6,25 @@
6
6
  gap: 16px;
7
7
  align-items: start;
8
8
  }
9
+
10
+ &.--group-background {
11
+ background-color: var(--group-background-color, transparent);
12
+ border-radius: 4px;
13
+ }
14
+
15
+ // With zero spacing the items sit flush; drop their individual rounding and
16
+ // clip to the group so the background reads as one connected surface.
17
+ &.--connected {
18
+ overflow: hidden;
19
+
20
+ .g-contact__items {
21
+ gap: 0;
22
+ }
23
+
24
+ .i-contact {
25
+ border-radius: 0;
26
+ }
27
+ }
9
28
  }
10
29
  }
11
30
 
@@ -1,17 +1,42 @@
1
1
  import {InnerBlocks} from '@wordpress/block-editor'
2
2
  import type {BlockConfiguration} from '@wordpress/blocks'
3
3
  import {__} from '@wordpress/i18n'
4
- import type {NumberArray} from '~/types'
5
- import {CONTACT_COLUMNS, CONTACT_COLUMNS_CONTEXT, DEFAULT_SHADOWS} from './constants'
4
+ import {ITEM_SPACING_ATTRIBUTE} from '~/components/ItemSpacingControl'
5
+ import type {NumberArray, OptionArray} from '~/types'
6
+ import {
7
+ CONTACT_COLUMNS,
8
+ CONTACT_COLUMNS_CONTEXT,
9
+ CONTACT_STYLE_CONTEXT,
10
+ DEFAULT_DIRECTIONS,
11
+ DEFAULT_ICON_BACKGROUND_SHAPES,
12
+ DEFAULT_ICON_BACKGROUND_SIZE,
13
+ DEFAULT_ICON_SIZE,
14
+ DEFAULT_SHADOWS,
15
+ } from './constants'
6
16
  import {createContactGroupEdit} from './edit'
7
17
  import type {ContactGroupAttributes, ContactGroupOptions} from './types'
8
18
 
9
19
  export type {ContactGroupAttributes, ContactGroupOptions}
10
20
 
11
- export function createContactGroupBlock<TColumns extends NumberArray = typeof CONTACT_COLUMNS>(
12
- options: ContactGroupOptions<TColumns>,
13
- ): BlockConfiguration<ContactGroupAttributes<TColumns[number]>> {
21
+ export function createContactGroupBlock<
22
+ TColumns extends NumberArray = typeof CONTACT_COLUMNS,
23
+ TDirections extends OptionArray = typeof DEFAULT_DIRECTIONS,
24
+ TShadows extends OptionArray = typeof DEFAULT_SHADOWS,
25
+ TIconBackgroundShapes extends OptionArray = typeof DEFAULT_ICON_BACKGROUND_SHAPES,
26
+ >(
27
+ options: ContactGroupOptions<TColumns, TDirections, TShadows, TIconBackgroundShapes>,
28
+ ): BlockConfiguration<
29
+ ContactGroupAttributes<
30
+ TColumns[number],
31
+ TDirections[number]['value'],
32
+ TShadows[number]['value'],
33
+ TIconBackgroundShapes[number]['value']
34
+ >
35
+ > {
14
36
  const columns = options.columns ?? CONTACT_COLUMNS
37
+ const directions = options.directions ?? DEFAULT_DIRECTIONS
38
+ const shadows = options.shadows ?? DEFAULT_SHADOWS
39
+ const iconBackgroundShapes = options.iconBackgroundShapes ?? DEFAULT_ICON_BACKGROUND_SHAPES
15
40
 
16
41
  return {
17
42
  name: options.name,
@@ -21,19 +46,47 @@ export function createContactGroupBlock<TColumns extends NumberArray = typeof CO
21
46
  ...(options.parent && {parent: options.parent}),
22
47
  icon: options.icon ?? 'id-alt',
23
48
  supports: {html: false, customClassName: false},
24
- providesContext: {[CONTACT_COLUMNS_CONTEXT]: 'columns'},
49
+ providesContext: {
50
+ [CONTACT_COLUMNS_CONTEXT]: 'columns',
51
+ [CONTACT_STYLE_CONTEXT]: 'style',
52
+ },
25
53
  attributes: {
26
54
  columns: {
27
55
  type: 'number',
28
56
  default: columns[1] ?? columns[0],
29
57
  enum: [...columns],
30
58
  },
59
+ groupBackgroundColor: {type: 'string', default: ''},
31
60
  style: {
32
61
  type: 'object',
33
- default: {shadow: DEFAULT_SHADOWS[0].value, borderColor: '', backgroundColor: '', textColor: '', textAlign: 'left'},
62
+ default: {
63
+ shadow: shadows[0].value,
64
+ direction: directions[0].value,
65
+ textAlign: 'left',
66
+ borderColor: '',
67
+ backgroundColor: '',
68
+ textColor: '',
69
+ icon: {
70
+ size: DEFAULT_ICON_SIZE,
71
+ color: '',
72
+ background: '',
73
+ backgroundSize: DEFAULT_ICON_BACKGROUND_SIZE,
74
+ backgroundShape: iconBackgroundShapes[0].value,
75
+ borderColor: '',
76
+ borderWidth: 1,
77
+ },
78
+ },
34
79
  },
80
+ ...ITEM_SPACING_ATTRIBUTE,
35
81
  },
36
82
  edit: createContactGroupEdit(options as unknown as ContactGroupOptions),
37
83
  save: () => <InnerBlocks.Content />,
38
- } as unknown as BlockConfiguration<ContactGroupAttributes<TColumns[number]>>
84
+ } as unknown as BlockConfiguration<
85
+ ContactGroupAttributes<
86
+ TColumns[number],
87
+ TDirections[number]['value'],
88
+ TShadows[number]['value'],
89
+ TIconBackgroundShapes[number]['value']
90
+ >
91
+ >
39
92
  }
@@ -1,6 +1,14 @@
1
- export type {ContactColumns, ContactGroupAttributes, ContactGroupOptions} from './types'
1
+ export type {
2
+ ContactColumns,
3
+ ContactDirection,
4
+ ContactGroupAttributes,
5
+ ContactGroupOptions,
6
+ ContactIconBackgroundShape,
7
+ ContactShadow,
8
+ ContactTextAlign,
9
+ } from './types'
2
10
  export {createContactGroupBlock} from './factory'
3
- export {CONTACT_COLUMNS, CONTACT_COLUMNS_CONTEXT} from './constants'
11
+ export {CONTACT_COLUMNS, CONTACT_COLUMNS_CONTEXT, CONTACT_STYLE_CONTEXT} from './constants'
4
12
 
5
13
  import type {ContactGroupOptions} from './types'
6
14
 
@@ -1,23 +1,65 @@
1
- import type {BriloBlockType, NumberArray} from '~/types'
2
- import type {CONTACT_COLUMNS, DEFAULT_SHADOWS, TEXT_ALIGNS} from './constants'
1
+ import type {BriloBlockType, NumberArray, OptionArray} from '~/types'
2
+ import type {
3
+ CONTACT_COLUMNS,
4
+ DEFAULT_DIRECTIONS,
5
+ DEFAULT_ICON_BACKGROUND_SHAPES,
6
+ DEFAULT_SHADOWS,
7
+ TEXT_ALIGNS,
8
+ } from './constants'
3
9
 
4
10
  export type ContactColumns = (typeof CONTACT_COLUMNS)[number]
5
11
 
6
12
  export type ContactShadow = (typeof DEFAULT_SHADOWS)[number]['value']
7
13
 
14
+ export type ContactDirection = (typeof DEFAULT_DIRECTIONS)[number]['value']
15
+
8
16
  export type ContactTextAlign = (typeof TEXT_ALIGNS)[number]['value']
9
17
 
10
- export interface ContactGroupAttributes<TColumns extends number = ContactColumns> extends Record<string, unknown> {
18
+ export type ContactIconBackgroundShape = (typeof DEFAULT_ICON_BACKGROUND_SHAPES)[number]['value']
19
+
20
+ export interface ContactSizePreset {
21
+ value: number
22
+ label: string
23
+ }
24
+
25
+ export interface ContactGroupAttributes<
26
+ TColumns extends number = ContactColumns,
27
+ TDirection extends string = ContactDirection,
28
+ TShadow extends string = ContactShadow,
29
+ TIconBackgroundShape extends string = ContactIconBackgroundShape,
30
+ > extends Record<string, unknown> {
11
31
  columns: TColumns
32
+ groupBackgroundColor: string
12
33
  style: {
13
- shadow: ContactShadow
34
+ shadow: TShadow
35
+ direction: TDirection
36
+ textAlign: ContactTextAlign
14
37
  borderColor: string
15
38
  backgroundColor: string
16
39
  textColor: string
17
- textAlign: ContactTextAlign
40
+ icon: {
41
+ size: number
42
+ color: string
43
+ background: string
44
+ backgroundSize: number
45
+ backgroundShape: TIconBackgroundShape
46
+ borderColor: string
47
+ borderWidth: number
48
+ }
18
49
  }
50
+ spacing?: number
19
51
  }
20
52
 
21
- export interface ContactGroupOptions<TColumns extends NumberArray = typeof CONTACT_COLUMNS> extends BriloBlockType {
53
+ export interface ContactGroupOptions<
54
+ TColumns extends NumberArray = typeof CONTACT_COLUMNS,
55
+ TDirections extends OptionArray = typeof DEFAULT_DIRECTIONS,
56
+ TShadows extends OptionArray = typeof DEFAULT_SHADOWS,
57
+ TIconBackgroundShapes extends OptionArray = typeof DEFAULT_ICON_BACKGROUND_SHAPES,
58
+ > extends BriloBlockType {
22
59
  columns?: TColumns
60
+ directions?: TDirections
61
+ shadows?: TShadows
62
+ iconSizePresets?: readonly ContactSizePreset[]
63
+ iconBackgroundSizePresets?: readonly ContactSizePreset[]
64
+ iconBackgroundShapes?: TIconBackgroundShapes
23
65
  }
@@ -0,0 +1,69 @@
1
+ import clsx from 'clsx'
2
+
3
+ export interface ContactSharedStyle {
4
+ direction?: string
5
+ textAlign?: string
6
+ shadow?: string
7
+ borderColor?: string
8
+ backgroundColor?: string
9
+ textColor?: string
10
+ icon?: {
11
+ size?: number
12
+ color?: string
13
+ background?: string
14
+ backgroundSize?: number
15
+ backgroundShape?: string
16
+ borderColor?: string
17
+ borderWidth?: number
18
+ }
19
+ }
20
+
21
+ export interface ContactPreviewStyle {
22
+ rootClassName: string
23
+ iconClassName: string
24
+ cssVars: Record<string, string>
25
+ }
26
+
27
+ export function buildContactPreviewStyle(
28
+ shared?: ContactSharedStyle,
29
+ resolveHex: (value: string) => string = (value) => value,
30
+ ): ContactPreviewStyle {
31
+ if (!shared) {
32
+ return {rootClassName: '', iconClassName: '', cssVars: {}}
33
+ }
34
+
35
+ const icon = shared.icon ?? {}
36
+
37
+ const rootClassName = clsx(
38
+ shared.direction && `--direction-${shared.direction}`,
39
+ shared.textAlign && `--align-${shared.textAlign}`,
40
+ shared.shadow && shared.shadow !== 'none' && `--shadow --shadow-${shared.shadow}`,
41
+ icon.background && icon.background !== 'none' && '--icon-background',
42
+ icon.color && icon.color !== 'none' && '--icon-color',
43
+ icon.borderColor && '--icon-bordered',
44
+ shared.backgroundColor && '--background-color',
45
+ shared.borderColor && '--border',
46
+ shared.textColor && '--text-color',
47
+ )
48
+
49
+ const iconClassName = clsx(
50
+ icon.backgroundShape && icon.backgroundShape !== 'none' && `--background-shape --background-shape-${icon.backgroundShape}`,
51
+ )
52
+
53
+ const cssVars: Record<string, string> = {}
54
+ if (shared.borderColor) cssVars['--border-color'] = resolveHex(shared.borderColor)
55
+ if (shared.backgroundColor) cssVars['--background-color'] = resolveHex(shared.backgroundColor)
56
+ if (shared.textColor) cssVars['--text-color'] = resolveHex(shared.textColor)
57
+ if (icon.background && icon.background !== 'none') cssVars['--icon-background-color'] = resolveHex(icon.background)
58
+ if (icon.color && icon.color !== 'none') cssVars['--icon-color'] = resolveHex(icon.color)
59
+ if (icon.size) cssVars['--icon-size'] = `${icon.size}px`
60
+ if (icon.background && icon.background !== 'none' && icon.backgroundSize) {
61
+ cssVars['--icon-background-size'] = `${icon.backgroundSize}px`
62
+ }
63
+ if (icon.borderColor) {
64
+ cssVars['--icon-outline-color'] = resolveHex(icon.borderColor)
65
+ cssVars['--icon-outline-width'] = `${icon.borderWidth || 1}px`
66
+ }
67
+
68
+ return {rootClassName, iconClassName, cssVars}
69
+ }