mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-09 05:26:24 +09:00
experimental: support css variables in dedicated sections (#4212)
Ref https://github.com/webstudio-is/webstudio/issues/3399 Added support for entering and autocomplete of css variables to dedicated style sections like size and typography. - color control - text control Also improved autocomplete to search with both var(--name) and --name. 
This commit is contained in:
1 parent
5bfdd683b3
commit
63460bd2cb
22 files changed
+76
-69
No files matched your search
@@ -1,12 +1,14 @@
|
||||
import { useStore } from "@nanostores/react";
|
||||
import type { StyleProperty } from "@webstudio-is/css-engine";
|
||||
import { ColorPicker } from "../../shared/color-picker";
|
||||
import { styleConfigByName } from "../../shared/configs";
|
||||
import { useComputedStyleDecl } from "../../shared/model";
|
||||
import { $availableVariables, useComputedStyleDecl } from "../../shared/model";
|
||||
import { deleteProperty, setProperty } from "../../shared/use-style-data";
|
||||
|
||||
export const ColorControl = ({ property }: { property: StyleProperty }) => {
|
||||
const computedStyleDecl = useComputedStyleDecl(property);
|
||||
const { items } = styleConfigByName(property);
|
||||
const availableVariables = useStore($availableVariables);
|
||||
const value = computedStyleDecl.cascadedValue;
|
||||
const currentColor = computedStyleDecl.usedValue;
|
||||
const setValue = setProperty(property);
|
||||
@@ -15,7 +17,13 @@ export const ColorControl = ({ property }: { property: StyleProperty }) => {
|
||||
property={property}
|
||||
value={value}
|
||||
currentColor={currentColor}
|
||||
keywords={items.map((item) => ({ type: "keyword", value: item.name }))}
|
||||
options={[
|
||||
...items.map((item) => ({
|
||||
type: "keyword" as const,
|
||||
value: item.name,
|
||||
})),
|
||||
...availableVariables,
|
||||
]}
|
||||
onChange={(styleValue) => setValue(styleValue, { isEphemeral: true })}
|
||||
onChangeComplete={setValue}
|
||||
onAbort={() => deleteProperty(property, { isEphemeral: true })}
|
||||
|
||||
+2
-2
@@ -110,7 +110,7 @@ export const PositionControl = ({
|
||||
<CssValueInputContainer
|
||||
property={property}
|
||||
styleSource={styleDecl.source.name}
|
||||
keywords={keywords}
|
||||
options={keywords}
|
||||
value={value.value[0]}
|
||||
setValue={setValueX}
|
||||
deleteProperty={deleteProperty}
|
||||
@@ -123,7 +123,7 @@ export const PositionControl = ({
|
||||
<CssValueInputContainer
|
||||
property={property}
|
||||
styleSource={styleDecl.source.name}
|
||||
keywords={keywords}
|
||||
options={keywords}
|
||||
value={value.value[1]}
|
||||
setValue={setValueY}
|
||||
deleteProperty={deleteProperty}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useState } from "react";
|
||||
import { useStore } from "@nanostores/react";
|
||||
import type { StyleProperty, StyleValue } from "@webstudio-is/css-engine";
|
||||
import {
|
||||
CssValueInput,
|
||||
@@ -6,7 +7,7 @@ import {
|
||||
} from "../../shared/css-value-input";
|
||||
import { styleConfigByName } from "../../shared/configs";
|
||||
import { deleteProperty, setProperty } from "../../shared/use-style-data";
|
||||
import { useComputedStyleDecl } from "../../shared/model";
|
||||
import { $availableVariables, useComputedStyleDecl } from "../../shared/model";
|
||||
|
||||
export const TextControl = ({ property }: { property: StyleProperty }) => {
|
||||
const computedStyleDecl = useComputedStyleDecl(property);
|
||||
@@ -16,13 +17,20 @@ export const TextControl = ({ property }: { property: StyleProperty }) => {
|
||||
StyleValue | IntermediateStyleValue
|
||||
>();
|
||||
const items = styleConfigByName(property).items;
|
||||
const availableVariables = useStore($availableVariables);
|
||||
return (
|
||||
<CssValueInput
|
||||
styleSource={computedStyleDecl.source.name}
|
||||
property={property}
|
||||
value={value}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={items.map((item) => ({ type: "keyword", value: item.name }))}
|
||||
options={[
|
||||
...items.map((item) => ({
|
||||
type: "keyword" as const,
|
||||
value: item.name,
|
||||
})),
|
||||
...availableVariables,
|
||||
]}
|
||||
onChange={(styleValue) => {
|
||||
setIntermediateValue(styleValue);
|
||||
if (styleValue === undefined) {
|
||||
|
||||
@@ -35,7 +35,7 @@ import { CssValueInputContainer } from "../../shared/css-value-input";
|
||||
import { styleConfigByName } from "../../shared/configs";
|
||||
import { deleteProperty, setProperty } from "../../shared/use-style-data";
|
||||
import {
|
||||
$definedStyles,
|
||||
$availableVariables,
|
||||
$matchingBreakpoints,
|
||||
getDefinedStyles,
|
||||
useComputedStyleDecl,
|
||||
@@ -210,16 +210,6 @@ const AdvancedPropertyLabel = ({ property }: { property: StyleProperty }) => {
|
||||
);
|
||||
};
|
||||
|
||||
const $availableCustomProperties = computed($definedStyles, (definedStyles) => {
|
||||
const customProperties = new Set<StyleProperty>();
|
||||
for (const { property } of definedStyles) {
|
||||
if (property.startsWith("--")) {
|
||||
customProperties.add(property);
|
||||
}
|
||||
}
|
||||
return customProperties;
|
||||
});
|
||||
|
||||
const AdvancedPropertyValue = ({
|
||||
autoFocus,
|
||||
property,
|
||||
@@ -228,7 +218,7 @@ const AdvancedPropertyValue = ({
|
||||
property: StyleProperty;
|
||||
}) => {
|
||||
const styleDecl = useComputedStyleDecl(property);
|
||||
const availableCustomProperties = useStore($availableCustomProperties);
|
||||
const availableVariables = useStore($availableVariables);
|
||||
const { items } = styleConfigByName(property);
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
useEffect(() => {
|
||||
@@ -265,16 +255,12 @@ const AdvancedPropertyValue = ({
|
||||
}
|
||||
property={property}
|
||||
styleSource={styleDecl.source.name}
|
||||
keywords={[
|
||||
options={[
|
||||
...items.map((item) => ({
|
||||
type: "keyword" as const,
|
||||
value: item.name,
|
||||
})),
|
||||
// very basic custom properties autocomplete
|
||||
...Array.from(availableCustomProperties).map((name) => ({
|
||||
type: "keyword" as const,
|
||||
value: name,
|
||||
})),
|
||||
...availableVariables,
|
||||
]}
|
||||
value={styleDecl.cascadedValue}
|
||||
setValue={(styleValue, options) => {
|
||||
|
||||
+2
-2
@@ -73,7 +73,7 @@ export const BackgroundPosition = ({ index }: { index: number }) => {
|
||||
<CssValueInputContainer
|
||||
property="backgroundPositionX"
|
||||
styleSource="default"
|
||||
keywords={[
|
||||
options={[
|
||||
{ type: "keyword", value: "center" },
|
||||
{ type: "keyword", value: "left" },
|
||||
{ type: "keyword", value: "right" },
|
||||
@@ -96,7 +96,7 @@ export const BackgroundPosition = ({ index }: { index: number }) => {
|
||||
<CssValueInputContainer
|
||||
property="backgroundPositionY"
|
||||
styleSource="default"
|
||||
keywords={[
|
||||
options={[
|
||||
{ type: "keyword", value: "center" },
|
||||
{ type: "keyword", value: "top" },
|
||||
{ type: "keyword", value: "bottom" },
|
||||
|
||||
+2
-2
@@ -146,7 +146,7 @@ export const BackgroundSize = ({ index }: { index: number }) => {
|
||||
disabled={customSizeDisabled}
|
||||
property={property}
|
||||
styleSource="default"
|
||||
keywords={customSizeOptions}
|
||||
options={customSizeOptions}
|
||||
value={customSizeValue.value[0]}
|
||||
setValue={setValueX}
|
||||
deleteProperty={() => {}}
|
||||
@@ -156,7 +156,7 @@ export const BackgroundSize = ({ index }: { index: number }) => {
|
||||
disabled={customSizeDisabled}
|
||||
property={property}
|
||||
styleSource="default"
|
||||
keywords={customSizeOptions}
|
||||
options={customSizeOptions}
|
||||
value={customSizeValue.value[1]}
|
||||
setValue={setValueY}
|
||||
deleteProperty={() => {}}
|
||||
|
||||
@@ -58,7 +58,7 @@ export const BorderColor = () => {
|
||||
currentColor={currentColor}
|
||||
property={local.property as StyleProperty}
|
||||
value={value}
|
||||
keywords={items.map((item) => ({
|
||||
options={items.map((item) => ({
|
||||
type: "keyword",
|
||||
value: item.name,
|
||||
}))}
|
||||
|
||||
@@ -85,7 +85,7 @@ export const BorderProperty = ({
|
||||
<CssValueInputContainer
|
||||
property={firstPropertyName}
|
||||
styleSource={styleValueSourceColor}
|
||||
keywords={keywords}
|
||||
options={keywords}
|
||||
value={value}
|
||||
setValue={(newValue, options) => {
|
||||
const batch = createBatchUpdate();
|
||||
@@ -123,7 +123,7 @@ export const BorderProperty = ({
|
||||
}
|
||||
property={styleDecl.property as StyleProperty}
|
||||
styleSource={styleDecl.source.name}
|
||||
keywords={keywords}
|
||||
options={keywords}
|
||||
value={styleDecl.cascadedValue}
|
||||
setValue={setProperty(styleDecl.property as StyleProperty)}
|
||||
deleteProperty={deleteProperty}
|
||||
|
||||
@@ -152,7 +152,7 @@ const GapInput = ({
|
||||
property={property}
|
||||
value={styleDecl.cascadedValue}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={items.map((item) => ({
|
||||
options={items.map((item) => ({
|
||||
type: "keyword",
|
||||
value: item.name,
|
||||
}))}
|
||||
|
||||
+2
-3
@@ -159,7 +159,7 @@ export const TransformAndPerspectiveOrigin = (
|
||||
/>
|
||||
<CssValueInputContainer
|
||||
value={origin.x}
|
||||
keywords={xOriginKeywords}
|
||||
options={xOriginKeywords}
|
||||
styleSource="local"
|
||||
property={fakePropertyX}
|
||||
deleteProperty={() => {}}
|
||||
@@ -186,7 +186,7 @@ export const TransformAndPerspectiveOrigin = (
|
||||
/>
|
||||
<CssValueInputContainer
|
||||
value={origin.y}
|
||||
keywords={yOriginKeywords}
|
||||
options={yOriginKeywords}
|
||||
styleSource="local"
|
||||
property={fakePropertyY}
|
||||
deleteProperty={() => {}}
|
||||
@@ -208,7 +208,6 @@ export const TransformAndPerspectiveOrigin = (
|
||||
/>
|
||||
<CssValueInputContainer
|
||||
value={origin.z}
|
||||
keywords={[]}
|
||||
styleSource="local"
|
||||
property={fakePropertyZ}
|
||||
deleteProperty={() => {}}
|
||||
|
||||
@@ -53,7 +53,6 @@ export const RotatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property="rotate"
|
||||
value={rotateX}
|
||||
keywords={[]}
|
||||
setValue={(value, options) =>
|
||||
updateTransformFunction(styleDecl, "rotateX", value, options)
|
||||
}
|
||||
@@ -73,7 +72,6 @@ export const RotatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property="rotate"
|
||||
value={rotateY}
|
||||
keywords={[]}
|
||||
setValue={(value, options) =>
|
||||
updateTransformFunction(styleDecl, "rotateY", value, options)
|
||||
}
|
||||
@@ -93,7 +91,6 @@ export const RotatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property="rotate"
|
||||
value={rotateZ}
|
||||
keywords={[]}
|
||||
setValue={(value, options) =>
|
||||
updateTransformFunction(styleDecl, "rotateZ", value, options)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,6 @@ export const ScalePanelContent = () => {
|
||||
<CssValueInput
|
||||
styleSource="local"
|
||||
property={property}
|
||||
keywords={[]}
|
||||
value={scaleX}
|
||||
intermediateValue={intermediateScalingX}
|
||||
onChange={(value) => {
|
||||
@@ -138,7 +137,6 @@ export const ScalePanelContent = () => {
|
||||
<CssValueInput
|
||||
styleSource="local"
|
||||
property={property}
|
||||
keywords={[]}
|
||||
value={scaleY}
|
||||
intermediateValue={intermediateScalingY}
|
||||
onChange={(value) => {
|
||||
@@ -179,7 +177,6 @@ export const ScalePanelContent = () => {
|
||||
<CssValueInput
|
||||
styleSource="local"
|
||||
property={property}
|
||||
keywords={[]}
|
||||
value={scaleZ}
|
||||
intermediateValue={intermediateScalingZ}
|
||||
onChange={(value) => {
|
||||
|
||||
@@ -50,7 +50,6 @@ export const SkewPanelContent = () => {
|
||||
styleSource="local"
|
||||
property={fakeProperty}
|
||||
value={skewX}
|
||||
keywords={[]}
|
||||
setValue={(value, options) =>
|
||||
updateTransformFunction(styleDecl, "skewX", value, options)
|
||||
}
|
||||
@@ -70,7 +69,6 @@ export const SkewPanelContent = () => {
|
||||
styleSource="local"
|
||||
property={fakeProperty}
|
||||
value={skewY}
|
||||
keywords={[]}
|
||||
setValue={(value, options) =>
|
||||
updateTransformFunction(styleDecl, "skewY", value, options)
|
||||
}
|
||||
|
||||
-3
@@ -59,7 +59,6 @@ export const TranslatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property={property}
|
||||
value={translateX}
|
||||
keywords={[]}
|
||||
setValue={(newValue, options) => setAxis(0, newValue, options)}
|
||||
deleteProperty={() => {}}
|
||||
/>
|
||||
@@ -77,7 +76,6 @@ export const TranslatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property={property}
|
||||
value={translateY}
|
||||
keywords={[]}
|
||||
setValue={(newValue, options) => setAxis(1, newValue, options)}
|
||||
deleteProperty={() => {}}
|
||||
/>
|
||||
@@ -95,7 +93,6 @@ export const TranslatePanelContent = () => {
|
||||
styleSource="local"
|
||||
property={property}
|
||||
value={translateZ}
|
||||
keywords={[]}
|
||||
setValue={(newValue, options) => setAxis(2, newValue, options)}
|
||||
deleteProperty={() => {}}
|
||||
/>
|
||||
|
||||
-2
@@ -147,7 +147,6 @@ export const TransitionContent = ({ index }: { index: number }) => {
|
||||
property={"transitionDuration"}
|
||||
styleSource="local"
|
||||
value={duration ?? properties.transitionDuration.initial}
|
||||
keywords={[]}
|
||||
deleteProperty={() => {}}
|
||||
setValue={(value, options) => {
|
||||
if (value === undefined) {
|
||||
@@ -175,7 +174,6 @@ export const TransitionContent = ({ index }: { index: number }) => {
|
||||
key={"transitionDelay"}
|
||||
styleSource="local"
|
||||
value={delay ?? properties.transitionDelay.initial}
|
||||
keywords={[]}
|
||||
deleteProperty={() => {}}
|
||||
setValue={(value, options) => {
|
||||
if (value === undefined) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import type {
|
||||
StyleValue,
|
||||
KeywordValue,
|
||||
RgbValue,
|
||||
VarValue,
|
||||
} from "@webstudio-is/css-engine";
|
||||
import {
|
||||
Popover,
|
||||
@@ -171,7 +172,7 @@ type ColorPickerProps = {
|
||||
onAbort: () => void;
|
||||
value: StyleValue;
|
||||
currentColor: StyleValue;
|
||||
keywords?: Array<KeywordValue>;
|
||||
options?: Array<KeywordValue | VarValue>;
|
||||
property: StyleProperty;
|
||||
disabled?: boolean;
|
||||
};
|
||||
@@ -239,7 +240,7 @@ export const ColorPopover = ({
|
||||
export const ColorPicker = ({
|
||||
value,
|
||||
currentColor,
|
||||
keywords,
|
||||
options,
|
||||
property,
|
||||
disabled,
|
||||
onChange,
|
||||
@@ -275,7 +276,7 @@ export const ColorPicker = ({
|
||||
property={property}
|
||||
value={value}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={keywords}
|
||||
options={options}
|
||||
onChange={(styleValue) => {
|
||||
if (styleValue === undefined) {
|
||||
setIntermediateValue(styleValue);
|
||||
@@ -289,6 +290,7 @@ export const ColorPicker = ({
|
||||
if (
|
||||
styleValue.type === "rgb" ||
|
||||
styleValue.type === "keyword" ||
|
||||
styleValue.type === "var" ||
|
||||
styleValue.type === "invalid"
|
||||
) {
|
||||
setIntermediateValue(styleValue);
|
||||
@@ -309,7 +311,11 @@ export const ColorPicker = ({
|
||||
}
|
||||
}}
|
||||
onChangeComplete={({ value }) => {
|
||||
if (value.type === "rgb" || value.type === "keyword") {
|
||||
if (
|
||||
value.type === "rgb" ||
|
||||
value.type === "keyword" ||
|
||||
value.type === "var"
|
||||
) {
|
||||
setIntermediateValue(undefined);
|
||||
onChangeComplete(value);
|
||||
return;
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@ type CssValueInputContainerProps = {
|
||||
|
||||
export const CssValueInputContainer = ({
|
||||
property,
|
||||
keywords,
|
||||
options,
|
||||
setValue,
|
||||
deleteProperty,
|
||||
...props
|
||||
@@ -31,7 +31,7 @@ export const CssValueInputContainer = ({
|
||||
{...props}
|
||||
property={property}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={keywords}
|
||||
options={options}
|
||||
onChange={(styleValue) => {
|
||||
setIntermediateValue(styleValue);
|
||||
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ export const WithKeywords = () => {
|
||||
property="width"
|
||||
value={value}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={[
|
||||
options={[
|
||||
{ type: "keyword", value: "auto" },
|
||||
{ type: "keyword", value: "min-content" },
|
||||
{ type: "keyword", value: "max-content" },
|
||||
@@ -67,7 +67,7 @@ export const WithIcons = () => {
|
||||
property="alignItems"
|
||||
value={value}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={[
|
||||
options={[
|
||||
{ type: "keyword", value: "normal" },
|
||||
{ type: "keyword", value: "start" },
|
||||
{ type: "keyword", value: "end" },
|
||||
@@ -113,7 +113,7 @@ export const WithUnits = () => {
|
||||
property="rowGap"
|
||||
value={value}
|
||||
intermediateValue={intermediateValue}
|
||||
keywords={[
|
||||
options={[
|
||||
{ type: "keyword", value: "auto" },
|
||||
{ type: "keyword", value: "min-content" },
|
||||
{ type: "keyword", value: "max-content" },
|
||||
|
||||
+9
-6
@@ -22,6 +22,7 @@ import type {
|
||||
StyleProperty,
|
||||
StyleValue,
|
||||
Unit,
|
||||
VarValue,
|
||||
} from "@webstudio-is/css-engine";
|
||||
import {
|
||||
type KeyboardEventHandler,
|
||||
@@ -310,7 +311,7 @@ type CssValueInputProps = Pick<
|
||||
/**
|
||||
* Selected item in the dropdown
|
||||
*/
|
||||
keywords?: Array<KeywordValue>;
|
||||
options?: Array<KeywordValue | VarValue>;
|
||||
onChange: (value: CssValueInputValue | undefined) => void;
|
||||
onChangeComplete: (event: ChangeCompleteEvent) => void;
|
||||
onHighlight: (value: StyleValue | undefined) => void;
|
||||
@@ -327,7 +328,7 @@ const initialValue: IntermediateStyleValue = {
|
||||
const itemToString = (item: CssValueInputValue | null) => {
|
||||
return item === null
|
||||
? ""
|
||||
: item.type === "keyword"
|
||||
: item.type === "keyword" || item.type === "var"
|
||||
? // E.g. we want currentcolor to be lower case
|
||||
toValue(item).toLocaleLowerCase()
|
||||
: item.type === "intermediate" || item.type === "unit"
|
||||
@@ -356,7 +357,7 @@ const Description = styled(Box, { width: theme.spacing[27] });
|
||||
* - Scrub interaction
|
||||
* - Click outside, unit selection or escape when list is open should unfocus the unit select trigger
|
||||
*
|
||||
* Keywords mode:
|
||||
* Options mode:
|
||||
* - When any character in the input is not a number we automatically switch to keywords mode on keydown
|
||||
* - Filterable keywords list (click on chevron or arrow down to show the list)
|
||||
* - Arrow keys are used to navigate keyword items
|
||||
@@ -375,7 +376,7 @@ export const CssValueInput = ({
|
||||
showSuffix = true,
|
||||
styleSource,
|
||||
property,
|
||||
keywords = [],
|
||||
options = [],
|
||||
onHighlight,
|
||||
onAbort,
|
||||
disabled,
|
||||
@@ -445,7 +446,7 @@ export const CssValueInput = ({
|
||||
highlightedIndex,
|
||||
} = useCombobox<CssValueInputValue>({
|
||||
// Used for description to match the item when nothing is highlighted yet and value is still in non keyword mode
|
||||
items: keywords,
|
||||
items: options,
|
||||
value,
|
||||
selectedItem: props.value,
|
||||
itemToString,
|
||||
@@ -729,7 +730,9 @@ export const CssValueInput = ({
|
||||
{...getItemProps({ item, index })}
|
||||
key={index}
|
||||
>
|
||||
{itemToString(item)}
|
||||
{item.type === "var"
|
||||
? `--${item.value}`
|
||||
: itemToString(item)}
|
||||
</ComboboxListboxItem>
|
||||
))}
|
||||
</ComboboxScrollArea>
|
||||
|
||||
@@ -213,7 +213,6 @@ export const FilterSectionContent = ({
|
||||
unit: "px",
|
||||
}
|
||||
}
|
||||
keywords={[]}
|
||||
setValue={handleFilterFunctionValueChange}
|
||||
deleteProperty={() => {}}
|
||||
/>
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
compareMedia,
|
||||
type StyleProperty,
|
||||
type StyleValue,
|
||||
type VarValue,
|
||||
} from "@webstudio-is/css-engine";
|
||||
import {
|
||||
ROOT_INSTANCE_ID,
|
||||
@@ -165,6 +166,20 @@ export const $definedStyles = computed(
|
||||
}
|
||||
);
|
||||
|
||||
export const $availableVariables = computed($definedStyles, (definedStyles) => {
|
||||
const availableVariables = new Map<string, VarValue>();
|
||||
for (const { property } of definedStyles) {
|
||||
if (property.startsWith("--")) {
|
||||
// deduplicate by property name
|
||||
availableVariables.set(property, {
|
||||
type: "var",
|
||||
value: property.slice(2),
|
||||
});
|
||||
}
|
||||
}
|
||||
return Array.from(availableVariables.values());
|
||||
});
|
||||
|
||||
const $model = computed(
|
||||
[
|
||||
$styles,
|
||||
|
||||
@@ -214,7 +214,6 @@ export const ShadowContent = ({
|
||||
// outline-offset is a fake property for validating box-shadow's offsetX.
|
||||
property="outlineOffset"
|
||||
styleSource="local"
|
||||
keywords={[]}
|
||||
value={offsetX ?? { type: "unit", value: 0, unit: "px" }}
|
||||
setValue={(value, options) =>
|
||||
handlePropertyChange({ offsetX: value }, options)
|
||||
@@ -238,7 +237,6 @@ export const ShadowContent = ({
|
||||
// outline-offset is a fake property for validating box-shadow's offsetY.
|
||||
property="outlineOffset"
|
||||
styleSource="local"
|
||||
keywords={[]}
|
||||
value={offsetY ?? { type: "unit", value: 0, unit: "px" }}
|
||||
setValue={(value, options) =>
|
||||
handlePropertyChange({ offsetY: value }, options)
|
||||
@@ -262,7 +260,6 @@ export const ShadowContent = ({
|
||||
// border-top-width is a fake property for validating box-shadow's blur.
|
||||
property="borderTopWidth"
|
||||
styleSource="local"
|
||||
keywords={[]}
|
||||
value={blur ?? { type: "unit", value: 0, unit: "px" }}
|
||||
setValue={(value, options) =>
|
||||
handlePropertyChange({ blur: value }, options)
|
||||
@@ -287,7 +284,6 @@ export const ShadowContent = ({
|
||||
// outline-offset is a fake property for validating box-shadow's spread.
|
||||
property="outlineOffset"
|
||||
styleSource="local"
|
||||
keywords={[]}
|
||||
value={spread ?? { type: "unit", value: 0, unit: "px" }}
|
||||
setValue={(value, options) =>
|
||||
handlePropertyChange({ spread: value }, options)
|
||||
@@ -320,7 +316,7 @@ export const ShadowContent = ({
|
||||
property="color"
|
||||
value={colorControlProp}
|
||||
currentColor={colorControlProp}
|
||||
keywords={styleConfigByName("color").items.map((item) => ({
|
||||
options={styleConfigByName("color").items.map((item) => ({
|
||||
type: "keyword",
|
||||
value: item.name,
|
||||
}))}
|
||||
|
||||
Reference in new issue
Block a user