@brilo/base-blocks 0.1.27 → 0.1.29

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 (145) hide show
  1. package/build/.tsbuildinfo +1 -1
  2. package/build/blocks/career/career-header/edit.d.ts +6 -0
  3. package/build/blocks/career/career-header/edit.d.ts.map +1 -0
  4. package/build/blocks/career/career-header/edit.js +11 -0
  5. package/build/blocks/career/career-header/factory.d.ts +5 -0
  6. package/build/blocks/career/career-header/factory.d.ts.map +1 -0
  7. package/build/blocks/career/career-header/factory.js +24 -0
  8. package/build/blocks/career/career-header/icon.d.ts +2 -0
  9. package/build/blocks/career/career-header/icon.d.ts.map +1 -0
  10. package/build/blocks/career/career-header/icon.js +2 -0
  11. package/build/blocks/career/career-header/index.d.ts +5 -0
  12. package/build/blocks/career/career-header/index.d.ts.map +1 -0
  13. package/build/blocks/career/career-header/index.js +4 -0
  14. package/build/blocks/career/career-header/types.d.ts +10 -0
  15. package/build/blocks/career/career-header/types.d.ts.map +1 -0
  16. package/build/blocks/career/career-header/types.js +1 -0
  17. package/build/blocks/career/job-position-group/JobPositionsSelectModal.d.ts +9 -0
  18. package/build/blocks/career/job-position-group/JobPositionsSelectModal.d.ts.map +1 -0
  19. package/build/blocks/career/job-position-group/JobPositionsSelectModal.js +123 -0
  20. package/build/blocks/career/job-position-group/constants.d.ts +10 -0
  21. package/build/blocks/career/job-position-group/constants.d.ts.map +1 -0
  22. package/build/blocks/career/job-position-group/constants.js +9 -0
  23. package/build/blocks/career/job-position-group/edit.d.ts +6 -0
  24. package/build/blocks/career/job-position-group/edit.d.ts.map +1 -0
  25. package/build/blocks/career/job-position-group/edit.js +17 -0
  26. package/build/blocks/career/job-position-group/factory.d.ts +5 -0
  27. package/build/blocks/career/job-position-group/factory.d.ts.map +1 -0
  28. package/build/blocks/career/job-position-group/factory.js +44 -0
  29. package/build/blocks/career/job-position-group/icon.d.ts +2 -0
  30. package/build/blocks/career/job-position-group/icon.d.ts.map +1 -0
  31. package/build/blocks/career/job-position-group/icon.js +2 -0
  32. package/build/blocks/career/job-position-group/index.d.ts +6 -0
  33. package/build/blocks/career/job-position-group/index.d.ts.map +1 -0
  34. package/build/blocks/career/job-position-group/index.js +5 -0
  35. package/build/blocks/career/job-position-group/types.d.ts +20 -0
  36. package/build/blocks/career/job-position-group/types.d.ts.map +1 -0
  37. package/build/blocks/career/job-position-group/types.js +1 -0
  38. package/build/blocks/document/documents-group/DocumentsSelectModal.d.ts +12 -0
  39. package/build/blocks/document/documents-group/DocumentsSelectModal.d.ts.map +1 -0
  40. package/build/blocks/document/documents-group/DocumentsSelectModal.js +153 -0
  41. package/build/blocks/document/documents-group/constants.d.ts +7 -0
  42. package/build/blocks/document/documents-group/constants.d.ts.map +1 -0
  43. package/build/blocks/document/documents-group/constants.js +5 -0
  44. package/build/blocks/document/documents-group/edit.d.ts +6 -0
  45. package/build/blocks/document/documents-group/edit.d.ts.map +1 -0
  46. package/build/blocks/document/documents-group/edit.js +27 -0
  47. package/build/blocks/document/documents-group/factory.d.ts +5 -0
  48. package/build/blocks/document/documents-group/factory.d.ts.map +1 -0
  49. package/build/blocks/document/documents-group/factory.js +50 -0
  50. package/build/blocks/document/documents-group/icon.d.ts +2 -0
  51. package/build/blocks/document/documents-group/icon.d.ts.map +1 -0
  52. package/build/blocks/document/documents-group/icon.js +2 -0
  53. package/build/blocks/document/documents-group/index.d.ts +6 -0
  54. package/build/blocks/document/documents-group/index.d.ts.map +1 -0
  55. package/build/blocks/document/documents-group/index.js +5 -0
  56. package/build/blocks/document/documents-group/types.d.ts +22 -0
  57. package/build/blocks/document/documents-group/types.d.ts.map +1 -0
  58. package/build/blocks/document/documents-group/types.js +1 -0
  59. package/build/blocks/layout/layout-aside/factory.d.ts.map +1 -1
  60. package/build/blocks/layout/layout-aside/icon.d.ts.map +1 -1
  61. package/build/blocks/layout/layout-content/factory.d.ts.map +1 -1
  62. package/build/blocks/layout/layout-content/icon.d.ts.map +1 -1
  63. package/build/blocks/layout/layout-content-w-aside/edit.d.ts.map +1 -1
  64. package/build/blocks/layout/layout-content-w-aside/edit.js +1 -1
  65. package/build/blocks/layout/layout-content-w-aside/factory.d.ts.map +1 -1
  66. package/build/blocks/layout/layout-content-w-aside/icon.d.ts.map +1 -1
  67. package/build/blocks/post/post-content/edit.d.ts +6 -0
  68. package/build/blocks/post/post-content/edit.d.ts.map +1 -0
  69. package/build/blocks/post/post-content/edit.js +9 -0
  70. package/build/blocks/post/post-content/factory.d.ts +5 -0
  71. package/build/blocks/post/post-content/factory.d.ts.map +1 -0
  72. package/build/blocks/post/post-content/factory.js +18 -0
  73. package/build/blocks/post/post-content/icon.d.ts +2 -0
  74. package/build/blocks/post/post-content/icon.d.ts.map +1 -0
  75. package/build/blocks/post/post-content/icon.js +2 -0
  76. package/build/blocks/post/post-content/index.d.ts +5 -0
  77. package/build/blocks/post/post-content/index.d.ts.map +1 -0
  78. package/build/blocks/post/post-content/index.js +4 -0
  79. package/build/blocks/post/post-content/types.d.ts +5 -0
  80. package/build/blocks/post/post-content/types.d.ts.map +1 -0
  81. package/build/blocks/post/post-content/types.js +1 -0
  82. package/build/blocks/sections/base-section/controls.d.ts.map +1 -1
  83. package/build/blocks/sections/base-section/controls.js +1 -1
  84. package/build/blocks/share/share/constants.d.ts +2 -0
  85. package/build/blocks/share/share/constants.d.ts.map +1 -0
  86. package/build/blocks/share/share/constants.js +1 -0
  87. package/build/blocks/share/share/edit.d.ts +6 -0
  88. package/build/blocks/share/share/edit.d.ts.map +1 -0
  89. package/build/blocks/share/share/edit.js +18 -0
  90. package/build/blocks/share/share/factory.d.ts +5 -0
  91. package/build/blocks/share/share/factory.d.ts.map +1 -0
  92. package/build/blocks/share/share/factory.js +26 -0
  93. package/build/blocks/share/share/icon.d.ts +2 -0
  94. package/build/blocks/share/share/icon.d.ts.map +1 -0
  95. package/build/blocks/share/share/icon.js +2 -0
  96. package/build/blocks/share/share/index.d.ts +5 -0
  97. package/build/blocks/share/share/index.d.ts.map +1 -0
  98. package/build/blocks/share/share/index.js +4 -0
  99. package/build/blocks/share/share/types.d.ts +11 -0
  100. package/build/blocks/share/share/types.d.ts.map +1 -0
  101. package/build/blocks/share/share/types.js +1 -0
  102. package/build/index.d.ts +10 -0
  103. package/build/index.d.ts.map +1 -1
  104. package/build/index.js +5 -0
  105. package/package.json +6 -1
  106. package/src/blocks/career/career-header/edit.tsx +61 -0
  107. package/src/blocks/career/career-header/factory.tsx +28 -0
  108. package/src/blocks/career/career-header/icon.tsx +8 -0
  109. package/src/blocks/career/career-header/index.ts +8 -0
  110. package/src/blocks/career/career-header/types.ts +11 -0
  111. package/src/blocks/career/job-position-group/JobPositionsSelectModal.tsx +238 -0
  112. package/src/blocks/career/job-position-group/constants.ts +11 -0
  113. package/src/blocks/career/job-position-group/edit.tsx +93 -0
  114. package/src/blocks/career/job-position-group/factory.tsx +56 -0
  115. package/src/blocks/career/job-position-group/icon.tsx +7 -0
  116. package/src/blocks/career/job-position-group/index.ts +15 -0
  117. package/src/blocks/career/job-position-group/types.ts +23 -0
  118. package/src/blocks/document/documents-group/DocumentsSelectModal.tsx +273 -0
  119. package/src/blocks/document/documents-group/constants.ts +7 -0
  120. package/src/blocks/document/documents-group/edit.tsx +96 -0
  121. package/src/blocks/document/documents-group/factory.tsx +59 -0
  122. package/src/blocks/document/documents-group/icon.tsx +9 -0
  123. package/src/blocks/document/documents-group/index.ts +15 -0
  124. package/src/blocks/document/documents-group/types.ts +25 -0
  125. package/src/blocks/layout/layout-aside/factory.tsx +1 -3
  126. package/src/blocks/layout/layout-aside/icon.tsx +1 -6
  127. package/src/blocks/layout/layout-content/editor.scss +1 -1
  128. package/src/blocks/layout/layout-content/factory.tsx +1 -3
  129. package/src/blocks/layout/layout-content/icon.tsx +1 -6
  130. package/src/blocks/layout/layout-content-w-aside/edit.tsx +5 -1
  131. package/src/blocks/layout/layout-content-w-aside/factory.tsx +1 -3
  132. package/src/blocks/layout/layout-content-w-aside/icon.tsx +1 -6
  133. package/src/blocks/post/post-content/edit.tsx +18 -0
  134. package/src/blocks/post/post-content/factory.tsx +22 -0
  135. package/src/blocks/post/post-content/icon.tsx +9 -0
  136. package/src/blocks/post/post-content/index.ts +8 -0
  137. package/src/blocks/post/post-content/types.ts +6 -0
  138. package/src/blocks/sections/base-section/controls.tsx +7 -1
  139. package/src/blocks/share/share/constants.ts +1 -0
  140. package/src/blocks/share/share/edit.tsx +57 -0
  141. package/src/blocks/share/share/factory.tsx +30 -0
  142. package/src/blocks/share/share/icon.tsx +9 -0
  143. package/src/blocks/share/share/index.ts +8 -0
  144. package/src/blocks/share/share/types.ts +12 -0
  145. package/src/index.ts +22 -0
