@brilo/base-blocks 0.1.60 → 0.1.62

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 (165) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/blocks/anchor/anchor-group/icon.js +1 -1
  3. package/build/blocks/career/career-benefits/icon.js +1 -1
  4. package/build/blocks/career/career-header/icon.js +1 -1
  5. package/build/blocks/career/job-position-group/icon.js +1 -1
  6. package/build/blocks/column/column-item/edit.d.ts.map +1 -1
  7. package/build/blocks/column/column-item/index.d.ts.map +1 -1
  8. package/build/blocks/column/column-item/index.js +1 -0
  9. package/build/blocks/compare/compare-option/edit.d.ts +1 -1
  10. package/build/blocks/compare/compare-option/edit.d.ts.map +1 -1
  11. package/build/blocks/compare/compare-option/edit.js +1 -1
  12. package/build/blocks/contact/contact-item/factory.d.ts.map +1 -1
  13. package/build/blocks/document/documents-grid/icon.js +1 -1
  14. package/build/blocks/event/event-detail-content/icon.js +1 -1
  15. package/build/blocks/event/event-detail-header/icon.js +1 -1
  16. package/build/blocks/event/event-list-group/icon.js +1 -1
  17. package/build/blocks/faq/faq-item/edit.d.ts.map +1 -1
  18. package/build/blocks/faq/faq-item/edit.js +2 -2
  19. package/build/blocks/food-menu/food-menu-group/FoodMenuPreview.d.ts.map +1 -1
  20. package/build/blocks/food-menu/food-menu-group/FoodMenuPreview.js +34 -4
  21. package/build/blocks/food-menu/food-menu-group/constants.d.ts +51 -3
  22. package/build/blocks/food-menu/food-menu-group/constants.d.ts.map +1 -1
  23. package/build/blocks/food-menu/food-menu-group/constants.js +32 -6
  24. package/build/blocks/food-menu/food-menu-group/edit.d.ts.map +1 -1
  25. package/build/blocks/food-menu/food-menu-group/edit.js +61 -2
  26. package/build/blocks/food-menu/food-menu-group/factory.d.ts.map +1 -1
  27. package/build/blocks/food-menu/food-menu-group/factory.js +77 -45
  28. package/build/blocks/food-menu/food-menu-group/index.d.ts +1 -1
  29. package/build/blocks/food-menu/food-menu-group/index.d.ts.map +1 -1
  30. package/build/blocks/food-menu/food-menu-group/types.d.ts +12 -5
  31. package/build/blocks/food-menu/food-menu-group/types.d.ts.map +1 -1
  32. package/build/blocks/food-menu/food-reservation/edit.d.ts +7 -0
  33. package/build/blocks/food-menu/food-reservation/edit.d.ts.map +1 -0
  34. package/build/blocks/food-menu/food-reservation/edit.js +69 -0
  35. package/build/blocks/food-menu/food-reservation/factory.d.ts +4 -0
  36. package/build/blocks/food-menu/food-reservation/factory.d.ts.map +1 -0
  37. package/build/blocks/food-menu/food-reservation/factory.js +24 -0
  38. package/build/blocks/food-menu/food-reservation/icon.d.ts +2 -0
  39. package/build/blocks/food-menu/food-reservation/icon.d.ts.map +1 -0
  40. package/build/blocks/food-menu/food-reservation/icon.js +2 -0
  41. package/build/blocks/food-menu/food-reservation/index.d.ts +5 -0
  42. package/build/blocks/food-menu/food-reservation/index.d.ts.map +1 -0
  43. package/build/blocks/food-menu/food-reservation/index.js +6 -0
  44. package/build/blocks/food-menu/food-reservation/types.d.ts +7 -0
  45. package/build/blocks/food-menu/food-reservation/types.d.ts.map +1 -0
  46. package/build/blocks/food-menu/food-reservation/types.js +1 -0
  47. package/build/blocks/form/form-field/types.d.ts +1 -1
  48. package/build/blocks/form/form-field/types.d.ts.map +1 -1
  49. package/build/blocks/groups/banner-group/icon.js +1 -1
  50. package/build/blocks/groups/content-group/icon.js +1 -1
  51. package/build/blocks/hero/hero-group/edit.js +1 -1
  52. package/build/blocks/hero/hero-group/icon.js +1 -1
  53. package/build/blocks/hero/hero-group/types.d.ts +1 -1
  54. package/build/blocks/hero/hero-group/types.d.ts.map +1 -1
  55. package/build/blocks/hero/hero-item/edit.js +1 -1
  56. package/build/blocks/layout/box/icon.js +1 -1
  57. package/build/blocks/layout/layout-aside/edit.d.ts +1 -2
  58. package/build/blocks/layout/layout-aside/edit.d.ts.map +1 -1
  59. package/build/blocks/layout/layout-aside/edit.js +1 -1
  60. package/build/blocks/layout/layout-aside/factory.d.ts.map +1 -1
  61. package/build/blocks/layout/layout-aside/icon.d.ts +1 -2
  62. package/build/blocks/layout/layout-aside/icon.d.ts.map +1 -1
  63. package/build/blocks/layout/layout-aside/icon.js +1 -1
  64. package/build/blocks/layout/layout-content/edit.d.ts +1 -2
  65. package/build/blocks/layout/layout-content/edit.d.ts.map +1 -1
  66. package/build/blocks/layout/layout-content/edit.js +1 -1
  67. package/build/blocks/layout/layout-content/factory.d.ts.map +1 -1
  68. package/build/blocks/layout/layout-content/icon.d.ts +1 -2
  69. package/build/blocks/layout/layout-content/icon.d.ts.map +1 -1
  70. package/build/blocks/layout/layout-content/icon.js +1 -1
  71. package/build/blocks/layout/layout-content-w-aside/edit.d.ts +1 -2
  72. package/build/blocks/layout/layout-content-w-aside/edit.d.ts.map +1 -1
  73. package/build/blocks/layout/layout-content-w-aside/factory.d.ts.map +1 -1
  74. package/build/blocks/layout/layout-content-w-aside/icon.d.ts +1 -2
  75. package/build/blocks/layout/layout-content-w-aside/icon.d.ts.map +1 -1
  76. package/build/blocks/layout/layout-content-w-aside/icon.js +1 -1
  77. package/build/blocks/link/link-item/icon.js +1 -1
  78. package/build/blocks/map/map-group/edit.d.ts.map +1 -1
  79. package/build/blocks/map/map-group/edit.js +1 -1
  80. package/build/blocks/map/map-group/factory.d.ts.map +1 -1
  81. package/build/blocks/map/map-group/types.d.ts.map +1 -1
  82. package/build/blocks/newsletter/newsletter-form/edit.d.ts.map +1 -1
  83. package/build/blocks/newsletter/newsletter-form/edit.js +2 -1
  84. package/build/blocks/person/person-group/icon.js +1 -1
  85. package/build/blocks/person/person-item/constants.d.ts.map +1 -1
  86. package/build/blocks/post/post-content/icon.js +1 -1
  87. package/build/blocks/post/post-content/types.d.ts.map +1 -1
  88. package/build/blocks/post/post-slider-group/icon.js +1 -1
  89. package/build/blocks/post/posts-grid/icon.js +1 -1
  90. package/build/blocks/share/share/icon.js +1 -1
  91. package/build/blocks/signpost/signpost-group/icon.js +1 -1
  92. package/build/blocks/step/step-group/factory.d.ts.map +1 -1
  93. package/build/blocks/step/step-group/icon.js +1 -1
  94. package/build/blocks/testimonial/testimonial-group/icon.js +1 -1
  95. package/build/components/ImagePicker/ImagePicker.d.ts.map +1 -1
  96. package/build/components/ImagePicker/ImagePicker.js +1 -5
  97. package/build/hooks/useGroupBlock.d.ts.map +1 -1
  98. package/build/hooks/useGroupBlock.js +10 -3
  99. package/build/index.d.ts +2 -0
  100. package/build/index.d.ts.map +1 -1
  101. package/build/index.js +1 -0
  102. package/package.json +4 -3
  103. package/src/blocks/anchor/anchor-group/icon.tsx +1 -1
  104. package/src/blocks/career/career-benefits/icon.tsx +1 -1
  105. package/src/blocks/career/career-header/icon.tsx +1 -1
  106. package/src/blocks/career/job-position-group/icon.tsx +1 -1
  107. package/src/blocks/column/column-item/edit.tsx +0 -1
  108. package/src/blocks/column/column-item/index.ts +1 -0
  109. package/src/blocks/compare/compare-option/edit.tsx +1 -1
  110. package/src/blocks/contact/contact-item/factory.tsx +1 -2
  111. package/src/blocks/document/documents-grid/icon.tsx +1 -1
  112. package/src/blocks/event/event-detail-content/icon.tsx +1 -1
  113. package/src/blocks/event/event-detail-header/icon.tsx +1 -1
  114. package/src/blocks/event/event-list-group/icon.tsx +1 -1
  115. package/src/blocks/faq/faq-item/edit.tsx +23 -25
  116. package/src/blocks/food-menu/food-menu-group/FoodMenuPreview.tsx +55 -6
  117. package/src/blocks/food-menu/food-menu-group/constants.ts +37 -6
  118. package/src/blocks/food-menu/food-menu-group/edit.tsx +116 -20
  119. package/src/blocks/food-menu/food-menu-group/editor.scss +35 -6
  120. package/src/blocks/food-menu/food-menu-group/factory.tsx +77 -39
  121. package/src/blocks/food-menu/food-menu-group/index.ts +2 -0
  122. package/src/blocks/food-menu/food-menu-group/types.ts +18 -5
  123. package/src/blocks/food-menu/food-reservation/edit.tsx +179 -0
  124. package/src/blocks/food-menu/food-reservation/factory.tsx +28 -0
  125. package/src/blocks/food-menu/food-reservation/icon.tsx +9 -0
  126. package/src/blocks/food-menu/food-reservation/index.ts +10 -0
  127. package/src/blocks/food-menu/food-reservation/types.ts +8 -0
  128. package/src/blocks/form/form-field/types.ts +1 -7
  129. package/src/blocks/groups/banner-group/edit.tsx +1 -1
  130. package/src/blocks/groups/banner-group/icon.tsx +1 -1
  131. package/src/blocks/groups/content-group/icon.tsx +1 -1
  132. package/src/blocks/hero/hero-group/edit.tsx +3 -3
  133. package/src/blocks/hero/hero-group/icon.tsx +1 -1
  134. package/src/blocks/hero/hero-group/types.ts +1 -1
  135. package/src/blocks/hero/hero-item/edit.tsx +5 -5
  136. package/src/blocks/layout/box/icon.tsx +1 -1
  137. package/src/blocks/layout/layout-aside/edit.tsx +2 -3
  138. package/src/blocks/layout/layout-aside/factory.tsx +0 -1
  139. package/src/blocks/layout/layout-aside/icon.tsx +1 -3
  140. package/src/blocks/layout/layout-content/edit.tsx +2 -3
  141. package/src/blocks/layout/layout-content/factory.tsx +0 -1
  142. package/src/blocks/layout/layout-content/icon.tsx +1 -3
  143. package/src/blocks/layout/layout-content-w-aside/edit.tsx +0 -1
  144. package/src/blocks/layout/layout-content-w-aside/factory.tsx +0 -1
  145. package/src/blocks/layout/layout-content-w-aside/icon.tsx +1 -3
  146. package/src/blocks/link/link-item/icon.tsx +1 -1
  147. package/src/blocks/map/map-group/edit.tsx +8 -3
  148. package/src/blocks/map/map-group/factory.tsx +1 -1
  149. package/src/blocks/map/map-group/types.ts +1 -1
  150. package/src/blocks/newsletter/newsletter-form/edit.tsx +5 -2
  151. package/src/blocks/person/person-group/icon.tsx +1 -1
  152. package/src/blocks/person/person-item/constants.ts +1 -1
  153. package/src/blocks/post/post-content/icon.tsx +1 -1
  154. package/src/blocks/post/post-content/types.ts +0 -1
  155. package/src/blocks/post/post-slider-group/icon.tsx +1 -1
  156. package/src/blocks/post/posts-grid/icon.tsx +1 -1
  157. package/src/blocks/share/share/icon.tsx +1 -1
  158. package/src/blocks/signpost/signpost-group/icon.tsx +1 -1
  159. package/src/blocks/step/step-group/factory.tsx +1 -1
  160. package/src/blocks/step/step-group/icon.tsx +1 -1
  161. package/src/blocks/testimonial/testimonial-group/icon.tsx +1 -1
  162. package/src/components/ImagePicker/ImagePicker.tsx +6 -6
  163. package/src/components/ItemIconControl/types.d.ts +0 -1
  164. package/src/hooks/useGroupBlock.ts +10 -2
  165. package/src/index.ts +2 -0
