PluginProbe
Tableberg – Simple Gutenberg Table Block / 1.1.5
Tableberg – Simple Gutenberg Table Block v1.1.5
1.1.5 1.1.4 1.1.3 1.1.2 1.1.1 1.1.0 1.0.5 1.0.4 1.0.3 1.0.2 1.0.1 trunk 0.0.2 0.2.1 0.3.2 0.3.3 0.4.1 0.5.0 0.5.1 0.5.2 0.5.3 0.5.4 0.5.5 0.5.6 0.5.7 All 42 releases
tableberg / components / editor / SpacingControlCustom.tsx

SpacingControlCustom.tsx in Tableberg – Simple Gutenberg Table Block 1.1.5, at components/editor/SpacingControlCustom.tsx

188 lines 6.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import {
2 RangeControl,
3 Button,
4 BaseControl,
5 __experimentalHStack as HStack,
6 __experimentalVStack as VStack,
7 __experimentalUnitControl as UnitControl,
8 __experimentalUseCustomUnits as useCustomUnits,
9 __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
10 } from "@wordpress/components";
11 import { __ } from "@wordpress/i18n";
12 import { settings } from "@wordpress/icons";
13 import { HTMLAttributes, useMemo, useState } from "react";
14 import { useSettings } from "@wordpress/block-editor";
15
16 export interface Props {
17 label: string;
18 value: string;
19 onChange: (value: string) => void;
20 style?: HTMLAttributes<HTMLFieldSetElement>["style"];
21 }
22
23 function getSlugFromValue(value: string): string | undefined {
24 if (!value) return undefined;
25 if (value === "0") return "0";
26 const match = value.match(/var\(--wp--preset--spacing--(.+)\)/);
27 return match ? match[1] : undefined;
28 }
29
30 function isPresetValue(value: string): boolean {
31 return value === "0" || /var\(--wp--preset--spacing--.+\)/.test(value);
32 }
33
34 export default function SpacingControlSingle({
35 label,
36 value,
37 onChange,
38 style,
39 }: Props) {
40 const [
41 legacySpacingSizes,
42 customSpacingSizes,
43 themeSpacingSizes,
44 defaultSpacingSizes,
45 defaultSpacingSizesEnabled,
46 ] = useSettings(
47 "spacing.spacingSizes",
48 "spacing.spacingSizes.custom",
49 "spacing.spacingSizes.theme",
50 "spacing.spacingSizes.default",
51 "spacing.defaultSpacingSizes"
52 );
53
54 const settingsSizes = legacySpacingSizes || [
55 ...(customSpacingSizes || []),
56 ...(themeSpacingSizes || []),
57 ...(defaultSpacingSizes && defaultSpacingSizesEnabled !== false
58 ? defaultSpacingSizes
59 : []),
60 ];
61 const spacingSizes = [{ slug: "0", size: 0 }, ...settingsSizes];
62
63 const [showCustomValueControl, setShowCustomValueControl] = useState(
64 !!value && !isPresetValue(value)
65 );
66
67 const [availableUnits] = useSettings("spacing.units");
68 const units = useCustomUnits({
69 availableUnits: availableUnits || ["px", "em", "rem"],
70 });
71
72 const presetIndex = useMemo(() => {
73 const slug = getSlugFromValue(value);
74 if (!slug) return 0;
75 const index = spacingSizes.findIndex(s => String(s.slug) === slug);
76 return index !== -1 ? index : NaN;
77 }, [value, spacingSizes]);
78
79 const [numericValue, currentUnit] = useMemo(
80 () => parseQuantityAndUnitFromRawValue(value),
81 [value]
82 );
83 const selectedUnit = currentUnit || units[0]?.value || "px";
84
85 const fieldsetStyle: HTMLAttributes<HTMLFieldSetElement>["style"] = {
86 ...style,
87 border: 0,
88 padding: 0,
89 margin: 0,
90 };
91
92 return (
93 <fieldset className="spacing-sizes-control" style={fieldsetStyle}>
94 <HStack
95 className="spacing-sizes-control__header"
96 style={{ marginBottom: "12px" }}
97 >
98 <BaseControl.VisualLabel
99 as="legend"
100 className="spacing-sizes-control__label"
101 >
102 {label}
103 </BaseControl.VisualLabel>
104 <Button
105 label={
106 showCustomValueControl
107 ? __("Use size preset")
108 : __("Set custom size")
109 }
110 icon={settings}
111 onClick={() =>
112 setShowCustomValueControl(!showCustomValueControl)
113 }
114 isPressed={showCustomValueControl}
115 size="small"
116 className="spacing-sizes-control__custom-toggle"
117 iconSize={24}
118 />
119 </HStack>
120
121 <VStack spacing={0.5}>
122 <HStack className="spacing-sizes-control__wrapper">
123 {showCustomValueControl ? (
124 <>
125 <UnitControl
126 hideLabelFromVision
127 className="spacing-sizes-control__unit-control"
128 size="__unstable-large"
129 value={value}
130 onChange={(newValue?: string) => {
131 if (
132 newValue &&
133 !isNaN(parseFloat(newValue))
134 ) {
135 onChange(newValue);
136 }
137 }}
138 />
139 <RangeControl
140 min={0}
141 max={100}
142 step={1}
143 withInputField={false}
144 className="spacing-sizes-control__custom-value-range"
145 label={label}
146 hideLabelFromVision
147 value={numericValue || 0}
148 onChange={(next?: number) => {
149 if (next !== undefined) {
150 onChange(`${next}${selectedUnit}`);
151 }
152 }}
153 __nextHasNoMarginBottom
154 />
155 </>
156 ) : (
157 <RangeControl
158 className="spacing-sizes-control__preset-range"
159 label={label}
160 hideLabelFromVision
161 value={presetIndex}
162 min={0}
163 max={spacingSizes.length - 1}
164 marks={spacingSizes.map((_, i) => ({
165 value: i,
166 label: undefined,
167 }))}
168 withInputField={false}
169 onChange={(index?: number) => {
170 if (index === undefined) return;
171 const slug = spacingSizes[index]?.slug;
172 if (slug === "0") {
173 onChange("0");
174 } else {
175 onChange(
176 `var(--wp--preset--spacing--${slug})`
177 );
178 }
179 }}
180 __nextHasNoMarginBottom
181 />
182 )}
183 </HStack>
184 </VStack>
185 </fieldset>
186 );
187 }
188