@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
@@ -1,9 +1,40 @@
1
- export const FOOD_MENU_GROUP_MODES = ['manual', 'today', 'week'] as const
2
- export const FOOD_MENU_GROUP_LAYOUTS = ['slider', 'list'] as const
1
+ import {__} from '@wordpress/i18n'
2
+
3
+ export const FOOD_MENU_GROUP_MODES = [
4
+ {value: 'manual', label: __('Ruční výběr', 'brilo-blocks')},
5
+ {value: 'today', label: __('Dnešní', 'brilo-blocks')},
6
+ {value: 'week', label: __('Týden', 'brilo-blocks')},
7
+ ] as const
8
+
9
+ export const FOOD_MENU_GROUP_LAYOUTS = [
10
+ {value: 'slider', label: __('Slider', 'brilo-blocks')},
11
+ {value: 'list', label: __('Seznam', 'brilo-blocks')},
12
+ ] as const
3
13
 
4
14
  /** What the block does on a day with no menu to show. */
5
- export const FOOD_MENU_GROUP_EMPTY_BEHAVIOURS = ['message', 'permanent', 'hide'] as const
15
+ export const FOOD_MENU_GROUP_EMPTY_BEHAVIOURS = [
16
+ {value: 'message', label: __('Zpráva', 'brilo-blocks')},
17
+ {value: 'permanent', label: __('Stálá nabídka', 'brilo-blocks')},
18
+ {value: 'hide', label: __('Skrýt', 'brilo-blocks')},
19
+ ] as const
20
+
21
+ /** How the "Rezervovat oběd" button under a daily menu works. */
22
+ export const FOOD_MENU_GROUP_RESERVATION_MODES = [
23
+ {value: 'modal', label: __('Modal', 'brilo-blocks')},
24
+ {value: 'link', label: __('Odkaz', 'brilo-blocks')},
25
+ {value: 'off', label: __('Vypnuto', 'brilo-blocks')},
26
+ ] as const
27
+
28
+ export const FOOD_MENU_GROUP_MODE = FOOD_MENU_GROUP_MODES[0].value
29
+ export const FOOD_MENU_GROUP_RESERVATION_MODE = FOOD_MENU_GROUP_RESERVATION_MODES[0].value
30
+ export const FOOD_MENU_GROUP_LAYOUT = FOOD_MENU_GROUP_LAYOUTS[0].value
31
+ export const FOOD_MENU_GROUP_EMPTY_BEHAVIOUR = FOOD_MENU_GROUP_EMPTY_BEHAVIOURS[0].value
32
+
33
+ /** Alignment of the texts around the dishes; the dish rows keep their own layout. */
34
+ export const FOOD_MENU_GROUP_TEXT_ALIGNS = [
35
+ {value: 'left', label: __('Vlevo', 'brilo-blocks')},
36
+ {value: 'center', label: __('Na střed', 'brilo-blocks')},
37
+ {value: 'right', label: __('Vpravo', 'brilo-blocks')},
38
+ ] as const
6
39
 
7
- export const FOOD_MENU_GROUP_MODE = FOOD_MENU_GROUP_MODES[0]
8
- export const FOOD_MENU_GROUP_LAYOUT = FOOD_MENU_GROUP_LAYOUTS[0]
9
- export const FOOD_MENU_GROUP_EMPTY_BEHAVIOUR = FOOD_MENU_GROUP_EMPTY_BEHAVIOURS[0]
40
+ export const FOOD_MENU_GROUP_TEXT_ALIGN = FOOD_MENU_GROUP_TEXT_ALIGNS[0].value
@@ -1,3 +1,4 @@
1
+ import apiFetch from '@wordpress/api-fetch'
1
2
  import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
