This commit is contained in:
Jeremy Rangel
2025-11-30 00:50:56 -08:00
commit f1e7005b26
12 changed files with 844 additions and 0 deletions

126
BorderRadiusControl.js Normal file
View File

@ -0,0 +1,126 @@
import { useState } from '@wordpress/element';
import {
BaseControl,
Button,
__experimentalUnitControl as UnitControl,
RangeControl,
__experimentalHStack as HStack,
__experimentalVStack as VStack,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { link, linkOff } from '@wordpress/icons';
export default function BorderRadiusControl({ label, value = { radius: '0px' }, onChange }) {
// Determine if value is advanced initially
const initialAdvanced = value.topLeft || value.topRight || value.bottomLeft || value.bottomRight ? true : false;
const [advanced, setAdvanced] = useState(initialAdvanced);
const parseValue = (val) => {
if (!val) return 0;
if (typeof val === 'string') return parseInt(val);
if (val.radius) return parseInt(val.radius);
return 0;
};
// Flat handlers
const handleFlatChange = (val) => {
const newValue = { radius: val };
console.log('Flat change →', newValue);
onChange(newValue);
};
const handleFlatRangeChange = (val) => {
const currentUnit = value.radius?.replace(/[0-9]/g, '') || 'px';
const newValue = { radius: `${val}${currentUnit}` };
console.log('Flat range change →', newValue);
onChange(newValue);
};
// Advanced handlers
const handleCornerChange = (corner, val) => {
// Always return a full object with all four corners
const newValue = {
topLeft: corner === 'topLeft' ? val : value.topLeft || '0px',
topRight: corner === 'topRight' ? val : value.topRight || '0px',
bottomRight: corner === 'bottomRight' ? val : value.bottomRight || '0px',
bottomLeft: corner === 'bottomLeft' ? val : value.bottomLeft || '0px',
};
console.log('Corner change →', newValue);
onChange(newValue);
};
return (
<BaseControl label={label}>
<HStack gap={8} align="flex-start">
{/* Left column: controls */}
<VStack gap={8} style={{ flex: 1 }}>
{!advanced && (
<HStack gap={8} align="center">
<UnitControl
value={value.radius || '0px'}
onChange={handleFlatChange}
label={__('Radius', 'directory-listings')}
min={0}
max={500}
style={{ flex: '0 0 auto' }}
/>
<div style={{ flex: 1 }}>
<RangeControl
value={parseValue(value)}
withInputField={false}
onChange={handleFlatRangeChange}
min={0}
max={500}
/>
</div>
</HStack>
)}
{advanced && (
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '8px' }}>
<UnitControl
label={__('Top Left', 'directory-listings')}
value={value.topLeft || '0px'}
onChange={(val) => handleCornerChange('topLeft', val)}
min={0}
max={500}
/>
<UnitControl
label={__('Top Right', 'directory-listings')}
value={value.topRight || '0px'}
onChange={(val) => handleCornerChange('topRight', val)}
min={0}
max={500}
/>
<UnitControl
label={__('Bottom Left', 'directory-listings')}
value={value.bottomLeft || '0px'}
onChange={(val) => handleCornerChange('bottomLeft', val)}
min={0}
max={500}
/>
<UnitControl
label={__('Bottom Right', 'directory-listings')}
value={value.bottomRight || '0px'}
onChange={(val) => handleCornerChange('bottomRight', val)}
min={0}
max={500}
/>
</div>
)}
</VStack>
{/* Right column: toggle button */}
<VStack>
<Button
icon={advanced ? linkOff : link}
iconSize={24}
isSecondary
onClick={() => setAdvanced(!advanced)}
aria-label={__('Toggle advanced border radius', 'directory-listings')}
/>
</VStack>
</HStack>
</BaseControl>
);
}