@@ -0,0 +1,179 @@
1
+ import apiFetch from '@wordpress/api-fetch'
2
+ import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
3
+ import {Button, ExternalLink, Notice, PanelBody, Spinner, TextareaControl} from '@wordpress/components'
4
+ import {__, sprintf} from '@wordpress/i18n'
5
+ import clsx from 'clsx'
6
+ import type React from 'react'
7
+ import {useEffect, useState} from 'react'
8
+ import {icon as reservationIcon} from './icon'
9
+ import type {FoodReservationAttributes, FoodReservationOptions} from './types'
10
+
11
+ type PreviewDay = {
12
+ menuId: number
13
+ date: string
14
+ label: string
15
+ deadline: string
16
+ }
17
+
18
+ type PreviewResponse = {
19
+ enabled: boolean
20
+ settingsUrl: string
21
+ anchor: string
22
+ days: PreviewDay[]
23
+ emptyMessage: string
24
+ }
25
+
26
+ // Shares the menu block's preview card styles (food-menu-group/editor.scss).
27
+ const BASE = 'brilo-food-menu-preview'
28
+
29
+ /**
30
+ * Which days the form would offer is decided on the server (deadlines,
31
+ * sold-out dishes, the site's time zone), so the preview asks the block's
32
+ * own endpoint. It describes the form instead of drawing it.
33
+ */
34
+ function useReservationPreview() {
35
+ const [data, setData] = useState<PreviewResponse | null>(null)
36
+ const [hasError, setHasError] = useState(false)
37
+ const [attempt, setAttempt] = useState(0)
38
+
39
+ // biome-ignore lint/correctness/useExhaustiveDependencies: attempt re-runs the effect on retry
40
+ useEffect(() => {
41
+ let cancelled = false
42
+ setHasError(false)
43
+
44
+ apiFetch<PreviewResponse>({path: '/brilo/v1/food-reservation/preview'})
45
+ .then((result) => {
46
+ if (!cancelled) {
47
+ setData(result)
48
+ }
49
+ })
50
+ .catch(() => {
51
+ if (!cancelled) {
52
+ setHasError(true)
53
+ }
54
+ })
55
+
56
+ return () => {
57
+ cancelled = true
58
+ }
59
+ }, [attempt])
60
+
61
+ return {data, hasError, retry: () => setAttempt((value) => value + 1)}
62
+ }
63
+
64
+ function DisabledNotice({settingsUrl}: {settingsUrl: string}) {
65
+ return (
66
+ <Notice status="warning" isDismissible={false}>
67
+ {__('Rezervace obědů jsou v nastavení modulu vypnuté, blok se na webu nezobrazí.', 'brilo-blocks')}{' '}
68
+ {settingsUrl && <ExternalLink href={settingsUrl}>{__('Nastavení jídelního lístku', 'brilo-blocks')}</ExternalLink>}
69
+ </Notice>
70
+ )
71
+ }
72
+
73
+ function PreviewCard({data, emptyText}: {data: PreviewResponse; emptyText: string}) {
74
+ const [first] = data.days
75
+
76
+ return (
77
+ <div className={`${BASE}__card`}>
78
+ <div className={`${BASE}__head`}>
79
+ <div className={`${BASE}__title`}>
80
+ {reservationIcon}
81
+ <span>{__('Rezervace obědu', 'brilo-blocks')}</span>
82
+ </div>
83
+
84
+ <div className={`${BASE}__meta`}>
85
+ <span className={clsx(`${BASE}__pill`, `${BASE}__pill--muted`)}>{`#${data.anchor}`}</span>
86
+ {first && <span className={clsx(`${BASE}__pill`, `${BASE}__pill--ok`)}>{__('Rezervace otevřené', 'brilo-blocks')}</span>}
87
+ </div>
88
+ </div>
89
+
90
+ <div className={`${BASE}__body`}>
91
+ {first ? (
92
+ <div className={`${BASE}__section`}>
93
+ <div className={`${BASE}__section-title`}>{__('Formulář nabídne dny', 'brilo-blocks')}</div>
94
+
95
+ {data.days.map((day, index) => (
96
+ <div className={clsx(`${BASE}__row`, `${BASE}__row--no-price`)} key={day.menuId}>
97
+ <span className={`${BASE}__unit`}>{0 === index ? __('výchozí', 'brilo-blocks') : ''}</span>
98
+ <span className={`${BASE}__name`}>
99
+ {day.label}
100
+ {day.deadline && <small className={`${BASE}__note`}>{sprintf(__('Uzávěrka: %s', 'brilo-blocks'), day.deadline)}</small>}
101
+ </span>
102
+ </div>
103
+ ))}
104
+ </div>
105
+ ) : (
106
+ <div className={`${BASE}__empty`}>
107
+ <div>
108
+ <b>{__('Teď není na který den rezervovat', 'brilo-blocks')}</b>
109
+ {sprintf(__('Na webu se ukáže věta „%s“', 'brilo-blocks'), emptyText.trim() || data.emptyMessage)}
110
+ </div>
111
+ </div>
112
+ )}
113
+
114
+ <div className={`${BASE}__foot`}>
115
+ <span>{sprintf(__('Odkaz se stránkou?menu=ID#%s předvybere den daného lístku.', 'brilo-blocks'), data.anchor)}</span>
116
+ </div>
117
+ </div>
118
+ </div>
119
+ )
120
+ }
121
+
122
+ export function createFoodReservationEdit(options: FoodReservationOptions) {
123
+ return function Edit({
124
+ attributes,
125
+ setAttributes,
126
+ }: {
127
+ attributes: FoodReservationAttributes
128
+ setAttributes: (a: Partial<FoodReservationAttributes>) => void
129
+ }) {
130
+ const {emptyText} = attributes
131
+ const blockProps = useBlockProps({className: clsx(options.blockClassName ?? 'g-food-reservation')})
132
+ const {data, hasError, retry} = useReservationPreview()
133
+
134
+ let content: React.ReactNode
135
+
136
+ if (hasError) {
137
+ content = (
138
+ <div className={`${BASE}__empty`}>
139
+ <div>
140
+ <b>{__('Náhled se nepodařilo načíst.', 'brilo-blocks')}</b>
141
+ <Button variant="secondary" size="small" className={`${BASE}__retry`} onClick={retry}>
142
+ {__('Zkusit znovu', 'brilo-blocks')}
143
+ </Button>
144
+ </div>
145
+ </div>
146
+ )
147
+ } else if (!data) {
148
+ content = <Spinner />
149
+ } else if (!data.enabled) {
150
+ content = <DisabledNotice settingsUrl={data.settingsUrl} />
151
+ } else {
152
+ content = <PreviewCard data={data} emptyText={emptyText} />
153
+ }
154
+
155
+ return (
156
+ <>
157
+ <InspectorControls>
158
+ <PanelBody title={__('Když není co rezervovat', 'brilo-blocks')}>
159
+ <TextareaControl
160
+ __nextHasNoMarginBottom
161
+ label={__('Vlastní text zprávy', 'brilo-blocks')}
162
+ help={__('Když zůstane prázdné, použije se výchozí věta.', 'brilo-blocks')}
163
+ rows={2}
164
+ value={emptyText}
165
+ onChange={(value) => setAttributes({emptyText: value})}
166
+ />
167
+ </PanelBody>
168
+ </InspectorControls>
169
+
170
+ <div {...blockProps}>
171
+ {/* Left-aligned headings: the menu block's centre default is about the menu, not this list. */}
172
+ <div className={BASE} style={{'--food-menu-preview-align': 'left'} as React.CSSProperties}>
173
+ {content}
174
+ </div>
175
+ </div>
176
+ </>
177
+ )
178
+ }
179
+ }
@@ -0,0 +1,28 @@
1
+ import type {BlockConfiguration} from '@wordpress/blocks'
2
+ import {__} from '@wordpress/i18n'
3
+ import {createFoodReservationEdit} from './edit'
4
+ import {icon as defaultIcon} from './icon'
5
+ import type {FoodReservationAttributes, FoodReservationOptions} from './types'
6
+
7
+ export function createFoodReservationBlock(options: FoodReservationOptions): BlockConfiguration<FoodReservationAttributes> {
8
+ return {
9
+ name: options.name,
10
+ title: options.title ?? __('Rezervace obědu', 'brilo-blocks'),
11
+ description:
12
+ options.description ??
13
+ __('Rezervační formulář přímo na stránce. Tlačítka „Rezervovat oběd“ na něj vedou přes kotvu #rezervace.', 'brilo-blocks'),
14
+ category: options.category ?? 'widgets',
15
+ ...(options.parent && {parent: options.parent}),
16
+ icon: options.icon ?? {src: defaultIcon},
17
+ // The anchor is fixed (`rezervace`), so the block takes no own HTML anchor.
18
+ supports: {html: false, customClassName: false, multiple: false},
19
+ attributes: {
20
+ emptyText: {
21
+ type: 'string',
22
+ default: '',
23
+ },
24
+ },
25
+ edit: createFoodReservationEdit(options),
26
+ save: () => null,
27
+ } as unknown as BlockConfiguration<FoodReservationAttributes>
28
+ }
@@ -0,0 +1,9 @@
1
+ export const icon = (
2
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Rezervace obědu">
3
+ <rect x="3" y="4" width="14" height="13" stroke="currentColor" fill="none" />
4
+ <line x1="3" y1="8" x2="17" y2="8" stroke="currentColor" />
5
+ <line x1="7" y1="2" x2="7" y2="6" stroke="currentColor" />
6
+ <line x1="13" y1="2" x2="13" y2="6" stroke="currentColor" />
7
+ <polyline points="7,12.5 9,14.5 13,10.5" stroke="currentColor" fill="none" />
8
+ </svg>
9
+ )
@@ -0,0 +1,10 @@
1
+ export type {FoodReservationAttributes, FoodReservationOptions} from './types'
2
+ export {createFoodReservationBlock} from './factory'
3
+
4
+ import type {FoodReservationOptions} from './types'
5
+
6
+ export const foodReservationDefaults: FoodReservationOptions = {
7
+ name: 'brilo/food-reservation',
8
+ // A section of its own, or a column next to the day's menu.
9
+ parent: ['brilo/base-section', 'brilo/column-item'],
10
+ }
@@ -0,0 +1,8 @@
1
+ import type {BriloBlockType} from '~/types'
2
+
3
+ export interface FoodReservationAttributes extends Record<string, unknown> {
4
+ /** Empty means "use the server's sentence". */
5
+ emptyText: string
6
+ }
7
+
8
+ export type FoodReservationOptions = BriloBlockType
@@ -1,10 +1,4 @@
1
- import {
2
- type FIELD_SELECT_MODE_VALUES,
3
- FIELD_TEXT_TYPES,
4
- type FIELD_TEXT_TYPE_VALUES,
5
- type FIELD_TYPE_VALUES,
6
- type FILE_BUTTON_VARIANT_VALUES,
7
- } from './constants'
1
+ import type {FIELD_SELECT_MODE_VALUES, FIELD_TEXT_TYPE_VALUES, FIELD_TYPE_VALUES, FILE_BUTTON_VARIANT_VALUES} from './constants'
8
2
  import type {BriloBlockType} from '~/types'
