mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-03 10:37:48 +09:00
feat: Disable scrub on non-numeric values (#5502)
ref #5501 ## Description - [x] disable scrub if value is not a number on a css value input, originally the idea was that if you scrub ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 0000) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
This commit is contained in:
1 parent
f1d04acbf3
commit
b18315e570
2 files changed
+45
-14
No files matched your search
@@ -32,6 +32,14 @@ type HoverTarget<P> = {
|
||||
element: HTMLElement | SVGElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Scrub hook for visual spacing diagram (box model UI)
|
||||
* - Works on any HTML/SVG element via hover target
|
||||
* - Supports multi-property editing with modifier keys (Shift/Alt)
|
||||
* - Has direction awareness (horizontal/vertical based on property)
|
||||
* - Returns status object with isActive, properties, and values
|
||||
* - Used in space.tsx for drag-to-adjust on the visual box model
|
||||
*/
|
||||
export const useScrub = <P extends CssProperty>(props: {
|
||||
value?: StyleValue;
|
||||
target: HoverTarget<P> | undefined;
|
||||
@@ -68,6 +76,19 @@ export const useScrub = <P extends CssProperty>(props: {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't activate scrub for keyword values
|
||||
if (props.value?.type === "keyword") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't activate scrub for non-numeric intermediate values
|
||||
const numericValue = Number.parseFloat(
|
||||
finalTarget.element.textContent ?? ""
|
||||
);
|
||||
if (Number.isNaN(numericValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const property = finalTarget.property;
|
||||
|
||||
const handleChange = (event: { value: number }, isEphemeral: boolean) => {
|
||||
@@ -144,7 +165,7 @@ export const useScrub = <P extends CssProperty>(props: {
|
||||
);
|
||||
},
|
||||
});
|
||||
}, [finalTarget]);
|
||||
}, [finalTarget, props.value?.type]);
|
||||
|
||||
return {
|
||||
isActive: activeTarget !== undefined,
|
||||
|
||||
+23
-13
@@ -45,7 +45,6 @@ import {
|
||||
camelCaseProperty,
|
||||
declarationDescriptions,
|
||||
isValidDeclaration,
|
||||
propertiesData,
|
||||
} from "@webstudio-is/css-data";
|
||||
import { $selectedInstanceSizes } from "~/shared/nano-states";
|
||||
import { convertUnits } from "./convert-units";
|
||||
@@ -60,13 +59,6 @@ import {
|
||||
import { useEffectEvent } from "~/shared/hook-utils/effect-event";
|
||||
import { scrollByPointer } from "../scroll-by-pointer";
|
||||
|
||||
// We need to enable scrub on properties that can have numeric value.
|
||||
const canBeNumber = (property: CssProperty, value: CssValueInputValue) => {
|
||||
const unitGroups = propertiesData[property]?.unitGroups ?? [];
|
||||
// allow scrubbing css variables with unit value
|
||||
return unitGroups.length !== 0 || value.type === "unit";
|
||||
};
|
||||
|
||||
// Subjective adjust ment based on how it feels on macbook/trackpad.
|
||||
// It won't be ideal for everyone with different input devices and preferences.
|
||||
// Ideally we also need some kind of acceleration setting with 1 value.
|
||||
@@ -79,6 +71,15 @@ const scrubUnitAcceleration = new Map<Unit, number>([
|
||||
["number", 1 / 20],
|
||||
]);
|
||||
|
||||
/**
|
||||
* Scrub hook for numeric input fields
|
||||
* - Works specifically on <input> elements (returns refs to attach)
|
||||
* - Handles single property at a time
|
||||
* - Manages intermediate values during typing
|
||||
* - Has abort functionality (ESC key restores original)
|
||||
* - Integrates with input focus/blur/selection behavior
|
||||
* - Custom shouldHandleEvent for preventing scrub on vars/unit selects
|
||||
*/
|
||||
const useScrub = ({
|
||||
value,
|
||||
intermediateValue,
|
||||
@@ -130,14 +131,23 @@ const useScrub = ({
|
||||
const scrubRefCurrent = scrubRef.current;
|
||||
|
||||
// Support only auto keyword to be scrubbable
|
||||
if (
|
||||
inputRefCurrent === null ||
|
||||
scrubRefCurrent === null ||
|
||||
canBeNumber(property, valueRef.current) === false
|
||||
) {
|
||||
if (inputRefCurrent === null || scrubRefCurrent === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't activate scrub for keyword values
|
||||
if (valueRef.current.type === "keyword") {
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't activate scrub for non-numeric intermediate values
|
||||
if (valueRef.current.type === "intermediate") {
|
||||
const numericValue = Number.parseFloat(valueRef.current.value);
|
||||
if (Number.isNaN(numericValue)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let unit: Unit = defaultUnit ?? "number";
|
||||
|
||||
const validateValue = (numericValue: number) => {
|
||||
|
||||
Reference in new issue
Block a user