@brilo/base-blocks 0.1.58 → 0.1.60

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 (100) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/blocks/food-menu/food-menu-group/FoodMenuPreview.js +2 -2
  3. package/build/blocks/food-menu/food-menu-group/edit.js +1 -1
  4. package/build/blocks/form/form-group/index.js +1 -1
  5. package/build/blocks/gallery/gallery-group/constants.d.ts +1 -19
  6. package/build/blocks/gallery/gallery-group/constants.d.ts.map +1 -1
  7. package/build/blocks/gallery/gallery-group/constants.js +1 -8
  8. package/build/blocks/gallery/gallery-group/edit.d.ts.map +1 -1
  9. package/build/blocks/gallery/gallery-group/edit.js +3 -19
  10. package/build/blocks/gallery/gallery-item/index.js +1 -1
  11. package/build/blocks/gallery/gallery-strip-group/constants.d.ts +34 -0
  12. package/build/blocks/gallery/gallery-strip-group/constants.d.ts.map +1 -0
  13. package/build/blocks/gallery/gallery-strip-group/constants.js +17 -0
  14. package/build/blocks/gallery/gallery-strip-group/edit.d.ts +7 -0
  15. package/build/blocks/gallery/gallery-strip-group/edit.d.ts.map +1 -0
  16. package/build/blocks/gallery/gallery-strip-group/edit.js +34 -0
  17. package/build/blocks/gallery/gallery-strip-group/factory.d.ts +5 -0
  18. package/build/blocks/gallery/gallery-strip-group/factory.d.ts.map +1 -0
  19. package/build/blocks/gallery/gallery-strip-group/factory.js +28 -0
  20. package/build/blocks/gallery/gallery-strip-group/index.d.ts +5 -0
  21. package/build/blocks/gallery/gallery-strip-group/index.d.ts.map +1 -0
  22. package/build/blocks/gallery/gallery-strip-group/index.js +7 -0
  23. package/build/blocks/gallery/gallery-strip-group/types.d.ts +18 -0
  24. package/build/blocks/gallery/gallery-strip-group/types.d.ts.map +1 -0
  25. package/build/blocks/gallery/gallery-strip-group/types.js +1 -0
  26. package/build/blocks/groups/text-and-media-group/index.d.ts.map +1 -1
  27. package/build/blocks/groups/text-and-media-group/index.js +2 -0
  28. package/build/blocks/hero/hero-item/index.js +1 -1
  29. package/build/blocks/review/review-summary-item/constants.d.ts +3 -0
  30. package/build/blocks/review/review-summary-item/constants.d.ts.map +1 -0
  31. package/build/blocks/review/review-summary-item/constants.js +2 -0
  32. package/build/blocks/review/review-summary-item/edit.d.ts +6 -0
  33. package/build/blocks/review/review-summary-item/edit.d.ts.map +1 -0
  34. package/build/blocks/review/review-summary-item/edit.js +17 -0
  35. package/build/blocks/review/review-summary-item/factory.d.ts +5 -0
  36. package/build/blocks/review/review-summary-item/factory.d.ts.map +1 -0
  37. package/build/blocks/review/review-summary-item/factory.js +23 -0
  38. package/build/blocks/review/review-summary-item/index.d.ts +5 -0
  39. package/build/blocks/review/review-summary-item/index.d.ts.map +1 -0
  40. package/build/blocks/review/review-summary-item/index.js +5 -0
  41. package/build/blocks/review/review-summary-item/types.d.ts +11 -0
  42. package/build/blocks/review/review-summary-item/types.d.ts.map +1 -0
  43. package/build/blocks/review/review-summary-item/types.js +1 -0
  44. package/build/blocks/urgency/urgency-item/constants.d.ts +56 -0
  45. package/build/blocks/urgency/urgency-item/constants.d.ts.map +1 -0
  46. package/build/blocks/urgency/urgency-item/constants.js +32 -0
  47. package/build/blocks/urgency/urgency-item/edit.d.ts +7 -0
  48. package/build/blocks/urgency/urgency-item/edit.d.ts.map +1 -0
  49. package/build/blocks/urgency/urgency-item/edit.js +83 -0
  50. package/build/blocks/urgency/urgency-item/factory.d.ts +5 -0
  51. package/build/blocks/urgency/urgency-item/factory.d.ts.map +1 -0
  52. package/build/blocks/urgency/urgency-item/factory.js +31 -0
  53. package/build/blocks/urgency/urgency-item/index.d.ts +5 -0
  54. package/build/blocks/urgency/urgency-item/index.d.ts.map +1 -0
  55. package/build/blocks/urgency/urgency-item/index.js +5 -0
  56. package/build/blocks/urgency/urgency-item/types.d.ts +22 -0
  57. package/build/blocks/urgency/urgency-item/types.d.ts.map +1 -0
  58. package/build/blocks/urgency/urgency-item/types.js +1 -0
  59. package/build/components/GalleryImagesAppender/index.d.ts +5 -0
  60. package/build/components/GalleryImagesAppender/index.d.ts.map +1 -0
  61. package/build/components/GalleryImagesAppender/index.js +12 -0
  62. package/build/constants.d.ts +19 -0
  63. package/build/constants.d.ts.map +1 -1
  64. package/build/constants.js +8 -0
  65. package/build/index.d.ts +6 -0
  66. package/build/index.d.ts.map +1 -1
  67. package/build/index.js +3 -0
  68. package/package.json +1 -1
  69. package/src/blocks/food-menu/food-menu-group/FoodMenuPreview.tsx +3 -3
  70. package/src/blocks/food-menu/food-menu-group/edit.tsx +2 -2
  71. package/src/blocks/form/form-group/index.ts +1 -1
  72. package/src/blocks/gallery/gallery-group/constants.ts +1 -8
  73. package/src/blocks/gallery/gallery-group/edit.tsx +3 -39
  74. package/src/blocks/gallery/gallery-group/editor.scss +0 -12
  75. package/src/blocks/gallery/gallery-item/index.ts +1 -1
  76. package/src/blocks/gallery/gallery-strip-group/constants.ts +22 -0
  77. package/src/blocks/gallery/gallery-strip-group/edit.tsx +112 -0
  78. package/src/blocks/gallery/gallery-strip-group/editor.scss +36 -0
  79. package/src/blocks/gallery/gallery-strip-group/factory.tsx +32 -0
  80. package/src/blocks/gallery/gallery-strip-group/index.ts +11 -0
  81. package/src/blocks/gallery/gallery-strip-group/types.ts +20 -0
  82. package/src/blocks/groups/text-and-media-group/index.ts +2 -0
  83. package/src/blocks/hero/hero-item/index.ts +1 -1
  84. package/src/blocks/review/review-summary-item/constants.ts +2 -0
  85. package/src/blocks/review/review-summary-item/edit.tsx +86 -0
  86. package/src/blocks/review/review-summary-item/editor.scss +44 -0
  87. package/src/blocks/review/review-summary-item/factory.tsx +27 -0
  88. package/src/blocks/review/review-summary-item/index.ts +9 -0
  89. package/src/blocks/review/review-summary-item/types.ts +11 -0
  90. package/src/blocks/urgency/urgency-item/constants.ts +39 -0
  91. package/src/blocks/urgency/urgency-item/edit.tsx +319 -0
  92. package/src/blocks/urgency/urgency-item/editor.scss +99 -0
  93. package/src/blocks/urgency/urgency-item/factory.tsx +36 -0
  94. package/src/blocks/urgency/urgency-item/index.ts +9 -0
  95. package/src/blocks/urgency/urgency-item/types.ts +23 -0
  96. package/src/components/GalleryImagesAppender/editor.scss +15 -0
  97. package/src/components/GalleryImagesAppender/index.tsx +29 -0
  98. package/src/constants.ts +9 -0
  99. package/src/editor.scss +4 -0
  100. package/src/index.ts +6 -0
