Skip to content

Commit

Permalink
refactor: migrate inset control to new style engine (#4231)
Browse files Browse the repository at this point in the history
Finally got rid from the last legacy property tooltip

![Screenshot 2024-10-06 at 17 49
14](https://github.com/user-attachments/assets/0d2dbff9-b22b-46bd-8e9a-169f83fe9aa6)
  • Loading branch information
TrySound authored Oct 6, 2024
1 parent 9b81aa6 commit 98ab3e1
Show file tree
Hide file tree
Showing 9 changed files with 110 additions and 604 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,11 @@ import {
} from "../../shared/css-value-input";
import { ToggleControl } from "../../controls/toggle/toggle-control";
import { PropertyInfo, PropertyLabel } from "../../property-label";
import { useComputedStyles, useComputedStyleDecl } from "../../shared/model";
import {
useComputedStyles,
useComputedStyleDecl,
$availableVariables,
} from "../../shared/model";
import type { ComputedStyleDecl } from "~/shared/style-object-model";

const GapLinked = ({
Expand Down Expand Up @@ -152,9 +156,13 @@ const GapInput = ({
property={property}
value={styleDecl.cascadedValue}
intermediateValue={intermediateValue}
getOptions={() =>
items.map((item) => ({ type: "keyword", value: item.name }))
}
getOptions={() => [
...items.map((item) => ({
type: "keyword" as const,
value: item.name,
})),
...$availableVariables.get(),
]}
onChange={(styleValue) => {
onIntermediateChange(styleValue);
if (styleValue === undefined) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,112 +1,52 @@
import type { Meta } from "@storybook/react";
import { InsetControl } from "./inset-control";
import type {
CreateBatchUpdate,
DeleteProperty,
SetProperty,
} from "../../shared/use-style-data";
import { useState, useRef } from "react";
import type { StyleInfo } from "../../shared/style-info";
import { Box } from "@webstudio-is/design-system";

const useStyleInfo = (styleInfoInitial: StyleInfo) => {
const [styleInfo, setStyleInfo] = useState(() => styleInfoInitial);

const setProperty: SetProperty = (name) => (value, options) => {
if (options?.isEphemeral) {
return;
}

setStyleInfo((styleInfo) => ({
...styleInfo,
[name]: {
...styleInfo[name],
value: value,
local: value,
},
}));
};

const deleteProperty: DeleteProperty = (name, options) => {
if (options?.isEphemeral) {
return;
}

setStyleInfo((styleInfo) => {
const styleInfoCopy = { ...styleInfo };

styleInfoCopy[name] = structuredClone(defaultValue);

return styleInfoCopy;
});
};

const execCommands = useRef<(() => void)[]>([]);

const createBatchUpdate: CreateBatchUpdate = () => ({
deleteProperty: (property) => {
execCommands.current.push(() => {
deleteProperty(property);
});
},
setProperty: (property) => (style) => {
execCommands.current.push(() => {
setProperty(property)(style);
});
},
publish: (options) => {
if (options?.isEphemeral) {
execCommands.current = [];
return;
}

for (const command of execCommands.current) {
command();
}

execCommands.current = [];
},
});

return { styleInfo, setProperty, deleteProperty, createBatchUpdate };
};

const defaultValue = {
value: {
type: "keyword",
value: "auto",
},
} as const;

const bigValue = {
import { getStyleDeclKey, StyleDecl } from "@webstudio-is/sdk";
import { InsetControl } from "./inset-control";
import { registerContainers } from "~/shared/sync";
import {
$breakpoints,
$selectedBreakpointId,
$selectedInstanceSelector,
$styles,
$styleSources,
$styleSourceSelections,
} from "~/shared/nano-states";

const right: StyleDecl = {
breakpointId: "base",
styleSourceId: "local",
property: "right",
value: {
type: "unit",
value: 123.27,
unit: "rem",
},
};

local: {
type: "unit",
value: 123.27,
unit: "rem",
},
} as const;
registerContainers();
$breakpoints.set(new Map([["base", { id: "base", label: "" }]]));
$selectedBreakpointId.set("base");
$styleSources.set(
new Map([
[
"local",
{
id: "local",
type: "local",
},
],
])
);
$styles.set(new Map([[getStyleDeclKey(right), right]]));
$styleSourceSelections.set(
new Map([["box", { instanceId: "box", values: ["local"] }]])
);
$selectedInstanceSelector.set(["box"]);

export const InsetControlComponent = () => {
const { styleInfo, deleteProperty, createBatchUpdate } = useStyleInfo({
left: defaultValue,
right: bigValue,
top: defaultValue,
bottom: defaultValue,
});

return (
<Box css={{ marginLeft: 100 }}>
<InsetControl
createBatchUpdate={createBatchUpdate}
currentStyle={styleInfo}
deleteProperty={deleteProperty}
/>
<InsetControl />
</Box>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,60 +1,43 @@
import { Grid, theme } from "@webstudio-is/design-system";
import { useRef, useState } from "react";
import { movementMapInset, useKeyboardNavigation } from "../shared/keyboard";
import type {
CreateBatchUpdate,
DeleteProperty,
} from "../../shared/use-style-data";
import { getStyleSource, type StyleInfo } from "../../shared/style-info";
import { createBatchUpdate, deleteProperty } from "../../shared/use-style-data";
import { getInsetModifiersGroup, useScrub } from "../shared/scrub";
import { ValueText } from "../shared/value-text";
import type { StyleValue } from "@webstudio-is/css-engine";
import { InputPopover } from "../shared/input-popover";
import { InsetLayout, type InsetProperty } from "./inset-layout";
import { InsetTooltip } from "./inset-tooltip";
import { useComputedStyleDecl, useComputedStyles } from "../../shared/model";

const Cell = ({
scrubStatus,
currentStyle,
property,
onHover,
isPopoverOpen,
onPopoverClose,
createBatchUpdate,
}: {
isPopoverOpen: boolean;
onPopoverClose: () => void;
scrubStatus: ReturnType<typeof useScrub>;
currentStyle: StyleInfo;
property: InsetProperty;
onHover: (target: HoverTarget | undefined) => void;
createBatchUpdate: CreateBatchUpdate;
}) => {
const styleInfo = currentStyle[property];
const finalValue: StyleValue | undefined = scrubStatus.isActive
? (scrubStatus.values[property] ?? styleInfo?.value)
: styleInfo?.value;
const styleSource = getStyleSource(styleInfo);

if (finalValue === undefined) {
return null;
}
const styleDecl = useComputedStyleDecl(property);
const finalValue: StyleValue | undefined =
(scrubStatus.isActive && scrubStatus.values[property]) ||
styleDecl.cascadedValue;

return (
<>
<InputPopover
styleSource={styleSource}
styleSource={styleDecl.source.name}
value={finalValue}
isOpen={isPopoverOpen}
property={property}
onClose={onPopoverClose}
/>
<InsetTooltip
property={property}
style={currentStyle}
createBatchUpdate={createBatchUpdate}
preventOpen={scrubStatus.isActive}
>
<InsetTooltip property={property} preventOpen={scrubStatus.isActive}>
<ValueText
css={{
// We want value to have `default` cursor to indicate that it's clickable,
Expand All @@ -66,7 +49,7 @@ const Cell = ({
pointerEvents: "all",
}}
value={finalValue}
source={styleSource}
source={styleDecl.source.name}
onMouseEnter={(event) =>
onHover({ property, element: event.currentTarget })
}
Expand All @@ -82,24 +65,14 @@ type HoverTarget = {
property: InsetProperty;
};

type InsetControlProps = {
deleteProperty: DeleteProperty;
createBatchUpdate: CreateBatchUpdate;
currentStyle: StyleInfo;
};

export const InsetControl = ({
createBatchUpdate,
currentStyle,
deleteProperty,
}: InsetControlProps) => {
export const InsetControl = () => {
const styles = useComputedStyles(["top", "right", "bottom", "left"]);
const [hoverTarget, setHoverTarget] = useState<HoverTarget>();

const scrubStatus = useScrub({
value:
hoverTarget === undefined
? undefined
: currentStyle[hoverTarget.property]?.value,
value: styles.find(
(styleDecl) => styleDecl.property === hoverTarget?.property
)?.usedValue,
target: hoverTarget,
getModifiersGroup: getInsetModifiersGroup,
onChange: (values, options) => {
Expand Down Expand Up @@ -176,7 +149,6 @@ export const InsetControl = ({
renderCell={(property) => (
<Cell
scrubStatus={scrubStatus}
currentStyle={currentStyle}
property={property}
onHover={handleHover}
isPopoverOpen={openProperty === property}
Expand All @@ -186,7 +158,6 @@ export const InsetControl = ({
layoutRef.current?.focus();
}
}}
createBatchUpdate={createBatchUpdate}
/>
)}
onHover={handleHover}
Expand Down
Loading

0 comments on commit 98ab3e1

Please sign in to comment.