9
3
 
10
4
  export type FormFieldType = (typeof FIELD_TYPE_VALUES)[number]
@@ -8,7 +8,7 @@ import {
8
8
  BaseControl,
9
9
  } from '@wordpress/components'
10
10
  import {__} from '@wordpress/i18n'
11
- import {ImagePickerBody, ImagePickerControl} from '~/components/ImagePicker'
11
+ import {ImagePickerControl} from '~/components/ImagePicker'
12
12
  import {useGroupBlock} from '~/hooks/useGroupBlock'
13
13
  import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
14
14
  import {DEFAULT_HEADING_STYLES, DEFAULT_VARIANTS} from './constants'
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="0.5" y="5.5" width="19" height="8" stroke="black" fill="none" />
4
4
  <path d="M2 8H8V9H2V8Z" fill="black" />
5
5
  <path d="M2 10H9V11H2V10Z" fill="black" />
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="1.5" y="12.5" width="17" height="7" stroke="black" fill="none" />
4
4
  <path fillRule="evenodd" clipRule="evenodd" d="M8.5 15L6 18L11 18L8.5 15Z" fill="black" />
5
5
  <path
@@ -54,13 +54,13 @@ export function createHeroGroupEdit(options: HeroGroupOptions) {
54
54
  <SelectControl
55
55
  label={__('Efekt přechodu', 'brilo-blocks')}
56
56
  value={effect}
57
- options={EFFECTS_OPTIONS as any}
57
+ options={EFFECTS_OPTIONS}
58
58
  onChange={(v) => setAttributes({effect: v as Effect})}
59
59
  />
60
60
  <SelectControl
61
61
  label={__('Poměr stran', 'brilo-blocks')}
62
62
  value={aspectRatio}
63
- options={ASPECT_RATIOS_OPTIONS as any}
63
+ options={ASPECT_RATIOS_OPTIONS}
64
64
  onChange={(v) => setAttributes({aspectRatio: v as AspectRatio})}
65
65
  />
66
66
  </PanelBody>
@@ -74,7 +74,7 @@ export function createHeroGroupEdit(options: HeroGroupOptions) {
74
74
  <NumberControl
75
75
  label={__('Rychlost přehrávání (ms)', 'brilo-blocks')}
76
76
  value={autoplaySpeed}
77
- onChange={(v) => setAttributes({autoplaySpeed: parseInt(v ?? '3000')})}
77
+ onChange={(v) => setAttributes({autoplaySpeed: parseInt(v ?? '3000', 10)})}
78
78
  />
79
79
  )}
