@brilo/base-blocks 0.1.0
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/.editorconfig +12 -0
- package/.prettierrc +8 -0
- package/README.md +59 -0
- package/USAGE.md +263 -0
- package/biome.json +38 -0
- package/bun.lock +1392 -0
- package/docs/block-anatomy.md +73 -0
- package/docs/conventions.md +204 -0
- package/docs/new-block.md +179 -0
- package/package.json +41 -0
- package/src/blocks/column/column-group/edit.tsx +56 -0
- package/src/blocks/column/column-group/editor.scss +7 -0
- package/src/blocks/column/column-group/factory.tsx +29 -0
- package/src/blocks/column/column-group/index.ts +14 -0
- package/src/blocks/column/column-group/types.ts +8 -0
- package/src/blocks/column/column-item/constants.ts +1 -0
- package/src/blocks/column/column-item/edit.tsx +48 -0
- package/src/blocks/column/column-item/editor.scss +34 -0
- package/src/blocks/column/column-item/factory.tsx +25 -0
- package/src/blocks/column/column-item/index.ts +10 -0
- package/src/blocks/column/column-item/types.ts +7 -0
- package/src/blocks/compare/compare-group/constants.ts +1 -0
- package/src/blocks/compare/compare-group/edit.tsx +52 -0
- package/src/blocks/compare/compare-group/factory.tsx +29 -0
- package/src/blocks/compare/compare-group/icon.tsx +7 -0
- package/src/blocks/compare/compare-group/index.ts +13 -0
- package/src/blocks/compare/compare-group/types.ts +12 -0
- package/src/blocks/compare/compare-item/edit.tsx +38 -0
- package/src/blocks/compare/compare-item/editor.scss +15 -0
- package/src/blocks/compare/compare-item/factory.tsx +28 -0
- package/src/blocks/compare/compare-item/icon.tsx +9 -0
- package/src/blocks/compare/compare-item/index.ts +13 -0
- package/src/blocks/compare/compare-item/types.ts +9 -0
- package/src/blocks/compare/compare-option/constants.ts +7 -0
- package/src/blocks/compare/compare-option/edit.tsx +64 -0
- package/src/blocks/compare/compare-option/editor.scss +26 -0
- package/src/blocks/compare/compare-option/factory.tsx +35 -0
- package/src/blocks/compare/compare-option/icon.tsx +7 -0
- package/src/blocks/compare/compare-option/index.ts +8 -0
- package/src/blocks/compare/compare-option/types.ts +12 -0
- package/src/blocks/contact/contact-group/constants.ts +3 -0
- package/src/blocks/contact/contact-group/edit.tsx +57 -0
- package/src/blocks/contact/contact-group/editor.scss +20 -0
- package/src/blocks/contact/contact-group/factory.tsx +35 -0
- package/src/blocks/contact/contact-group/index.ts +12 -0
- package/src/blocks/contact/contact-group/types.ts +12 -0
- package/src/blocks/contact/contact-item/constants.ts +17 -0
- package/src/blocks/contact/contact-item/edit.tsx +93 -0
- package/src/blocks/contact/contact-item/editor.scss +38 -0
- package/src/blocks/contact/contact-item/factory.tsx +35 -0
- package/src/blocks/contact/contact-item/index.ts +23 -0
- package/src/blocks/contact/contact-item/types.ts +21 -0
- package/src/blocks/core/basic-button/constants.ts +17 -0
- package/src/blocks/core/basic-button/edit.tsx +107 -0
- package/src/blocks/core/basic-button/editor.scss +80 -0
- package/src/blocks/core/basic-button/factory.tsx +54 -0
- package/src/blocks/core/basic-button/index.ts +8 -0
- package/src/blocks/core/basic-button/types.ts +29 -0
- package/src/blocks/core/basic-heading/constants.ts +1 -0
- package/src/blocks/core/basic-heading/edit.tsx +76 -0
- package/src/blocks/core/basic-heading/editor.scss +8 -0
- package/src/blocks/core/basic-heading/factory.tsx +40 -0
- package/src/blocks/core/basic-heading/index.ts +8 -0
- package/src/blocks/core/basic-heading/types.ts +20 -0
- package/src/blocks/core/basic-overline/edit.tsx +28 -0
- package/src/blocks/core/basic-overline/editor.scss +14 -0
- package/src/blocks/core/basic-overline/factory.tsx +22 -0
- package/src/blocks/core/basic-overline/index.ts +8 -0
- package/src/blocks/core/basic-overline/types.ts +7 -0
- package/src/blocks/faq/faq-group/constants.ts +11 -0
- package/src/blocks/faq/faq-group/edit.tsx +55 -0
- package/src/blocks/faq/faq-group/editor.scss +11 -0
- package/src/blocks/faq/faq-group/factory.tsx +39 -0
- package/src/blocks/faq/faq-group/index.ts +11 -0
- package/src/blocks/faq/faq-group/types.ts +14 -0
- package/src/blocks/faq/faq-item/edit.tsx +50 -0
- package/src/blocks/faq/faq-item/editor.scss +57 -0
- package/src/blocks/faq/faq-item/factory.tsx +24 -0
- package/src/blocks/faq/faq-item/index.ts +9 -0
- package/src/blocks/faq/faq-item/types.ts +7 -0
- package/src/blocks/form/form-field/constants.ts +14 -0
- package/src/blocks/form/form-field/edit.tsx +178 -0
- package/src/blocks/form/form-field/editor.scss +71 -0
- package/src/blocks/form/form-field/factory.tsx +32 -0
- package/src/blocks/form/form-field/index.ts +10 -0
- package/src/blocks/form/form-field/types.ts +18 -0
- package/src/blocks/form/form-group/constants.ts +16 -0
- package/src/blocks/form/form-group/edit.tsx +190 -0
- package/src/blocks/form/form-group/editor.scss +41 -0
- package/src/blocks/form/form-group/factory.tsx +35 -0
- package/src/blocks/form/form-group/index.ts +18 -0
- package/src/blocks/form/form-group/types.ts +22 -0
- package/src/blocks/groups/banner-group/constants.ts +15 -0
- package/src/blocks/groups/banner-group/edit.tsx +122 -0
- package/src/blocks/groups/banner-group/editor.scss +18 -0
- package/src/blocks/groups/banner-group/factory.tsx +64 -0
- package/src/blocks/groups/banner-group/icon.tsx +13 -0
- package/src/blocks/groups/banner-group/index.ts +11 -0
- package/src/blocks/groups/banner-group/types.ts +30 -0
- package/src/blocks/groups/basic-header-group/constants.ts +9 -0
- package/src/blocks/groups/basic-header-group/edit.tsx +99 -0
- package/src/blocks/groups/basic-header-group/editor.scss +35 -0
- package/src/blocks/groups/basic-header-group/factory.tsx +46 -0
- package/src/blocks/groups/basic-header-group/icon.tsx +17 -0
- package/src/blocks/groups/basic-header-group/index.ts +9 -0
- package/src/blocks/groups/basic-header-group/types.ts +27 -0
- package/src/blocks/groups/button-group/constants.ts +7 -0
- package/src/blocks/groups/button-group/edit.tsx +52 -0
- package/src/blocks/groups/button-group/editor.scss +23 -0
- package/src/blocks/groups/button-group/factory.tsx +34 -0
- package/src/blocks/groups/button-group/index.ts +11 -0
- package/src/blocks/groups/button-group/types.ts +12 -0
- package/src/blocks/groups/text-and-media-group/constants.ts +43 -0
- package/src/blocks/groups/text-and-media-group/edit.tsx +241 -0
- package/src/blocks/groups/text-and-media-group/editor.scss +123 -0
- package/src/blocks/groups/text-and-media-group/factory.tsx +100 -0
- package/src/blocks/groups/text-and-media-group/icon.tsx +37 -0
- package/src/blocks/groups/text-and-media-group/index.ts +18 -0
- package/src/blocks/groups/text-and-media-group/types.ts +60 -0
- package/src/blocks/hero/hero-group/constants.ts +23 -0
- package/src/blocks/hero/hero-group/edit.tsx +85 -0
- package/src/blocks/hero/hero-group/editor.scss +0 -0
- package/src/blocks/hero/hero-group/factory.tsx +45 -0
- package/src/blocks/hero/hero-group/icon.tsx +28 -0
- package/src/blocks/hero/hero-group/index.ts +11 -0
- package/src/blocks/hero/hero-group/types.ts +22 -0
- package/src/blocks/hero/hero-item/constants.ts +15 -0
- package/src/blocks/hero/hero-item/edit.tsx +107 -0
- package/src/blocks/hero/hero-item/editor.scss +87 -0
- package/src/blocks/hero/hero-item/factory.tsx +49 -0
- package/src/blocks/hero/hero-item/index.ts +10 -0
- package/src/blocks/hero/hero-item/types.ts +38 -0
- package/src/blocks/map/map-group/constants.ts +20 -0
- package/src/blocks/map/map-group/edit.tsx +108 -0
- package/src/blocks/map/map-group/editor.scss +24 -0
- package/src/blocks/map/map-group/factory.tsx +51 -0
- package/src/blocks/map/map-group/index.ts +9 -0
- package/src/blocks/map/map-group/types.ts +16 -0
- package/src/blocks/newsletter/newsletter-form/constants.ts +5 -0
- package/src/blocks/newsletter/newsletter-form/edit.tsx +194 -0
- package/src/blocks/newsletter/newsletter-form/editor.scss +68 -0
- package/src/blocks/newsletter/newsletter-form/factory.tsx +59 -0
- package/src/blocks/newsletter/newsletter-form/index.ts +11 -0
- package/src/blocks/newsletter/newsletter-form/types.ts +45 -0
- package/src/blocks/post/post-slider-group/constants.ts +3 -0
- package/src/blocks/post/post-slider-group/edit.tsx +76 -0
- package/src/blocks/post/post-slider-group/factory.tsx +43 -0
- package/src/blocks/post/post-slider-group/icon.tsx +13 -0
- package/src/blocks/post/post-slider-group/index.ts +9 -0
- package/src/blocks/post/post-slider-group/types.ts +20 -0
- package/src/blocks/responsive-grid/responsive-grid-group/edit.tsx +95 -0
- package/src/blocks/responsive-grid/responsive-grid-group/factory.tsx +33 -0
- package/src/blocks/responsive-grid/responsive-grid-group/index.ts +13 -0
- package/src/blocks/responsive-grid/responsive-grid-group/types.ts +9 -0
- package/src/blocks/responsive-grid/responsive-grid-item/edit.tsx +19 -0
- package/src/blocks/responsive-grid/responsive-grid-item/factory.tsx +20 -0
- package/src/blocks/responsive-grid/responsive-grid-item/index.ts +9 -0
- package/src/blocks/responsive-grid/responsive-grid-item/types.ts +5 -0
- package/src/blocks/sections/base-section/attributes.ts +17 -0
- package/src/blocks/sections/base-section/constants.ts +18 -0
- package/src/blocks/sections/base-section/controls.tsx +70 -0
- package/src/blocks/sections/base-section/edit.tsx +34 -0
- package/src/blocks/sections/base-section/editor.scss +24 -0
- package/src/blocks/sections/base-section/factory.tsx +47 -0
- package/src/blocks/sections/base-section/icon.tsx +6 -0
- package/src/blocks/sections/base-section/index.ts +14 -0
- package/src/blocks/sections/base-section/types.ts +26 -0
- package/src/blocks/signpost/signpost-group/constants.ts +3 -0
- package/src/blocks/signpost/signpost-group/edit.tsx +75 -0
- package/src/blocks/signpost/signpost-group/editor.scss +0 -0
- package/src/blocks/signpost/signpost-group/factory.tsx +40 -0
- package/src/blocks/signpost/signpost-group/icon.tsx +19 -0
- package/src/blocks/signpost/signpost-group/index.ts +15 -0
- package/src/blocks/signpost/signpost-group/types.ts +9 -0
- package/src/blocks/signpost/signpost-item/constants.ts +4 -0
- package/src/blocks/signpost/signpost-item/edit.tsx +90 -0
- package/src/blocks/signpost/signpost-item/editor.scss +25 -0
- package/src/blocks/signpost/signpost-item/factory.tsx +29 -0
- package/src/blocks/signpost/signpost-item/icon.tsx +7 -0
- package/src/blocks/signpost/signpost-item/index.ts +10 -0
- package/src/blocks/signpost/signpost-item/types.ts +12 -0
- package/src/blocks/step/step-group/constants.ts +6 -0
- package/src/blocks/step/step-group/edit.tsx +64 -0
- package/src/blocks/step/step-group/editor.scss +19 -0
- package/src/blocks/step/step-group/factory.tsx +36 -0
- package/src/blocks/step/step-group/icon.tsx +27 -0
- package/src/blocks/step/step-group/index.ts +15 -0
- package/src/blocks/step/step-group/types.ts +13 -0
- package/src/blocks/step/step-item/constants.ts +6 -0
- package/src/blocks/step/step-item/edit.tsx +60 -0
- package/src/blocks/step/step-item/editor.scss +18 -0
- package/src/blocks/step/step-item/factory.tsx +27 -0
- package/src/blocks/step/step-item/index.ts +11 -0
- package/src/blocks/step/step-item/types.ts +12 -0
- package/src/blocks/testimonial/testimonial-group/constants.ts +27 -0
- package/src/blocks/testimonial/testimonial-group/edit.tsx +74 -0
- package/src/blocks/testimonial/testimonial-group/editor.scss +38 -0
- package/src/blocks/testimonial/testimonial-group/factory.tsx +44 -0
- package/src/blocks/testimonial/testimonial-group/icon.tsx +33 -0
- package/src/blocks/testimonial/testimonial-group/index.ts +15 -0
- package/src/blocks/testimonial/testimonial-group/types.ts +19 -0
- package/src/blocks/testimonial/testimonial-item/edit.tsx +48 -0
- package/src/blocks/testimonial/testimonial-item/editor.scss +20 -0
- package/src/blocks/testimonial/testimonial-item/factory.tsx +35 -0
- package/src/blocks/testimonial/testimonial-item/index.ts +9 -0
- package/src/blocks/testimonial/testimonial-item/types.ts +9 -0
- package/src/blocks/text-and-form/text-and-form-group/constants.ts +6 -0
- package/src/blocks/text-and-form/text-and-form-group/edit.tsx +59 -0
- package/src/blocks/text-and-form/text-and-form-group/editor.scss +21 -0
- package/src/blocks/text-and-form/text-and-form-group/factory.tsx +38 -0
- package/src/blocks/text-and-form/text-and-form-group/icon.tsx +23 -0
- package/src/blocks/text-and-form/text-and-form-group/index.ts +9 -0
- package/src/blocks/text-and-form/text-and-form-group/types.ts +23 -0
- package/src/blocks/text-and-form/text-and-form-text-column/constants.ts +10 -0
- package/src/blocks/text-and-form/text-and-form-text-column/edit.tsx +94 -0
- package/src/blocks/text-and-form/text-and-form-text-column/editor.scss +29 -0
- package/src/blocks/text-and-form/text-and-form-text-column/factory.tsx +41 -0
- package/src/blocks/text-and-form/text-and-form-text-column/index.ts +18 -0
- package/src/blocks/text-and-form/text-and-form-text-column/types.ts +23 -0
- package/src/blocks/usp/usp-group/constants.ts +54 -0
- package/src/blocks/usp/usp-group/edit.tsx +197 -0
- package/src/blocks/usp/usp-group/editor.scss +24 -0
- package/src/blocks/usp/usp-group/factory.tsx +113 -0
- package/src/blocks/usp/usp-group/icon.tsx +18 -0
- package/src/blocks/usp/usp-group/index.ts +15 -0
- package/src/blocks/usp/usp-group/types.ts +70 -0
- package/src/blocks/usp/usp-item/constants.ts +7 -0
- package/src/blocks/usp/usp-item/edit.tsx +65 -0
- package/src/blocks/usp/usp-item/editor.scss +17 -0
- package/src/blocks/usp/usp-item/factory.tsx +30 -0
- package/src/blocks/usp/usp-item/index.ts +11 -0
- package/src/blocks/usp/usp-item/types.ts +17 -0
- package/src/components/IconControl/IconControl.tsx +55 -0
- package/src/components/IconControl/editor.scss +53 -0
- package/src/components/IconControl/index.ts +2 -0
- package/src/components/IconControl/index.tsx +1 -0
- package/src/components/ImagePicker/ImagePicker.tsx +124 -0
- package/src/components/ImagePicker/editor.scss +79 -0
- package/src/components/ImagePicker/index.ts +2 -0
- package/src/components/ImagePicker/index.tsx +1 -0
- package/src/components/ItemIconControl/ItemIconControl.tsx +72 -0
- package/src/components/ItemIconControl/ItemIconModal.tsx +12 -0
- package/src/components/ItemIconControl/ItemIconPreview.tsx +93 -0
- package/src/components/ItemIconControl/editor.scss +52 -0
- package/src/components/ItemIconControl/index.ts +2 -0
- package/src/components/ItemIconControl/types.d.ts +30 -0
- package/src/constants.ts +20 -0
- package/src/editor.scss +34 -0
- package/src/globals.scss +237 -0
- package/src/hooks/useGroupBlock.ts +53 -0
- package/src/index.ts +122 -0
- package/src/types.ts +33 -0
- package/src/utils/createEditAdapter.ts +11 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Block anatomy
|
|
2
|
+
|
|
3
|
+
Every block in `@brilo/base-blocks` consists of exactly these files:
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
blocks/<category>/<block-name>/
|
|
7
|
+
├── factory.tsx — block config, attributes, options interface
|
|
8
|
+
├── edit.tsx — editor component (createXxxEdit)
|
|
9
|
+
├── constants.ts — option arrays and defaults used in edit.tsx
|
|
10
|
+
├── index.ts — barrel export
|
|
11
|
+
└── editor.scss — editor-only styles
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Categories
|
|
15
|
+
|
|
16
|
+
| Category | Purpose | Example |
|
|
17
|
+
|------------|------------------------------------------------|--------------------|
|
|
18
|
+
| `core/` | Atomic blocks — no inner blocks | `basic-button` |
|
|
19
|
+
| `groups/` | Container blocks — wrap inner blocks | `usp-group` |
|
|
20
|
+
| `items/` | Item blocks — live inside a group | `usp-item` |
|
|
21
|
+
| `sections/`| Top-level page sections — wrap groups | `base-section` |
|
|
22
|
+
|
|
23
|
+
Use `core/` for anything that renders a single element (text, button, image).
|
|
24
|
+
Use `groups/` when the block contains `InnerBlocks`.
|
|
25
|
+
Use `items/` when the block is designed to be a child of a specific group (`parent` restriction).
|
|
26
|
+
Use `sections/` for full-width page sections.
|
|
27
|
+
|
|
28
|
+
## factory.tsx
|
|
29
|
+
|
|
30
|
+
Exports:
|
|
31
|
+
- `XxxAttributes` — attribute interface extending `Record<string, unknown>`
|
|
32
|
+
- `XxxOptions` — options passed to the factory at tenant registration time
|
|
33
|
+
- `createXxxBlock(options)` — returns `BlockConfiguration<XxxAttributes>`
|
|
34
|
+
- `xxxDefaults` — sensible default options object
|
|
35
|
+
|
|
36
|
+
The factory sets: `name`, `title`, `category`, `supports`, `attributes`, `edit`, `save`.
|
|
37
|
+
Tenant-customisable values live in `XxxOptions`. Hardcoded values never need to change across tenants.
|
|
38
|
+
|
|
39
|
+
## edit.tsx
|
|
40
|
+
|
|
41
|
+
Exports a single function `createXxxEdit(options: XxxOptions)` that returns a React component.
|
|
42
|
+
|
|
43
|
+
Rules:
|
|
44
|
+
- No inline constant arrays — all arrays live in `constants.ts`
|
|
45
|
+
- No `__` calls on module level — only inside the returned component or in `constants.ts`
|
|
46
|
+
- Imports only from `./constants`, `./factory`, and `@wordpress/*`
|
|
47
|
+
|
|
48
|
+
## constants.ts
|
|
49
|
+
|
|
50
|
+
Contains all option arrays (`SelectOption[]`, `readonly number[]`, `readonly string[]`) used by `edit.tsx`.
|
|
51
|
+
|
|
52
|
+
Rules:
|
|
53
|
+
- Block-specific constants defined locally
|
|
54
|
+
- Constants shared with other blocks imported from `../../../constants` (or `../../constants` for items)
|
|
55
|
+
- Naming conflict resolved with import alias: `import { HEADING_LEVELS as SHARED_HEADING_LEVELS } from '../../../constants'`
|
|
56
|
+
|
|
57
|
+
See [conventions.md](./conventions.md) for naming rules.
|
|
58
|
+
|
|
59
|
+
## index.ts
|
|
60
|
+
|
|
61
|
+
Re-exports everything needed by `src/index.ts`:
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
export type {XxxAttributes, XxxOptions} from './factory'
|
|
65
|
+
export {createXxxBlock, xxxDefaults} from './factory'
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`edit.tsx` and `constants.ts` are never exported from `index.ts`.
|
|
69
|
+
|
|
70
|
+
## editor.scss
|
|
71
|
+
|
|
72
|
+
Editor-only styles scoped to the block. Do not put frontend styles here.
|
|
73
|
+
Compiled output is imported via `src/editor.scss` barrel.
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Conventions
|
|
2
|
+
|
|
3
|
+
## Naming
|
|
4
|
+
|
|
5
|
+
### Files
|
|
6
|
+
```
|
|
7
|
+
factory.tsx — always this exact name
|
|
8
|
+
edit.tsx — always this exact name
|
|
9
|
+
constants.ts — always this exact name
|
|
10
|
+
index.ts — always this exact name
|
|
11
|
+
editor.scss — always this exact name
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Functions and types
|
|
15
|
+
|
|
16
|
+
| Thing | Pattern | Example |
|
|
17
|
+
|-------------------|--------------------------|----------------------------|
|
|
18
|
+
| Factory function | `createXxxBlock` | `createBasicButtonBlock` |
|
|
19
|
+
| Edit factory | `createXxxEdit` | `createBasicButtonEdit` |
|
|
20
|
+
| Attributes type | `XxxAttributes` | `BasicButtonAttributes` |
|
|
21
|
+
| Options type | `XxxOptions` | `BasicButtonOptions` |
|
|
22
|
+
| Defaults object | `xxxDefaults` | `basicButtonDefaults` |
|
|
23
|
+
|
|
24
|
+
### Constants
|
|
25
|
+
|
|
26
|
+
All-caps snake case. No `DEFAULT_` prefix unless the constant is a fallback for an overridable option.
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// Overridable option default → DEFAULT_ prefix
|
|
30
|
+
export const DEFAULT_VARIANTS = [...] as const
|
|
31
|
+
|
|
32
|
+
// Fixed set, not exposed in options → no prefix
|
|
33
|
+
export const HEADING_LEVELS = [1, 2, 3, 4] as const
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Shared constants in `src/constants.ts`: `HEADING_LEVELS`, `HEADING_STYLES`, `CONTENT_SIZES`.
|
|
37
|
+
Import directly from `../../../constants` in block `constants.ts` files. Use alias on name conflict.
|
|
38
|
+
|
|
39
|
+
## Types
|
|
40
|
+
|
|
41
|
+
`SelectOption` — use for any `{value, label}` pair. Import from `src/types.ts`:
|
|
42
|
+
```ts
|
|
43
|
+
import type {SelectOption} from '../../../types'
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`readonly number[]` / `readonly string[]` — use `as const` for level/style arrays that must match TS literal types.
|
|
47
|
+
|
|
48
|
+
### Derived union types from constants
|
|
49
|
+
|
|
50
|
+
Allowed values for block attributes are derived directly from `as const` arrays in `constants.ts`. Never write union types by hand.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
constants.ts (as const arrays)
|
|
54
|
+
→ derived union types in types.ts
|
|
55
|
+
→ XxxAttributes interface
|
|
56
|
+
→ consumed by edit.tsx (attributes + setAttributes)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Pattern:
|
|
60
|
+
```ts
|
|
61
|
+
// constants.ts
|
|
62
|
+
export const MEDIA_POSITIONS = [
|
|
63
|
+
{value: 'left', label: ...},
|
|
64
|
+
{value: 'right', label: ...},
|
|
65
|
+
] as const
|
|
66
|
+
|
|
67
|
+
// types.ts
|
|
68
|
+
export type MediaPositions = (typeof MEDIA_POSITIONS)[number]['value']
|
|
69
|
+
// → 'left' | 'right'
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
For plain number/string arrays without `value` key (e.g. `HEADING_LEVELS = [1, 2, 3, 4] as const`):
|
|
73
|
+
```ts
|
|
74
|
+
export type HeadingLevels = (typeof HEADING_LEVELS)[number]
|
|
75
|
+
// → 1 | 2 | 3 | 4
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
To add or remove an allowed value, edit the source constant — the type updates automatically.
|
|
79
|
+
|
|
80
|
+
## Options pattern
|
|
81
|
+
|
|
82
|
+
Every factory accepts an `XxxOptions` object. Options that can be overridden by tenants have defaults defined in `constants.ts` and applied with `??`:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
export function createXxxEdit(options: XxxOptions) {
|
|
86
|
+
const variants = options.variants ?? DEFAULT_VARIANTS
|
|
87
|
+
// ...
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The same resolved array is used for both the WordPress `attributes.enum` definition and the edit UI — never hardcode `DEFAULT_*` directly in the factory `attributes` object:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// ✓ correct — uses resolved value, reflects tenant override
|
|
95
|
+
const variants = options.variants ?? DEFAULT_VARIANTS
|
|
96
|
+
attributes: { variant: { enum: variants.map((v) => v.value) } }
|
|
97
|
+
|
|
98
|
+
// ✗ wrong — ignores tenant override
|
|
99
|
+
attributes: { variant: { enum: DEFAULT_VARIANTS.map((v) => v.value) } }
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Options that are mandatory (like `name`) have no default and are required in the interface.
|
|
103
|
+
|
|
104
|
+
## Generic factories
|
|
105
|
+
|
|
106
|
+
Every factory whose options contain overridable enum arrays is generic. This lets TypeScript narrow attribute value types to the exact set a tenant provides.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
// factory.tsx
|
|
110
|
+
export function createBasicButtonBlock<
|
|
111
|
+
TVariants extends OptionArray = typeof DEFAULT_VARIANTS,
|
|
112
|
+
TSizes extends OptionArray = typeof DEFAULT_SIZES,
|
|
113
|
+
>(
|
|
114
|
+
options: BasicButtonOptions<TVariants, TSizes>,
|
|
115
|
+
): BlockConfiguration<BasicButtonAttributes<TVariants[number]['value'], TSizes[number]['value']>>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
// types.ts — Options and Attributes are also generic with matching defaults
|
|
120
|
+
export interface BasicButtonAttributes<
|
|
121
|
+
TVariant extends string = ButtonVariant,
|
|
122
|
+
TSize extends string = ButtonSize,
|
|
123
|
+
> extends Record<string, unknown> {
|
|
124
|
+
variant: TVariant
|
|
125
|
+
size: TSize
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface BasicButtonOptions<
|
|
129
|
+
TVariants extends OptionArray = typeof DEFAULT_VARIANTS,
|
|
130
|
+
TSizes extends OptionArray = typeof DEFAULT_SIZES,
|
|
131
|
+
> {
|
|
132
|
+
variants?: TVariants
|
|
133
|
+
sizes?: TSizes
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Use the shared constraint types from `src/types.ts`:
|
|
138
|
+
|
|
139
|
+
| Constraint | Use for |
|
|
140
|
+
|---|---|
|
|
141
|
+
| `OptionArray` | `ReadonlyArray<{value: string; label: string}>` — SelectOption arrays |
|
|
142
|
+
| `NumberArray` | `ReadonlyArray<number>` — level arrays |
|
|
143
|
+
| `StringArray` | `ReadonlyArray<string>` — style/class arrays |
|
|
144
|
+
|
|
145
|
+
**Tenant usage** — base (no generics needed, defaults inferred):
|
|
146
|
+
```ts
|
|
147
|
+
createBasicButtonBlock({...basicButtonDefaults})
|
|
148
|
+
// variant: 'primary' | 'secondary'
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Tenant usage** — custom enum:
|
|
152
|
+
```ts
|
|
153
|
+
const MY_VARIANTS = [
|
|
154
|
+
{value: 'primary', label: 'Primární'},
|
|
155
|
+
{value: 'brand', label: 'Brand'},
|
|
156
|
+
] as const // as const is required for literal inference
|
|
157
|
+
|
|
158
|
+
createBasicButtonBlock({...basicButtonDefaults, variants: MY_VARIANTS})
|
|
159
|
+
// variant: 'primary' | 'brand'
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
`edit.tsx` stays non-generic — `createXxxEdit` takes the non-generic `XxxOptions` type. The factory casts options when calling it:
|
|
163
|
+
```ts
|
|
164
|
+
edit: createBasicButtonEdit(options as unknown as BasicButtonOptions),
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Fixed arrays that are not exposed in options (e.g. `HEADING_LEVELS`, `CHIP_POSITIONS`) are not type params — they remain hardcoded in `attributes` and render.
|
|
168
|
+
|
|
169
|
+
## Exports
|
|
170
|
+
|
|
171
|
+
Only `factory.tsx` exports from a block. `edit.tsx` and `constants.ts` are internal.
|
|
172
|
+
|
|
173
|
+
`src/index.ts` re-exports:
|
|
174
|
+
- Types: `XxxAttributes`, `XxxOptions`
|
|
175
|
+
- Values: `createXxxBlock`, `xxxDefaults`
|
|
176
|
+
|
|
177
|
+
Do not export `SelectOption` from individual factory files — it lives in `src/types.ts` and is exported from there.
|
|
178
|
+
|
|
179
|
+
## CSS class composition
|
|
180
|
+
|
|
181
|
+
Use `clsx` to compose `className` in `useBlockProps`. Each modifier class reflects a piece of component state — readable and styleable per state:
|
|
182
|
+
|
|
183
|
+
```tsx
|
|
184
|
+
const blockProps = useBlockProps({
|
|
185
|
+
className: clsx(
|
|
186
|
+
options.blockClassName ?? 'i-button',
|
|
187
|
+
`--variant-${variant}`,
|
|
188
|
+
`--size-${size}`,
|
|
189
|
+
outline && '--outline',
|
|
190
|
+
fullWidth !== 'false' && `--full-width-${fullWidth}`,
|
|
191
|
+
),
|
|
192
|
+
})
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
Rules:
|
|
196
|
+
- Base class first (from `options.blockClassName` or block default)
|
|
197
|
+
- BEM modifier classes (`--variant-x`, `--size-x`) as template literals
|
|
198
|
+
- Boolean modifiers as `condition && '--class'` — falsy values dropped by `clsx`
|
|
199
|
+
- No manual string concatenation or ternaries for class toggling
|
|
200
|
+
|
|
201
|
+
## i18n
|
|
202
|
+
|
|
203
|
+
All user-visible strings use `__('string', 'brilo-blocks')`.
|
|
204
|
+
Constants with translated labels live in `constants.ts`, not in `edit.tsx`.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Adding a new block
|
|
2
|
+
|
|
3
|
+
## 1. Choose a category
|
|
4
|
+
|
|
5
|
+
See [block-anatomy.md](./block-anatomy.md#categories) for when to use `core/`, `groups/`, `items/`, or `sections/`.
|
|
6
|
+
|
|
7
|
+
## 2. Create the directory
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
src/blocks/<category>/<block-name>/
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 3. Create the files
|
|
14
|
+
|
|
15
|
+
Copy the templates below into the directory. Replace every `Xxx` / `xxx` / `block-name` with your block name.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
### `factory.tsx`
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import type {BlockConfiguration} from '@wordpress/blocks'
|
|
23
|
+
import {createXxxEdit} from './edit'
|
|
24
|
+
|
|
25
|
+
export interface XxxAttributes extends Record<string, unknown> {
|
|
26
|
+
// TODO: define attributes
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface XxxOptions {
|
|
30
|
+
name: string
|
|
31
|
+
title?: string
|
|
32
|
+
description?: string
|
|
33
|
+
category?: string
|
|
34
|
+
blockClassName?: string
|
|
35
|
+
// TODO: add overridable options
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const xxxDefaults: XxxOptions = {
|
|
39
|
+
name: 'brilo/xxx',
|
|
40
|
+
title: 'TODO: Block title',
|
|
41
|
+
// TODO: fill defaults
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function createXxxBlock(options: XxxOptions): BlockConfiguration<XxxAttributes> {
|
|
45
|
+
return {
|
|
46
|
+
name: options.name,
|
|
47
|
+
title: options.title ?? 'TODO',
|
|
48
|
+
description: options.description,
|
|
49
|
+
category: options.category ?? 'common',
|
|
50
|
+
supports: {html: false, customClassName: false},
|
|
51
|
+
attributes: {
|
|
52
|
+
// TODO: mirror XxxAttributes shape
|
|
53
|
+
},
|
|
54
|
+
edit: createXxxEdit(options),
|
|
55
|
+
save: () => null,
|
|
56
|
+
} as unknown as BlockConfiguration<XxxAttributes>
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
### `constants.ts`
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import {__} from '@wordpress/i18n'
|
|
66
|
+
import type {SelectOption} from '../../../types'
|
|
67
|
+
|
|
68
|
+
// Import shared constants if needed:
|
|
69
|
+
// export {HEADING_LEVELS, HEADING_STYLES, CONTENT_SIZES} from '../../../constants'
|
|
70
|
+
|
|
71
|
+
// TODO: define block-specific constants
|
|
72
|
+
// export const MY_OPTIONS: SelectOption[] = [
|
|
73
|
+
// {value: 'foo', label: __('Foo', 'brilo-blocks')},
|
|
74
|
+
// ]
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
### `edit.tsx`
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import {InspectorControls, useBlockProps} from '@wordpress/block-editor'
|
|
83
|
+
import {PanelBody} from '@wordpress/components'
|
|
84
|
+
import {__} from '@wordpress/i18n'
|
|
85
|
+
import type {XxxAttributes, XxxOptions} from './factory'
|
|
86
|
+
// import {MY_OPTIONS} from './constants'
|
|
87
|
+
|
|
88
|
+
export function createXxxEdit(options: XxxOptions) {
|
|
89
|
+
return function Edit({
|
|
90
|
+
attributes,
|
|
91
|
+
setAttributes,
|
|
92
|
+
}: {
|
|
93
|
+
attributes: XxxAttributes
|
|
94
|
+
setAttributes: (a: Partial<XxxAttributes>) => void
|
|
95
|
+
}) {
|
|
96
|
+
const blockProps = useBlockProps({className: options.blockClassName ?? 'TODO'})
|
|
97
|
+
|
|
98
|
+
return (
|
|
99
|
+
<>
|
|
100
|
+
<InspectorControls>
|
|
101
|
+
<PanelBody title={__('TODO', 'brilo-blocks')}>
|
|
102
|
+
{/* TODO: add controls */}
|
|
103
|
+
</PanelBody>
|
|
104
|
+
</InspectorControls>
|
|
105
|
+
<div {...blockProps}>
|
|
106
|
+
{/* TODO: render block */}
|
|
107
|
+
</div>
|
|
108
|
+
</>
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
For group blocks (with inner blocks), use `useGroupBlock` instead of `useBlockProps`:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
import {useGroupBlock} from '../../../hooks/useGroupBlock'
|
|
118
|
+
|
|
119
|
+
const {blockProps, innerBlocksProps} = useGroupBlock({
|
|
120
|
+
blockClassName: options.blockClassName ?? 'g-xxx wp-block-section',
|
|
121
|
+
allowedBlocks: options.allowedBlocks,
|
|
122
|
+
template: options.template,
|
|
123
|
+
})
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
### `index.ts`
|
|
129
|
+
|
|
130
|
+
```ts
|
|
131
|
+
export type {XxxAttributes, XxxOptions} from './factory'
|
|
132
|
+
export {createXxxBlock, xxxDefaults} from './factory'
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### `editor.scss`
|
|
138
|
+
|
|
139
|
+
```scss
|
|
140
|
+
.TODO-block-class {
|
|
141
|
+
// editor-only styles
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## 4. Register in src/index.ts
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
export type {XxxAttributes, XxxOptions} from './blocks/<category>/xxx'
|
|
151
|
+
export {createXxxBlock, xxxDefaults} from './blocks/<category>/xxx'
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## 5. Import in src/editor.scss
|
|
155
|
+
|
|
156
|
+
```scss
|
|
157
|
+
@import './blocks/<category>/<block-name>/editor';
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## 6. Build
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
bun run build
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## 7. Register in tenant
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import {createXxxBlock, xxxDefaults} from '@brilo/base-blocks'
|
|
170
|
+
import {registerBlockType} from '@wordpress/blocks'
|
|
171
|
+
|
|
172
|
+
const config = createXxxBlock({
|
|
173
|
+
...xxxDefaults,
|
|
174
|
+
// override what the tenant needs
|
|
175
|
+
})
|
|
176
|
+
registerBlockType(config.name as string, config)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Add `block.json` in the tenant with only build metadata (`$schema`, `apiVersion`, `name`, `editorScript`, `editorStyle`).
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@brilo/base-blocks",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"author": "Brilo",
|
|
5
|
+
"main": "./build/index.js",
|
|
6
|
+
"types": "./build/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc && tsc-alias",
|
|
9
|
+
"watch": "tsc --watch",
|
|
10
|
+
"lint": "biome lint ./src",
|
|
11
|
+
"format": "biome format --write ./src && prettier --write \"./src/**/*.scss\"",
|
|
12
|
+
"check": "biome check --write ./src"
|
|
13
|
+
},
|
|
14
|
+
"peerDependencies": {
|
|
15
|
+
"@wordpress/block-editor": "15.21.0",
|
|
16
|
+
"@wordpress/blocks": "15.21.0",
|
|
17
|
+
"@wordpress/components": "35.0.0",
|
|
18
|
+
"@wordpress/i18n": "6.21.0",
|
|
19
|
+
"react": "*"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@biomejs/biome": "2.4.16",
|
|
23
|
+
"@types/react": "^18.3.12",
|
|
24
|
+
"@types/wordpress__block-editor": "^15.0.6",
|
|
25
|
+
"@wordpress/block-editor": "^15.21.0",
|
|
26
|
+
"@wordpress/blocks": "^15.21.0",
|
|
27
|
+
"@wordpress/components": "^35.0.0",
|
|
28
|
+
"@wordpress/data": "^10.48.0",
|
|
29
|
+
"@wordpress/element": "^8.0.0",
|
|
30
|
+
"@wordpress/i18n": "^6.21.0",
|
|
31
|
+
"prettier": "^3.0.0",
|
|
32
|
+
"tsc-alias": "^1.8.17",
|
|
33
|
+
"typescript": "^5.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"clsx": "^2.1.1"
|
|
37
|
+
},
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import {InspectorControls} from '@wordpress/block-editor'
|
|
2
|
+
import {PanelBody, RangeControl} from '@wordpress/components'
|
|
3
|
+
import {__} from '@wordpress/i18n'
|
|
4
|
+
import {useGroupBlock} from '~/hooks/useGroupBlock'
|
|
5
|
+
import type {ColumnGroupAttributes, ColumnGroupOptions} from './types'
|
|
6
|
+
|
|
7
|
+
export function createColumnGroupEdit(options: ColumnGroupOptions) {
|
|
8
|
+
return function Edit({
|
|
9
|
+
attributes,
|
|
10
|
+
setAttributes,
|
|
11
|
+
}: {
|
|
12
|
+
attributes: ColumnGroupAttributes
|
|
13
|
+
setAttributes: (a: Partial<ColumnGroupAttributes>) => void
|
|
14
|
+
}) {
|
|
15
|
+
const {spacingX, spacingY} = attributes
|
|
16
|
+
const {blockProps, innerBlocksProps} = useGroupBlock({
|
|
17
|
+
blockClassName: options.blockClassName ?? 'g-column wp-block-section',
|
|
18
|
+
containerClassName: options.containerClassName ?? 'g-column__inner',
|
|
19
|
+
allowedBlocks: options.allowedBlocks,
|
|
20
|
+
template: options.template,
|
|
21
|
+
layout: {type: 'default'},
|
|
22
|
+
containerStyle: {
|
|
23
|
+
'--gap-x': `${spacingX}px`,
|
|
24
|
+
'--gap-y': `${spacingY}px`,
|
|
25
|
+
},
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<InspectorControls>
|
|
31
|
+
<PanelBody title={__('Nastavení sloupců', 'brilo-blocks')}>
|
|
32
|
+
<RangeControl
|
|
33
|
+
label={__('Horizontální mezera (px)', 'brilo-blocks')}
|
|
34
|
+
value={spacingX}
|
|
35
|
+
onChange={(v) => setAttributes({spacingX: v ?? 0})}
|
|
36
|
+
min={0}
|
|
37
|
+
max={64}
|
|
38
|
+
step={8}
|
|
39
|
+
/>
|
|
40
|
+
<RangeControl
|
|
41
|
+
label={__('Vertikální mezera (px)', 'brilo-blocks')}
|
|
42
|
+
value={spacingY}
|
|
43
|
+
onChange={(v) => setAttributes({spacingY: v ?? 0})}
|
|
44
|
+
min={0}
|
|
45
|
+
max={64}
|
|
46
|
+
step={8}
|
|
47
|
+
/>
|
|
48
|
+
</PanelBody>
|
|
49
|
+
</InspectorControls>
|
|
50
|
+
<div {...blockProps}>
|
|
51
|
+
<div {...innerBlocksProps} />
|
|
52
|
+
</div>
|
|
53
|
+
</>
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {InnerBlocks} from '@wordpress/block-editor'
|
|
2
|
+
import type {BlockConfiguration} from '@wordpress/blocks'
|
|
3
|
+
import {__} from '@wordpress/i18n'
|
|
4
|
+
import {createColumnGroupEdit} from './edit'
|
|
5
|
+
import type {ColumnGroupAttributes, ColumnGroupOptions} from './types'
|
|
6
|
+
|
|
7
|
+
export function createColumnGroupBlock(options: ColumnGroupOptions): BlockConfiguration<ColumnGroupAttributes> {
|
|
8
|
+
return {
|
|
9
|
+
name: options.name,
|
|
10
|
+
title: options.title ?? __('Obsahové sloupce', 'brilo-blocks'),
|
|
11
|
+
description: options.description,
|
|
12
|
+
category: options.category ?? 'layout',
|
|
13
|
+
...(options.parent && {parent: options.parent}),
|
|
14
|
+
icon: options.icon ?? 'columns',
|
|
15
|
+
supports: {html: false, customClassName: false},
|
|
16
|
+
attributes: {
|
|
17
|
+
spacingX: {
|
|
18
|
+
type: 'number',
|
|
19
|
+
default: 16,
|
|
20
|
+
},
|
|
21
|
+
spacingY: {
|
|
22
|
+
type: 'number',
|
|
23
|
+
default: 16,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
edit: createColumnGroupEdit(options),
|
|
27
|
+
save: () => <InnerBlocks.Content />,
|
|
28
|
+
} as BlockConfiguration<ColumnGroupAttributes>
|
|
29
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type {ColumnGroupAttributes, ColumnGroupOptions} from './types'
|
|
2
|
+
export {createColumnGroupBlock} from './factory'
|
|
3
|
+
|
|
4
|
+
import type {ColumnGroupOptions} from './types'
|
|
5
|
+
|
|
6
|
+
export const columnGroupDefaults: ColumnGroupOptions = {
|
|
7
|
+
name: 'brilo/column-group',
|
|
8
|
+
allowedBlocks: ['brilo/column-item'],
|
|
9
|
+
parent: ['brilo/base-section'],
|
|
10
|
+
template: [
|
|
11
|
+
['brilo/column-item', {}],
|
|
12
|
+
['brilo/column-item', {}],
|
|
13
|
+
],
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const SIZES = ['1/4', '1/3', '1/2', '2/3', '3/4', '1/1']
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import {InspectorControls} from '@wordpress/block-editor'
|
|
2
|
+
import {PanelBody, RangeControl} from '@wordpress/components'
|
|
3
|
+
import {__} from '@wordpress/i18n'
|
|
4
|
+
import clsx from 'clsx'
|
|
5
|
+
import {useGroupBlock} from '~/hooks/useGroupBlock'
|
|
6
|
+
import type {ColumnItemAttributes, ColumnItemOptions} from './types'
|
|
7
|
+
import {SIZES} from './constants'
|
|
8
|
+
|
|
9
|
+
export function createColumnItemEdit(options: ColumnItemOptions) {
|
|
10
|
+
return function Edit({
|
|
11
|
+
attributes,
|
|
12
|
+
setAttributes,
|
|
13
|
+
}: {
|
|
14
|
+
attributes: ColumnItemAttributes
|
|
15
|
+
setAttributes: (a: Partial<ColumnItemAttributes>) => void
|
|
16
|
+
}) {
|
|
17
|
+
const {size} = attributes
|
|
18
|
+
const {blockProps, innerBlocksProps} = useGroupBlock({
|
|
19
|
+
blockClassName: clsx(options.blockClassName ?? 'i-column', `--size-${size}`),
|
|
20
|
+
containerClassName: options.containerClassName ?? 'i-column__inner',
|
|
21
|
+
allowedBlocks: options.allowedBlocks,
|
|
22
|
+
template: options.template,
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
const sizeIndex = SIZES.indexOf(size)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<InspectorControls>
|
|
30
|
+
<PanelBody title={__('Nastavení položky sloupce', 'brilo-blocks')}>
|
|
31
|
+
<RangeControl
|
|
32
|
+
label={__('Šířka sloupce', 'brilo-blocks')}
|
|
33
|
+
value={sizeIndex}
|
|
34
|
+
onChange={(v) => setAttributes({size: SIZES[v as number]})}
|
|
35
|
+
min={0}
|
|
36
|
+
max={SIZES.length - 1}
|
|
37
|
+
withInputField={false}
|
|
38
|
+
marks={SIZES.map((s, i) => ({label: s, value: i}))}
|
|
39
|
+
/>
|
|
40
|
+
</PanelBody>
|
|
41
|
+
</InspectorControls>
|
|
42
|
+
<div {...blockProps}>
|
|
43
|
+
<div {...innerBlocksProps} />
|
|
44
|
+
</div>
|
|
45
|
+
</>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
}
|