@@ -0,0 +1,61 @@
1
+ import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
2
+ import {PanelBody, ToggleControl} from '@wordpress/components'
3
+ import {__} from '@wordpress/i18n'
4
+ import type {CareerHeaderAttributes, CareerHeaderOptions} from './types'
5
+
6
+ export function createCareerHeaderEdit(_options: CareerHeaderOptions) {
7
+ return function Edit({
8
+ attributes,
9
+ setAttributes,
10
+ }: {
11
+ attributes: CareerHeaderAttributes
12
+ setAttributes: (a: Partial<CareerHeaderAttributes>) => void
13
+ }) {
14
+ const {showExcerpt, showLocation, showSalary, showBenefits, showEmploymentType} = attributes
15
+
16
+ const blockProps = useBlockProps({className: 'wp-block-section'})
17
+
18
+ return (
19
+ <>
20
+ <InspectorControls>
21
+ <PanelBody title={__('Zobrazené údaje', 'brilo-blocks')} initialOpen>
22
+ <ToggleControl
23
+ label={__('Zobrazit perex', 'brilo-blocks')}
24
+ checked={showExcerpt}
25
+ onChange={(value) => setAttributes({showExcerpt: value})}
26
+ />
27
+ <ToggleControl
28
+ label={__('Zobrazit lokalitu', 'brilo-blocks')}
29
+ checked={showLocation}
30
+ onChange={(value) => setAttributes({showLocation: value})}
31
+ />
32
+ <ToggleControl
33
+ label={__('Zobrazit plat', 'brilo-blocks')}
34
+ checked={showSalary}
35
+ onChange={(value) => setAttributes({showSalary: value})}
36
+ />
37
+ <ToggleControl
38
+ label={__('Zobrazit benefity', 'brilo-blocks')}
39
+ checked={showBenefits}
40
+ onChange={(value) => setAttributes({showBenefits: value})}
41
+ />
42
+ <ToggleControl
43
+ label={__('Zobrazit typ úvazku', 'brilo-blocks')}
44
+ checked={showEmploymentType}
45
+ onChange={(value) => setAttributes({showEmploymentType: value})}
46
+ />
47
+ </PanelBody>
48
+ </InspectorControls>
49
+
50
+ <div {...blockProps}>
51
+ <div className="components-placeholder">
52
+ <div className="components-placeholder__label">{__('Hlavička kariéry', 'brilo-blocks')}</div>
53
+ <div className="components-placeholder__instructions">
54
+ {__('Zobrazí data aktuální pozice — název, perex, lokalitu, plat, benefity a typ úvazku.', 'brilo-blocks')}
55
+ </div>
56
+ </div>
57
+ </div>
58
+ </>
59
+ )
60
+ }
61
+ }
@@ -0,0 +1,28 @@
1
+ import type {BlockConfiguration} from '@wordpress/blocks'
2
+ import {__} from '@wordpress/i18n'
3
+ import {createCareerHeaderEdit} from './edit'
4
+ import {icon as defaultIcon} from './icon'
5
+ import type {CareerHeaderAttributes, CareerHeaderOptions} from './types'
6
+
7
+ export type {CareerHeaderAttributes, CareerHeaderOptions}
8
+
9
+ export function createCareerHeaderBlock(options: CareerHeaderOptions): BlockConfiguration<CareerHeaderAttributes> {
10
+ return {
11
+ name: options.name,
12
+ title: options.title ?? __('Hlavička kariéry', 'brilo-blocks'),
13
+ description: options.description,
14
+ category: options.category ?? 'widgets',
15
+ ...(options.parent && {parent: options.parent}),
16
+ icon: options.icon ?? {src: defaultIcon},
17
+ supports: {html: false, customClassName: false},
18
+ attributes: {
19
+ showExcerpt: {type: 'boolean', default: true},
20
+ showLocation: {type: 'boolean', default: true},
21
+ showSalary: {type: 'boolean', default: true},
22
+ showBenefits: {type: 'boolean', default: true},
23
+ showEmploymentType: {type: 'boolean', default: true},
24
+ },
25
+ edit: createCareerHeaderEdit(options),
26
+ save: () => null,
27
+ } as unknown as BlockConfiguration<CareerHeaderAttributes>
28
+ }
@@ -0,0 +1,8 @@
1
+ export const icon = (
2
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <rect x="2" y="3" width="16" height="4" rx="1" stroke="black" fill="none" />
4
+ <line x1="2" y1="10" x2="14" y2="10" stroke="black" />
5
+ <line x1="2" y1="13" x2="18" y2="13" stroke="black" />
6
+ <line x1="2" y1="16" x2="10" y2="16" stroke="black" />
7
+ </svg>
8
+ )
@@ -0,0 +1,8 @@
1
+ export type {CareerHeaderAttributes, CareerHeaderOptions} from './types'
2
+ export {createCareerHeaderBlock} from './factory'
3
+
4
+ import type {CareerHeaderOptions} from './types'
5
+
6
+ export const careerHeaderDefaults: CareerHeaderOptions = {
7
+ name: 'brilo/career-header',
8
+ }
@@ -0,0 +1,11 @@
1
+ import type {BriloBlockType} from '~/types'
2
+
3
+ export interface CareerHeaderAttributes extends Record<string, unknown> {
4
+ showExcerpt: boolean
5
+ showLocation: boolean
6
+ showSalary: boolean
7
+ showBenefits: boolean
8
+ showEmploymentType: boolean
9
+ }
10
+
11
+ export type CareerHeaderOptions = BriloBlockType
@@ -0,0 +1,238 @@
1
+ import apiFetch from '@wordpress/api-fetch'
2
+ import {Button, Card, CardBody, __experimentalHStack as HStack, Modal, __experimentalVStack as VStack} from '@wordpress/components'
3
+ import {DataViews, type View} from '@wordpress/dataviews/wp'
4
+ import {__} from '@wordpress/i18n'
5
+ import {arrowDown, arrowUp, close, plusCircle} from '@wordpress/icons'
6
+ // biome-ignore lint/correctness/noUnusedImports: required in scope for classic JSX transform
7
+ import React, {useEffect, useMemo, useState} from 'react'
8
+ import type {SelectControlProps} from './types'
9
+
10
+ type JobPositionRecord = {
11
+ id: number
12
+ title: {rendered: string}
13
+ date: string
14
+ }
15
+
16
+ const DEFAULT_VIEW: View = {
17
+ type: 'table',
18
+ search: '',
19
+ filters: [],
20
+ page: 1,
21
+ perPage: 20,
22
+ sort: {field: 'title', direction: 'asc'},
23
+ fields: ['date'],
24
+ titleField: 'title',
25
+ }
26
+
27
+ function useJobPositions() {
28
+ const [positions, setPositions] = useState<JobPositionRecord[]>([])
29
+ const [isLoading, setIsLoading] = useState(true)
30
+
31
+ useEffect(() => {
32
+ setIsLoading(true)
33
+ apiFetch<JobPositionRecord[]>({
34
+ path: '/wp/v2/job_position?per_page=100&orderby=title&order=asc&_fields=id,title,date',
35
+ })
36
+ .then((result) => setPositions(result))
37
+ .catch(() => setPositions([]))
38
+ .finally(() => setIsLoading(false))
39
+ }, [])
40
+
41
+ return {positions, isLoading}
42
+ }
43
+
44
+ function SelectedOrderList({
45
+ items,
46
+ onChange,
47
+ onRemove,
48
+ }: {
49
+ items: JobPositionRecord[]
50
+ onChange: (ids: number[]) => void
51
+ onRemove: (id: number) => void
52
+ }) {
53
+ if (0 === items.length) {
54
+ return <p className="i-job-position-select-modal__empty">{__('Nevybrány žádné pozice.', 'brilo-blocks')}</p>
55
+ }
56
+
57
+ const move = (index: number, direction: -1 | 1) => {
58
+ const target = index + direction
59
+
60
+ if (target < 0 || target >= items.length) {
61
+ return
62
+ }
63
+
64
+ const next = [...items]
65
+ ;[next[index], next[target]] = [next[target], next[index]]
66
+ onChange(next.map((item) => item.id))
67
+ }
68
+
69
+ return (
70
+ <VStack spacing={2}>
71
+ {items.map((item, index) => (
72
+ <Card size="small" className="i-job-position-select-modal__item" key={item.id}>
73
+ <CardBody>
74
+ <HStack alignment="center">
75
+ <span
76
+ className="i-job-position-select-modal__item-title"
77
+ style={{
78
+ flexGrow: 1,
79
+ minWidth: 0,
80
+ textAlign: 'left',
81
+ overflow: 'hidden',
82
+ textOverflow: 'ellipsis',
83
+ whiteSpace: 'nowrap',
84
+ }}
85
+ >
86
+ {item.title.rendered || __('(bez názvu)', 'brilo-blocks')}
87
+ </span>
88
+
89
+ <HStack expanded={false} spacing={1}>
90
+ <Button
91
+ size="small"
92
+ icon={arrowUp}
93
+ label={__('Posunout výš', 'brilo-blocks')}
94
+ onClick={() => move(index, -1)}
95
+ disabled={0 === index}
96
+ />
97
+ <Button
98
+ size="small"
99
+ icon={arrowDown}
100
+ label={__('Posunout níž', 'brilo-blocks')}
101
+ onClick={() => move(index, 1)}
102
+ disabled={index === items.length - 1}
103
+ />
104
+ <Button size="small" icon={close} isDestructive label={__('Odebrat', 'brilo-blocks')} onClick={() => onRemove(item.id)} />
105
+ </HStack>
106
+ </HStack>
107
+ </CardBody>
108
+ </Card>
109
+ ))}
110
+ </VStack>
111
+ )
112
+ }
113
+
114
+ /**
115
+ * Manual job_position picker built on @wordpress/dataviews, mirroring
116
+ * DocumentsSelectModal closely (table view, search, sort, checkbox
117
+ * selection, reorderable selection list) but with just title/date columns.
118
+ */
119
+ export function JobPositionsSelectModal({selectedItems, onChange}: SelectControlProps) {
120
+ const {positions, isLoading} = useJobPositions()
121
+ const [isOpen, setIsOpen] = useState(false)
122
+ const [view, setView] = useState<View>(DEFAULT_VIEW)
123
+
124
+ const selectedPositions = useMemo(
125
+ () => selectedItems.map((id) => positions.find((pos) => pos.id === id)).filter((pos): pos is JobPositionRecord => undefined !== pos),
126
+ [selectedItems, positions],
127
+ )
128
+
129
+ const fields = useMemo(
130
+ () => [
131
+ {
132
+ id: 'title',
133
+ label: __('Název', 'brilo-blocks'),
134
+ enableHiding: false,
135
+ enableSorting: true,
136
+ render: ({item}: {item: JobPositionRecord}) => item.title.rendered || __('(bez názvu)', 'brilo-blocks'),
137
+ },
138
+ {
139
+ id: 'date',
140
+ label: __('Datum', 'brilo-blocks'),
141
+ enableSorting: true,
142
+ render: ({item}: {item: JobPositionRecord}) => (item.date ? new Date(item.date).toLocaleDateString() : '—'),
143
+ },
144
+ ],
145
+ [],
146
+ )
147
+
148
+ const {data, paginationInfo} = useMemo(() => {
149
+ let filtered = positions
150
+
151
+ if (view.search) {
152
+ const needle = view.search.toLowerCase()
153
+ filtered = filtered.filter((pos) => pos.title.rendered.toLowerCase().includes(needle))
154
+ }
155
+
156
+ if (view.sort?.field) {
157
+ const {field, direction} = view.sort
158
+ const sorted = [...filtered]
159
+
160
+ sorted.sort((a, b) => {
161
+ const valueA = 'title' === field ? a.title.rendered : ((a as never)[field] ?? '')
162
+ const valueB = 'title' === field ? b.title.rendered : ((b as never)[field] ?? '')
163
+ const result = String(valueA).localeCompare(String(valueB))
164
+
165
+ return 'desc' === direction ? -result : result
166
+ })
167
+
168
+ filtered = sorted
169
+ }
170
+
171
+ const perPage = view.perPage ?? 20
172
+ const page = view.page ?? 1
173
+ const start = (page - 1) * perPage
174
+
175
+ return {
176
+ data: filtered.slice(start, start + perPage),
177
+ paginationInfo: {totalItems: filtered.length, totalPages: Math.ceil(filtered.length / perPage) || 1},
178
+ }
179
+ }, [positions, view])
180
+
181
+ const toggleSelected = (id: number) => {
182
+ onChange(selectedItems.includes(id) ? selectedItems.filter((itemId) => itemId !== id) : [...selectedItems, id])
183
+ }
184
+
185
+ return (
186
+ <VStack spacing={3} className="i-job-position-select-modal">
187
+ <Button variant="secondary" icon={plusCircle} onClick={() => setIsOpen(true)}>
188
+ {__('Vybrat pozice', 'brilo-blocks')}
189
+ </Button>
190
+
191
+ <SelectedOrderList
192
+ items={selectedPositions}
193
+ onChange={onChange}
194
+ onRemove={(id) => onChange(selectedItems.filter((itemId) => itemId !== id))}
195
+ />
196
+
197
+ {isOpen && (
198
+ <Modal title={__('Vybrat pozice', 'brilo-blocks')} onRequestClose={() => setIsOpen(false)} size="fill">
199
+ <VStack spacing={4} style={{height: '100%'}}>
200
+ <div style={{flexGrow: 1, minHeight: 0}}>
201
+ <DataViews<JobPositionRecord>
202
+ data={data}
203
+ fields={fields}
204
+ view={view}
205
+ onChangeView={setView}
206
+ paginationInfo={paginationInfo}
207
+ isLoading={isLoading}
208
+ defaultLayouts={{table: {}}}
209
+ getItemId={(item) => String(item.id)}
210
+ selection={selectedItems.map(String)}
211
+ onChangeSelection={(ids) => onChange(ids.map(Number))}
212
+ actions={[
213
+ {
214
+ id: 'toggle',
215
+ label: (items) =>
216
+ items.length && selectedItems.includes(items[0].id) ? __('Odebrat', 'brilo-blocks') : __('Přidat', 'brilo-blocks'),
217
+ supportsBulk: true,
218
+ callback: (items) => {
219
+ items.forEach((item) => {
220
+ toggleSelected(item.id)
221
+ })
222
+ },
223
+ },
224
+ ]}
225
+ />
226
+ </div>
227
+
228
+ <HStack justify="flex-end">
229
+ <Button variant="primary" onClick={() => setIsOpen(false)}>
230
+ {__('Hotovo', 'brilo-blocks')}
231
+ </Button>
232
+ </HStack>
233
+ </VStack>
234
+ </Modal>
235
+ )}
236
+ </VStack>
237
+ )
238
+ }
@@ -0,0 +1,11 @@
1
+ export const JOB_POSITION_GROUP_MODES = ['selected', 'listing'] as const
2
+ export const JOB_POSITION_GROUP_SORT_BYS = ['date', 'title', 'start_date', 'menu_order'] as const
3
+ export const JOB_POSITION_GROUP_SORT_ORDERS = ['asc', 'desc'] as const
4
+
5
+ export const JOB_POSITION_GROUP_MODE = JOB_POSITION_GROUP_MODES[0]
6
+ export const JOB_POSITION_GROUP_SORT_BY = JOB_POSITION_GROUP_SORT_BYS[0]
7
+ export const JOB_POSITION_GROUP_SORT_ORDER = JOB_POSITION_GROUP_SORT_ORDERS[1]
8
+
9
+ export const JOB_POSITION_GROUP_PER_PAGE_MIN = 1
10
+ export const JOB_POSITION_GROUP_PER_PAGE_MAX = 24
11
+ export const JOB_POSITION_GROUP_PER_PAGE = 6
@@ -0,0 +1,93 @@
1
+ import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
2
+ import {
3
+ PanelBody,
4
+ RangeControl,
5
+ __experimentalToggleGroupControl as ToggleGroupControl,
6
+ __experimentalToggleGroupControlOption as ToggleGroupControlOption,
7
+ } from '@wordpress/components'
8
+ import {__} from '@wordpress/i18n'
9
+ import {JOB_POSITION_GROUP_PER_PAGE, JOB_POSITION_GROUP_PER_PAGE_MAX, JOB_POSITION_GROUP_PER_PAGE_MIN} from './constants'
10
+ import type {JobPositionGroupAttributes, JobPositionGroupOptions} from './types'
11
+
12
+ export function createJobPositionGroupEdit(options: JobPositionGroupOptions) {
13
+ return function Edit({
14
+ attributes,
15
+ setAttributes,
16
+ }: {
17
+ attributes: JobPositionGroupAttributes
18
+ setAttributes: (a: Partial<JobPositionGroupAttributes>) => void
19
+ }) {
20
+ const {mode, selectedPositions, perPage, sortBy, sortOrder} = attributes
21
+
22
+ const blockProps = useBlockProps({className: 'wp-block-section'})
23
+
24
+ return (
25
+ <>
26
+ <InspectorControls>
27
+ <PanelBody title={__('Nastavení výpisu', 'brilo-blocks')} initialOpen>
28
+ <ToggleGroupControl
29
+ label={__('Zdroj pozic', 'brilo-blocks')}
30
+ value={mode}
31
+ onChange={(value) => setAttributes({mode: value as JobPositionGroupAttributes['mode']})}
32
+ isBlock
33
+ >
34
+ <ToggleGroupControlOption value="selected" label={__('Vybrané', 'brilo-blocks')} />
35
+ <ToggleGroupControlOption value="listing" label={__('Výpis', 'brilo-blocks')} />
36
+ </ToggleGroupControl>
37
+
38
+ {'listing' === mode && (
39
+ <>
40
+ <RangeControl
41
+ label={__('Počet pozic', 'brilo-blocks')}
42
+ value={perPage}
43
+ onChange={(value) => setAttributes({perPage: value ?? JOB_POSITION_GROUP_PER_PAGE})}
44
+ min={JOB_POSITION_GROUP_PER_PAGE_MIN}
45
+ max={JOB_POSITION_GROUP_PER_PAGE_MAX}
46
+ />
47
+
48
+ <ToggleGroupControl
49
+ label={__('Řazení', 'brilo-blocks')}
50
+ value={sortBy}
51
+ onChange={(value) => setAttributes({sortBy: value as JobPositionGroupAttributes['sortBy']})}
52
+ isBlock
53
+ >
54
+ <ToggleGroupControlOption value="date" label={__('Datum publikace', 'brilo-blocks')} />
55
+ <ToggleGroupControlOption value="title" label={__('Název', 'brilo-blocks')} />
56
+ <ToggleGroupControlOption value="start_date" label={__('Datum nástupu', 'brilo-blocks')} />
57
+ <ToggleGroupControlOption value="menu_order" label={__('Pořadí', 'brilo-blocks')} />
58
+ </ToggleGroupControl>
59
+
60
+ <ToggleGroupControl
61
+ label={__('Směr řazení', 'brilo-blocks')}
62
+ value={sortOrder}
63
+ onChange={(value) => setAttributes({sortOrder: value as JobPositionGroupAttributes['sortOrder']})}
64
+ isBlock
65
+ >
66
+ <ToggleGroupControlOption value="desc" label={__('Sestupně', 'brilo-blocks')} />
67
+ <ToggleGroupControlOption value="asc" label={__('Vzestupně', 'brilo-blocks')} />
68
+ </ToggleGroupControl>
69
+ </>
70
+ )}
71
+ </PanelBody>
72
+ </InspectorControls>
73
+
74
+ <div {...blockProps}>
75
+ {'selected' === mode &&
76
+ options.renderPositionsControl?.({
77
+ selectedItems: selectedPositions,
78
+ onChange: (ids: number[]) => setAttributes({selectedPositions: ids}),
79
+ })}
80
+
81
+ {'listing' === mode && (
82
+ <div className="components-placeholder">
83
+ <div className="components-placeholder__label">{__('Pracovní pozice', 'brilo-blocks')}</div>
84
+ <div className="components-placeholder__instructions">
85
+ {`${__('Zobrazí', 'brilo-blocks')} ${perPage} ${__('pracovních pozic.', 'brilo-blocks')}`}
86
+ </div>
87
+ </div>
88
+ )}
89
+ </div>
90
+ </>
91
+ )
92
+ }
93
+ }
@@ -0,0 +1,56 @@
1
+ import type {BlockConfiguration} from '@wordpress/blocks'
2
+ import {__} from '@wordpress/i18n'
3
+ import {
4
+ JOB_POSITION_GROUP_MODE,
5
+ JOB_POSITION_GROUP_MODES,
6
+ JOB_POSITION_GROUP_PER_PAGE,
7
+ JOB_POSITION_GROUP_SORT_BY,
8
+ JOB_POSITION_GROUP_SORT_BYS,
9
+ JOB_POSITION_GROUP_SORT_ORDER,
10
+ JOB_POSITION_GROUP_SORT_ORDERS,
11
+ } from './constants'
12
+ import {createJobPositionGroupEdit} from './edit'
13
+ import {icon as defaultIcon} from './icon'
14
+ import type {JobPositionGroupAttributes, JobPositionGroupOptions} from './types'
15
+
16
+ export type {JobPositionGroupAttributes, JobPositionGroupOptions}
17
+
18
+ export function createJobPositionGroupBlock(options: JobPositionGroupOptions): BlockConfiguration<JobPositionGroupAttributes> {
19
+ return {
20
+ name: options.name,
21
+ title: options.title ?? __('Pracovní pozice', 'brilo-blocks'),
22
+ description: options.description,
23
+ category: options.category ?? 'widgets',
24
+ ...(options.parent && {parent: options.parent}),
25
+ icon: options.icon ?? {src: defaultIcon},
26
+ supports: {html: false, customClassName: false},
27
+ attributes: {
28
+ mode: {
29
+ type: 'string',
30
+ default: JOB_POSITION_GROUP_MODE,
31
+ enum: [...JOB_POSITION_GROUP_MODES],
32
+ },
33
+ selectedPositions: {
34
+ type: 'array',
35
+ default: [],
36
+ items: {type: 'number'},
37
+ },
38
+ perPage: {
39
+ type: 'number',
40
+ default: JOB_POSITION_GROUP_PER_PAGE,
41
+ },
42
+ sortBy: {
43
+ type: 'string',
44
+ default: JOB_POSITION_GROUP_SORT_BY,
45
+ enum: [...JOB_POSITION_GROUP_SORT_BYS],
46
+ },
47
+ sortOrder: {
48
+ type: 'string',
49
+ default: JOB_POSITION_GROUP_SORT_ORDER,
50
+ enum: [...JOB_POSITION_GROUP_SORT_ORDERS],
51
+ },
52
+ },
53
+ edit: createJobPositionGroupEdit(options),
54
+ save: () => null,
55
+ } as unknown as BlockConfiguration<JobPositionGroupAttributes>
56
+ }
@@ -0,0 +1,7 @@
1
+ export const icon = (
2
+ <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <rect x="2" y="6" width="16" height="11" rx="1" stroke="black" fill="none" />
4
+ <path d="M7 6V4C7 3.44772 7.44772 3 8 3H12C12.5523 3 13 3.44772 13 4V6" stroke="black" fill="none" />
5
+ <line x1="2" y1="11" x2="18" y2="11" stroke="black" />
6
+ </svg>
7
+ )
@@ -0,0 +1,15 @@
1
+ export type {
2
+ JobPositionGroupAttributes,
3
+ JobPositionGroupOptions,
4
+ JobPositionGroupMode,
5
+ JobPositionGroupSortBy,
6
+ JobPositionGroupSortOrder,
7
+ } from './types'
8
+ export {createJobPositionGroupBlock} from './factory'
9
+ export {JobPositionsSelectModal} from './JobPositionsSelectModal'
10
+
11
+ import type {JobPositionGroupOptions} from './types'
12
+
13
+ export const jobPositionGroupDefaults: JobPositionGroupOptions = {
14
+ name: 'brilo/job-position-group',
15
+ }
@@ -0,0 +1,23 @@
1
+ import type {BriloBlockType} from '~/types'
2
+ import type {JOB_POSITION_GROUP_MODES, JOB_POSITION_GROUP_SORT_BYS, JOB_POSITION_GROUP_SORT_ORDERS} from './constants'
3
+
4
+ export type JobPositionGroupMode = (typeof JOB_POSITION_GROUP_MODES)[number]
5
+ export type JobPositionGroupSortBy = (typeof JOB_POSITION_GROUP_SORT_BYS)[number]
6
+ export type JobPositionGroupSortOrder = (typeof JOB_POSITION_GROUP_SORT_ORDERS)[number]
7
+
8
+ export interface JobPositionGroupAttributes extends Record<string, unknown> {
9
+ mode: JobPositionGroupMode
10
+ selectedPositions: number[]
11
+ perPage: number
12
+ sortBy: JobPositionGroupSortBy
13
+ sortOrder: JobPositionGroupSortOrder
14
+ }
15
+
16
+ export interface SelectControlProps {
17
+ selectedItems: number[]
18
+ onChange: (ids: number[]) => void
19
+ }
20
+
21
+ export interface JobPositionGroupOptions extends BriloBlockType {
22
+ renderPositionsControl?: (props: SelectControlProps) => JSX.Element
23
+ }