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 / SizeControl.tsx

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

190 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 import { useMemo } from "react";
2 import {
3 BaseControl,
4 RangeControl,
5 Flex,
6 FlexItem,
7 __experimentalSpacer as Spacer,
8 __experimentalUseCustomUnits as useCustomUnits,
9 __experimentalUnitControl as UnitControl,
10 __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
11 } from "@wordpress/components";
12 import { __ } from "@wordpress/i18n";
13
14 // @ts-ignore
15 import { useSettings } from "@wordpress/block-editor";
16
17 const RANGE_CONTROL_CUSTOM_SETTINGS = {
18 "px": { max: 1000, step: 1 },
19 "%": { max: 100, step: 1 },
20 "vw": { max: 100, step: 1 },
21 "vh": { max: 100, step: 1 },
22 "em": { max: 50, step: 0.1 },
23 "rem": { max: 50, step: 0.1 },
24 "svw": { max: 100, step: 1 },
25 "lvw": { max: 100, step: 1 },
26 "dvw": { max: 100, step: 1 },
27 "svh": { max: 100, step: 1 },
28 "lvh": { max: 100, step: 1 },
29 "dvh": { max: 100, step: 1 },
30 "vi": { max: 100, step: 1 },
31 "svi": { max: 100, step: 1 },
32 "lvi": { max: 100, step: 1 },
33 "dvi": { max: 100, step: 1 },
34 "vb": { max: 100, step: 1 },
35 "svb": { max: 100, step: 1 },
36 "lvb": { max: 100, step: 1 },
37 "dvb": { max: 100, step: 1 },
38 "vmin": { max: 100, step: 1 },
39 "svmin": { max: 100, step: 1 },
40 "lvmin": { max: 100, step: 1 },
41 "dvmin": { max: 100, step: 1 },
42 "vmax": { max: 100, step: 1 },
43 "svmax": { max: 100, step: 1 },
44 "lvmax": { max: 100, step: 1 },
45 "dvmax": { max: 100, step: 1 },
46 } as const;
47
48 export interface SizeControlProps {
49 label: string;
50 value: string;
51 onChange: (newVal?: string) => void;
52 rangeConfig?: {
53 [Key in keyof typeof RANGE_CONTROL_CUSTOM_SETTINGS]?: {
54 min?: number;
55 max?: number;
56 step?: number;
57 };
58 };
59 initialPosition?: string;
60 disabled?: boolean;
61 }
62
63 export default function SizeControl({
64 label,
65 onChange,
66 value,
67 rangeConfig = {},
68 initialPosition,
69 disabled,
70 }: SizeControlProps) {
71 const customRangeValue = parseFloat(value || "0");
72
73 const [availableUnits] = useSettings("spacing.units");
74 const units = useCustomUnits({
75 availableUnits: availableUnits || ["%", "px", "em", "rem", "vh", "vw"],
76 });
77
78 const selectedUnit =
79 useMemo(() => parseQuantityAndUnitFromRawValue(value), [value])[1] ||
80 units[0]?.value ||
81 "px";
82
83 const handleSliderChange = (next: any) => {
84 onChange([next, selectedUnit].join(""));
85 };
86
87 const handleUnitChange = (newUnit: any) => {
88 // Attempt to smooth over differences between currentUnit and newUnit.
89 // This should slightly improve the experience of switching between unit types.
90 const [currentValue, currentUnit] =
91 parseQuantityAndUnitFromRawValue(value);
92
93 if (["em", "rem"].includes(newUnit) && currentUnit === "px") {
94 // Convert pixel value to an approximate of the new unit, assuming a root size of 16px.
95 onChange((currentValue! / 16).toFixed(2) + newUnit);
96 } else if (["em", "rem"].includes(currentUnit!) && newUnit === "px") {
97 // Convert to pixel value assuming a root size of 16px.
98 onChange(Math.round(currentValue! * 16) + newUnit);
99 } else if (
100 currentValue! > 100 &&
101 [
102 "%",
103 "vw",
104 "svw",
105 "lvw",
106 "dvw",
107 "vh",
108 "svh",
109 "lvh",
110 "dvh",
111 "vi",
112 "svi",
113 "lvi",
114 "dvi",
115 "vb",
116 "svb",
117 "lvb",
118 "dvb",
119 "vmin",
120 "svmin",
121 "lvmin",
122 "dvmin",
123 "vmax",
124 "svmax",
125 "lvmax",
126 "dvmax",
127 ].includes(newUnit)
128 ) {
129 // When converting to `%` or viewport-relative units, cap the new value at 100.
130 onChange(100 + newUnit);
131 }
132 };
133
134 // @ts-ignore
135 const customConfig = rangeConfig[selectedUnit];
136 // @ts-ignore
137 const defaultConfig = RANGE_CONTROL_CUSTOM_SETTINGS[selectedUnit];
138
139 let minVal = customConfig?.min ?? defaultConfig?.min ?? 0;
140 let maxVal = customConfig?.max ?? defaultConfig?.max ?? 100;
141 const stepVal = customConfig?.step ?? defaultConfig?.step ?? 0.1;
142
143 minVal = Math.min(minVal, customRangeValue);
144 maxVal = Math.max(maxVal, customRangeValue);
145
146 return (
147 <fieldset className="block-editor-height-control">
148 <BaseControl.VisualLabel as="legend">
149 {label}
150 </BaseControl.VisualLabel>
151 <Flex>
152 <FlexItem isBlock>
153 <UnitControl
154 value={value}
155 units={units}
156 onChange={onChange}
157 onUnitChange={handleUnitChange}
158 min={minVal}
159 size={"__unstable-large"}
160 label={label}
161 hideLabelFromVision
162 disabled={disabled}
163 />
164 </FlexItem>
165 <FlexItem isBlock>
166 <Spacer marginX={2} marginBottom={0}>
167 <RangeControl
168 value={!value ? undefined : customRangeValue}
169 min={minVal}
170 max={maxVal}
171 step={stepVal}
172 withInputField={false}
173 onChange={handleSliderChange}
174 __nextHasNoMarginBottom
175 label={label}
176 hideLabelFromVision
177 initialPosition={
178 initialPosition
179 ? parseFloat(initialPosition)
180 : undefined
181 }
182 disabled={disabled}
183 />
184 </Spacer>
185 </FlexItem>
186 </Flex>
187 </fieldset>
188 );
189 }
190