@siratik/wp-component-library 0.1.1 → 0.1.3
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/LICENSE +5 -0
- package/README.md +43 -5
- package/components/attachment-image/README.md +118 -0
- package/components/attachment-image/index.js +105 -0
- package/components/attributes-panel/README.md +92 -0
- package/components/attributes-panel/index.js +324 -0
- package/components/badge/README.md +61 -0
- package/components/badge/index.js +105 -0
- package/components/block-appender/README.md +158 -0
- package/components/block-appender/index.js +135 -0
- package/components/block-extension/index.js +214 -0
- package/components/business-hours/SpecialHoursControl.js +211 -0
- package/components/business-hours/WeeklyHoursControl.js +419 -0
- package/components/business-hours/index.js +8 -0
- package/components/button/README.md +172 -0
- package/components/button/index.js +84 -0
- package/components/captcha-placeholder/CloudflareTurnstile.js +111 -0
- package/components/captcha-placeholder/GoogleRecaptcha.js +132 -0
- package/components/captcha-placeholder/HCaptcha.js +99 -0
- package/components/captcha-placeholder/README.md +228 -0
- package/components/captcha-placeholder/index.js +39 -0
- package/components/captcha-placeholder/styles.js +33 -0
- package/components/geocoder/AddressEntryControl.js +390 -0
- package/components/geocoder/GeocoderSearchControl.js +353 -0
- package/components/geocoder/countryOptions.js +66 -0
- package/components/geocoder/geocoder.js +400 -0
- package/components/geocoder/index.js +16 -0
- package/components/icon-picker/Icon.js +53 -0
- package/components/icon-picker/IconPicker.js +70 -0
- package/components/icon-picker/IconPickerModal.js +474 -0
- package/components/icon-picker/IconPickerToolbarButton.js +60 -0
- package/components/icon-picker/InlineIconPicker.js +92 -0
- package/components/icon-picker/api.js +181 -0
- package/components/icon-picker/config-bootstrap.js +108 -0
- package/components/icon-picker/hooks.js +157 -0
- package/components/icon-picker/index.js +39 -0
- package/components/icon-picker/load-script.js +33 -0
- package/components/icon-picker/loaders.js +79 -0
- package/components/icon-picker/store.js +223 -0
- package/components/icon-picker/styles.js +232 -0
- package/components/icon-picker/utils.js +138 -0
- package/components/layout/README.md +268 -0
- package/components/link-tools-panel/README.md +49 -0
- package/components/link-tools-panel/index.js +198 -0
- package/components/link-tools-panel/styles.js +90 -0
- package/components/media/README.md +288 -0
- package/components/media/SettingsMediaUpload.js +186 -0
- package/components/media/editor-media-upload.js +65 -0
- package/components/media/image-controls.js +196 -0
- package/components/media/index.js +13 -0
- package/components/media/inspector-media-upload.js +290 -0
- package/components/media/toolbar-media-upload.js +53 -0
- package/components/media/utils/aspect-ratios.js +118 -0
- package/components/meta/MetaPanel.js +75 -0
- package/components/meta/README.md +46 -0
- package/components/meta/index.js +6 -0
- package/components/meta/meta-gated-editor.js +282 -0
- package/components/query/README.md +340 -0
- package/components/query/cardTemplatePartPanel.js +69 -0
- package/components/query/cardTemplatePartSelect.js +165 -0
- package/components/query/cardTemplatePartUtils.js +119 -0
- package/components/query/columnCountControl.js +63 -0
- package/components/query/displayTypeSelect.js +52 -0
- package/components/query/examples.js +166 -0
- package/components/query/hideCurrentPostControl.js +47 -0
- package/components/query/index.js +20 -0
- package/components/query/manualPostSelector.js +125 -0
- package/components/query/manualTermSelector.js +141 -0
- package/components/query/orderBySelect.js +95 -0
- package/components/query/postTypeSelect.js +67 -0
- package/components/query/postsPerPageControl.js +51 -0
- package/components/query/selectionModeControl.js +61 -0
- package/components/query/taxonomySelect.js +139 -0
- package/components/query/utils.js +75 -0
- package/components/repeater/README.md +159 -0
- package/components/repeater/index.js +829 -0
- package/components/segmented-bar/README.md +30 -0
- package/components/segmented-bar/index.js +68 -0
- package/components/sortable-select/README.md +153 -0
- package/components/sortable-select/custom-sortable-token.js +127 -0
- package/components/sortable-select/index.js +693 -0
- package/components/style-picker/README.md +36 -0
- package/components/style-picker/index.js +92 -0
- package/components/variable-field/README.md +299 -0
- package/components/variable-field/index.js +592 -0
- package/components/variable-field/value-to-chip-html.js +38 -0
- package/components/variable-inserter/README.md +68 -0
- package/components/variable-inserter/index.js +168 -0
- package/constants/statusColors.js +1 -1
- package/editor.js +16 -0
- package/index.js +127 -0
- package/package.json +21 -13
- package/utils/kitaris-localize.js +128 -0
- package/utils/slug-aware-color-setter.js +27 -0
- package/build/index.asset.php +0 -20
- package/build/index.js +0 -1242
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Layout Components
|
|
2
|
+
|
|
3
|
+
A comprehensive set of layout control components for WordPress blocks, providing flexbox-based alignment and positioning controls for both toolbar and inspector contexts.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Complete flexbox layout control system
|
|
8
|
+
- Toolbar and inspector panel variations
|
|
9
|
+
- Orientation switching (horizontal/vertical)
|
|
10
|
+
- Justification control (main axis alignment)
|
|
11
|
+
- Alignment control (cross axis alignment)
|
|
12
|
+
- Content alignment (text alignment)
|
|
13
|
+
- Flex wrap control
|
|
14
|
+
- Layout width control (full/constrained)
|
|
15
|
+
- Responsive and accessible UI
|
|
16
|
+
|
|
17
|
+
## Components
|
|
18
|
+
|
|
19
|
+
### Toolbar Components
|
|
20
|
+
For use in block toolbars:
|
|
21
|
+
- `AlignmentToolbar` - Cross axis alignment
|
|
22
|
+
- `JustificationToolbar` - Main axis alignment
|
|
23
|
+
- `OrientationToolbar` - Flex direction control
|
|
24
|
+
- `ContentAlignmentToolbar` - Text alignment
|
|
25
|
+
|
|
26
|
+
### Inspector Components
|
|
27
|
+
For use in inspector panels:
|
|
28
|
+
- `AlignmentSettings` - Cross axis alignment settings
|
|
29
|
+
- `JustificationSettings` - Main axis alignment settings
|
|
30
|
+
- `OrientationSettings` - Flex direction settings
|
|
31
|
+
- `ContentAlignmentSettings` - Text alignment settings
|
|
32
|
+
- `AllowWrapSettings` - Flex wrap toggle
|
|
33
|
+
- `LayoutPanel` - Complete layout panel with all controls
|
|
34
|
+
- `LayoutWidthControl` - Full width vs constrained toggle
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```jsx
|
|
39
|
+
import {
|
|
40
|
+
LayoutPanel,
|
|
41
|
+
OrientationToolbar,
|
|
42
|
+
JustificationToolbar,
|
|
43
|
+
AlignmentToolbar
|
|
44
|
+
} from '@siratik/wp-component-library/components/layout';
|
|
45
|
+
|
|
46
|
+
// In block toolbar
|
|
47
|
+
<BlockControls>
|
|
48
|
+
<OrientationToolbar
|
|
49
|
+
value={orientation}
|
|
50
|
+
onChange={setOrientation}
|
|
51
|
+
/>
|
|
52
|
+
<JustificationToolbar
|
|
53
|
+
value={justification}
|
|
54
|
+
onChange={setJustification}
|
|
55
|
+
orientation={orientation}
|
|
56
|
+
/>
|
|
57
|
+
</BlockControls>
|
|
58
|
+
|
|
59
|
+
// In inspector controls
|
|
60
|
+
<InspectorControls>
|
|
61
|
+
<LayoutPanel
|
|
62
|
+
orientation={orientation}
|
|
63
|
+
onOrientationChange={setOrientation}
|
|
64
|
+
justification={justification}
|
|
65
|
+
onJustificationChange={setJustification}
|
|
66
|
+
alignment={alignment}
|
|
67
|
+
onAlignmentChange={setAlignment}
|
|
68
|
+
allowWrap={allowWrap}
|
|
69
|
+
onAllowWrapChange={setAllowWrap}
|
|
70
|
+
showOrientationControl={true}
|
|
71
|
+
showJustificationControl={true}
|
|
72
|
+
showAlignmentControl={true}
|
|
73
|
+
showAllowWrapControl={true}
|
|
74
|
+
/>
|
|
75
|
+
</InspectorControls>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Layout Panel Props
|
|
79
|
+
|
|
80
|
+
| Prop | Type | Default | Description |
|
|
81
|
+
|------|------|---------|-------------|
|
|
82
|
+
| `orientation` | `string` | `"horizontal"` | Flex direction: "horizontal" or "vertical" |
|
|
83
|
+
| `onOrientationChange` | `function` | - | Orientation change handler |
|
|
84
|
+
| `justification` | `string` | `"flex-start"` | Main axis alignment |
|
|
85
|
+
| `onJustificationChange` | `function` | - | Justification change handler |
|
|
86
|
+
| `alignment` | `string` | `"flex-start"` | Cross axis alignment |
|
|
87
|
+
| `onAlignmentChange` | `function` | - | Alignment change handler |
|
|
88
|
+
| `contentAlignment` | `string` | `"left"` | Text alignment within items |
|
|
89
|
+
| `onContentAlignmentChange` | `function` | - | Content alignment change handler |
|
|
90
|
+
| `allowWrap` | `boolean` | `false` | Allow flex items to wrap |
|
|
91
|
+
| `onAllowWrapChange` | `function` | - | Wrap change handler |
|
|
92
|
+
| `showOrientationControl` | `boolean` | `true` | Show orientation control |
|
|
93
|
+
| `showJustificationControl` | `boolean` | `true` | Show justification control |
|
|
94
|
+
| `showAlignmentControl` | `boolean` | `true` | Show alignment control |
|
|
95
|
+
| `showContentAlignmentControl` | `boolean` | `false` | Show content alignment control |
|
|
96
|
+
| `showAllowWrapControl` | `boolean` | `true` | Show wrap control |
|
|
97
|
+
| `group` | `string` | `"styles"` | Inspector control group |
|
|
98
|
+
| `resetAll` | `function` | - | Reset all values handler |
|
|
99
|
+
|
|
100
|
+
## Individual Control Props
|
|
101
|
+
|
|
102
|
+
All individual controls follow a similar pattern:
|
|
103
|
+
```jsx
|
|
104
|
+
<ControlName
|
|
105
|
+
value={currentValue}
|
|
106
|
+
onChange={handleChange}
|
|
107
|
+
orientation={orientation} // For context-aware controls
|
|
108
|
+
/>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Alignment Values
|
|
112
|
+
|
|
113
|
+
### Justification (Main Axis)
|
|
114
|
+
- `flex-start` - Start of container
|
|
115
|
+
- `center` - Center of container
|
|
116
|
+
- `flex-end` - End of container
|
|
117
|
+
- `space-between` - Space between items
|
|
118
|
+
|
|
119
|
+
### Alignment (Cross Axis)
|
|
120
|
+
- `flex-start` - Start of container
|
|
121
|
+
- `center` - Center of container
|
|
122
|
+
- `flex-end` - End of container
|
|
123
|
+
- `stretch` - Stretch to fill container
|
|
124
|
+
|
|
125
|
+
### Content Alignment (Text)
|
|
126
|
+
- `left` - Left aligned text
|
|
127
|
+
- `center` - Center aligned text
|
|
128
|
+
- `right` - Right aligned text
|
|
129
|
+
|
|
130
|
+
## CSS Generation
|
|
131
|
+
|
|
132
|
+
The components are designed to work with CSS classes or inline styles:
|
|
133
|
+
|
|
134
|
+
```jsx
|
|
135
|
+
// Generate CSS classes
|
|
136
|
+
const layoutClasses = classnames({
|
|
137
|
+
[`is-orientation-${orientation}`]: orientation,
|
|
138
|
+
[`is-justified-${justification}`]: justification,
|
|
139
|
+
[`is-aligned-${alignment}`]: alignment,
|
|
140
|
+
'is-wrap-allowed': allowWrap
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Or use inline styles
|
|
144
|
+
const layoutStyles = {
|
|
145
|
+
display: 'flex',
|
|
146
|
+
flexDirection: orientation === 'vertical' ? 'column' : 'row',
|
|
147
|
+
justifyContent: justification,
|
|
148
|
+
alignItems: alignment,
|
|
149
|
+
flexWrap: allowWrap ? 'wrap' : 'nowrap'
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Examples
|
|
154
|
+
|
|
155
|
+
### Basic Row Layout
|
|
156
|
+
```jsx
|
|
157
|
+
function RowBlock({ attributes, setAttributes }) {
|
|
158
|
+
const { orientation = 'horizontal', justification = 'flex-start' } = attributes;
|
|
159
|
+
|
|
160
|
+
return (
|
|
161
|
+
<>
|
|
162
|
+
<BlockControls>
|
|
163
|
+
<JustificationToolbar
|
|
164
|
+
value={justification}
|
|
165
|
+
onChange={(value) => setAttributes({ justification: value })}
|
|
166
|
+
orientation={orientation}
|
|
167
|
+
/>
|
|
168
|
+
</BlockControls>
|
|
169
|
+
|
|
170
|
+
<div className={`row is-justified-${justification}`}>
|
|
171
|
+
<InnerBlocks />
|
|
172
|
+
</div>
|
|
173
|
+
</>
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Advanced Grid Layout
|
|
179
|
+
```jsx
|
|
180
|
+
function GridBlock({ attributes, setAttributes }) {
|
|
181
|
+
return (
|
|
182
|
+
<InspectorControls>
|
|
183
|
+
<LayoutPanel
|
|
184
|
+
{...attributes}
|
|
185
|
+
onOrientationChange={(orientation) => setAttributes({ orientation })}
|
|
186
|
+
onJustificationChange={(justification) => setAttributes({ justification })}
|
|
187
|
+
onAlignmentChange={(alignment) => setAttributes({ alignment })}
|
|
188
|
+
onAllowWrapChange={(allowWrap) => setAttributes({ allowWrap })}
|
|
189
|
+
showContentAlignmentControl={true}
|
|
190
|
+
onContentAlignmentChange={(contentAlignment) => setAttributes({ contentAlignment })}
|
|
191
|
+
/>
|
|
192
|
+
</InspectorControls>
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Responsive Column Layout
|
|
198
|
+
```jsx
|
|
199
|
+
function ColumnLayout({ attributes, setAttributes }) {
|
|
200
|
+
const { orientation, alignment, allowWrap } = attributes;
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<>
|
|
204
|
+
<InspectorControls>
|
|
205
|
+
<PanelBody title="Layout">
|
|
206
|
+
<OrientationSettings
|
|
207
|
+
value={orientation}
|
|
208
|
+
onChange={(value) => setAttributes({ orientation: value })}
|
|
209
|
+
/>
|
|
210
|
+
<AlignmentSettings
|
|
211
|
+
value={alignment}
|
|
212
|
+
onChange={(value) => setAttributes({ alignment: value })}
|
|
213
|
+
orientation={orientation}
|
|
214
|
+
/>
|
|
215
|
+
<AllowWrapSettings
|
|
216
|
+
value={allowWrap}
|
|
217
|
+
onChange={(value) => setAttributes({ allowWrap: value })}
|
|
218
|
+
/>
|
|
219
|
+
</PanelBody>
|
|
220
|
+
</InspectorControls>
|
|
221
|
+
|
|
222
|
+
<div
|
|
223
|
+
style={{
|
|
224
|
+
display: 'flex',
|
|
225
|
+
flexDirection: orientation === 'vertical' ? 'column' : 'row',
|
|
226
|
+
alignItems: alignment,
|
|
227
|
+
flexWrap: allowWrap ? 'wrap' : 'nowrap'
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
<InnerBlocks />
|
|
231
|
+
</div>
|
|
232
|
+
</>
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Layout Width Control
|
|
238
|
+
|
|
239
|
+
Control whether content uses full width or is constrained:
|
|
240
|
+
|
|
241
|
+
```jsx
|
|
242
|
+
<LayoutWidthControl
|
|
243
|
+
layout={layout}
|
|
244
|
+
onChange={(newLayout) => setAttributes({ layout: newLayout })}
|
|
245
|
+
/>
|
|
246
|
+
|
|
247
|
+
// Layout object structure:
|
|
248
|
+
{
|
|
249
|
+
type: 'constrained' | 'default',
|
|
250
|
+
contentSize: '840px', // For constrained layout
|
|
251
|
+
wideSize: '1200px' // For wide alignment
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## Accessibility
|
|
256
|
+
|
|
257
|
+
- All controls include proper ARIA labels
|
|
258
|
+
- Keyboard navigation fully supported
|
|
259
|
+
- Visual feedback for current selections
|
|
260
|
+
- Screen reader friendly descriptions
|
|
261
|
+
|
|
262
|
+
## Notes
|
|
263
|
+
|
|
264
|
+
- Orientation affects available justification/alignment options
|
|
265
|
+
- Icons rotate appropriately for vertical orientation
|
|
266
|
+
- Controls integrate with WordPress ToolsPanel for consistent UX
|
|
267
|
+
- Styled with Emotion for customizable theming
|
|
268
|
+
- All controls are fully controlled components
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Link Tools Panel
|
|
2
|
+
|
|
3
|
+
Link settings for a block: a URL (WordPress's link search), "Use post permalink", "Open in new tab" and, opt-in, the link's `rel`.
|
|
4
|
+
WordPress's `LinkControl` is laid out for popovers; here it sits flush and fills the panel's width.
|
|
5
|
+
|
|
6
|
+
## Usage
|
|
7
|
+
|
|
8
|
+
```jsx
|
|
9
|
+
import { LinkToolsPanel, LinkToolsPanelItems } from '@siratik/wp-component-library';
|
|
10
|
+
|
|
11
|
+
// Its own "Link" panel (sidebar or a toolbar popover)
|
|
12
|
+
<LinkToolsPanel
|
|
13
|
+
link={ link }
|
|
14
|
+
opensInNewTab={ opensInNewTab }
|
|
15
|
+
isPermalink={ isPermalink }
|
|
16
|
+
onChange={ ( changes ) => setAttributes( changes ) }
|
|
17
|
+
panelId={ `${ clientId }-link` }
|
|
18
|
+
/>
|
|
19
|
+
|
|
20
|
+
// Inside a panel the block already has
|
|
21
|
+
<ToolsPanel label="Settings">
|
|
22
|
+
<LinkToolsPanelItems
|
|
23
|
+
link={ link }
|
|
24
|
+
opensInNewTab={ opensInNewTab }
|
|
25
|
+
isPermalink={ isPermalink }
|
|
26
|
+
onChange={ ( changes ) => setAttributes( changes ) }
|
|
27
|
+
/>
|
|
28
|
+
</ToolsPanel>
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Props
|
|
32
|
+
|
|
33
|
+
| Prop | Type | Default | Description |
|
|
34
|
+
|------|------|---------|-------------|
|
|
35
|
+
| `link` | `string` | `''` | Link URL |
|
|
36
|
+
| `opensInNewTab` | `boolean` | `false` | Whether the link opens in a new tab |
|
|
37
|
+
| `isPermalink` | `boolean` | `false` | Use the current post's permalink instead of `link` |
|
|
38
|
+
| `onChange` | `Function` | - | Called with the changed values, e.g. `{ link }` or `{ opensInNewTab }` |
|
|
39
|
+
| `panelId` | `string` | - | The surrounding panel's `panelId`. Items only register with a panel whose id matches |
|
|
40
|
+
| `isShownByDefault` | `boolean` | `true` | Whether URL and "Open in new tab" show before they have a value |
|
|
41
|
+
| `showPermalink` | `boolean` | `true` | Whether to offer "Use post permalink"; pass `false` for blocks with no such setting |
|
|
42
|
+
| `permalinkHelp` | `string` | generic | Help text for "Use post permalink" |
|
|
43
|
+
| `newTabHelp` | `string` | - | Help text shown while "Open in new tab" is on |
|
|
44
|
+
| `showRel` | `boolean` | `false` | Whether to offer "Link rel"; only for blocks that save and render it |
|
|
45
|
+
| `rel` | `string` | `''` | Link rel, e.g. `nofollow sponsored` |
|
|
46
|
+
|
|
47
|
+
`LinkToolsPanel` also accepts `label` (panel title, default "Link") and `className`.
|
|
48
|
+
|
|
49
|
+
`LINK_DEFAULTS` holds the default values (`{ link: '', opensInNewTab: false, isPermalink: false, rel: '' }`). `LinkToolsPanel`'s reset only clears `rel` when `showRel` is on.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Link Tools Panel
|
|
3
|
+
*
|
|
4
|
+
* Link settings for a block: a URL (WordPress's link search), "Use post
|
|
5
|
+
* permalink", "Open in new tab" and, when the block asks for it, the link's
|
|
6
|
+
* rel (e.g. nofollow).
|
|
7
|
+
*
|
|
8
|
+
* - `LinkToolsPanelItems`: the controls as tools panel items, for a block
|
|
9
|
+
* that already has a ToolsPanel to put them in.
|
|
10
|
+
* - `LinkToolsPanel`: the same items in their own "Link" panel.
|
|
11
|
+
*/
|
|
12
|
+
import { __experimentalLinkControl as LinkControl } from "@wordpress/block-editor";
|
|
13
|
+
import {
|
|
14
|
+
TextControl,
|
|
15
|
+
ToggleControl,
|
|
16
|
+
__experimentalToolsPanel as ToolsPanel,
|
|
17
|
+
__experimentalToolsPanelItem as ToolsPanelItem,
|
|
18
|
+
} from "@wordpress/components";
|
|
19
|
+
import { __ } from "@wordpress/i18n";
|
|
20
|
+
|
|
21
|
+
import { LinkField } from "./styles";
|
|
22
|
+
|
|
23
|
+
export const LINK_DEFAULTS = {
|
|
24
|
+
link: "",
|
|
25
|
+
opensInNewTab: false,
|
|
26
|
+
isPermalink: false,
|
|
27
|
+
rel: "",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Link controls as tools panel items.
|
|
32
|
+
*
|
|
33
|
+
* @param {Object} props
|
|
34
|
+
* @param {string} props.link Link URL.
|
|
35
|
+
* @param {boolean} props.opensInNewTab Whether the link opens in a new tab.
|
|
36
|
+
* @param {boolean} props.isPermalink Whether the current post's permalink is used.
|
|
37
|
+
* @param {Function} props.onChange Called with the changed values, e.g. `{ link }`.
|
|
38
|
+
* @param {string} [props.panelId] The surrounding ToolsPanel's `panelId`, if it has one. Items only register with a panel whose id matches.
|
|
39
|
+
* @param {boolean} [props.isShownByDefault=true] Whether URL and "Open in new tab" show before they have a value; when false they are added from the panel menu.
|
|
40
|
+
* @param {boolean} [props.showPermalink=true] Whether to offer "Use post permalink", for blocks that have no such setting.
|
|
41
|
+
* @param {string} [props.permalinkHelp] Help text for "Use post permalink".
|
|
42
|
+
* @param {string} [props.newTabHelp] Help text shown while "Open in new tab" is on.
|
|
43
|
+
* @param {boolean} [props.showRel=false] Whether to offer the link's rel, for blocks that save and render it.
|
|
44
|
+
* @param {string} [props.rel] Link rel, e.g. "nofollow sponsored".
|
|
45
|
+
*/
|
|
46
|
+
export function LinkToolsPanelItems({
|
|
47
|
+
link = LINK_DEFAULTS.link,
|
|
48
|
+
opensInNewTab = LINK_DEFAULTS.opensInNewTab,
|
|
49
|
+
isPermalink = LINK_DEFAULTS.isPermalink,
|
|
50
|
+
onChange,
|
|
51
|
+
panelId,
|
|
52
|
+
isShownByDefault = true,
|
|
53
|
+
showPermalink = true,
|
|
54
|
+
permalinkHelp = __(
|
|
55
|
+
"Automatically use the current post's permalink as the link.",
|
|
56
|
+
"wp-component-library",
|
|
57
|
+
),
|
|
58
|
+
newTabHelp,
|
|
59
|
+
showRel = false,
|
|
60
|
+
rel = LINK_DEFAULTS.rel,
|
|
61
|
+
}) {
|
|
62
|
+
return (
|
|
63
|
+
<>
|
|
64
|
+
{showPermalink && (
|
|
65
|
+
<ToolsPanelItem
|
|
66
|
+
panelId={panelId}
|
|
67
|
+
hasValue={() =>
|
|
68
|
+
isPermalink !== LINK_DEFAULTS.isPermalink
|
|
69
|
+
}
|
|
70
|
+
label={__("Use post permalink", "wp-component-library")}
|
|
71
|
+
onDeselect={() =>
|
|
72
|
+
onChange({ isPermalink: LINK_DEFAULTS.isPermalink })
|
|
73
|
+
}
|
|
74
|
+
isShownByDefault={false}
|
|
75
|
+
>
|
|
76
|
+
<ToggleControl
|
|
77
|
+
__nextHasNoMarginBottom
|
|
78
|
+
label={__(
|
|
79
|
+
"Use post permalink",
|
|
80
|
+
"wp-component-library",
|
|
81
|
+
)}
|
|
82
|
+
checked={isPermalink}
|
|
83
|
+
onChange={(value) => onChange({ isPermalink: value })}
|
|
84
|
+
help={permalinkHelp}
|
|
85
|
+
/>
|
|
86
|
+
</ToolsPanelItem>
|
|
87
|
+
)}
|
|
88
|
+
|
|
89
|
+
{!isPermalink && (
|
|
90
|
+
<ToolsPanelItem
|
|
91
|
+
panelId={panelId}
|
|
92
|
+
hasValue={() => link !== LINK_DEFAULTS.link}
|
|
93
|
+
label={__("URL", "wp-component-library")}
|
|
94
|
+
onDeselect={() => onChange({ link: LINK_DEFAULTS.link })}
|
|
95
|
+
isShownByDefault={isShownByDefault}
|
|
96
|
+
>
|
|
97
|
+
<LinkField>
|
|
98
|
+
<LinkControl
|
|
99
|
+
searchInputPlaceholder={__(
|
|
100
|
+
"Search content or type URL",
|
|
101
|
+
"wp-component-library",
|
|
102
|
+
)}
|
|
103
|
+
value={{ url: link }}
|
|
104
|
+
onChange={({ url }) => onChange({ link: url })}
|
|
105
|
+
onRemove={() =>
|
|
106
|
+
onChange({ link: LINK_DEFAULTS.link })
|
|
107
|
+
}
|
|
108
|
+
showInitialSuggestions={true}
|
|
109
|
+
settings={[]}
|
|
110
|
+
/>
|
|
111
|
+
</LinkField>
|
|
112
|
+
</ToolsPanelItem>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<ToolsPanelItem
|
|
116
|
+
panelId={panelId}
|
|
117
|
+
hasValue={() =>
|
|
118
|
+
opensInNewTab !== LINK_DEFAULTS.opensInNewTab
|
|
119
|
+
}
|
|
120
|
+
label={__("Open in new tab", "wp-component-library")}
|
|
121
|
+
onDeselect={() =>
|
|
122
|
+
onChange({ opensInNewTab: LINK_DEFAULTS.opensInNewTab })
|
|
123
|
+
}
|
|
124
|
+
isShownByDefault={isShownByDefault}
|
|
125
|
+
>
|
|
126
|
+
<ToggleControl
|
|
127
|
+
__nextHasNoMarginBottom
|
|
128
|
+
label={__("Open in new tab", "wp-component-library")}
|
|
129
|
+
checked={opensInNewTab}
|
|
130
|
+
onChange={(value) => onChange({ opensInNewTab: value })}
|
|
131
|
+
help={opensInNewTab ? newTabHelp : undefined}
|
|
132
|
+
/>
|
|
133
|
+
</ToolsPanelItem>
|
|
134
|
+
|
|
135
|
+
{showRel && (
|
|
136
|
+
<ToolsPanelItem
|
|
137
|
+
panelId={panelId}
|
|
138
|
+
hasValue={() => !!rel}
|
|
139
|
+
label={__("Link rel", "wp-component-library")}
|
|
140
|
+
onDeselect={() => onChange({ rel: LINK_DEFAULTS.rel })}
|
|
141
|
+
isShownByDefault={false}
|
|
142
|
+
>
|
|
143
|
+
<TextControl
|
|
144
|
+
__next40pxDefaultSize
|
|
145
|
+
__nextHasNoMarginBottom
|
|
146
|
+
label={__("Link rel", "wp-component-library")}
|
|
147
|
+
help={__(
|
|
148
|
+
"Space-separated values, e.g. nofollow or sponsored.",
|
|
149
|
+
"wp-component-library",
|
|
150
|
+
)}
|
|
151
|
+
value={rel}
|
|
152
|
+
onChange={(value) => onChange({ rel: value })}
|
|
153
|
+
/>
|
|
154
|
+
</ToolsPanelItem>
|
|
155
|
+
)}
|
|
156
|
+
</>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Link controls in their own tools panel.
|
|
162
|
+
*
|
|
163
|
+
* Takes the same props as `LinkToolsPanelItems`, plus:
|
|
164
|
+
*
|
|
165
|
+
* @param {Object} props
|
|
166
|
+
* @param {string} [props.label] Panel title. Default "Link".
|
|
167
|
+
* @param {string} [props.panelId] Unique id for the panel.
|
|
168
|
+
* @param {string} [props.className] Extra class for the panel.
|
|
169
|
+
* @param {Function} props.onChange Called with the changed values.
|
|
170
|
+
*/
|
|
171
|
+
export function LinkToolsPanel({
|
|
172
|
+
label = __("Link", "wp-component-library"),
|
|
173
|
+
panelId = "link-tools-panel",
|
|
174
|
+
className,
|
|
175
|
+
onChange,
|
|
176
|
+
...itemProps
|
|
177
|
+
}) {
|
|
178
|
+
return (
|
|
179
|
+
<ToolsPanel
|
|
180
|
+
label={label}
|
|
181
|
+
panelId={panelId}
|
|
182
|
+
resetAll={() => {
|
|
183
|
+
// rel only for blocks that offer it (they have the attribute).
|
|
184
|
+
const { rel, ...defaults } = LINK_DEFAULTS;
|
|
185
|
+
onChange(itemProps.showRel ? { ...defaults, rel } : defaults);
|
|
186
|
+
}}
|
|
187
|
+
className={className}
|
|
188
|
+
>
|
|
189
|
+
<LinkToolsPanelItems
|
|
190
|
+
{...itemProps}
|
|
191
|
+
onChange={onChange}
|
|
192
|
+
panelId={panelId}
|
|
193
|
+
/>
|
|
194
|
+
</ToolsPanel>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export default LinkToolsPanel;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Emotion styled components for the Link Tools Panel.
|
|
3
|
+
*/
|
|
4
|
+
import styled from "@emotion/styled";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Wraps WordPress's LinkControl inside a tools panel.
|
|
8
|
+
*
|
|
9
|
+
* LinkControl is laid out for popovers: a 350px minimum width and 16px
|
|
10
|
+
* gutters around each of its parts. In a tools panel the panel provides the
|
|
11
|
+
* gutters, so the field sits flush and fills the panel's width.
|
|
12
|
+
*/
|
|
13
|
+
export const LinkField = styled.div`
|
|
14
|
+
.block-editor-link-control {
|
|
15
|
+
min-width: 0;
|
|
16
|
+
width: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.block-editor-link-control__search-input-wrapper {
|
|
20
|
+
margin-bottom: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.block-editor-link-control__field {
|
|
24
|
+
margin: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.block-editor-url-input {
|
|
28
|
+
min-width: 0;
|
|
29
|
+
width: 100%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* A chosen link: its preview row. */
|
|
33
|
+
.block-editor-link-control__preview {
|
|
34
|
+
padding: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.block-editor-link-control__search-actions {
|
|
38
|
+
padding: 8px 0 0;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* Search results: a bordered list under the field, as wide as the panel. */
|
|
42
|
+
.block-editor-link-control__search-results-wrapper {
|
|
43
|
+
margin-top: 4px;
|
|
44
|
+
|
|
45
|
+
/* Core's scroll fades are positioned for the popover's gutters. */
|
|
46
|
+
&::before,
|
|
47
|
+
&::after {
|
|
48
|
+
display: none;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.block-editor-link-control__search-results {
|
|
53
|
+
margin: 0;
|
|
54
|
+
padding: 4px;
|
|
55
|
+
max-height: 240px;
|
|
56
|
+
overflow-x: hidden;
|
|
57
|
+
background: var(--wp-components-color-background, #fff);
|
|
58
|
+
border: 1px solid var(--wp-components-color-gray-300, #ddd);
|
|
59
|
+
border-radius: 2px;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.block-editor-link-control__search-item.components-button {
|
|
63
|
+
width: 100%;
|
|
64
|
+
min-width: 0;
|
|
65
|
+
height: auto;
|
|
66
|
+
padding: 6px 8px;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.block-editor-link-control__search-item .components-menu-item__item,
|
|
70
|
+
.block-editor-link-control__search-item .components-menu-item__info-wrapper {
|
|
71
|
+
min-width: 0;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* One line each for the title and URL, truncated to the panel's width. */
|
|
75
|
+
.block-editor-link-control__search-item .components-menu-item__info-wrapper > * {
|
|
76
|
+
display: block;
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
text-overflow: ellipsis;
|
|
79
|
+
white-space: nowrap;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* The type label ("Page", "Attachment") doesn't fit; the icon shows the type. */
|
|
83
|
+
.block-editor-link-control__search-item .components-menu-item__shortcut {
|
|
84
|
+
display: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.block-editor-link-control__help {
|
|
88
|
+
padding: 0;
|
|
89
|
+
}
|
|
90
|
+
`;
|