@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.
- package/build/.tsbuildinfo +1 -1
- package/build/blocks/career/career-header/edit.d.ts +6 -0
- package/build/blocks/career/career-header/edit.d.ts.map +1 -0
- package/build/blocks/career/career-header/edit.js +11 -0
- package/build/blocks/career/career-header/factory.d.ts +5 -0
- package/build/blocks/career/career-header/factory.d.ts.map +1 -0
- package/build/blocks/career/career-header/factory.js +24 -0
- package/build/blocks/career/career-header/icon.d.ts +2 -0
- package/build/blocks/career/career-header/icon.d.ts.map +1 -0
- package/build/blocks/career/career-header/icon.js +2 -0
- package/build/blocks/career/career-header/index.d.ts +5 -0
- package/build/blocks/career/career-header/index.d.ts.map +1 -0
- package/build/blocks/career/career-header/index.js +4 -0
- package/build/blocks/career/career-header/types.d.ts +10 -0
- package/build/blocks/career/career-header/types.d.ts.map +1 -0
- package/build/blocks/career/career-header/types.js +1 -0
- package/build/blocks/career/job-position-group/JobPositionsSelectModal.d.ts +9 -0
- package/build/blocks/career/job-position-group/JobPositionsSelectModal.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/JobPositionsSelectModal.js +123 -0
- package/build/blocks/career/job-position-group/constants.d.ts +10 -0
- package/build/blocks/career/job-position-group/constants.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/constants.js +9 -0
- package/build/blocks/career/job-position-group/edit.d.ts +6 -0
- package/build/blocks/career/job-position-group/edit.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/edit.js +17 -0
- package/build/blocks/career/job-position-group/factory.d.ts +5 -0
- package/build/blocks/career/job-position-group/factory.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/factory.js +44 -0
- package/build/blocks/career/job-position-group/icon.d.ts +2 -0
- package/build/blocks/career/job-position-group/icon.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/icon.js +2 -0
- package/build/blocks/career/job-position-group/index.d.ts +6 -0
- package/build/blocks/career/job-position-group/index.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/index.js +5 -0
- package/build/blocks/career/job-position-group/types.d.ts +20 -0
- package/build/blocks/career/job-position-group/types.d.ts.map +1 -0
- package/build/blocks/career/job-position-group/types.js +1 -0
- package/build/blocks/document/documents-group/DocumentsSelectModal.d.ts +12 -0
- package/build/blocks/document/documents-group/DocumentsSelectModal.d.ts.map +1 -0
- package/build/blocks/document/documents-group/DocumentsSelectModal.js +153 -0
- package/build/blocks/document/documents-group/constants.d.ts +7 -0
- package/build/blocks/document/documents-group/constants.d.ts.map +1 -0
- package/build/blocks/document/documents-group/constants.js +5 -0
- package/build/blocks/document/documents-group/edit.d.ts +6 -0
- package/build/blocks/document/documents-group/edit.d.ts.map +1 -0
- package/build/blocks/document/documents-group/edit.js +27 -0
- package/build/blocks/document/documents-group/factory.d.ts +5 -0
- package/build/blocks/document/documents-group/factory.d.ts.map +1 -0
- package/build/blocks/document/documents-group/factory.js +50 -0
- package/build/blocks/document/documents-group/icon.d.ts +2 -0
- package/build/blocks/document/documents-group/icon.d.ts.map +1 -0
- package/build/blocks/document/documents-group/icon.js +2 -0
- package/build/blocks/document/documents-group/index.d.ts +6 -0
- package/build/blocks/document/documents-group/index.d.ts.map +1 -0
- package/build/blocks/document/documents-group/index.js +5 -0
- package/build/blocks/document/documents-group/types.d.ts +22 -0
- package/build/blocks/document/documents-group/types.d.ts.map +1 -0
- package/build/blocks/document/documents-group/types.js +1 -0
- package/build/blocks/layout/layout-aside/factory.d.ts.map +1 -1
- package/build/blocks/layout/layout-aside/icon.d.ts.map +1 -1
- package/build/blocks/layout/layout-content/factory.d.ts.map +1 -1
- package/build/blocks/layout/layout-content/icon.d.ts.map +1 -1
- package/build/blocks/layout/layout-content-w-aside/edit.d.ts.map +1 -1
- package/build/blocks/layout/layout-content-w-aside/edit.js +1 -1
- package/build/blocks/layout/layout-content-w-aside/factory.d.ts.map +1 -1
- package/build/blocks/layout/layout-content-w-aside/icon.d.ts.map +1 -1
- package/build/blocks/post/post-content/edit.d.ts +6 -0
- package/build/blocks/post/post-content/edit.d.ts.map +1 -0
- package/build/blocks/post/post-content/edit.js +9 -0
- package/build/blocks/post/post-content/factory.d.ts +5 -0
- package/build/blocks/post/post-content/factory.d.ts.map +1 -0
- package/build/blocks/post/post-content/factory.js +18 -0
- package/build/blocks/post/post-content/icon.d.ts +2 -0
- package/build/blocks/post/post-content/icon.d.ts.map +1 -0
- package/build/blocks/post/post-content/icon.js +2 -0
- package/build/blocks/post/post-content/index.d.ts +5 -0
- package/build/blocks/post/post-content/index.d.ts.map +1 -0
- package/build/blocks/post/post-content/index.js +4 -0
- package/build/blocks/post/post-content/types.d.ts +5 -0
- package/build/blocks/post/post-content/types.d.ts.map +1 -0
- package/build/blocks/post/post-content/types.js +1 -0
- package/build/blocks/sections/base-section/controls.d.ts.map +1 -1
- package/build/blocks/sections/base-section/controls.js +1 -1
- package/build/blocks/share/share/constants.d.ts +2 -0
- package/build/blocks/share/share/constants.d.ts.map +1 -0
- package/build/blocks/share/share/constants.js +1 -0
- package/build/blocks/share/share/edit.d.ts +6 -0
- package/build/blocks/share/share/edit.d.ts.map +1 -0
- package/build/blocks/share/share/edit.js +18 -0
- package/build/blocks/share/share/factory.d.ts +5 -0
- package/build/blocks/share/share/factory.d.ts.map +1 -0
- package/build/blocks/share/share/factory.js +26 -0
- package/build/blocks/share/share/icon.d.ts +2 -0
- package/build/blocks/share/share/icon.d.ts.map +1 -0
- package/build/blocks/share/share/icon.js +2 -0
- package/build/blocks/share/share/index.d.ts +5 -0
- package/build/blocks/share/share/index.d.ts.map +1 -0
- package/build/blocks/share/share/index.js +4 -0
- package/build/blocks/share/share/types.d.ts +11 -0
- package/build/blocks/share/share/types.d.ts.map +1 -0
- package/build/blocks/share/share/types.js +1 -0
- package/build/index.d.ts +10 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -0
- package/package.json +6 -1
- package/src/blocks/career/career-header/edit.tsx +61 -0
- package/src/blocks/career/career-header/factory.tsx +28 -0
- package/src/blocks/career/career-header/icon.tsx +8 -0
- package/src/blocks/career/career-header/index.ts +8 -0
- package/src/blocks/career/career-header/types.ts +11 -0
- package/src/blocks/career/job-position-group/JobPositionsSelectModal.tsx +238 -0
- package/src/blocks/career/job-position-group/constants.ts +11 -0
- package/src/blocks/career/job-position-group/edit.tsx +93 -0
- package/src/blocks/career/job-position-group/factory.tsx +56 -0
- package/src/blocks/career/job-position-group/icon.tsx +7 -0
- package/src/blocks/career/job-position-group/index.ts +15 -0
- package/src/blocks/career/job-position-group/types.ts +23 -0
- package/src/blocks/document/documents-group/DocumentsSelectModal.tsx +273 -0
- package/src/blocks/document/documents-group/constants.ts +7 -0
- package/src/blocks/document/documents-group/edit.tsx +96 -0
- package/src/blocks/document/documents-group/factory.tsx +59 -0
- package/src/blocks/document/documents-group/icon.tsx +9 -0
- package/src/blocks/document/documents-group/index.ts +15 -0
- package/src/blocks/document/documents-group/types.ts +25 -0
- package/src/blocks/layout/layout-aside/factory.tsx +1 -3
- package/src/blocks/layout/layout-aside/icon.tsx +1 -6
- package/src/blocks/layout/layout-content/editor.scss +1 -1
- package/src/blocks/layout/layout-content/factory.tsx +1 -3
- package/src/blocks/layout/layout-content/icon.tsx +1 -6
- package/src/blocks/layout/layout-content-w-aside/edit.tsx +5 -1
- package/src/blocks/layout/layout-content-w-aside/factory.tsx +1 -3
- package/src/blocks/layout/layout-content-w-aside/icon.tsx +1 -6
- package/src/blocks/post/post-content/edit.tsx +18 -0
- package/src/blocks/post/post-content/factory.tsx +22 -0
- package/src/blocks/post/post-content/icon.tsx +9 -0
- package/src/blocks/post/post-content/index.ts +8 -0
- package/src/blocks/post/post-content/types.ts +6 -0
- package/src/blocks/sections/base-section/controls.tsx +7 -1
- package/src/blocks/share/share/constants.ts +1 -0
- package/src/blocks/share/share/edit.tsx +57 -0
- package/src/blocks/share/share/factory.tsx +30 -0
- package/src/blocks/share/share/icon.tsx +9 -0
- package/src/blocks/share/share/index.ts +8 -0
- package/src/blocks/share/share/types.ts +12 -0
- package/src/index.ts +22 -0
|
@@ -0,0 +1,273 @@
|
|
|
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 DocumentRecord = {
|
|
11
|
+
id: number
|
|
12
|
+
title: {rendered: string}
|
|
13
|
+
date: string
|
|
14
|
+
document_alt_title?: string
|
|
15
|
+
document_url?: string
|
|
16
|
+
document_file_display?: string
|
|
17
|
+
document_category_names?: string
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const DEFAULT_VIEW: View = {
|
|
21
|
+
type: 'table',
|
|
22
|
+
search: '',
|
|
23
|
+
filters: [],
|
|
24
|
+
page: 1,
|
|
25
|
+
perPage: 20,
|
|
26
|
+
sort: {field: 'title', direction: 'asc'},
|
|
27
|
+
fields: ['document_file_display', 'document_category_names', 'document_alt_title', 'document_url'],
|
|
28
|
+
titleField: 'title',
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function useDocuments() {
|
|
32
|
+
const [documents, setDocuments] = useState<DocumentRecord[]>([])
|
|
33
|
+
const [isLoading, setIsLoading] = useState(true)
|
|
34
|
+
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
setIsLoading(true)
|
|
37
|
+
apiFetch<DocumentRecord[]>({
|
|
38
|
+
path:
|
|
39
|
+
'/wp/v2/document?per_page=100&orderby=title&order=asc&' +
|
|
40
|
+
'_fields=id,title,date,document_alt_title,document_url,document_file_display,document_category_names',
|
|
41
|
+
})
|
|
42
|
+
.then((result) => setDocuments(result))
|
|
43
|
+
.catch(() => setDocuments([]))
|
|
44
|
+
.finally(() => setIsLoading(false))
|
|
45
|
+
}, [])
|
|
46
|
+
|
|
47
|
+
return {documents, isLoading}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function SelectedOrderList({
|
|
51
|
+
items,
|
|
52
|
+
onChange,
|
|
53
|
+
onRemove,
|
|
54
|
+
}: {
|
|
55
|
+
items: DocumentRecord[]
|
|
56
|
+
onChange: (ids: number[]) => void
|
|
57
|
+
onRemove: (id: number) => void
|
|
58
|
+
}) {
|
|
59
|
+
if (0 === items.length) {
|
|
60
|
+
return <p className="i-documents-select-modal__empty">{__('Nevybrány žádné dokumenty.', 'brilo-blocks')}</p>
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const move = (index: number, direction: -1 | 1) => {
|
|
64
|
+
const target = index + direction
|
|
65
|
+
|
|
66
|
+
if (target < 0 || target >= items.length) {
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const next = [...items]
|
|
71
|
+
;[next[index], next[target]] = [next[target], next[index]]
|
|
72
|
+
onChange(next.map((item) => item.id))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<VStack spacing={2}>
|
|
77
|
+
{items.map((item, index) => (
|
|
78
|
+
<Card size="small" className="i-documents-select-modal__item" key={item.id}>
|
|
79
|
+
<CardBody>
|
|
80
|
+
<HStack alignment="center">
|
|
81
|
+
<span
|
|
82
|
+
className="i-documents-select-modal__item-title"
|
|
83
|
+
style={{
|
|
84
|
+
flexGrow: 1,
|
|
85
|
+
minWidth: 0,
|
|
86
|
+
textAlign: 'left',
|
|
87
|
+
overflow: 'hidden',
|
|
88
|
+
textOverflow: 'ellipsis',
|
|
89
|
+
whiteSpace: 'nowrap',
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
{item.title.rendered || __('(bez názvu)', 'brilo-blocks')}
|
|
93
|
+
</span>
|
|
94
|
+
|
|
95
|
+
<HStack expanded={false} spacing={1}>
|
|
96
|
+
<Button
|
|
97
|
+
size="small"
|
|
98
|
+
icon={arrowUp}
|
|
99
|
+
label={__('Posunout výš', 'brilo-blocks')}
|
|
100
|
+
onClick={() => move(index, -1)}
|
|
101
|
+
disabled={0 === index}
|
|
102
|
+
/>
|
|
103
|
+
<Button
|
|
104
|
+
size="small"
|
|
105
|
+
icon={arrowDown}
|
|
106
|
+
label={__('Posunout níž', 'brilo-blocks')}
|
|
107
|
+
onClick={() => move(index, 1)}
|
|
108
|
+
disabled={index === items.length - 1}
|
|
109
|
+
/>
|
|
110
|
+
<Button size="small" icon={close} isDestructive label={__('Odebrat', 'brilo-blocks')} onClick={() => onRemove(item.id)} />
|
|
111
|
+
</HStack>
|
|
112
|
+
</HStack>
|
|
113
|
+
</CardBody>
|
|
114
|
+
</Card>
|
|
115
|
+
))}
|
|
116
|
+
</VStack>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Manual document picker built on the real @wordpress/dataviews package: a
|
|
122
|
+
* fill-size modal (table view, search, sort, checkbox selection) for
|
|
123
|
+
* browsing/selecting documents, plus an up/down-reorderable list of the
|
|
124
|
+
* current selection below (drag-and-drop conflicted with the block editor's
|
|
125
|
+
* own native block dragging — see git history). Local to this block — not a
|
|
126
|
+
* shared @brilo/gutenberg-toolkit component.
|
|
127
|
+
*/
|
|
128
|
+
export function DocumentsSelectModal({selectedItems, onChange}: SelectControlProps) {
|
|
129
|
+
const {documents, isLoading} = useDocuments()
|
|
130
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
131
|
+
const [view, setView] = useState<View>(DEFAULT_VIEW)
|
|
132
|
+
|
|
133
|
+
const selectedDocuments = useMemo(
|
|
134
|
+
() => selectedItems.map((id) => documents.find((doc) => doc.id === id)).filter((doc): doc is DocumentRecord => undefined !== doc),
|
|
135
|
+
[selectedItems, documents],
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
const fields = useMemo(
|
|
139
|
+
() => [
|
|
140
|
+
{
|
|
141
|
+
id: 'title',
|
|
142
|
+
label: __('Název', 'brilo-blocks'),
|
|
143
|
+
enableHiding: false,
|
|
144
|
+
enableSorting: true,
|
|
145
|
+
render: ({item}: {item: DocumentRecord}) => item.title.rendered || __('(bez názvu)', 'brilo-blocks'),
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'document_file_display',
|
|
149
|
+
label: __('Soubor', 'brilo-blocks'),
|
|
150
|
+
enableSorting: false,
|
|
151
|
+
render: ({item}: {item: DocumentRecord}) => item.document_file_display || '—',
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
id: 'document_category_names',
|
|
155
|
+
label: __('Kategorie', 'brilo-blocks'),
|
|
156
|
+
enableSorting: false,
|
|
157
|
+
render: ({item}: {item: DocumentRecord}) => item.document_category_names || '—',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'document_alt_title',
|
|
161
|
+
label: __('Alternativní titulek', 'brilo-blocks'),
|
|
162
|
+
enableSorting: false,
|
|
163
|
+
render: ({item}: {item: DocumentRecord}) => item.document_alt_title || '—',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
id: 'document_url',
|
|
167
|
+
label: __('Alternativní URL', 'brilo-blocks'),
|
|
168
|
+
enableSorting: false,
|
|
169
|
+
render: ({item}: {item: DocumentRecord}) => item.document_url || '—',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: 'date',
|
|
173
|
+
label: __('Datum', 'brilo-blocks'),
|
|
174
|
+
enableSorting: true,
|
|
175
|
+
render: ({item}: {item: DocumentRecord}) => (item.date ? new Date(item.date).toLocaleDateString() : '—'),
|
|
176
|
+
},
|
|
177
|
+
],
|
|
178
|
+
[],
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
const {data, paginationInfo} = useMemo(() => {
|
|
182
|
+
let filtered = documents
|
|
183
|
+
|
|
184
|
+
if (view.search) {
|
|
185
|
+
const needle = view.search.toLowerCase()
|
|
186
|
+
filtered = filtered.filter((doc) => doc.title.rendered.toLowerCase().includes(needle))
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (view.sort?.field) {
|
|
190
|
+
const {field, direction} = view.sort
|
|
191
|
+
const sorted = [...filtered]
|
|
192
|
+
|
|
193
|
+
sorted.sort((a, b) => {
|
|
194
|
+
const valueA = 'title' === field ? a.title.rendered : ((a as never)[field] ?? '')
|
|
195
|
+
const valueB = 'title' === field ? b.title.rendered : ((b as never)[field] ?? '')
|
|
196
|
+
const result = String(valueA).localeCompare(String(valueB))
|
|
197
|
+
|
|
198
|
+
return 'desc' === direction ? -result : result
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
filtered = sorted
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const perPage = view.perPage ?? 20
|
|
205
|
+
const page = view.page ?? 1
|
|
206
|
+
const start = (page - 1) * perPage
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
data: filtered.slice(start, start + perPage),
|
|
210
|
+
paginationInfo: {totalItems: filtered.length, totalPages: Math.ceil(filtered.length / perPage) || 1},
|
|
211
|
+
}
|
|
212
|
+
}, [documents, view])
|
|
213
|
+
|
|
214
|
+
const toggleSelected = (id: number) => {
|
|
215
|
+
onChange(selectedItems.includes(id) ? selectedItems.filter((itemId) => itemId !== id) : [...selectedItems, id])
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return (
|
|
219
|
+
<VStack spacing={3} className="i-documents-select-modal">
|
|
220
|
+
<Button variant="secondary" icon={plusCircle} onClick={() => setIsOpen(true)}>
|
|
221
|
+
{__('Vybrat dokumenty', 'brilo-blocks')}
|
|
222
|
+
</Button>
|
|
223
|
+
|
|
224
|
+
<SelectedOrderList
|
|
225
|
+
items={selectedDocuments}
|
|
226
|
+
onChange={onChange}
|
|
227
|
+
onRemove={(id) => onChange(selectedItems.filter((itemId) => itemId !== id))}
|
|
228
|
+
/>
|
|
229
|
+
|
|
230
|
+
{isOpen && (
|
|
231
|
+
<Modal title={__('Vybrat dokumenty', 'brilo-blocks')} onRequestClose={() => setIsOpen(false)} size="fill">
|
|
232
|
+
<VStack spacing={4} style={{height: '100%'}}>
|
|
233
|
+
<div style={{flexGrow: 1, minHeight: 0}}>
|
|
234
|
+
<DataViews<DocumentRecord>
|
|
235
|
+
data={data}
|
|
236
|
+
fields={fields}
|
|
237
|
+
view={view}
|
|
238
|
+
onChangeView={setView}
|
|
239
|
+
paginationInfo={paginationInfo}
|
|
240
|
+
isLoading={isLoading}
|
|
241
|
+
defaultLayouts={{table: {}}}
|
|
242
|
+
getItemId={(item) => String(item.id)}
|
|
243
|
+
selection={selectedItems.map(String)}
|
|
244
|
+
onChangeSelection={(ids) => onChange(ids.map(Number))}
|
|
245
|
+
actions={[
|
|
246
|
+
{
|
|
247
|
+
id: 'toggle',
|
|
248
|
+
label: (items) =>
|
|
249
|
+
items.length && selectedItems.includes(items[0].id) ? __('Odebrat', 'brilo-blocks') : __('Přidat', 'brilo-blocks'),
|
|
250
|
+
// supportsBulk is what makes DataViews render a checkbox per row —
|
|
251
|
+
// without it there's no way to select items other than this menu.
|
|
252
|
+
supportsBulk: true,
|
|
253
|
+
callback: (items) => {
|
|
254
|
+
items.forEach((item) => {
|
|
255
|
+
toggleSelected(item.id)
|
|
256
|
+
})
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
]}
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
262
|
+
|
|
263
|
+
<HStack justify="flex-end">
|
|
264
|
+
<Button variant="primary" onClick={() => setIsOpen(false)}>
|
|
265
|
+
{__('Hotovo', 'brilo-blocks')}
|
|
266
|
+
</Button>
|
|
267
|
+
</HStack>
|
|
268
|
+
</VStack>
|
|
269
|
+
</Modal>
|
|
270
|
+
)}
|
|
271
|
+
</VStack>
|
|
272
|
+
)
|
|
273
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type {DocumentsGroupColumns, DocumentsGroupMode, DocumentsGroupListingStyle, DocumentsGroupSortBy} from './types'
|
|
2
|
+
|
|
3
|
+
export const DOCUMENTS_GROUP_MODE_DEFAULT: DocumentsGroupMode = 'manual'
|
|
4
|
+
export const DOCUMENTS_GROUP_LISTING_STYLE_DEFAULT: DocumentsGroupListingStyle = 'classic'
|
|
5
|
+
export const DOCUMENTS_GROUP_SORT_BY_DEFAULT: DocumentsGroupSortBy = 'manual-order'
|
|
6
|
+
export const DOCUMENTS_GROUP_COLUMNS_DEFAULT: DocumentsGroupColumns = 1
|
|
7
|
+
export const DOCUMENTS_GROUP_COLUMNS: DocumentsGroupColumns[] = [1, 2, 3, 4, 6]
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
|
|
2
|
+
import {
|
|
3
|
+
PanelBody,
|
|
4
|
+
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
5
|
+
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
6
|
+
} from '@wordpress/components'
|
|
7
|
+
import {__} from '@wordpress/i18n'
|
|
8
|
+
import {DOCUMENTS_GROUP_COLUMNS} from './constants'
|
|
9
|
+
import type {DocumentsGroupAttributes, DocumentsGroupOptions} from './types'
|
|
10
|
+
|
|
11
|
+
export function createDocumentsGroupEdit(options: DocumentsGroupOptions) {
|
|
12
|
+
return function Edit({
|
|
13
|
+
attributes,
|
|
14
|
+
setAttributes,
|
|
15
|
+
}: {
|
|
16
|
+
attributes: DocumentsGroupAttributes
|
|
17
|
+
setAttributes: (a: Partial<DocumentsGroupAttributes>) => void
|
|
18
|
+
}) {
|
|
19
|
+
const {mode, listingStyle, sortBy, columns, selectedDocuments, selectedCategories} = attributes
|
|
20
|
+
|
|
21
|
+
const blockProps = useBlockProps({className: 'wp-block-section'})
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
<InspectorControls>
|
|
26
|
+
<PanelBody title={__('Nastavení výpisu', 'brilo-blocks')} initialOpen>
|
|
27
|
+
<ToggleGroupControl
|
|
28
|
+
label={__('Zdroj dokumentů', 'brilo-blocks')}
|
|
29
|
+
value={mode}
|
|
30
|
+
onChange={(value) => {
|
|
31
|
+
const nextMode = value as DocumentsGroupAttributes['mode']
|
|
32
|
+
setAttributes({
|
|
33
|
+
mode: nextMode,
|
|
34
|
+
sortBy: 'manual' === nextMode ? sortBy : sortBy === 'manual-order' ? 'menu_order' : sortBy,
|
|
35
|
+
})
|
|
36
|
+
}}
|
|
37
|
+
isBlock
|
|
38
|
+
>
|
|
39
|
+
<ToggleGroupControlOption value="manual" label={__('Ruční výběr', 'brilo-blocks')} />
|
|
40
|
+
<ToggleGroupControlOption value="category" label={__('Dle kategorie', 'brilo-blocks')} />
|
|
41
|
+
</ToggleGroupControl>
|
|
42
|
+
|
|
43
|
+
<ToggleGroupControl
|
|
44
|
+
label={__('Styl výpisu', 'brilo-blocks')}
|
|
45
|
+
value={listingStyle}
|
|
46
|
+
onChange={(value) => setAttributes({listingStyle: value as DocumentsGroupAttributes['listingStyle']})}
|
|
47
|
+
isBlock
|
|
48
|
+
>
|
|
49
|
+
<ToggleGroupControlOption value="classic" label={__('Klasický výpis', 'brilo-blocks')} />
|
|
50
|
+
<ToggleGroupControlOption value="group-by-category" label={__('Dle kategorií', 'brilo-blocks')} />
|
|
51
|
+
</ToggleGroupControl>
|
|
52
|
+
|
|
53
|
+
<ToggleGroupControl
|
|
54
|
+
label={__('Řazení', 'brilo-blocks')}
|
|
55
|
+
value={sortBy}
|
|
56
|
+
onChange={(value) => setAttributes({sortBy: value as DocumentsGroupAttributes['sortBy']})}
|
|
57
|
+
isBlock
|
|
58
|
+
>
|
|
59
|
+
<ToggleGroupControlOption value="menu_order" label={__('Pořadí', 'brilo-blocks')} />
|
|
60
|
+
<ToggleGroupControlOption value="date" label={__('Datum', 'brilo-blocks')} />
|
|
61
|
+
{'manual' === mode && <ToggleGroupControlOption value="manual-order" label={__('Dle výběru', 'brilo-blocks')} />}
|
|
62
|
+
</ToggleGroupControl>
|
|
63
|
+
|
|
64
|
+
<ToggleGroupControl
|
|
65
|
+
label={__('Počet sloupců', 'brilo-blocks')}
|
|
66
|
+
help={
|
|
67
|
+
'group-by-category' === listingStyle ? __('Platí pro seznam dokumentů uvnitř každé kategorie.', 'brilo-blocks') : undefined
|
|
68
|
+
}
|
|
69
|
+
value={String(columns)}
|
|
70
|
+
onChange={(value) => setAttributes({columns: Number(value) as DocumentsGroupAttributes['columns']})}
|
|
71
|
+
isBlock
|
|
72
|
+
>
|
|
73
|
+
{DOCUMENTS_GROUP_COLUMNS.map((c) => (
|
|
74
|
+
<ToggleGroupControlOption key={c} value={String(c)} label={String(c)} />
|
|
75
|
+
))}
|
|
76
|
+
</ToggleGroupControl>
|
|
77
|
+
</PanelBody>
|
|
78
|
+
</InspectorControls>
|
|
79
|
+
|
|
80
|
+
<div {...blockProps}>
|
|
81
|
+
{'category' === mode &&
|
|
82
|
+
options.renderCategoryControl?.({
|
|
83
|
+
selectedItems: selectedCategories,
|
|
84
|
+
onChange: (ids: number[]) => setAttributes({selectedCategories: ids}),
|
|
85
|
+
})}
|
|
86
|
+
|
|
87
|
+
{'manual' === mode &&
|
|
88
|
+
options.renderDocumentsControl?.({
|
|
89
|
+
selectedItems: selectedDocuments,
|
|
90
|
+
onChange: (ids: number[]) => setAttributes({selectedDocuments: ids}),
|
|
91
|
+
})}
|
|
92
|
+
</div>
|
|
93
|
+
</>
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type {BlockConfiguration} from '@wordpress/blocks'
|
|
2
|
+
import {__} from '@wordpress/i18n'
|
|
3
|
+
import {
|
|
4
|
+
DOCUMENTS_GROUP_COLUMNS_DEFAULT,
|
|
5
|
+
DOCUMENTS_GROUP_LISTING_STYLE_DEFAULT,
|
|
6
|
+
DOCUMENTS_GROUP_MODE_DEFAULT,
|
|
7
|
+
DOCUMENTS_GROUP_SORT_BY_DEFAULT,
|
|
8
|
+
} from './constants'
|
|
9
|
+
import {createDocumentsGroupEdit} from './edit'
|
|
10
|
+
import {icon as defaultIcon} from './icon'
|
|
11
|
+
import type {DocumentsGroupAttributes, DocumentsGroupOptions} from './types'
|
|
12
|
+
|
|
13
|
+
export type {DocumentsGroupAttributes, DocumentsGroupOptions}
|
|
14
|
+
|
|
15
|
+
export function createDocumentsGroupBlock(options: DocumentsGroupOptions): BlockConfiguration<DocumentsGroupAttributes> {
|
|
16
|
+
return {
|
|
17
|
+
name: options.name,
|
|
18
|
+
title: options.title ?? __('Dokumenty', 'brilo-blocks'),
|
|
19
|
+
description: options.description,
|
|
20
|
+
category: options.category ?? 'widgets',
|
|
21
|
+
...(options.parent && {parent: options.parent}),
|
|
22
|
+
icon: options.icon ?? {src: defaultIcon},
|
|
23
|
+
supports: {html: false, customClassName: false},
|
|
24
|
+
attributes: {
|
|
25
|
+
mode: {
|
|
26
|
+
type: 'string',
|
|
27
|
+
default: DOCUMENTS_GROUP_MODE_DEFAULT,
|
|
28
|
+
enum: ['manual', 'category'],
|
|
29
|
+
},
|
|
30
|
+
listingStyle: {
|
|
31
|
+
type: 'string',
|
|
32
|
+
default: DOCUMENTS_GROUP_LISTING_STYLE_DEFAULT,
|
|
33
|
+
enum: ['classic', 'group-by-category'],
|
|
34
|
+
},
|
|
35
|
+
sortBy: {
|
|
36
|
+
type: 'string',
|
|
37
|
+
default: DOCUMENTS_GROUP_SORT_BY_DEFAULT,
|
|
38
|
+
enum: ['menu_order', 'date', 'manual-order'],
|
|
39
|
+
},
|
|
40
|
+
columns: {
|
|
41
|
+
type: 'number',
|
|
42
|
+
default: DOCUMENTS_GROUP_COLUMNS_DEFAULT,
|
|
43
|
+
enum: [1, 2, 3, 4, 6],
|
|
44
|
+
},
|
|
45
|
+
selectedDocuments: {
|
|
46
|
+
type: 'array',
|
|
47
|
+
default: [],
|
|
48
|
+
items: {type: 'number'},
|
|
49
|
+
},
|
|
50
|
+
selectedCategories: {
|
|
51
|
+
type: 'array',
|
|
52
|
+
default: [],
|
|
53
|
+
items: {type: 'number'},
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
edit: createDocumentsGroupEdit(options),
|
|
57
|
+
save: () => null,
|
|
58
|
+
} as unknown as BlockConfiguration<DocumentsGroupAttributes>
|
|
59
|
+
}
|
|
@@ -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">
|
|
3
|
+
<path d="M4 1H12L16 5V19H4V1Z" stroke="black" fill="none" />
|
|
4
|
+
<path d="M12 1V5H16" stroke="black" fill="none" />
|
|
5
|
+
<line x1="6.5" y1="9" x2="13.5" y2="9" stroke="black" />
|
|
6
|
+
<line x1="6.5" y1="12" x2="13.5" y2="12" stroke="black" />
|
|
7
|
+
<line x1="6.5" y1="15" x2="11" y2="15" stroke="black" />
|
|
8
|
+
</svg>
|
|
9
|
+
)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type {
|
|
2
|
+
DocumentsGroupAttributes,
|
|
3
|
+
DocumentsGroupOptions,
|
|
4
|
+
DocumentsGroupListingStyle,
|
|
5
|
+
DocumentsGroupMode,
|
|
6
|
+
DocumentsGroupSortBy,
|
|
7
|
+
} from './types'
|
|
8
|
+
export {createDocumentsGroupBlock} from './factory'
|
|
9
|
+
export {DocumentsSelectModal} from './DocumentsSelectModal'
|
|
10
|
+
|
|
11
|
+
import type {DocumentsGroupOptions} from './types'
|
|
12
|
+
|
|
13
|
+
export const documentsGroupDefaults: DocumentsGroupOptions = {
|
|
14
|
+
name: 'brilo/documents-group',
|
|
15
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type {BriloBlockType} from '~/types'
|
|
2
|
+
|
|
3
|
+
export type DocumentsGroupMode = 'manual' | 'category'
|
|
4
|
+
export type DocumentsGroupListingStyle = 'classic' | 'group-by-category'
|
|
5
|
+
export type DocumentsGroupSortBy = 'menu_order' | 'date' | 'manual-order'
|
|
6
|
+
export type DocumentsGroupColumns = 1 | 2 | 3 | 4 | 6
|
|
7
|
+
|
|
8
|
+
export interface DocumentsGroupAttributes extends Record<string, unknown> {
|
|
9
|
+
mode: DocumentsGroupMode
|
|
10
|
+
listingStyle: DocumentsGroupListingStyle
|
|
11
|
+
sortBy: DocumentsGroupSortBy
|
|
12
|
+
columns: DocumentsGroupColumns
|
|
13
|
+
selectedDocuments: number[]
|
|
14
|
+
selectedCategories: number[]
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface SelectControlProps {
|
|
18
|
+
selectedItems: number[]
|
|
19
|
+
onChange: (ids: number[]) => void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface DocumentsGroupOptions extends BriloBlockType {
|
|
23
|
+
renderCategoryControl?: (props: SelectControlProps) => JSX.Element
|
|
24
|
+
renderDocumentsControl?: (props: SelectControlProps) => JSX.Element
|
|
25
|
+
}
|
|
@@ -6,9 +6,7 @@ import {createAsideEdit} from './edit'
|
|
|
6
6
|
import {icon as defaultIcon} from './icon'
|
|
7
7
|
import type {AsideAttributes, AsideOptions} from './types'
|
|
8
8
|
|
|
9
|
-
export function createAsideBlock(
|
|
10
|
-
options: AsideOptions,
|
|
11
|
-
): BlockConfiguration<AsideAttributes> {
|
|
9
|
+
export function createAsideBlock(options: AsideOptions): BlockConfiguration<AsideAttributes> {
|
|
12
10
|
return {
|
|
13
11
|
name: options.name,
|
|
14
12
|
title: options.title ?? __('Postranní panel', 'brilo-blocks'),
|
|
@@ -2,11 +2,6 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
export const icon = (
|
|
4
4
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
-
<path
|
|
6
|
-
fillRule="evenodd"
|
|
7
|
-
clipRule="evenodd"
|
|
8
|
-
d="M8 4H20V20H8V4ZM10 6H18V18H10V6Z"
|
|
9
|
-
fill="currentColor"
|
|
10
|
-
/>
|
|
5
|
+
<path fillRule="evenodd" clipRule="evenodd" d="M8 4H20V20H8V4ZM10 6H18V18H10V6Z" fill="currentColor" />
|
|
11
6
|
</svg>
|
|
12
7
|
)
|
|
@@ -6,9 +6,7 @@ import {createContentEdit} from './edit'
|
|
|
6
6
|
import {icon as defaultIcon} from './icon'
|
|
7
7
|
import type {ContentAttributes, ContentOptions} from './types'
|
|
8
8
|
|
|
9
|
-
export function createContentBlock(
|
|
10
|
-
options: ContentOptions,
|
|
11
|
-
): BlockConfiguration<ContentAttributes> {
|
|
9
|
+
export function createContentBlock(options: ContentOptions): BlockConfiguration<ContentAttributes> {
|
|
12
10
|
return {
|
|
13
11
|
name: options.name,
|
|
14
12
|
title: options.title ?? __('Obsah', 'brilo-blocks'),
|
|
@@ -2,11 +2,6 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
export const icon = (
|
|
4
4
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
-
<path
|
|
6
|
-
fillRule="evenodd"
|
|
7
|
-
clipRule="evenodd"
|
|
8
|
-
d="M4 4H16V20H4V4ZM6 6H14V18H6V6Z"
|
|
9
|
-
fill="currentColor"
|
|
10
|
-
/>
|
|
5
|
+
<path fillRule="evenodd" clipRule="evenodd" d="M4 4H16V20H4V4ZM6 6H14V18H6V6Z" fill="currentColor" />
|
|
11
6
|
</svg>
|
|
12
7
|
)
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import {InspectorControls} from '@wordpress/block-editor'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
PanelBody,
|
|
4
|
+
__experimentalToggleGroupControl as ToggleGroupControl,
|
|
5
|
+
__experimentalToggleGroupControlOption as ToggleGroupControlOption,
|
|
6
|
+
} from '@wordpress/components'
|
|
3
7
|
import {__} from '@wordpress/i18n'
|
|
4
8
|
import React from 'react'
|
|
5
9
|
import {useGroupBlock} from '~/hooks/useGroupBlock'
|
|
@@ -8,9 +8,7 @@ import {createContentWithAsideEdit} from './edit'
|
|
|
8
8
|
import {icon as defaultIcon} from './icon'
|
|
9
9
|
import type {ContentWithAsideAttributes, ContentWithAsideOptions} from './types'
|
|
10
10
|
|
|
11
|
-
export function createContentWithAsideBlock<
|
|
12
|
-
TAsideSizes extends OptionArray = typeof ASIDE_SIZES,
|
|
13
|
-
>(
|
|
11
|
+
export function createContentWithAsideBlock<TAsideSizes extends OptionArray = typeof ASIDE_SIZES>(
|
|
14
12
|
options: ContentWithAsideOptions<TAsideSizes>,
|
|
15
13
|
): BlockConfiguration<ContentWithAsideAttributes<TAsideSizes[number]['value']>> {
|
|
16
14
|
const asideSizes = options.asideSizes ?? ASIDE_SIZES
|
|
@@ -2,11 +2,6 @@ import React from 'react'
|
|
|
2
2
|
|
|
3
3
|
export const icon = (
|
|
4
4
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
5
|
-
<path
|
|
6
|
-
fillRule="evenodd"
|
|
7
|
-
clipRule="evenodd"
|
|
8
|
-
d="M4 4H20V20H4V4ZM6 6H13V18H6V6ZM15 6H18V18H15V6Z"
|
|
9
|
-
fill="currentColor"
|
|
10
|
-
/>
|
|
5
|
+
<path fillRule="evenodd" clipRule="evenodd" d="M4 4H20V20H4V4ZM6 6H13V18H6V6ZM15 6H18V18H15V6Z" fill="currentColor" />
|
|
11
6
|
</svg>
|
|
12
7
|
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import {useBlockProps} from '@wordpress/block-editor'
|
|
2
|
+
import {__} from '@wordpress/i18n'
|
|
3
|
+
import type {PostContentAttributes, PostContentOptions} from './types'
|
|
4
|
+
|
|
5
|
+
export function createPostContentEdit(_options: PostContentOptions) {
|
|
6
|
+
return function Edit(_props: {attributes: PostContentAttributes; setAttributes: (a: Partial<PostContentAttributes>) => void}) {
|
|
7
|
+
const blockProps = useBlockProps({className: 'wp-block-section'})
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<div {...blockProps}>
|
|
11
|
+
<div className="components-placeholder">
|
|
12
|
+
<div className="components-placeholder__label">{__('Obsah postu', 'brilo-blocks')}</div>
|
|
13
|
+
<div className="components-placeholder__instructions">{__('Zobrazí obsah aktuální postu.', 'brilo-blocks')}</div>
|
|
14
|
+
</div>
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type {BlockConfiguration} from '@wordpress/blocks'
|
|
2
|
+
import {__} from '@wordpress/i18n'
|
|
3
|
+
import {createPostContentEdit} from './edit'
|
|
4
|
+
import {icon as defaultIcon} from './icon'
|
|
5
|
+
import type {PostContentAttributes, PostContentOptions} from './types'
|
|
6
|
+
|
|
7
|
+
export type {PostContentAttributes, PostContentOptions}
|
|
8
|
+
|
|
9
|
+
export function createPostContentBlock(options: PostContentOptions): BlockConfiguration<PostContentAttributes> {
|
|
10
|
+
return {
|
|
11
|
+
name: options.name,
|
|
12
|
+
title: options.title ?? __('Content postu', '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
|
+
edit: createPostContentEdit(options),
|
|
20
|
+
save: () => null,
|
|
21
|
+
} as unknown as BlockConfiguration<PostContentAttributes>
|
|
22
|
+
}
|
|
@@ -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">
|
|
3
|
+
<rect x="3" y="2" width="14" height="16" rx="1" stroke="black" fill="none" />
|
|
4
|
+
<line x1="6" y1="6" x2="14" y2="6" stroke="black" />
|
|
5
|
+
<line x1="6" y1="9" x2="14" y2="9" stroke="black" />
|
|
6
|
+
<line x1="6" y1="12" x2="14" y2="12" stroke="black" />
|
|
7
|
+
<line x1="6" y1="15" x2="10" y2="15" stroke="black" />
|
|
8
|
+
</svg>
|
|
9
|
+
)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type {PostContentAttributes, PostContentOptions} from './types'
|
|
2
|
+
export {createPostContentBlock} from './factory'
|
|
3
|
+
|
|
4
|
+
import type {PostContentOptions} from './types'
|
|
5
|
+
|
|
6
|
+
export const postContentDefaults: PostContentOptions = {
|
|
7
|
+
name: 'brilo/post-content',
|
|
8
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type {BriloBlockType} from '~/types'
|
|
2
|
+
|
|
3
|
+
// biome-ignore lint/complexity/noBannedTypes: no block-specific attributes, matches BriloBlockType's generic constraint shape
|
|
4
|
+
export interface PostContentAttributes extends Record<string, unknown> {}
|
|
5
|
+
|
|
6
|
+
export type PostContentOptions = BriloBlockType
|