@@ -0,0 +1,319 @@
1
+ import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
2
+ import {
3
+ BaseControl,
4
+ Button,
5
+ ColorPalette,
6
+ DateTimePicker,
7
+ Notice,
8
+ PanelBody,
9
+ RangeControl,
10
+ TextControl,
11
+ __experimentalToggleGroupControl as ToggleGroupControl,
12
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
13
+ } from '@wordpress/components'
14
+ import {useDispatch} from '@wordpress/data'
15
+ import {dateI18n, getDate, getSettings} from '@wordpress/date'
16
+ import {__} from '@wordpress/i18n'
17
+ import clsx from 'clsx'
18
+ import {type CSSProperties, useEffect} from 'react'
19
+ import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
20
+ import {
21
+ COUNTDOWN_UNITS,
22
+ DEADLINE_DISPLAYS,
23
+ TEXTS,
24
+ NUMBER_SIZE_MAX,
25
+ NUMBER_SIZE_MIN,
26
+ NUMBER_SIZE_PRESETS,
27
+ TEXT_SIZES,
28
+ TYPES,
29
+ } from './constants'
30
+ import type {UrgencyDeadlineDisplay, UrgencyItemAttributes, UrgencyItemOptions, UrgencyTextSize, UrgencyType} from './types'
31
+
32
+ const TEXT_VALUES: string[] = Object.values(TEXTS)
33
+
34
+ function defaultTextFor(type: UrgencyType, display: UrgencyDeadlineDisplay): string {
35
+ return type === 'deadline' ? TEXTS[display] : TEXTS[type]
36
+ }
37
+
38
+ function parseCount(value: string): number | undefined {
39
+ return value === '' ? undefined : Math.max(0, Number.parseInt(value, 10) || 0)
40
+ }
41
+
42
+ function countdownParts(milliseconds: number): Record<(typeof COUNTDOWN_UNITS)[number]['key'], string> {
43
+ const totalSeconds = Math.max(0, Math.floor(milliseconds / 1000))
44
+ const pad = (n: number) => String(n).padStart(2, '0')
45
+
46
+ return {
47
+ days: pad(Math.floor(totalSeconds / 86400)),
48
+ hours: pad(Math.floor((totalSeconds % 86400) / 3600)),
49
+ minutes: pad(Math.floor((totalSeconds % 3600) / 60)),
50
+ seconds: pad(totalSeconds % 60),
51
+ }
52
+ }
53
+
54
+ function formatDeadline(deadline: string): string {
55
+ const {formats} = getSettings()
56
+ const time = deadline.slice(11, 16)
57
+ const format = time === '00:00' || time === '23:59' ? formats.date : `${formats.date} ${formats.time}`
58
+
59
+ return dateI18n(format, getDate(deadline))
60
+ }
61
+
62
+ function endOfDay(date: string): number {
63
+ return getDate(`${date}T23:59:59`).getTime()
64
+ }
65
+
66
+ function ColorControl({label, id, value, onChange}: {label: string; id: string; value: string; onChange: (v: string) => void}) {
67
+ const {paletteColors} = useTenantColorPalette()
68
+
69
+ return (
70
+ <BaseControl label={label} id={id}>
71
+ <ColorPalette colors={paletteColors} value={value || undefined} onChange={(v) => onChange(v ?? '')} />
72
+ </BaseControl>
73
+ )
74
+ }
75
+
76
+ function NumberSizeControl({value, onChange}: {value?: number; onChange: (v?: number) => void}) {
77
+ return (
78
+ <BaseControl
79
+ label={__('Velikost čísel (px)', 'brilo-blocks')}
80
+ help={__('Bez nastavení se použije velikost nadpisu ze šablony.', 'brilo-blocks')}
81
+ id="urgency-item-number-size"
82
+ >
83
+ <div className="i-urgency__number-presets">
84
+ {NUMBER_SIZE_PRESETS.map((p) => (
85
+ <Button key={p.label} variant={value === p.value ? 'primary' : 'secondary'} size="small" onClick={() => onChange(p.value)}>
86
+ {p.label}
87
+ </Button>
88
+ ))}
89
+ </div>
90
+ <RangeControl value={value} onChange={onChange} min={NUMBER_SIZE_MIN} max={NUMBER_SIZE_MAX} step={1} withInputField allowReset />
91
+ </BaseControl>
92
+ )
93
+ }
94
+
95
+ export function createUrgencyItemEdit(options: UrgencyItemOptions) {
96
+ return function Edit({
97
+ attributes,
98
+ setAttributes,
99
+ clientId,
100
+ }: {
101
+ attributes: UrgencyItemAttributes
102
+ setAttributes: (a: Partial<UrgencyItemAttributes>) => void
103
+ clientId: string
104
+ }) {
105
+ const {
106
+ type,
107
+ text,
108
+ deadline,
109
+ display,
110
+ remaining,
111
+ total,
112
+ endDate,
113
+ textSize,
114
+ numberSize,
115
+ backgroundColor,
116
+ numberBackgroundColor,
117
+ textColor,
118
+ } = attributes
119
+ // core/editor is missing outside the post editor (widgets, site editor) – dispatch returns undefined there.
120
+ const editorDispatch = useDispatch('core/editor') as unknown as
121
+ | {lockPostSaving: (lockName: string) => void; unlockPostSaving: (lockName: string) => void}
122
+ | undefined
123
+ const lockPostSaving = editorDispatch?.lockPostSaving
124
+ const unlockPostSaving = editorDispatch?.unlockPostSaving
125
+
126
+ const isDeadlineMissing = type === 'deadline' && !deadline
127
+ const isCapacityMissing = type === 'capacity' && (typeof remaining !== 'number' || typeof total !== 'number' || total <= 0)
128
+ const expiresAt =
129
+ type === 'deadline' && deadline ? getDate(deadline).getTime() : type === 'season' && endDate ? endOfDay(endDate) : null
130
+ const isExpired = expiresAt !== null && expiresAt <= Date.now()
131
+
132
+ useEffect(() => {
133
+ if (!lockPostSaving || !unlockPostSaving) {
134
+ return
135
+ }
136
+
137
+ const lockName = `brilo-urgency-item-${clientId}`
138
+
139
+ if (isDeadlineMissing || isCapacityMissing) {
140
+ lockPostSaving(lockName)
141
+ } else {
142
+ unlockPostSaving(lockName)
143
+ }
144
+
145
+ return () => unlockPostSaving(lockName)
146
+ }, [clientId, isDeadlineMissing, isCapacityMissing, lockPostSaving, unlockPostSaving])
147
+
148
+ const switchText = (nextType: UrgencyType, nextDisplay: UrgencyDeadlineDisplay) =>
149
+ !text || TEXT_VALUES.includes(text) ? {text: defaultTextFor(nextType, nextDisplay)} : {}
150
+
151
+ const countdown = countdownParts(deadline ? getDate(deadline).getTime() - Date.now() : 0)
152
+ const takenPercent =
153
+ type === 'capacity' && total ? Math.min(100, Math.max(0, ((total - Math.min(remaining ?? total, total)) / total) * 100)) : 0
154
+
155
+ const blockProps = useBlockProps({className: clsx(options.blockClassName ?? 'i-urgency wp-block-section', `--${type}`)})
156
+ const isCountdown = type === 'deadline' && display === 'countdown'
157
+ const cardStyle = {
158
+ color: textColor || undefined,
159
+ '--urgency-background': backgroundColor || undefined,
160
+ '--urgency-number-background': numberBackgroundColor || undefined,
161
+ '--urgency-text-color': textColor || undefined,
162
+ '--urgency-number-size': numberSize ? `${numberSize}px` : undefined,
163
+ } as CSSProperties
164
+
165
+ return (
166
+ <>
167
+ <InspectorControls>
168
+ <PanelBody title={__('Nastavení', 'brilo-blocks')}>
169
+ <ToggleGroupControl
170
+ isBlock
171
+ label={__('Co zobrazit', 'brilo-blocks')}
172
+ value={type}
173
+ onChange={(v) => setAttributes({type: v as UrgencyType, ...switchText(v as UrgencyType, display)})}
174
+ >
175
+ {TYPES.map((t) => (
176
+ <ToggleGroupControlOption key={t.value} value={t.value} label={t.label} />
177
+ ))}
178
+ </ToggleGroupControl>
179
+ <TextControl
180
+ label={__('Text', 'brilo-blocks')}
181
+ value={text}
182
+ placeholder={defaultTextFor(type, display)}
183
+ onChange={(v) => setAttributes({text: v})}
184
+ />
185
+ </PanelBody>
186
+
187
+ {type === 'deadline' && (
188
+ <PanelBody title={__('Termín', 'brilo-blocks')}>
189
+ <ToggleGroupControl
190
+ isBlock
191
+ label={__('Zobrazit jako', 'brilo-blocks')}
192
+ value={display}
193
+ onChange={(v) => setAttributes({display: v as UrgencyDeadlineDisplay, ...switchText(type, v as UrgencyDeadlineDisplay)})}
194
+ >
195
+ {DEADLINE_DISPLAYS.map((d) => (
196
+ <ToggleGroupControlOption key={d.value} value={d.value} label={d.label} />
197
+ ))}
198
+ </ToggleGroupControl>
199
+ <DateTimePicker currentDate={deadline || null} onChange={(v) => setAttributes({deadline: v ?? ''})} is12Hour={false} />
200
+ </PanelBody>
201
+ )}
202
+
203
+ {type === 'capacity' && (
204
+ <PanelBody title={__('Volná místa', 'brilo-blocks')}>
205
+ <TextControl
206
+ type="number"
207
+ min={0}
208
+ label={__('Zbývá míst', 'brilo-blocks')}
209
+ value={typeof remaining === 'number' ? String(remaining) : ''}
210
+ onChange={(v) => setAttributes({remaining: parseCount(v)})}
211
+ />
212
+ <TextControl
213
+ type="number"
214
+ min={1}
215
+ label={__('Celkem míst', 'brilo-blocks')}
216
+ value={typeof total === 'number' ? String(total) : ''}
217
+ onChange={(v) => setAttributes({total: parseCount(v)})}
218
+ />
219
+ </PanelBody>
220
+ )}
221
+
222
+ {type === 'season' && (
223
+ <PanelBody title={__('Sezóna', 'brilo-blocks')}>
224
+ <TextControl
225
+ type="date"
226
+ label={__('Konec sezóny (volitelné)', 'brilo-blocks')}
227
+ help={__('Po tomto dni se blok na webu skryje.', 'brilo-blocks')}
228
+ value={endDate}
229
+ onChange={(v) => setAttributes({endDate: v})}
230
+ />
231
+ </PanelBody>
232
+ )}
233
+
234
+ <PanelBody title={__('Styl', 'brilo-blocks')}>
235
+ <ToggleGroupControl
236
+ isBlock
237
+ label={__('Velikost textu', 'brilo-blocks')}
238
+ value={textSize}
239
+ onChange={(v) => setAttributes({textSize: v as UrgencyTextSize})}
240
+ >
241
+ {TEXT_SIZES.map((s) => (
242
+ <ToggleGroupControlOption key={s.value} value={s.value} label={s.label} />
243
+ ))}
244
+ </ToggleGroupControl>
245
+ {type !== 'season' && <NumberSizeControl value={numberSize} onChange={(v) => setAttributes({numberSize: v})} />}
246
+ <ColorControl
247
+ label={__('Barva pozadí', 'brilo-blocks')}
248
+ id="urgency-item-background-color"
249
+ value={backgroundColor}
250
+ onChange={(v) => setAttributes({backgroundColor: v})}
251
+ />
252
+ {isCountdown && (
253
+ <ColorControl
254
+ label={__('Pozadí čísel', 'brilo-blocks')}
255
+ id="urgency-item-number-background-color"
256
+ value={numberBackgroundColor}
257
+ onChange={(v) => setAttributes({numberBackgroundColor: v})}
258
+ />
259
+ )}
260
+ <ColorControl
261
+ label={__('Barva textu', 'brilo-blocks')}
262
+ id="urgency-item-text-color"
263
+ value={textColor}
264
+ onChange={(v) => setAttributes({textColor: v})}
265
+ />
266
+ </PanelBody>
267
+ </InspectorControls>
268
+
269
+ <div {...blockProps}>
270
+ {isDeadlineMissing && (
271
+ <Notice status="error" isDismissible={false}>
272
+ {__('Vyberte termín v postranním panelu – bez něj nelze stránku uložit.', 'brilo-blocks')}
273
+ </Notice>
274
+ )}
275
+ {isCapacityMissing && (
276
+ <Notice status="error" isDismissible={false}>
277
+ {__('Vyplňte volná a celková místa v postranním panelu – bez nich nelze stránku uložit.', 'brilo-blocks')}
278
+ </Notice>
279
+ )}
280
+ {isExpired && (
281
+ <Notice status="warning" isDismissible={false}>
282
+ {__('Termín vypršel – na webu se nezobrazuje.', 'brilo-blocks')}
283
+ </Notice>
284
+ )}
285
+
286
+ <div className={clsx('i-urgency__card', `--text-${textSize}`)} style={cardStyle}>
287
+ {text && <span className="i-urgency__label">{text}</span>}
288
+
289
+ {isCountdown && (
290
+ <span className="i-urgency__countdown">
291
+ {COUNTDOWN_UNITS.map((unit) => (
292
+ <span key={unit.key} className="i-urgency__unit">
293
+ <span className="i-urgency__number">{countdown[unit.key]}</span>
294
+ <span className="i-urgency__unit-label">{unit.label}</span>
295
+ </span>
296
+ ))}
297
+ </span>
298
+ )}
299
+
300
+ {type === 'deadline' && display === 'date' && (
301
+ <span className="i-urgency__value">{deadline ? formatDeadline(deadline) : '—'}</span>
302
+ )}
303
+
304
+ {type === 'capacity' && (
305
+ <>
306
+ <span className="i-urgency__value">
307
+ {remaining ?? '—'} / {total ?? '—'}
308
+ </span>
309
+ <span className="i-urgency__progress">
310
+ <span className="i-urgency__progress-fill" style={{width: `${takenPercent}%`}} />
311
+ </span>
312
+ </>
313
+ )}
314
+ </div>
315
+ </div>
316
+ </>
317
+ )
318
+ }
319
+ }
@@ -0,0 +1,99 @@
1
+ .i-urgency {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 8px;
5
+
6
+ .components-notice {
7
+ margin: 0;
8
+ }
9
+ }
10
+
11
+ .i-urgency__card {
12
+ display: flex;
13
+ flex-direction: column;
14
+ align-items: center;
15
+ gap: 12px;
16
+ padding: 20px 16px;
17
+ border-radius: 8px;
18
+ background: var(--urgency-background, #f3f4f6);
19
+ text-align: center;
20
+
21
+ &.--text-sm {
22
+ .i-urgency__label {
23
+ font-size: 14px;
24
+ }
25
+
26
+ .i-urgency__unit-label {
27
+ font-size: 12px;
28
+ }
29
+ }
30
+
31
+ &.--text-lg {
32
+ .i-urgency__label {
33
+ font-size: 18px;
34
+ }
35
+
36
+ .i-urgency__unit-label {
37
+ font-size: 16px;
38
+ }
39
+ }
40
+ }
41
+
42
+ .i-urgency__label {
43
+ font-size: 16px;
44
+ font-weight: 600;
45
+ }
46
+
47
+ .i-urgency__countdown {
48
+ display: flex;
49
+ flex-wrap: wrap;
50
+ justify-content: center;
51
+ gap: 8px;
52
+ }
53
+
54
+ .i-urgency__unit {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: center;
58
+ gap: 4px;
59
+ min-width: 64px;
60
+ padding: 10px 8px;
61
+ border-radius: 6px;
62
+ background: var(--urgency-number-background, #fff);
63
+ }
64
+
65
+ .i-urgency__number,
66
+ .i-urgency__value {
67
+ font-size: var(--urgency-number-size, 28px);
68
+ font-weight: 700;
69
+ line-height: 1;
70
+ font-variant-numeric: tabular-nums;
71
+ }
72
+
73
+ .i-urgency__unit-label {
74
+ font-size: 14px;
75
+ color: var(--urgency-text-color, #50575e);
76
+ }
77
+
78
+ .i-urgency__progress {
79
+ display: block;
80
+ width: 240px;
81
+ max-width: 100%;
82
+ height: 8px;
83
+ border-radius: 4px;
84
+ background: #fff;
85
+ overflow: hidden;
86
+ }
87
+
88
+ .i-urgency__progress-fill {
89
+ display: block;
90
+ height: 100%;
91
+ background: #1e2d45;
92
+ }
93
+
94
+ .i-urgency__number-presets {
95
+ display: flex;
96
+ flex-wrap: wrap;
97
+ gap: 4px;
98
+ margin-bottom: 8px;
99
+ }
@@ -0,0 +1,36 @@
1
+ import type {BlockConfiguration} from '@wordpress/blocks'
2
+ import {__} from '@wordpress/i18n'
3
+ import {DEADLINE_DISPLAYS, TEXTS, TEXT_SIZES, TYPES} from './constants'
4
+ import {createUrgencyItemEdit} from './edit'
5
+ import type {UrgencyItemAttributes, UrgencyItemOptions} from './types'
6
+
7
+ export type {UrgencyItemAttributes, UrgencyItemOptions}
8
+
9
+ export function createUrgencyItemBlock(options: UrgencyItemOptions): BlockConfiguration<UrgencyItemAttributes> {
10
+ return {
11
+ name: options.name,
12
+ title: options.title ?? __('Naléhavost', 'brilo-blocks'),
13
+ description:
14
+ options.description ?? __('Skutečný termín, počet volných míst nebo sezóna. Po vypršení termínu se na webu skryje.', 'brilo-blocks'),
15
+ category: options.category ?? 'layout',
16
+ ...(options.parent && {parent: options.parent}),
17
+ icon: options.icon ?? 'clock',
18
+ supports: {html: false, customClassName: false},
19
+ attributes: {
20
+ type: {type: 'string', default: TYPES[0].value, enum: TYPES.map((t) => t.value)},
21
+ text: {type: 'string', default: TEXTS.countdown},
22
+ deadline: {type: 'string', default: ''},
23
+ display: {type: 'string', default: DEADLINE_DISPLAYS[0].value, enum: DEADLINE_DISPLAYS.map((d) => d.value)},
24
+ remaining: {type: 'number'},
25
+ total: {type: 'number'},
26
+ endDate: {type: 'string', default: ''},
27
+ textSize: {type: 'string', default: TEXT_SIZES[1].value, enum: TEXT_SIZES.map((s) => s.value)},
28
+ numberSize: {type: 'number'},
29
+ backgroundColor: {type: 'string', default: ''},
30
+ numberBackgroundColor: {type: 'string', default: ''},
31
+ textColor: {type: 'string', default: ''},
32
+ },
33
+ edit: createUrgencyItemEdit(options),
34
+ save: () => null,
35
+ } as unknown as BlockConfiguration<UrgencyItemAttributes>
36
+ }
@@ -0,0 +1,9 @@
1
+ export type {UrgencyItemAttributes, UrgencyItemOptions} from './types'
2
+ export {createUrgencyItemBlock} from './factory'
3
+
4
+ import type {UrgencyItemOptions} from './types'
5
+
6
+ export const urgencyItemDefaults: UrgencyItemOptions = {
7
+ name: 'brilo/urgency-item',
8
+ parent: ['brilo/base-section', 'brilo/text-and-media-group', 'brilo/text-and-form-text-column', 'brilo/column-item'],
9
+ }
@@ -0,0 +1,23 @@
1
+ import type {BriloBlockType} from '~/types'
2
+ import type {DEADLINE_DISPLAYS, TEXT_SIZES, TYPES} from './constants'
3
+
4
+ export type UrgencyType = (typeof TYPES)[number]['value']
5
+ export type UrgencyDeadlineDisplay = (typeof DEADLINE_DISPLAYS)[number]['value']
6
+ export type UrgencyTextSize = (typeof TEXT_SIZES)[number]['value']
7
+
8
+ export interface UrgencyItemAttributes extends Record<string, unknown> {
9
+ type: UrgencyType
10
+ text: string
11
+ deadline: string
12
+ display: UrgencyDeadlineDisplay
13
+ remaining?: number
14
+ total?: number
15
+ endDate: string
16
+ textSize: UrgencyTextSize
17
+ numberSize?: number
18
+ backgroundColor: string
19
+ numberBackgroundColor: string
20
+ textColor: string
21
+ }
22
+
23
+ export interface UrgencyItemOptions extends BriloBlockType {}
@@ -0,0 +1,15 @@
1
+ .g-gallery__appender {
2
+ padding: 16px;
3
+ display: flex;
4
+ align-items: center;
5
+ justify-content: center;
6
+ border: 2px dashed lightblue;
7
+ height: 100%;
8
+ cursor: pointer;
9
+ box-sizing: border-box;
10
+ min-height: 256px;
11
+ width: 100%;
12
+ background: none;
13
+ font: inherit;
14
+ color: inherit;
15
+ }
@@ -0,0 +1,29 @@
1
+ import {MediaUpload} from '@wordpress/block-editor'
2
+ import {createBlock} from '@wordpress/blocks'
3
+ import {useDispatch} from '@wordpress/data'
4
+ import {__} from '@wordpress/i18n'
5
+
6
+ export function GalleryImagesAppender({clientId, itemBlock}: {clientId: string; itemBlock: string}) {
7
+ const {insertBlocks} = useDispatch('core/block-editor')
8
+
9
+ const onSelectImages = (media: {id: number}[]) => {
10
+ insertBlocks(
11
+ media.map((item) => createBlock(itemBlock, {img: {id: item.id}})),
12
+ undefined,
13
+ clientId,
14
+ )
15
+ }
16
+
17
+ return (
18
+ <MediaUpload
19
+ onSelect={onSelectImages}
20
+ multiple="add"
21
+ allowedTypes={['image']}
22
+ render={({open}) => (
23
+ <button type="button" onClick={open} className="g-gallery__appender">
24
+ {__('Přidat obrázky', 'brilo-blocks')}
25
+ </button>
26
+ )}
27
+ />
28
+ )
29
+ }
package/src/constants.ts CHANGED
@@ -18,3 +18,12 @@ export const CONTENT_SIZES = [
18
18
  {value: 'default', label: __('Výchozí', 'brilo-blocks')},
19
19
  {value: 'lg', label: __('Velká', 'brilo-blocks')},
20
20
  ] as const
21
+
22
+ export const GALLERY_RATIOS = [
23
+ {value: '4:3', label: '4:3'},
24
+ {value: '16:9', label: '16:9'},
25
+ {value: '3:2', label: '3:2'},
26
+ {value: '1:1', label: '1:1'},
27
+ {value: '2:1', label: '2:1'},
28
+ {value: '3:4', label: '3:4'},
29
+ ] as const
package/src/editor.scss CHANGED
@@ -47,6 +47,7 @@
47
47
  @forward "./blocks/layout/layout-content/editor";
48
48
  @forward "./blocks/layout/layout-content-w-aside/editor";
49
49
  @forward "./components/IconControl/editor";
50
+ @forward "./components/GalleryImagesAppender/editor";
50
51
  @forward "./components/ImagePicker/editor";
51
52
  @forward "./components/ItemIconControl/editor";
52
53
  @forward "./blocks/priceplan/priceplan-group/editor";
@@ -55,3 +56,6 @@
55
56
  @forward "./blocks/video/video-group/editor";
56
57
  @forward "./blocks/review/review-group/editor";
57
58
  @forward "./blocks/review/review-item/editor";
59
+ @forward "./blocks/review/review-summary-item/editor";
60
+ @forward "./blocks/gallery/gallery-strip-group/editor";
61
+ @forward "./blocks/urgency/urgency-item/editor";
package/src/index.ts CHANGED
@@ -270,3 +270,9 @@ export type {ReviewGroupAttributes, ReviewGroupOptions} from './blocks/review/re
270
270
  export {createReviewGroupBlock, reviewGroupDefaults} from './blocks/review/review-group'
271
271
  export type {ReviewAuthor, ReviewItemAttributes, ReviewItemOptions, ReviewRating} from './blocks/review/review-item'
272
272
  export {createReviewItemBlock, reviewItemDefaults} from './blocks/review/review-item'
273
+ export type {ReviewSummaryItemAttributes, ReviewSummaryItemOptions} from './blocks/review/review-summary-item'
274
+ export {createReviewSummaryItemBlock, reviewSummaryItemDefaults} from './blocks/review/review-summary-item'
275
+ export type {GalleryStripGroupAttributes, GalleryStripGroupOptions} from './blocks/gallery/gallery-strip-group'
276
+ export {createGalleryStripGroupBlock, galleryStripGroupDefaults} from './blocks/gallery/gallery-strip-group'
277
+ export type {UrgencyItemAttributes, UrgencyItemOptions} from './blocks/urgency/urgency-item'
278
+ export {createUrgencyItemBlock, urgencyItemDefaults} from './blocks/urgency/urgency-item'