@wordpress-gcb/fields 0.2.0 → 0.2.2
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/README.md +51 -35
- 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 +241 -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 +141 -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 +35 -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
package/src/controls/color.js
DELETED
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ColorField — ported verbatim from the original GCB.
|
|
3
|
-
* Tabbed color/gradient picker that uses theme.json palettes via useSetting.
|
|
4
|
-
*
|
|
5
|
-
* Control config can opt out of gradients with `showGradients: false`.
|
|
6
|
-
* For dual-attribute mode (separate color + gradient attrs), set
|
|
7
|
-
* `gradientAttributeKey` on the control config.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { __ } from '@wordpress/i18n';
|
|
11
|
-
import {
|
|
12
|
-
BaseControl,
|
|
13
|
-
Button,
|
|
14
|
-
ColorPalette,
|
|
15
|
-
GradientPicker,
|
|
16
|
-
TabPanel,
|
|
17
|
-
__experimentalHStack as HStack,
|
|
18
|
-
} from '@wordpress/components';
|
|
19
|
-
import { useSetting } from '@wordpress/block-editor';
|
|
20
|
-
import PopoverOrModal from './PopoverOrModal';
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* The popover contents — palette + (optional) gradient tab.
|
|
24
|
-
*/
|
|
25
|
-
function ColorPanel({
|
|
26
|
-
colorValue,
|
|
27
|
-
gradientValue,
|
|
28
|
-
onColorChange,
|
|
29
|
-
onGradientChange,
|
|
30
|
-
colors,
|
|
31
|
-
gradients,
|
|
32
|
-
enableAlpha,
|
|
33
|
-
disableCustomColors,
|
|
34
|
-
disableCustomGradients,
|
|
35
|
-
showGradients,
|
|
36
|
-
}) {
|
|
37
|
-
const palette = (
|
|
38
|
-
<>
|
|
39
|
-
<ColorPalette
|
|
40
|
-
colors={colors}
|
|
41
|
-
value={colorValue}
|
|
42
|
-
onChange={onColorChange}
|
|
43
|
-
clearable
|
|
44
|
-
disableCustomColors={disableCustomColors}
|
|
45
|
-
enableAlpha={enableAlpha}
|
|
46
|
-
/>
|
|
47
|
-
{colorValue && (
|
|
48
|
-
<Button variant="secondary" onClick={() => onColorChange('')} style={{ marginTop: 10 }}>
|
|
49
|
-
{__('Reset Color', 'gcblite')}
|
|
50
|
-
</Button>
|
|
51
|
-
)}
|
|
52
|
-
</>
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
if (!showGradients) {
|
|
56
|
-
return <div style={{ minWidth: 260, padding: 12 }}>{palette}</div>;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<div style={{ minWidth: 260, padding: 12 }}>
|
|
61
|
-
<TabPanel
|
|
62
|
-
className="gcb-color-field-tabs"
|
|
63
|
-
activeClass="is-active"
|
|
64
|
-
tabs={[
|
|
65
|
-
{ name: 'color', title: __('Color', 'gcblite'), className: 'tab-color' },
|
|
66
|
-
{ name: 'gradient', title: __('Gradient', 'gcblite'), className: 'tab-gradient' },
|
|
67
|
-
]}
|
|
68
|
-
>
|
|
69
|
-
{(tab) => (
|
|
70
|
-
<>
|
|
71
|
-
{tab.name === 'color' && palette}
|
|
72
|
-
{tab.name === 'gradient' && (
|
|
73
|
-
<>
|
|
74
|
-
<GradientPicker
|
|
75
|
-
value={gradientValue || undefined}
|
|
76
|
-
onChange={(next) => onGradientChange(next || '')}
|
|
77
|
-
gradients={gradients || []}
|
|
78
|
-
clearable
|
|
79
|
-
disableCustomGradients={disableCustomGradients}
|
|
80
|
-
__experimentalIsRenderedInSidebar
|
|
81
|
-
/>
|
|
82
|
-
{gradientValue && (
|
|
83
|
-
<Button
|
|
84
|
-
variant="secondary"
|
|
85
|
-
onClick={() => onGradientChange('')}
|
|
86
|
-
style={{ marginTop: 10 }}
|
|
87
|
-
>
|
|
88
|
-
{__('Reset Gradient', 'gcblite')}
|
|
89
|
-
</Button>
|
|
90
|
-
)}
|
|
91
|
-
</>
|
|
92
|
-
)}
|
|
93
|
-
</>
|
|
94
|
-
)}
|
|
95
|
-
</TabPanel>
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* The trigger swatch — large white tile with a colour swatch on the left,
|
|
102
|
-
* the resolved value (or label) on the right. Same "popout" pattern as the
|
|
103
|
-
* image / post-object controls.
|
|
104
|
-
*/
|
|
105
|
-
function ColorTrigger({ label, colorValue, gradientValue, onToggle, isOpen }) {
|
|
106
|
-
const hasValue = !!(colorValue || gradientValue);
|
|
107
|
-
const swatchBackground = gradientValue || colorValue || 'transparent';
|
|
108
|
-
const isCheckered = !hasValue;
|
|
109
|
-
|
|
110
|
-
return (
|
|
111
|
-
<Button
|
|
112
|
-
onClick={onToggle}
|
|
113
|
-
aria-expanded={isOpen}
|
|
114
|
-
aria-label={label}
|
|
115
|
-
className="gcb-modal-toggle-button gcb-color-trigger"
|
|
116
|
-
>
|
|
117
|
-
<HStack spacing={3}>
|
|
118
|
-
<span
|
|
119
|
-
aria-hidden
|
|
120
|
-
className={isCheckered ? 'gcb-color-trigger__swatch is-empty' : 'gcb-color-trigger__swatch'}
|
|
121
|
-
style={{
|
|
122
|
-
width: 24,
|
|
123
|
-
height: 24,
|
|
124
|
-
borderRadius: '100%',
|
|
125
|
-
background: swatchBackground,
|
|
126
|
-
flexShrink: 0,
|
|
127
|
-
border: '1px solid #ddd',
|
|
128
|
-
display: 'inline-block',
|
|
129
|
-
}}
|
|
130
|
-
/>
|
|
131
|
-
<span style={{ flex: 1, textAlign: 'left', fontSize: 13, color: '#1e1e1e', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
|
|
132
|
-
{hasValue ? (gradientValue ? __('Gradient', 'gcblite') : colorValue) : __('Select a color', 'gcblite')}
|
|
133
|
-
</span>
|
|
134
|
-
</HStack>
|
|
135
|
-
</Button>
|
|
136
|
-
);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function ColorFieldImpl({
|
|
140
|
-
label = __('Color', 'gcblite'),
|
|
141
|
-
colorValue,
|
|
142
|
-
gradientValue,
|
|
143
|
-
onColorChange,
|
|
144
|
-
onGradientChange,
|
|
145
|
-
colors,
|
|
146
|
-
gradients,
|
|
147
|
-
enableAlpha = true,
|
|
148
|
-
disableCustomColors = false,
|
|
149
|
-
disableCustomGradients = false,
|
|
150
|
-
showGradients = true,
|
|
151
|
-
className = '',
|
|
152
|
-
help,
|
|
153
|
-
}) {
|
|
154
|
-
const themeColors = useSetting('color.palette');
|
|
155
|
-
const themeGradients = useSetting('color.gradients');
|
|
156
|
-
|
|
157
|
-
// Always end up with arrays — `useSetting('color.gradients')` returns
|
|
158
|
-
// undefined on themes that don't declare any gradients, and feeding that
|
|
159
|
-
// to <GradientPicker> crashes on `.orientation`.
|
|
160
|
-
const finalColors = (colors && colors.length ? colors : (themeColors || []));
|
|
161
|
-
const finalGradients = (gradients && gradients.length ? gradients : (themeGradients || []));
|
|
162
|
-
|
|
163
|
-
return (
|
|
164
|
-
<BaseControl
|
|
165
|
-
label={label}
|
|
166
|
-
help={help}
|
|
167
|
-
className={`gcb-color-control components-base-control ${className}`.trim()}
|
|
168
|
-
__nextHasNoMarginBottom
|
|
169
|
-
>
|
|
170
|
-
<PopoverOrModal
|
|
171
|
-
modalTitle={label}
|
|
172
|
-
dropdownProps={{ popoverProps: { placement: 'left-start' } }}
|
|
173
|
-
renderToggle={({ isOpen, onToggle }) => (
|
|
174
|
-
<ColorTrigger
|
|
175
|
-
label={label}
|
|
176
|
-
colorValue={colorValue}
|
|
177
|
-
gradientValue={gradientValue}
|
|
178
|
-
onToggle={onToggle}
|
|
179
|
-
isOpen={isOpen}
|
|
180
|
-
/>
|
|
181
|
-
)}
|
|
182
|
-
renderContent={() => (
|
|
183
|
-
<ColorPanel
|
|
184
|
-
colorValue={colorValue}
|
|
185
|
-
gradientValue={gradientValue}
|
|
186
|
-
onColorChange={onColorChange}
|
|
187
|
-
onGradientChange={onGradientChange}
|
|
188
|
-
colors={finalColors}
|
|
189
|
-
gradients={finalGradients}
|
|
190
|
-
enableAlpha={enableAlpha}
|
|
191
|
-
disableCustomColors={disableCustomColors}
|
|
192
|
-
disableCustomGradients={disableCustomGradients}
|
|
193
|
-
showGradients={showGradients}
|
|
194
|
-
/>
|
|
195
|
-
)}
|
|
196
|
-
/>
|
|
197
|
-
</BaseControl>
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
/**
|
|
202
|
-
* Adapter for the registry contract.
|
|
203
|
-
*
|
|
204
|
-
* The control stores a single string value — either a colour (e.g. `#ff0000`,
|
|
205
|
-
* `var(--wp--preset--color--primary)`) or a gradient (e.g. `linear-gradient(...)`).
|
|
206
|
-
* When the user picks one, the other is cleared. This matches the WP attribute
|
|
207
|
-
* type `string` that the loader generates for `color` controls.
|
|
208
|
-
*
|
|
209
|
-
* For separate color + gradient attributes on the same block, declare two
|
|
210
|
-
* controls (one with `showGradients: false`, one purely gradient — coming in v0.2).
|
|
211
|
-
*/
|
|
212
|
-
export default function ColorField({ control, value, onChange }) {
|
|
213
|
-
const stringValue = typeof value === 'string' ? value : '';
|
|
214
|
-
const isGradient = stringValue.includes('gradient(');
|
|
215
|
-
const colorValue = isGradient ? '' : stringValue;
|
|
216
|
-
const gradientValue = isGradient ? stringValue : '';
|
|
217
|
-
|
|
218
|
-
const handleColor = (next) => onChange(next || '');
|
|
219
|
-
const handleGradient = (next) => onChange(next || '');
|
|
220
|
-
|
|
221
|
-
return (
|
|
222
|
-
<ColorFieldImpl
|
|
223
|
-
label={control.label}
|
|
224
|
-
help={control.helpText}
|
|
225
|
-
colorValue={colorValue}
|
|
226
|
-
gradientValue={gradientValue}
|
|
227
|
-
onColorChange={handleColor}
|
|
228
|
-
onGradientChange={handleGradient}
|
|
229
|
-
showGradients={control.showGradients !== false}
|
|
230
|
-
enableAlpha={control.enableAlpha !== false}
|
|
231
|
-
disableCustomColors={control.disableCustomColors === true}
|
|
232
|
-
disableCustomGradients={control.disableCustomGradients === true}
|
|
233
|
-
/>
|
|
234
|
-
);
|
|
235
|
-
}
|
package/src/controls/date.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { BaseControl, Button, DatePicker } from '@wordpress/components';
|
|
2
|
-
import { __ } from '@wordpress/i18n';
|
|
3
|
-
import PopoverOrModal from './PopoverOrModal';
|
|
4
|
-
|
|
5
|
-
export default function DateField({ control, value, onChange }) {
|
|
6
|
-
return (
|
|
7
|
-
<BaseControl label={control.label} help={control.helpText} __nextHasNoMarginBottom>
|
|
8
|
-
<PopoverOrModal
|
|
9
|
-
modalTitle={control.label || __('Pick a date', 'gcblite')}
|
|
10
|
-
dropdownProps={{ popoverProps: { placement: 'bottom-start' } }}
|
|
11
|
-
renderToggle={({ onToggle }) => (
|
|
12
|
-
<>
|
|
13
|
-
<Button variant="secondary" onClick={onToggle}>
|
|
14
|
-
{value ? new Date(value).toLocaleDateString() : __('Pick a date', 'gcblite')}
|
|
15
|
-
</Button>
|
|
16
|
-
{value && (
|
|
17
|
-
<Button variant="tertiary" size="small" isDestructive onClick={() => onChange('')} style={{ marginLeft: 8 }}>
|
|
18
|
-
{__('Clear', 'gcblite')}
|
|
19
|
-
</Button>
|
|
20
|
-
)}
|
|
21
|
-
</>
|
|
22
|
-
)}
|
|
23
|
-
renderContent={({ close }) => (
|
|
24
|
-
<div style={{ padding: 8 }}>
|
|
25
|
-
<DatePicker
|
|
26
|
-
currentDate={value || undefined}
|
|
27
|
-
onChange={(next) => {
|
|
28
|
-
onChange(next || '');
|
|
29
|
-
close();
|
|
30
|
-
}}
|
|
31
|
-
/>
|
|
32
|
-
</div>
|
|
33
|
-
)}
|
|
34
|
-
/>
|
|
35
|
-
</BaseControl>
|
|
36
|
-
);
|
|
37
|
-
}
|
package/src/controls/datetime.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* DateTime — like Date, but with a time picker too. Stores an ISO 8601
|
|
3
|
-
* timestamp string (e.g. "2026-05-25T14:30:00").
|
|
4
|
-
*
|
|
5
|
-
* Uses WP's DateTimePicker rather than DatePicker so the panel shows hours
|
|
6
|
-
* and minutes alongside the calendar. Renders inside PopoverOrModal so it
|
|
7
|
-
* behaves correctly in both sidebar (popover) and metabox (modal) contexts.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { BaseControl, Button, DateTimePicker } from '@wordpress/components';
|
|
11
|
-
import { __ } from '@wordpress/i18n';
|
|
12
|
-
import PopoverOrModal from './PopoverOrModal';
|
|
13
|
-
|
|
14
|
-
export default function DatetimeField({ control, value, onChange }) {
|
|
15
|
-
const displayLabel = value
|
|
16
|
-
? new Date(value).toLocaleString()
|
|
17
|
-
: __('Pick a date and time', 'gcblite');
|
|
18
|
-
|
|
19
|
-
return (
|
|
20
|
-
<BaseControl label={control.label} help={control.helpText} __nextHasNoMarginBottom>
|
|
21
|
-
<PopoverOrModal
|
|
22
|
-
modalTitle={control.label || __('Pick a date and time', 'gcblite')}
|
|
23
|
-
dropdownProps={{ popoverProps: { placement: 'bottom-start' } }}
|
|
24
|
-
renderToggle={({ onToggle }) => (
|
|
25
|
-
<>
|
|
26
|
-
<Button variant="secondary" onClick={onToggle}>
|
|
27
|
-
{displayLabel}
|
|
28
|
-
</Button>
|
|
29
|
-
{value && (
|
|
30
|
-
<Button
|
|
31
|
-
variant="tertiary"
|
|
32
|
-
size="small"
|
|
33
|
-
isDestructive
|
|
34
|
-
onClick={() => onChange('')}
|
|
35
|
-
style={{ marginLeft: 8 }}
|
|
36
|
-
>
|
|
37
|
-
{__('Clear', 'gcblite')}
|
|
38
|
-
</Button>
|
|
39
|
-
)}
|
|
40
|
-
</>
|
|
41
|
-
)}
|
|
42
|
-
renderContent={() => (
|
|
43
|
-
<div style={{ padding: 8 }}>
|
|
44
|
-
<DateTimePicker
|
|
45
|
-
currentDate={value || undefined}
|
|
46
|
-
onChange={(next) => onChange(next || '')}
|
|
47
|
-
is12Hour
|
|
48
|
-
/>
|
|
49
|
-
</div>
|
|
50
|
-
)}
|
|
51
|
-
/>
|
|
52
|
-
</BaseControl>
|
|
53
|
-
);
|
|
54
|
-
}
|
package/src/controls/email.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { TextControl } from '@wordpress/components';
|
|
2
|
-
|
|
3
|
-
export default function EmailField({ control, value, onChange }) {
|
|
4
|
-
return (
|
|
5
|
-
<TextControl
|
|
6
|
-
label={control.label}
|
|
7
|
-
help={control.helpText}
|
|
8
|
-
placeholder={control.placeholder ?? 'name@example.com'}
|
|
9
|
-
type="email"
|
|
10
|
-
value={value ?? ''}
|
|
11
|
-
onChange={onChange}
|
|
12
|
-
__nextHasNoMarginBottom
|
|
13
|
-
/>
|
|
14
|
-
);
|
|
15
|
-
}
|
package/src/controls/file.js
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* FileField — non-image attachment picker. Stores `{ id, url, filename, title }`.
|
|
3
|
-
*
|
|
4
|
-
* The trigger button mirrors the image control's "popout" tile (file icon +
|
|
5
|
-
* filename + chevron) so the Inspector feels consistent.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { __ } from '@wordpress/i18n';
|
|
9
|
-
import {
|
|
10
|
-
Button,
|
|
11
|
-
__experimentalHStack as HStack,
|
|
12
|
-
__experimentalTruncate as Truncate,
|
|
13
|
-
} from '@wordpress/components';
|
|
14
|
-
import MediaPicker from './MediaPicker';
|
|
15
|
-
import PopoverOrModal from './PopoverOrModal';
|
|
16
|
-
import MediaCapabilityGate from './MediaCapabilityGate';
|
|
17
|
-
import MediaTriggerBadges from './MediaTriggerBadges';
|
|
18
|
-
|
|
19
|
-
const TOGGLE_BUTTON_STYLE = {
|
|
20
|
-
width: '100%',
|
|
21
|
-
height: 'auto',
|
|
22
|
-
padding: '12px',
|
|
23
|
-
justifyContent: 'flex-start',
|
|
24
|
-
border: '1px solid #ddd',
|
|
25
|
-
borderRadius: '2px',
|
|
26
|
-
backgroundColor: '#fff',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
function FileIcon() {
|
|
30
|
-
return (
|
|
31
|
-
<svg
|
|
32
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
33
|
-
viewBox="0 0 24 24"
|
|
34
|
-
width="20"
|
|
35
|
-
height="20"
|
|
36
|
-
style={{ flexShrink: 0, fill: '#1e1e1e' }}
|
|
37
|
-
aria-hidden
|
|
38
|
-
>
|
|
39
|
-
<path d="M14 9V3.5L19.5 9H14zM6 2h9l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2zm0 2v16h12V11h-5V4H6z" />
|
|
40
|
-
</svg>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export default function FileField({ control, value, onChange }) {
|
|
45
|
-
const fileValue = (typeof value === 'object' && value !== null)
|
|
46
|
-
? value
|
|
47
|
-
: { id: null, url: value || '', filename: '', title: '' };
|
|
48
|
-
const hasFile = !!(fileValue.id || fileValue.url);
|
|
49
|
-
const displayTitle = fileValue.title || fileValue.filename || __('(no title)', 'gcblite');
|
|
50
|
-
|
|
51
|
-
return (
|
|
52
|
-
<div className="components-base-control gcb-file-control">
|
|
53
|
-
<div className="components-base-control__field">
|
|
54
|
-
<label className="components-base-control__label">{control.label}</label>
|
|
55
|
-
</div>
|
|
56
|
-
{control.helpText && (
|
|
57
|
-
<p className="components-base-control__help">{control.helpText}</p>
|
|
58
|
-
)}
|
|
59
|
-
|
|
60
|
-
<MediaCapabilityGate>
|
|
61
|
-
<MediaPicker
|
|
62
|
-
onSelect={(media) => onChange({
|
|
63
|
-
id: media.id,
|
|
64
|
-
url: media.url,
|
|
65
|
-
filename: media.filename,
|
|
66
|
-
title: media.title,
|
|
67
|
-
})}
|
|
68
|
-
allowedTypes={control.allowedTypes || ['application', 'text', 'image', 'video', 'audio']}
|
|
69
|
-
value={fileValue.id}
|
|
70
|
-
render={({ open }) => (
|
|
71
|
-
<div>
|
|
72
|
-
{!hasFile && (
|
|
73
|
-
<Button
|
|
74
|
-
onClick={open}
|
|
75
|
-
variant="secondary"
|
|
76
|
-
style={{ marginBottom: 8 }}
|
|
77
|
-
>
|
|
78
|
-
{__('Select File', 'gcblite')}
|
|
79
|
-
</Button>
|
|
80
|
-
)}
|
|
81
|
-
|
|
82
|
-
{hasFile && (
|
|
83
|
-
<PopoverOrModal
|
|
84
|
-
modalTitle={control.label || __('File', 'gcblite')}
|
|
85
|
-
dropdownProps={{ popoverProps: { placement: 'left-start' } }}
|
|
86
|
-
renderToggle={({ isOpen, onToggle }) => (
|
|
87
|
-
<MediaTriggerBadges onClear={() => onChange({ id: null, url: '', filename: '', title: '' })}>
|
|
88
|
-
<Button
|
|
89
|
-
onClick={onToggle}
|
|
90
|
-
aria-expanded={isOpen}
|
|
91
|
-
className="gcb-modal-toggle-button gcb-file-control-toggle"
|
|
92
|
-
style={TOGGLE_BUTTON_STYLE}
|
|
93
|
-
>
|
|
94
|
-
<HStack spacing={3}>
|
|
95
|
-
<FileIcon />
|
|
96
|
-
<Truncate numberOfLines={1}>{displayTitle}</Truncate>
|
|
97
|
-
</HStack>
|
|
98
|
-
</Button>
|
|
99
|
-
</MediaTriggerBadges>
|
|
100
|
-
)}
|
|
101
|
-
renderContent={({ close }) => (
|
|
102
|
-
<div style={{ padding: 16, minWidth: 280 }}>
|
|
103
|
-
<Button
|
|
104
|
-
onClick={() => { close(); open(); }}
|
|
105
|
-
variant="secondary"
|
|
106
|
-
style={{ width: '100%', marginBottom: 12 }}
|
|
107
|
-
>
|
|
108
|
-
{__('Replace File', 'gcblite')}
|
|
109
|
-
</Button>
|
|
110
|
-
<Button
|
|
111
|
-
onClick={() => { onChange({ id: null, url: '', filename: '', title: '' }); close(); }}
|
|
112
|
-
variant="tertiary"
|
|
113
|
-
isDestructive
|
|
114
|
-
style={{ width: '100%' }}
|
|
115
|
-
>
|
|
116
|
-
{__('Remove File', 'gcblite')}
|
|
117
|
-
</Button>
|
|
118
|
-
</div>
|
|
119
|
-
)}
|
|
120
|
-
/>
|
|
121
|
-
)}
|
|
122
|
-
|
|
123
|
-
{!hasFile && (
|
|
124
|
-
<p style={{ fontSize: 13, color: '#757575', margin: 0 }}>
|
|
125
|
-
{__('No file selected', 'gcblite')}
|
|
126
|
-
</p>
|
|
127
|
-
)}
|
|
128
|
-
</div>
|
|
129
|
-
)}
|
|
130
|
-
/>
|
|
131
|
-
</MediaCapabilityGate>
|
|
132
|
-
</div>
|
|
133
|
-
);
|
|
134
|
-
}
|