@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.
- package/build/.tsbuildinfo +1 -1
- package/build/blocks/food-menu/food-menu-group/FoodMenuPreview.js +2 -2
- package/build/blocks/food-menu/food-menu-group/edit.js +1 -1
- package/build/blocks/form/form-group/index.js +1 -1
- package/build/blocks/gallery/gallery-group/constants.d.ts +1 -19
- package/build/blocks/gallery/gallery-group/constants.d.ts.map +1 -1
- package/build/blocks/gallery/gallery-group/constants.js +1 -8
- package/build/blocks/gallery/gallery-group/edit.d.ts.map +1 -1
- package/build/blocks/gallery/gallery-group/edit.js +3 -19
- package/build/blocks/gallery/gallery-item/index.js +1 -1
- package/build/blocks/gallery/gallery-strip-group/constants.d.ts +34 -0
- package/build/blocks/gallery/gallery-strip-group/constants.d.ts.map +1 -0
- package/build/blocks/gallery/gallery-strip-group/constants.js +17 -0
- package/build/blocks/gallery/gallery-strip-group/edit.d.ts +7 -0
- package/build/blocks/gallery/gallery-strip-group/edit.d.ts.map +1 -0
- package/build/blocks/gallery/gallery-strip-group/edit.js +34 -0
- package/build/blocks/gallery/gallery-strip-group/factory.d.ts +5 -0
- package/build/blocks/gallery/gallery-strip-group/factory.d.ts.map +1 -0
- package/build/blocks/gallery/gallery-strip-group/factory.js +28 -0
- package/build/blocks/gallery/gallery-strip-group/index.d.ts +5 -0
- package/build/blocks/gallery/gallery-strip-group/index.d.ts.map +1 -0
- package/build/blocks/gallery/gallery-strip-group/index.js +7 -0
- package/build/blocks/gallery/gallery-strip-group/types.d.ts +18 -0
- package/build/blocks/gallery/gallery-strip-group/types.d.ts.map +1 -0
- package/build/blocks/gallery/gallery-strip-group/types.js +1 -0
- package/build/blocks/groups/text-and-media-group/index.d.ts.map +1 -1
- package/build/blocks/groups/text-and-media-group/index.js +2 -0
- package/build/blocks/hero/hero-item/index.js +1 -1
- package/build/blocks/review/review-summary-item/constants.d.ts +3 -0
- package/build/blocks/review/review-summary-item/constants.d.ts.map +1 -0
- package/build/blocks/review/review-summary-item/constants.js +2 -0
- package/build/blocks/review/review-summary-item/edit.d.ts +6 -0
- package/build/blocks/review/review-summary-item/edit.d.ts.map +1 -0
- package/build/blocks/review/review-summary-item/edit.js +17 -0
- package/build/blocks/review/review-summary-item/factory.d.ts +5 -0
- package/build/blocks/review/review-summary-item/factory.d.ts.map +1 -0
- package/build/blocks/review/review-summary-item/factory.js +23 -0
- package/build/blocks/review/review-summary-item/index.d.ts +5 -0
- package/build/blocks/review/review-summary-item/index.d.ts.map +1 -0
- package/build/blocks/review/review-summary-item/index.js +5 -0
- package/build/blocks/review/review-summary-item/types.d.ts +11 -0
- package/build/blocks/review/review-summary-item/types.d.ts.map +1 -0
- package/build/blocks/review/review-summary-item/types.js +1 -0
- package/build/blocks/urgency/urgency-item/constants.d.ts +56 -0
- package/build/blocks/urgency/urgency-item/constants.d.ts.map +1 -0
- package/build/blocks/urgency/urgency-item/constants.js +32 -0
- package/build/blocks/urgency/urgency-item/edit.d.ts +7 -0
- package/build/blocks/urgency/urgency-item/edit.d.ts.map +1 -0
- package/build/blocks/urgency/urgency-item/edit.js +83 -0
- package/build/blocks/urgency/urgency-item/factory.d.ts +5 -0
- package/build/blocks/urgency/urgency-item/factory.d.ts.map +1 -0
- package/build/blocks/urgency/urgency-item/factory.js +31 -0
- package/build/blocks/urgency/urgency-item/index.d.ts +5 -0
- package/build/blocks/urgency/urgency-item/index.d.ts.map +1 -0
- package/build/blocks/urgency/urgency-item/index.js +5 -0
- package/build/blocks/urgency/urgency-item/types.d.ts +22 -0
- package/build/blocks/urgency/urgency-item/types.d.ts.map +1 -0
- package/build/blocks/urgency/urgency-item/types.js +1 -0
- package/build/components/GalleryImagesAppender/index.d.ts +5 -0
- package/build/components/GalleryImagesAppender/index.d.ts.map +1 -0
- package/build/components/GalleryImagesAppender/index.js +12 -0
- package/build/constants.d.ts +19 -0
- package/build/constants.d.ts.map +1 -1
- package/build/constants.js +8 -0
- package/build/index.d.ts +6 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -0
- package/package.json +1 -1
- package/src/blocks/food-menu/food-menu-group/FoodMenuPreview.tsx +3 -3
- package/src/blocks/food-menu/food-menu-group/edit.tsx +2 -2
- package/src/blocks/form/form-group/index.ts +1 -1
- package/src/blocks/gallery/gallery-group/constants.ts +1 -8
- package/src/blocks/gallery/gallery-group/edit.tsx +3 -39
- package/src/blocks/gallery/gallery-group/editor.scss +0 -12
- package/src/blocks/gallery/gallery-item/index.ts +1 -1
- package/src/blocks/gallery/gallery-strip-group/constants.ts +22 -0
- package/src/blocks/gallery/gallery-strip-group/edit.tsx +112 -0
- package/src/blocks/gallery/gallery-strip-group/editor.scss +36 -0
- package/src/blocks/gallery/gallery-strip-group/factory.tsx +32 -0
- package/src/blocks/gallery/gallery-strip-group/index.ts +11 -0
- package/src/blocks/gallery/gallery-strip-group/types.ts +20 -0
- package/src/blocks/groups/text-and-media-group/index.ts +2 -0
- package/src/blocks/hero/hero-item/index.ts +1 -1
- package/src/blocks/review/review-summary-item/constants.ts +2 -0
- package/src/blocks/review/review-summary-item/edit.tsx +86 -0
- package/src/blocks/review/review-summary-item/editor.scss +44 -0
- package/src/blocks/review/review-summary-item/factory.tsx +27 -0
- package/src/blocks/review/review-summary-item/index.ts +9 -0
- package/src/blocks/review/review-summary-item/types.ts +11 -0
- package/src/blocks/urgency/urgency-item/constants.ts +39 -0
- package/src/blocks/urgency/urgency-item/edit.tsx +319 -0
- package/src/blocks/urgency/urgency-item/editor.scss +99 -0
- package/src/blocks/urgency/urgency-item/factory.tsx +36 -0
- package/src/blocks/urgency/urgency-item/index.ts +9 -0
- package/src/blocks/urgency/urgency-item/types.ts +23 -0
- package/src/components/GalleryImagesAppender/editor.scss +15 -0
- package/src/components/GalleryImagesAppender/index.tsx +29 -0
- package/src/constants.ts +9 -0
- package/src/editor.scss +4 -0
- 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'
|