@wordpress-gcb/fields 0.2.1 → 0.2.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/dist/conditional-logic.js +83 -0
- package/{src → dist}/control-context.js +3 -2
- package/{src → dist}/controls/MediaCapabilityGate.js +12 -8
- package/dist/controls/MediaPicker.js +149 -0
- package/dist/controls/MediaTriggerBadges.js +35 -0
- package/{src → dist}/controls/PopoverOrModal.js +49 -43
- package/dist/controls/SortableItem.js +126 -0
- package/dist/controls/button-group.js +46 -0
- package/dist/controls/checkbox-group.js +65 -0
- package/dist/controls/checkbox.js +15 -0
- package/dist/controls/code.js +24 -0
- package/dist/controls/color.js +249 -0
- package/dist/controls/date.js +55 -0
- package/dist/controls/datetime.js +61 -0
- package/dist/controls/email.js +17 -0
- package/dist/controls/file.js +163 -0
- package/dist/controls/gallery.js +371 -0
- package/dist/controls/google-map.js +143 -0
- package/dist/controls/heading-level.js +93 -0
- package/dist/controls/icon.js +292 -0
- package/dist/controls/image.js +360 -0
- package/dist/controls/index.js +88 -0
- package/dist/controls/message.js +86 -0
- package/dist/controls/number.js +19 -0
- package/dist/controls/oembed.js +42 -0
- package/{src → dist}/controls/page-link.js +1 -2
- package/dist/controls/post-object.js +913 -0
- package/dist/controls/radio.js +19 -0
- package/dist/controls/range.js +108 -0
- package/{src → dist}/controls/relationship.js +12 -7
- package/dist/controls/repeater.js +277 -0
- package/dist/controls/richtext.js +494 -0
- package/dist/controls/select.js +144 -0
- package/dist/controls/size.js +59 -0
- package/dist/controls/spacing.js +172 -0
- package/dist/controls/taxonomy.js +569 -0
- package/dist/controls/text.js +16 -0
- package/dist/controls/textarea.js +17 -0
- package/dist/controls/toggle-group.js +28 -0
- package/dist/controls/toggle.js +15 -0
- package/dist/controls/url.js +235 -0
- package/dist/controls/user.js +383 -0
- package/{src → dist}/controls/wysiwyg.js +1 -1
- package/{src → dist}/hooks/useTokens.js +25 -21
- package/{src → dist}/index.js +2 -8
- package/dist/inspector.js +163 -0
- package/{src → dist}/provider.js +18 -17
- package/dist/utils/map-utils.js +54 -0
- package/dist/utils/token-helper.js +396 -0
- package/{src → dist}/validation-context.js +4 -4
- package/package.json +20 -13
- package/src/conditional-logic.js +0 -77
- package/src/controls/MediaPicker.js +0 -139
- package/src/controls/MediaTriggerBadges.js +0 -31
- package/src/controls/SortableItem.js +0 -110
- package/src/controls/button-group.js +0 -49
- package/src/controls/checkbox-group.js +0 -55
- package/src/controls/checkbox.js +0 -13
- package/src/controls/code.js +0 -21
- package/src/controls/color.js +0 -235
- package/src/controls/date.js +0 -37
- package/src/controls/datetime.js +0 -54
- package/src/controls/email.js +0 -15
- package/src/controls/file.js +0 -134
- package/src/controls/gallery.js +0 -338
- package/src/controls/google-map.js +0 -117
- package/src/controls/heading-level.js +0 -99
- package/src/controls/icon.js +0 -301
- package/src/controls/image.js +0 -334
- package/src/controls/index.js +0 -95
- package/src/controls/message.js +0 -56
- package/src/controls/number.js +0 -17
- package/src/controls/oembed.js +0 -32
- package/src/controls/post-object.js +0 -788
- package/src/controls/radio.js +0 -18
- package/src/controls/range.js +0 -110
- package/src/controls/repeater.js +0 -290
- package/src/controls/richtext.js +0 -505
- package/src/controls/select.js +0 -141
- package/src/controls/size.js +0 -49
- package/src/controls/spacing.js +0 -141
- package/src/controls/taxonomy.js +0 -488
- package/src/controls/text.js +0 -14
- package/src/controls/textarea.js +0 -15
- package/src/controls/toggle-group.js +0 -34
- package/src/controls/toggle.js +0 -13
- package/src/controls/url.js +0 -164
- package/src/controls/user.js +0 -343
- package/src/inspector.js +0 -174
- package/src/utils/map-utils.js +0 -51
- package/src/utils/token-helper.js +0 -243
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SpacingField — preset spacing (None / S / M / L) with a custom-value escape hatch.
|
|
3
|
+
*
|
|
4
|
+
* Stored value is either one of the preset keys (`'small'`, etc.) or a CSS
|
|
5
|
+
* length string (e.g. `'2rem'`). When set to a custom value, the toggle group
|
|
6
|
+
* is disabled and a "custom value applied" hint shows.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { __ } from '@wordpress/i18n';
|
|
10
|
+
import { Button, TextControl, Notice } from '@wordpress/components';
|
|
11
|
+
import { useState } from '@wordpress/element';
|
|
12
|
+
import { __experimentalToggleGroupControl as ToggleGroupControl, __experimentalToggleGroupControlOption as ToggleGroupControlOption, __experimentalHStack as HStack } from '@wordpress/components';
|
|
13
|
+
import { useTokens, getTokensByGroup } from '../hooks/useTokens';
|
|
14
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
const DEFAULT_PRESETS = [{
|
|
16
|
+
label: 'None',
|
|
17
|
+
value: 'none'
|
|
18
|
+
}, {
|
|
19
|
+
label: 'S',
|
|
20
|
+
value: 'small'
|
|
21
|
+
}, {
|
|
22
|
+
label: 'M',
|
|
23
|
+
value: 'medium'
|
|
24
|
+
}, {
|
|
25
|
+
label: 'L',
|
|
26
|
+
value: 'large'
|
|
27
|
+
}];
|
|
28
|
+
const PRESET_KEYS = new Set(['none', 'small', 'medium', 'large']);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Build the toggle presets from the theme's spacing tokens when the field was
|
|
32
|
+
* configured with a token group (and optional checked subset). Falls back to
|
|
33
|
+
* the simple None/S/M/L presets when no tokens are configured.
|
|
34
|
+
*/
|
|
35
|
+
function tokenPresets(control, tokens) {
|
|
36
|
+
const group = control.tokenGroup;
|
|
37
|
+
if (!group || !tokens) return null;
|
|
38
|
+
let list = getTokensByGroup(tokens, group);
|
|
39
|
+
if (!Array.isArray(list) || list.length === 0) return null;
|
|
40
|
+
if (Array.isArray(control.tokenKeys) && control.tokenKeys.length > 0) {
|
|
41
|
+
list = list.filter(t => control.tokenKeys.includes(t.slug || t.key));
|
|
42
|
+
}
|
|
43
|
+
if (list.length === 0) return null;
|
|
44
|
+
// Compact label (the slug or short name) — the value is the slug.
|
|
45
|
+
return list.map(t => ({
|
|
46
|
+
label: t.name || t.label || t.slug || t.key,
|
|
47
|
+
value: t.slug || t.key
|
|
48
|
+
}));
|
|
49
|
+
}
|
|
50
|
+
function isValidCSSValue(input) {
|
|
51
|
+
if (!input) return true;
|
|
52
|
+
return /^(\d*\.?\d+)(px|rem|em|%|vw|vh|vmin|vmax)?$/.test(String(input).trim());
|
|
53
|
+
}
|
|
54
|
+
export default function SpacingField({
|
|
55
|
+
control,
|
|
56
|
+
value,
|
|
57
|
+
onChange
|
|
58
|
+
}) {
|
|
59
|
+
const {
|
|
60
|
+
tokens
|
|
61
|
+
} = useTokens();
|
|
62
|
+
|
|
63
|
+
// Token-driven presets (from theme.json) take priority over the explicit
|
|
64
|
+
// `presets` config and the simple None/S/M/L fallback.
|
|
65
|
+
const presets = tokenPresets(control, tokens) || control.presets || DEFAULT_PRESETS;
|
|
66
|
+
const presetKeys = new Set(presets.map(p => p.value));
|
|
67
|
+
const firstPreset = presets[0]?.value || 'medium';
|
|
68
|
+
|
|
69
|
+
// Decide if value is a preset or a custom string.
|
|
70
|
+
const isCustom = typeof value === 'string' && value !== '' && !presetKeys.has(value);
|
|
71
|
+
const presetValue = isCustom ? firstPreset : value || firstPreset;
|
|
72
|
+
const [showCustom, setShowCustom] = useState(isCustom);
|
|
73
|
+
const [customInput, setCustomInput] = useState(isCustom ? value : '');
|
|
74
|
+
const [error, setError] = useState(null);
|
|
75
|
+
const handlePreset = next => {
|
|
76
|
+
setShowCustom(false);
|
|
77
|
+
setCustomInput('');
|
|
78
|
+
setError(null);
|
|
79
|
+
onChange(next);
|
|
80
|
+
};
|
|
81
|
+
const handleCustom = next => {
|
|
82
|
+
setCustomInput(next);
|
|
83
|
+
if (next && !isValidCSSValue(next)) {
|
|
84
|
+
setError(__('Invalid spacing value. Use a number with a unit (e.g. 2rem, 20px).', 'gcblite'));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
setError(null);
|
|
88
|
+
onChange(next || firstPreset);
|
|
89
|
+
};
|
|
90
|
+
const handleReset = () => {
|
|
91
|
+
setShowCustom(false);
|
|
92
|
+
setCustomInput('');
|
|
93
|
+
setError(null);
|
|
94
|
+
onChange(firstPreset);
|
|
95
|
+
};
|
|
96
|
+
const displayHint = showCustom ? 'Custom' : presetValue.charAt(0).toUpperCase() + presetValue.slice(1);
|
|
97
|
+
return /*#__PURE__*/_jsx("div", {
|
|
98
|
+
className: `gcb-spacing-field components-base-control ${control.className || ''}`.trim(),
|
|
99
|
+
children: /*#__PURE__*/_jsxs("div", {
|
|
100
|
+
className: "components-base-control__field",
|
|
101
|
+
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
102
|
+
children: [/*#__PURE__*/_jsxs("span", {
|
|
103
|
+
className: "components-base-control__label",
|
|
104
|
+
children: [control.label, /*#__PURE__*/_jsx("span", {
|
|
105
|
+
className: "components-font-size-picker__header__hint",
|
|
106
|
+
children: displayHint
|
|
107
|
+
})]
|
|
108
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
109
|
+
size: "small",
|
|
110
|
+
label: __('Set custom spacing', 'gcblite'),
|
|
111
|
+
onClick: () => setShowCustom(true),
|
|
112
|
+
isPressed: showCustom,
|
|
113
|
+
icon: /*#__PURE__*/_jsxs("svg", {
|
|
114
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
115
|
+
viewBox: "0 0 24 24",
|
|
116
|
+
width: "24",
|
|
117
|
+
height: "24",
|
|
118
|
+
"aria-hidden": true,
|
|
119
|
+
focusable: "false",
|
|
120
|
+
children: [/*#__PURE__*/_jsx("path", {
|
|
121
|
+
d: "m19 7.5h-7.628c-.3089-.87389-1.1423-1.5-2.122-1.5-.97966 0-1.81309.62611-2.12197 1.5h-2.12803v1.5h2.12803c.30888.87389 1.14231 1.5 2.12197 1.5.9797 0 1.8131-.62611 2.122-1.5h7.628z"
|
|
122
|
+
}), /*#__PURE__*/_jsx("path", {
|
|
123
|
+
d: "m19 15h-2.128c-.3089-.8739-1.1423-1.5-2.122-1.5s-1.8131.6261-2.122 1.5h-7.628v1.5h7.628c.3089.8739 1.1423 1.5 2.122 1.5s1.8131-.6261 2.122-1.5h2.128z"
|
|
124
|
+
})]
|
|
125
|
+
})
|
|
126
|
+
})]
|
|
127
|
+
}), error && /*#__PURE__*/_jsx(Notice, {
|
|
128
|
+
status: "warning",
|
|
129
|
+
isDismissible: true,
|
|
130
|
+
onRemove: () => setError(null),
|
|
131
|
+
children: error
|
|
132
|
+
}), showCustom && /*#__PURE__*/_jsxs("div", {
|
|
133
|
+
style: {
|
|
134
|
+
marginBottom: 16,
|
|
135
|
+
fontSize: 13
|
|
136
|
+
},
|
|
137
|
+
children: [/*#__PURE__*/_jsx("span", {
|
|
138
|
+
children: __('Custom value applied', 'gcblite')
|
|
139
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
140
|
+
variant: "link",
|
|
141
|
+
onClick: handleReset,
|
|
142
|
+
style: {
|
|
143
|
+
marginLeft: 8,
|
|
144
|
+
fontSize: 13
|
|
145
|
+
},
|
|
146
|
+
children: __('Reset', 'gcblite')
|
|
147
|
+
})]
|
|
148
|
+
}), /*#__PURE__*/_jsx(ToggleGroupControl, {
|
|
149
|
+
label: control.label,
|
|
150
|
+
value: presetValue,
|
|
151
|
+
onChange: handlePreset,
|
|
152
|
+
isBlock: true,
|
|
153
|
+
hideLabelFromVision: true,
|
|
154
|
+
disabled: showCustom,
|
|
155
|
+
className: showCustom ? 'is-disabled' : '',
|
|
156
|
+
__nextHasNoMarginBottom: true,
|
|
157
|
+
__next40pxDefaultSize: true,
|
|
158
|
+
children: presets.map(preset => /*#__PURE__*/_jsx(ToggleGroupControlOption, {
|
|
159
|
+
value: preset.value,
|
|
160
|
+
label: preset.label
|
|
161
|
+
}, preset.value))
|
|
162
|
+
}), showCustom && /*#__PURE__*/_jsx(TextControl, {
|
|
163
|
+
label: __('Custom Spacing', 'gcblite'),
|
|
164
|
+
value: customInput,
|
|
165
|
+
onChange: handleCustom,
|
|
166
|
+
placeholder: "e.g. 2rem or 20px",
|
|
167
|
+
help: __('Enter a value with unit (e.g. 2rem, 20px, 5%) or leave empty for 0.', 'gcblite'),
|
|
168
|
+
__nextHasNoMarginBottom: true
|
|
169
|
+
})]
|
|
170
|
+
})
|
|
171
|
+
});
|
|
172
|
+
}
|