2
3
  import {
3
4
  PanelBody,
@@ -10,8 +11,16 @@ import {
10
11
  import {__, sprintf} from '@wordpress/i18n'
11
12
  import clsx from 'clsx'
12
13
  // biome-ignore lint/correctness/noUnusedImports: required in scope for classic JSX transform
13
- import React from 'react'
14
+ import React, {useEffect, useState} from 'react'
15
+ import {DEFAULT_SURFACE_SHADOWS, SurfaceStylePanel} from '~/components/SurfaceStyleControl'
14
16
  import {plural} from '~/utils/plural'
17
+ import {
18
+ FOOD_MENU_GROUP_EMPTY_BEHAVIOURS,
19
+ FOOD_MENU_GROUP_LAYOUTS,
20
+ FOOD_MENU_GROUP_MODES,
21
+ FOOD_MENU_GROUP_RESERVATION_MODES,
22
+ FOOD_MENU_GROUP_TEXT_ALIGNS,
23
+ } from './constants'
15
24
  import {FoodMenuPreview} from './FoodMenuPreview'
16
25
  import type {FoodMenuGroupAttributes, FoodMenuGroupOptions} from './types'
17
26
 
@@ -27,6 +36,74 @@ const EMPTY_HINTS: Record<FoodMenuGroupAttributes['emptyBehaviour'], string> = {
27
36
  hide: __('Blok ze stránky zmizí. Stránka pak může zůstat prázdná.', 'brilo-blocks'),
28
37
  }
29
38
 
39
+ type ReservationPage = {title: string; url: string} | null
40
+
41
+ /**
42
+ * The "Stránka rezervace" module setting, for the hint under the reservation
43
+ * mode: the link mode needs it and falls back to the modal without it.
44
+ */
45
+ function useReservationPage(enabled: boolean): {page: ReservationPage; isLoading: boolean} {
46
+ const [page, setPage] = useState<ReservationPage>(null)
47
+ const [isLoading, setIsLoading] = useState(enabled)
48
+
49
+ useEffect(() => {
50
+ if (!enabled) {
51
+ return
52
+ }
53
+
54
+ let cancelled = false
55
+ setIsLoading(true)
56
+
57
+ apiFetch<{page: ReservationPage}>({path: '/brilo/v1/food-reservation/preview'})
58
+ .then((result) => {
59
+ if (!cancelled) {
60
+ setPage(result.page)
61
+ }
62
+ })
63
+ .catch(() => {
64
+ if (!cancelled) {
65
+ setPage(null)
66
+ }
67
+ })
68
+ .finally(() => {
69
+ if (!cancelled) {
70
+ setIsLoading(false)
71
+ }
72
+ })
73
+
74
+ return () => {
75
+ cancelled = true
76
+ }
77
+ }, [enabled])
78
+
79
+ return {page, isLoading}
80
+ }
81
+
82
+ function reservationHint(reservationMode: FoodMenuGroupAttributes['reservationMode'], page: ReservationPage, isLoading: boolean): string {
83
+ const scope = __('Tlačítko se ukáže jen u denních lístků a jen když jsou rezervace zapnuté v nastavení modulu.', 'brilo-blocks')
84
+
85
+ if ('off' === reservationMode) {
86
+ return __('Pod lístkem nebude tlačítko rezervace, formulář ani uzávěrka.', 'brilo-blocks')
87
+ }
88
+
89
+ if ('modal' === reservationMode) {
90
+ return `${__('Tlačítko otevře rezervační formulář v okně.', 'brilo-blocks')} ${scope}`
91
+ }
92
+
93
+ if (isLoading) {
94
+ return scope
95
+ }
96
+
97
+ if (!page) {
98
+ return __(
99
+ 'Stránka rezervace není v nastavení modulu vybraná, tlačítko proto zatím otevře formulář v okně. Vyberte ji v Nastavení jídelního lístku.',
100
+ 'brilo-blocks',
101
+ )
102
+ }
103
+
104
+ return `${sprintf(__('Tlačítko povede na stránku „%s“ k bloku Rezervace obědu s předvybraným dnem.', 'brilo-blocks'), page.title)} ${scope}`
105
+ }
106
+
30
107
  function pickedNote(count: number): string {
31
108
  if (0 === count) {
32
109
  return __('Zatím nevybrán žádný lístek.', 'brilo-blocks')
@@ -43,6 +120,8 @@ function pickedNote(count: number): string {
43
120
  }
44
121
 
45
122
  export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
123
+ const shadows = options.shadows ?? DEFAULT_SURFACE_SHADOWS
124
+
46
125
  return function Edit({
47
126
  attributes,
48
127
  setAttributes,
@@ -50,7 +129,8 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
50
129
  attributes: FoodMenuGroupAttributes
51
130
  setAttributes: (a: Partial<FoodMenuGroupAttributes>) => void
52
131
  }) {
53
- const {mode, layout, menuIds, showPrices, showAllergens, showReservation, emptyBehaviour, emptyText} = attributes
132
+ const {mode, layout, menuIds, showPrices, showAllergens, reservationMode, emptyBehaviour, emptyText, style, textAlign} = attributes
133
+ const {page, isLoading} = useReservationPage('link' === reservationMode)
54
134
 
55
135
  const blockProps = useBlockProps({className: clsx(options.blockClassName ?? 'g-food-menu', `--${layout}`)})
56
136
 
@@ -65,9 +145,9 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
65
145
  onChange={(value) => setAttributes({mode: value as FoodMenuGroupAttributes['mode']})}
66
146
  isBlock
67
147
  >
68
- <ToggleGroupControlOption value="manual" label={__('Ruční výběr', 'brilo-blocks')} />
69
- <ToggleGroupControlOption value="today" label={__('Dnešní', 'brilo-blocks')} />
70
- <ToggleGroupControlOption value="week" label={__('Týden', 'brilo-blocks')} />
148
+ {FOOD_MENU_GROUP_MODES.map((option) => (
149
+ <ToggleGroupControlOption key={option.value} value={option.value} label={option.label} />
150
+ ))}
71
151
  </ToggleGroupControl>
72
152
 
73
153
  <ToggleGroupControl
@@ -77,8 +157,9 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
77
157
  onChange={(value) => setAttributes({layout: value as FoodMenuGroupAttributes['layout']})}
78
158
  isBlock
79
159
  >
80
- <ToggleGroupControlOption value="slider" label={__('Slider', 'brilo-blocks')} />
81
- <ToggleGroupControlOption value="list" label={__('Seznam', 'brilo-blocks')} />
160
+ {FOOD_MENU_GROUP_LAYOUTS.map((option) => (
161
+ <ToggleGroupControlOption key={option.value} value={option.value} label={option.label} />
162
+ ))}
82
163
  </ToggleGroupControl>
83
164
 
84
165
  <ToggleControl
@@ -95,16 +176,17 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
95
176
  onChange={(value) => setAttributes({showAllergens: value})}
96
177
  />
97
178
 
98
- <ToggleControl
99
- __nextHasNoMarginBottom
100
- label={__('Umožnit rezervaci obědu', 'brilo-blocks')}
101
- help={__(
102
- 'Tlačítko rezervace se ukáže jen u denních lístků a jen když jsou rezervace zapnuté v nastavení modulu.',
103
- 'brilo-blocks',
104
- )}
105
- checked={showReservation}
106
- onChange={(value) => setAttributes({showReservation: value})}
107
- />
179
+ <ToggleGroupControl
180
+ label={__('Rezervace', 'brilo-blocks')}
181
+ help={reservationHint(reservationMode, page, isLoading)}
182
+ value={reservationMode}
183
+ onChange={(value) => setAttributes({reservationMode: value as FoodMenuGroupAttributes['reservationMode']})}
184
+ isBlock
185
+ >
186
+ {FOOD_MENU_GROUP_RESERVATION_MODES.map((option) => (
187
+ <ToggleGroupControlOption key={option.value} value={option.value} label={option.label} />
188
+ ))}
189
+ </ToggleGroupControl>
108
190
  </PanelBody>
109
191
 
110
192
  <PanelBody title={__('Když není co zobrazit', 'brilo-blocks')} initialOpen={false}>
@@ -115,9 +197,9 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
115
197
  onChange={(value) => setAttributes({emptyBehaviour: value as FoodMenuGroupAttributes['emptyBehaviour']})}
116
198
  isBlock
117
199
  >
118
- <ToggleGroupControlOption value="message" label={__('Zpráva', 'brilo-blocks')} />
119
- <ToggleGroupControlOption value="permanent" label={__('Stálá nabídka', 'brilo-blocks')} />
120
- <ToggleGroupControlOption value="hide" label={__('Skrýt', 'brilo-blocks')} />
200
+ {FOOD_MENU_GROUP_EMPTY_BEHAVIOURS.map((option) => (
201
+ <ToggleGroupControlOption key={option.value} value={option.value} label={option.label} />
202
+ ))}
121
203
  </ToggleGroupControl>
122
204
 
123
205
  {'hide' !== emptyBehaviour && (
@@ -131,6 +213,20 @@ export function createFoodMenuGroupEdit(options: FoodMenuGroupOptions) {
131
213
  />
132
214
  )}
133
215
  </PanelBody>
216
+
217
+ <SurfaceStylePanel style={style} shadows={shadows} idPrefix="food-menu-group" onChange={(next) => setAttributes({style: next})}>
218
+ <ToggleGroupControl
219
+ label={__('Zarovnání textu', 'brilo-blocks')}
220
+ help={__('Nadpisy, názvy chodů a texty pod lístkem. Řádky jídel zůstávají beze změny.', 'brilo-blocks')}
221
+ value={textAlign}
222
+ onChange={(value) => setAttributes({textAlign: value as FoodMenuGroupAttributes['textAlign']})}
223
+ isBlock
224
+ >
225
+ {FOOD_MENU_GROUP_TEXT_ALIGNS.map((align) => (
226
+ <ToggleGroupControlOption key={align.value} value={align.value} label={align.label} />
227
+ ))}
228
+ </ToggleGroupControl>
229
+ </SurfaceStylePanel>
134
230
  </InspectorControls>
135
231
 
136
232
  <div {...blockProps}>
@@ -34,6 +34,14 @@ $warn: #9a6700;
34
34
  padding: 10px 0 14px;
35
35
  }
36
36
 
37
+ // The block's own style (see `previewStyle`) overrides the admin palette
38
+ // through these properties; unset, the card looks as before.
39
+ .brilo-food-menu-preview__card {
40
+ color: var(--food-menu-preview-text, $fg);
41
+ border-radius: 4px;
42
+ box-shadow: var(--food-menu-preview-shadow, none);
43
+ }
44
+
37
45
  .brilo-food-menu-preview__head {
38
46
  display: flex;
39
47
  flex-wrap: wrap;
@@ -41,8 +49,8 @@ $warn: #9a6700;
41
49
  align-items: center;
42
50
  justify-content: space-between;
43
51
  padding: 10px 14px;
44
- background: $surface;
45
- border: 1px solid $line;
52
+ background: var(--food-menu-preview-background, $surface);
53
+ border: 1px solid var(--food-menu-preview-border, $line);
46
54
  border-bottom: 0;
47
55
  border-radius: 4px 4px 0 0;
48
56
  }
@@ -105,7 +113,8 @@ $warn: #9a6700;
105
113
  }
106
114
 
107
115
  .brilo-food-menu-preview__body {
108
- border: 1px solid $line;
116
+ background: var(--food-menu-preview-background, transparent);
117
+ border: 1px solid var(--food-menu-preview-border, $line);
109
118
  border-radius: 0 0 4px 4px;
110
119
  }
111
120
 
@@ -164,9 +173,29 @@ $warn: #9a6700;
164
173
  }
165
174
  }
166
175
 
176
+ // Paired half sections of a standing lístek, side by side as on the page.
177
+ .brilo-food-menu-preview__sections--split {
178
+ display: grid;
179
+ grid-template-columns: repeat(2, minmax(0, 1fr));
180
+
181
+ .brilo-food-menu-preview__section:not(.brilo-food-menu-preview__section--half) {
182
+ grid-column: 1 / -1;
183
+ }
184
+
185
+ .brilo-food-menu-preview__section--half:not(.brilo-food-menu-preview__section--first-half) {
186
+ border-left: 1px solid var(--food-menu-preview-border, $line);
187
+ }
188
+
189
+ // A pair opening the lístek has no line above either half.
190
+ .brilo-food-menu-preview__section--first-half:first-child + .brilo-food-menu-preview__section--half {
191
+ border-top: 0;
192
+ }
193
+ }
194
+
167
195
  .brilo-food-menu-preview__section-title {
168
196
  margin: 0 0 4px;
169
- color: $muted;
197
+ color: var(--food-menu-preview-text, $muted);
198
+ text-align: var(--food-menu-preview-align, left);
170
199
  font-weight: 600;
171
200
  font-size: 11px;
172
201
  letter-spacing: 0.08em;
@@ -234,8 +263,8 @@ $warn: #9a6700;
234
263
  padding: 8px 14px;
235
264
  color: $muted;
236
265
  font-size: 12px;
237
- background: $surface;
238
- border-top: 1px solid $line;
266
+ background: var(--food-menu-preview-background, $surface);
267
+ border-top: 1px solid var(--food-menu-preview-border, $line);
239
268
  border-radius: 0 0 4px 4px;
240
269
  }
241
270
 
@@ -1,5 +1,7 @@
1
1
  import type {BlockConfiguration} from '@wordpress/blocks'
2
2
  import {__} from '@wordpress/i18n'
3
+ import {DEFAULT_SURFACE_SHADOWS, surfaceStyleAttribute} from '~/components/SurfaceStyleControl'
4
+ import {withObjectDefaults} from '~/utils/withObjectDefaults'
3
5
  import {
4
6
  FOOD_MENU_GROUP_EMPTY_BEHAVIOUR,
5
7
  FOOD_MENU_GROUP_EMPTY_BEHAVIOURS,
@@ -7,12 +9,65 @@ import {
7
9
  FOOD_MENU_GROUP_LAYOUTS,
8
10
  FOOD_MENU_GROUP_MODE,
9
11
  FOOD_MENU_GROUP_MODES,
12
+ FOOD_MENU_GROUP_RESERVATION_MODE,
13
+ FOOD_MENU_GROUP_RESERVATION_MODES,
14
+ FOOD_MENU_GROUP_TEXT_ALIGN,
15
+ FOOD_MENU_GROUP_TEXT_ALIGNS,
10
16
  } from './constants'
11
17
  import {createFoodMenuGroupEdit} from './edit'
12
18
  import {icon as defaultIcon} from './icon'
13
19
  import type {FoodMenuGroupAttributes, FoodMenuGroupOptions} from './types'
14
20
 
15
21
  export function createFoodMenuGroupBlock(options: FoodMenuGroupOptions): BlockConfiguration<FoodMenuGroupAttributes> {
22
+ const attributes = {
23
+ mode: {
24
+ type: 'string',
25
+ default: FOOD_MENU_GROUP_MODE,
26
+ enum: FOOD_MENU_GROUP_MODES.map((option) => option.value),
27
+ },
28
+ layout: {
29
+ type: 'string',
30
+ default: FOOD_MENU_GROUP_LAYOUT,
31
+ enum: FOOD_MENU_GROUP_LAYOUTS.map((option) => option.value),
32
+ },
33
+ menuIds: {
34
+ type: 'array',
35
+ default: [],
36
+ items: {type: 'number'},
37
+ },
38
+ showPrices: {
39
+ type: 'boolean',
40
+ default: true,
41
+ },
42
+ showAllergens: {
43
+ type: 'boolean',
44
+ default: true,
45
+ },
46
+ reservationMode: {
47
+ type: 'string',
48
+ default: FOOD_MENU_GROUP_RESERVATION_MODE,
49
+ enum: FOOD_MENU_GROUP_RESERVATION_MODES.map((option) => option.value),
50
+ },
51
+ emptyBehaviour: {
52
+ type: 'string',
53
+ default: FOOD_MENU_GROUP_EMPTY_BEHAVIOUR,
54
+ enum: FOOD_MENU_GROUP_EMPTY_BEHAVIOURS.map((option) => option.value),
55
+ },
56
+ // Empty means "use the wording the server picks for this mode".
57
+ emptyText: {
58
+ type: 'string',
59
+ default: '',
60
+ },
61
+ style: surfaceStyleAttribute(options.shadows ?? DEFAULT_SURFACE_SHADOWS),
62
+ textAlign: {
63
+ type: 'string',
64
+ default: FOOD_MENU_GROUP_TEXT_ALIGN,
65
+ enum: FOOD_MENU_GROUP_TEXT_ALIGNS.map((align) => align.value),
66
+ },
67
+ }
68
+
69
+ const {reservationMode: _reservationMode, ...withoutReservationMode} = attributes
70
+
16
71
  return {
17
72
  name: options.name,
18
73
  title: options.title ?? __('Jídelní lístek', 'brilo-blocks'),
@@ -21,46 +76,29 @@ export function createFoodMenuGroupBlock(options: FoodMenuGroupOptions): BlockCo
21
76
  ...(options.parent && {parent: options.parent}),
22
77
  icon: options.icon ?? {src: defaultIcon},
23
78
  supports: {html: false, customClassName: false},
24
- attributes: {
25
- mode: {
26
- type: 'string',
27
- default: FOOD_MENU_GROUP_MODE,
28
- enum: [...FOOD_MENU_GROUP_MODES],
29
- },
30
- layout: {
31
- type: 'string',
32
- default: FOOD_MENU_GROUP_LAYOUT,
33
- enum: [...FOOD_MENU_GROUP_LAYOUTS],
34
- },
35
- menuIds: {
36
- type: 'array',
37
- default: [],
38
- items: {type: 'number'},
39
- },
40
- showPrices: {
41
- type: 'boolean',
42
- default: true,
43
- },
44
- showAllergens: {
45
- type: 'boolean',
46
- default: true,
79
+ attributes,
80
+ // The on/off "Umožnit rezervaci obědu" toggle became a three-way choice.
81
+ // A dynamic block is always valid, so the migration opts in through
82
+ // `isEligible`, which sees the raw comment attributes. Blocks that never
83
+ // stored the toggle had it on, which is the new default too.
84
+ deprecated: [
85
+ {
86
+ attributes: {
87
+ ...withoutReservationMode,
88
+ showReservation: {
89
+ type: 'boolean',
90
+ default: true,
91
+ },
92
+ },
93
+ isEligible: (raw: Record<string, unknown>) => 'showReservation' in raw && !('reservationMode' in raw),
94
+ migrate: ({showReservation, ...rest}: Record<string, unknown>) => ({
95
+ ...rest,
96
+ reservationMode: false === showReservation ? 'off' : 'modal',
97
+ }),
98
+ save: () => null,
47
99
  },
48
- showReservation: {
49
- type: 'boolean',
50
- default: true,
51
- },
52
- emptyBehaviour: {
53
- type: 'string',
54
- default: FOOD_MENU_GROUP_EMPTY_BEHAVIOUR,
55
- enum: [...FOOD_MENU_GROUP_EMPTY_BEHAVIOURS],
56
- },
57
- // Empty means "use the wording the server picks for this mode".
58
- emptyText: {
59
- type: 'string',
60
- default: '',
61
- },
62
- },
63
- edit: createFoodMenuGroupEdit(options),
100
+ ],
101
+ edit: withObjectDefaults(createFoodMenuGroupEdit(options)),
64
102
  save: () => null,
65
103
  } as unknown as BlockConfiguration<FoodMenuGroupAttributes>
66
104
  }
@@ -4,6 +4,8 @@ export type {
4
4
  FoodMenuGroupLayout,
5
5
  FoodMenuGroupMode,
6
6
  FoodMenuGroupOptions,
7
+ FoodMenuGroupReservationMode,
8
+ FoodMenuGroupTextAlign,
7
9
  } from './types'
8
10
  export {createFoodMenuGroupBlock} from './factory'
9
11
  export {FoodMenuSelectModal} from './FoodMenuSelectModal'
@@ -1,9 +1,18 @@
1
+ import type {SurfaceShadowOption, SurfaceStyle} from '~/components/SurfaceStyleControl'
1
2
  import type {BriloBlockType, SelectControlProps} from '~/types'
2
- import type {FOOD_MENU_GROUP_EMPTY_BEHAVIOURS, FOOD_MENU_GROUP_LAYOUTS, FOOD_MENU_GROUP_MODES} from './constants'
3
+ import type {
4
+ FOOD_MENU_GROUP_EMPTY_BEHAVIOURS,
5
+ FOOD_MENU_GROUP_LAYOUTS,
6
+ FOOD_MENU_GROUP_MODES,
7
+ FOOD_MENU_GROUP_RESERVATION_MODES,
8
+ FOOD_MENU_GROUP_TEXT_ALIGNS,
9
+ } from './constants'
3
10
 
4
- export type FoodMenuGroupMode = (typeof FOOD_MENU_GROUP_MODES)[number]
5
- export type FoodMenuGroupLayout = (typeof FOOD_MENU_GROUP_LAYOUTS)[number]
6
- export type FoodMenuGroupEmptyBehaviour = (typeof FOOD_MENU_GROUP_EMPTY_BEHAVIOURS)[number]
11
+ export type FoodMenuGroupMode = (typeof FOOD_MENU_GROUP_MODES)[number]['value']
12
+ export type FoodMenuGroupLayout = (typeof FOOD_MENU_GROUP_LAYOUTS)[number]['value']
13
+ export type FoodMenuGroupEmptyBehaviour = (typeof FOOD_MENU_GROUP_EMPTY_BEHAVIOURS)[number]['value']
14
+ export type FoodMenuGroupReservationMode = (typeof FOOD_MENU_GROUP_RESERVATION_MODES)[number]['value']
15
+ export type FoodMenuGroupTextAlign = (typeof FOOD_MENU_GROUP_TEXT_ALIGNS)[number]['value']
7
16
 
8
17
  export interface FoodMenuGroupAttributes extends Record<string, unknown> {
9
18
  mode: FoodMenuGroupMode
@@ -11,11 +20,15 @@ export interface FoodMenuGroupAttributes extends Record<string, unknown> {
11
20
  menuIds: number[]
12
21
  showPrices: boolean
13
22
  showAllergens: boolean
14
- showReservation: boolean
23
+ reservationMode: FoodMenuGroupReservationMode
15
24
  emptyBehaviour: FoodMenuGroupEmptyBehaviour
16
25
  emptyText: string
26
+ style: SurfaceStyle<string>
27
+ textAlign: FoodMenuGroupTextAlign
17
28
  }
18
29
 
19
30
  export interface FoodMenuGroupOptions extends BriloBlockType {
20
31
  renderMenusControl?: (props: SelectControlProps) => JSX.Element
32
+ /** Overrides the shared shadow presets — see `DEFAULT_SURFACE_SHADOWS`. */
33
+ shadows?: readonly SurfaceShadowOption[]
21
34
  }