80
80
  <ToggleControl
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <path d="M4 4H8V5H4V4Z" fill="black" />
4
4
  <path d="M7 19H9V20H7V19Z" fill="black" />
5
5
  <path d="M10 19H11V20H10V19Z" fill="black" />
@@ -2,7 +2,7 @@ import type {BlockEditProps} from '@wordpress/blocks'
2
2
  import type {ReactNode} from 'react'
3
3
  import type {BriloBlockType, OptionArray} from '~/types'
4
4
  import type {HeroSliderItem} from '../hero-item/types'
5
- import {DEFAULT_ASPECT_RATIOS, EFFECTS, VARIANTS} from './constants'
5
+ import type {DEFAULT_ASPECT_RATIOS, EFFECTS, VARIANTS} from './constants'
6
6
 
7
7
  export type Variant = (typeof VARIANTS)[number]['value']
8
8
  export type Effect = (typeof EFFECTS)[number]['value']
@@ -1,4 +1,4 @@
1
- import {InspectorControls, RichText, useBlockProps, useInnerBlocksProps} from '@wordpress/block-editor'
1
+ import {InspectorControls, RichText} from '@wordpress/block-editor'
2
2
  import type {BlockEditProps} from '@wordpress/blocks'
3
3
  import {
4
4
  PanelBody,
@@ -12,7 +12,7 @@ import {
12
12
  } from '@wordpress/components'
13
13
  import {__} from '@wordpress/i18n'
14
14
  import {ImagePickerBody, ImagePickerControl} from '~/components/ImagePicker'
15
- import {CONTENT_POSITIONS, HEADING_LEVELS} from './constants'
15
+ import {HEADING_LEVELS} from './constants'
16
16
  import type {ContentPosition, HeroItemAttributes, HeroItemOptions} from './types'
17
17
  import {useGroupBlock} from '~/hooks/useGroupBlock'
18
18
  import {useTenantColorPalette} from '~/hooks/useTenantColorPalette'
@@ -41,14 +41,14 @@ export function createHeroItemEdit(options: HeroItemOptions) {
41
41
 
42
42
  <BaseControl label={__('Focal point (desktop)', 'brilo-blocks')}>
43
43
  <AlignmentMatrixControl
44
- value={focalPoint.point as any}
44
+ value={focalPoint.point}
45
45
  onChange={(v) => setAttributes({focalPoint: {...focalPoint, point: (v ?? 'center center') as ContentPosition}})}
46
46
  />
47
47
  </BaseControl>
48
48
 
49
49
  <BaseControl label={__('Focal point (mobil)', 'brilo-blocks')}>
50
50
  <AlignmentMatrixControl
51
- value={(focalPoint.sm?.point ?? 'center center') as any}
51
+ value={focalPoint.sm?.point ?? 'center center'}
52
52
  onChange={(v) => setAttributes({focalPoint: {...focalPoint, sm: {point: (v ?? 'center center') as ContentPosition}}})}
53
53
  />
54
54
  </BaseControl>
@@ -136,7 +136,7 @@ export function createHeroItemEdit(options: HeroItemOptions) {
136
136
  />
137
137
 
138
138
  <RichText
139
- tagName={`h${headingLevel}` as any}
139
+ tagName={`h${headingLevel}` as 'h1' | 'h2' | 'h3' | 'h4'}
140
140
  className="i-hero__title u-text-editable"
141
141
  style={titleColor ? {color: titleColor} : undefined}
142
142
  value={title}
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="1.5" y="1.5" width="17" height="17" rx="2" stroke="black" fill="none" />
4
4
  </svg>
5
5
  )
@@ -1,8 +1,7 @@
1
- import React from 'react'
2
1
  import {useGroupBlock} from '~/hooks/useGroupBlock'
3
- import type {AsideAttributes, AsideOptions} from './types'
2
+ import type {AsideOptions} from './types'
4
3
 
5
- export function createAsideEdit(options: AsideOptions) {
4
+ export function createAsideEdit(_options: AsideOptions) {
6
5
  return function Edit() {
7
6
  const {blockProps, innerBlocksProps} = useGroupBlock({
8
7
  blockClassName: 'l-content-w-aside__aside',
@@ -1,7 +1,6 @@
1
1
  import {InnerBlocks} from '@wordpress/block-editor'
2
2
  import type {BlockConfiguration} from '@wordpress/blocks'
3
3
  import {__} from '@wordpress/i18n'
4
- import React from 'react'
5
4
  import {createAsideEdit} from './edit'
6
5
  import {icon as defaultIcon} from './icon'
7
6
  import type {AsideAttributes, AsideOptions} from './types'
@@ -1,7 +1,5 @@
1
- import React from 'react'
2
-
3
1
  export const icon = (
4
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5
3
  <path fillRule="evenodd" clipRule="evenodd" d="M8 4H20V20H8V4ZM10 6H18V18H10V6Z" fill="currentColor" />
6
4
  </svg>
7
5
  )
@@ -1,8 +1,7 @@
1
- import React from 'react'
2
1
  import {useGroupBlock} from '~/hooks/useGroupBlock'
3
- import type {ContentAttributes, ContentOptions} from './types'
2
+ import type {ContentOptions} from './types'
4
3
 
5
- export function createContentEdit(options: ContentOptions) {
4
+ export function createContentEdit(_options: ContentOptions) {
6
5
  return function Edit() {
7
6
  const {blockProps, innerBlocksProps} = useGroupBlock({
8
7
  blockClassName: 'l-content-w-aside__content',
@@ -1,7 +1,6 @@
1
1
  import {InnerBlocks} from '@wordpress/block-editor'
2
2
  import type {BlockConfiguration} from '@wordpress/blocks'
3
3
  import {__} from '@wordpress/i18n'
4
- import React from 'react'
5
4
  import {createContentEdit} from './edit'
6
5
  import {icon as defaultIcon} from './icon'
7
6
  import type {ContentAttributes, ContentOptions} from './types'
@@ -1,7 +1,5 @@
1
- import React from 'react'
2
-
3
1
  export const icon = (
4
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5
3
  <path fillRule="evenodd" clipRule="evenodd" d="M4 4H16V20H4V4ZM6 6H14V18H6V6Z" fill="currentColor" />
6
4
  </svg>
7
5
  )
@@ -5,7 +5,6 @@ import {
5
5
  __experimentalToggleGroupControlOption as ToggleGroupControlOption,
6
6
  } from '@wordpress/components'
7
7
  import {__} from '@wordpress/i18n'
8
- import React from 'react'
9
8
  import {useGroupBlock} from '~/hooks/useGroupBlock'
10
9
  import {ASIDE_SIZES} from './constants'
11
10
  import type {AsideSize, ContentWithAsideAttributes, ContentWithAsideOptions} from './types'
@@ -1,7 +1,6 @@
1
1
  import {InnerBlocks} from '@wordpress/block-editor'
2
2
  import type {BlockConfiguration} from '@wordpress/blocks'
3
3
  import {__} from '@wordpress/i18n'
4
- import React from 'react'
5
4
  import type {OptionArray} from '~/types'
6
5
  import {ASIDE_SIZES} from './constants'
7
6
  import {createContentWithAsideEdit} from './edit'
@@ -1,7 +1,5 @@
1
- import React from 'react'
2
-
3
1
  export const icon = (
4
- <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
5
3
  <path fillRule="evenodd" clipRule="evenodd" d="M4 4H20V20H4V4ZM6 6H13V18H6V6ZM15 6H18V18H15V6Z" fill="currentColor" />
6
4
  </svg>
7
5
  )
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <path d="M8 4H4C2.895 4 2 4.895 2 6v10c0 1.105.895 2 2 2h10c1.105 0 2-.895 2-2v-4" stroke="black" strokeWidth="1.5" fill="none" />
4
4
  <path d="M12 2h6v6M18 2L10 10" stroke="black" strokeWidth="1.5" strokeLinecap="round" />
5
5
  </svg>
@@ -1,4 +1,4 @@
1
- import {InspectorControls, RichText, useBlockProps} from '@wordpress/block-editor'
1
+ import {InspectorControls, RichText} from '@wordpress/block-editor'
2
2
  import {
3
3
  PanelBody,
4
4
  BaseControl,
@@ -157,8 +157,13 @@ export function createMapGroupEdit(options: MapGroupOptions) {
157
157
  <p>{[lat, long].filter(Boolean).join(', ')}</p>
158
158
  </div>
159
159
  )}
160
- {mapType === 'url' && iframeSrc && <iframe src={iframeSrc} width={640} height={320}></iframe>}
161
- {mapType === 'element' && iframeElement && <div dangerouslySetInnerHTML={{__html: iframeElement}} />}
160
+ {mapType === 'url' && iframeSrc && (
161
+ <iframe src={iframeSrc} title={__('Náhled mapy', 'brilo-blocks')} width={640} height={320}></iframe>
162
+ )}
163
+ {mapType === 'element' && iframeElement && (
164
+ // biome-ignore lint/security/noDangerouslySetInnerHtml: the editor's own embed code (an iframe from the map provider), previewed as the page will show it
165
+ <div dangerouslySetInnerHTML={{__html: iframeElement}} />
166
+ )}
162
167
  {mapType === 'image' && img && <ImagePickerControl value={img} onChange={(v) => setAttributes({img: v})} size={[640, 320]} />}
163
168
  {(!mapType ||
164
169
  (mapType === 'gps' && !lat && !long) ||
@@ -5,7 +5,7 @@ import {createMapGroupEdit} from './edit'
5
5
  import type {MapGroupAttributes, MapGroupOptions} from './types'
6
6
  import {MAP_TYPES} from './constants'
7
7
  import type {StringArray} from '~/types'
8
- import {DEFAULT_HEADING_STYLES, DEFAULT_VARIANTS} from '~/blocks/groups/banner-group/constants'
8
+ import {DEFAULT_HEADING_STYLES} from '~/blocks/groups/banner-group/constants'
9
9
  import {InnerBlocks} from '@wordpress/block-editor'
10
10
  import {HEADING_LEVELS} from '~/constants'
11
11
 
@@ -1,4 +1,4 @@
1
- import type {BriloBlockType, Media, OptionArray, StringArray} from '~/types'
1
+ import type {BriloBlockType, Media, StringArray} from '~/types'
2
2
  import type {DEFAULT_HEADING_STYLES, MAP_TYPES} from './constants'
3
3
  import type {HEADING_LEVELS} from '~/constants'
4
4
 
@@ -26,6 +26,7 @@ export function createNewsletterFormEdit(options: NewsletterFormOptions) {
26
26
  }) {
27
27
  const {heading, description, form} = attributes
28
28
  const {email, submit, terms} = form.fields
29
+ const TermsTag = terms.isCheckbox ? 'label' : 'div'
29
30
 
30
31
  const setForm = (patch: Partial<NewsletterFormAttributes['form']>) => setAttributes({form: {...form, ...patch}})
31
32
  const setFields = (patch: Partial<NewsletterFormAttributes['form']['fields']>) => setForm({fields: {...form.fields, ...patch}})
@@ -77,6 +78,7 @@ export function createNewsletterFormEdit(options: NewsletterFormOptions) {
77
78
 
78
79
  <PanelBody title={__('Skrytá pole', 'brilo-blocks')} initialOpen={false}>
79
80
  {form.hiddenFields.map((field, i) => (
81
+ // biome-ignore lint/suspicious/noArrayIndexKey: hidden fields carry no id; the list is edited by position
80
82
  <div key={i} className="f-newsletter__hidden-field">
81
83
  <TextControl
82
84
  label={__('Název', 'brilo-blocks')}
@@ -176,7 +178,8 @@ export function createNewsletterFormEdit(options: NewsletterFormOptions) {
176
178
  </button>
177
179
  </div>
178
180
 
179
- <label className="f-newsletter__terms">
181
+ {/* A label only around a checkbox; without one the terms are plain text. */}
182
+ <TermsTag className="f-newsletter__terms">
180
183
  {terms.isCheckbox && <input type="checkbox" disabled />}
181
184
  <RichText
182
185
  tagName="span"
@@ -186,7 +189,7 @@ export function createNewsletterFormEdit(options: NewsletterFormOptions) {
186
189
  placeholder={__('Souhlas se zpracováním...', 'brilo-blocks')}
187
190
  allowedFormats={['core/bold', 'core/italic', 'core/link']}
188
191
  />
189
- </label>
192
+ </TermsTag>
190
193
  </div>
191
194
  </>
192
195
  )
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="2.5" y="1.5" width="15" height="17" stroke="black" fill="none" />
4
4
  <path d="M7 13H13V14H7V13Z" fill="black" />
5
5
  <path d="M6 15H14V16H6V15Z" fill="black" />
@@ -1 +1 @@
1
- import {__} from '@wordpress/i18n'
1
+ export {}
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="3" y="2" width="14" height="16" rx="1" stroke="black" fill="none" />
4
4
  <line x1="6" y1="6" x2="14" y2="6" stroke="black" />
5
5
  <line x1="6" y1="9" x2="14" y2="9" stroke="black" />
@@ -1,6 +1,5 @@
1
1
  import type {BriloBlockType} from '~/types'
2
2
 
3
- // biome-ignore lint/complexity/noBannedTypes: no block-specific attributes, matches BriloBlockType's generic constraint shape
4
3
  export interface PostContentAttributes extends Record<string, unknown> {}
5
4
 
6
5
  export type PostContentOptions = BriloBlockType
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="1" y="4" width="18" height="12" rx="1" stroke="black" fill="none" />
4
4
  <rect x="3" y="6" width="6" height="5" stroke="black" fill="none" />
5
5
  <path d="M3 13H7V14H3V13Z" fill="black" />
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="1" y="1" width="8" height="8" stroke="black" fill="none" />
4
4
  <rect x="11" y="1" width="8" height="8" stroke="black" fill="none" />
5
5
  <rect x="1" y="11" width="8" height="8" stroke="black" fill="none" />
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <circle cx="5" cy="10" r="2" stroke="black" fill="none" />
4
4
  <circle cx="15" cy="4" r="2" stroke="black" fill="none" />
5
5
  <circle cx="15" cy="16" r="2" stroke="black" fill="none" />
@@ -1,5 +1,5 @@
1
1
  export const icon = (
2
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <svg aria-hidden="true" focusable="false" width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
3
  <rect x="0.5" y="7.5" width="8" height="11" stroke="black" fill="none" />
4
4
  <rect x="2.5" y="9.5" width="4" height="3" stroke="black" fill="none" />
5
5
  <path d="M2 14H6V15H2V14Z" fill="black" />
@@ -1,7 +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 {DEFAULT_ICON_BACKGROUND_SIZE, DEFAULT_ICON_SIZE, DEFAULT_SHADOWS, DEFAULT_VARIANTS, TEXT_ALIGNS} from './constants'
4
+ import {DEFAULT_ICON_BACKGROUND_SIZE, DEFAULT_SHADOWS, DEFAULT_VARIANTS, TEXT_ALIGNS} from './constants'
5
5
  import {createStepGroupEdit} from './edit'
6
6
  import type {StepGroupAttributes, StepGroupOptions} from './types'
7
7
  import {icon} from '~/blocks/step/step-group/icon'