diff --git a/app/packages/core/src/plugins/SchemaIO/components/AutocompleteView.tsx b/app/packages/core/src/plugins/SchemaIO/components/AutocompleteView.tsx index 4abf36779e..8a1f749a9a 100644 --- a/app/packages/core/src/plugins/SchemaIO/components/AutocompleteView.tsx +++ b/app/packages/core/src/plugins/SchemaIO/components/AutocompleteView.tsx @@ -4,6 +4,7 @@ import FieldWrapper from "./FieldWrapper"; import autoFocus from "../utils/auto-focus"; import { getComponentProps } from "../utils"; import ChoiceMenuItemBody from "./ChoiceMenuItemBody"; +import { useKey } from "../hooks"; export default function AutocompleteView(props) { const { onChange, path, schema, data } = props; @@ -11,17 +12,22 @@ export default function AutocompleteView(props) { const { choices = [], readOnly } = view; const multiple = schema.type === "array"; + const [key, setUserChanged] = useKey(path, schema, data, true); return ( onChange(path, choice?.value || choice)} + onChange={(e, choice) => { + onChange(path, choice?.value || choice); + setUserChanged(); + }} options={choices.map((choice) => ({ id: choice.value, label: choice.label || choice.value, diff --git a/app/packages/core/src/plugins/SchemaIO/components/CheckboxView.tsx b/app/packages/core/src/plugins/SchemaIO/components/CheckboxView.tsx index 7f05412e8b..94acb000cd 100644 --- a/app/packages/core/src/plugins/SchemaIO/components/CheckboxView.tsx +++ b/app/packages/core/src/plugins/SchemaIO/components/CheckboxView.tsx @@ -3,18 +3,24 @@ import React from "react"; import HeaderView from "./HeaderView"; import autoFocus from "../utils/auto-focus"; import { getComponentProps } from "../utils"; +import { useKey } from "../hooks"; export default function CheckboxView(props) { const { onChange, path, schema, data } = props; + const [key, setUserChanged] = useKey(path, schema, data, true); return ( onChange(path, value)} + defaultChecked={data === true} + onChange={(e, value) => { + onChange(path, value); + setUserChanged(); + }} {...getComponentProps(props, "checkbox")} /> } diff --git a/app/packages/core/src/plugins/SchemaIO/components/CodeView.tsx b/app/packages/core/src/plugins/SchemaIO/components/CodeView.tsx index 35656c0829..ec06669392 100644 --- a/app/packages/core/src/plugins/SchemaIO/components/CodeView.tsx +++ b/app/packages/core/src/plugins/SchemaIO/components/CodeView.tsx @@ -4,13 +4,14 @@ import React from "react"; import HeaderView from "./HeaderView"; import autoFocus from "../utils/auto-focus"; import { getComponentProps } from "../utils"; +import { useKey } from "../hooks"; export default function CodeView(props) { const { mode } = useColorScheme(); const { onChange, path, schema, data } = props; - const { default: defaultValue, view = {} } = schema; + const { view = {} } = schema; const { language, readOnly } = view; - const src = data ?? defaultValue; + const src = data; let height = view.height ?? 250; if (view.height === "auto") { const lineHeight = 19; @@ -18,6 +19,8 @@ export default function CodeView(props) { height = lineHeight * numLines; } + const [key, setUserChanged] = useKey(path, schema, data, true); + return ( onChange(path, value)} + onChange={(value) => { + onChange(path, value); + setUserChanged(); + }} language={language} options={{ readOnly }} onMount={(editor) => { diff --git a/app/packages/core/src/plugins/SchemaIO/components/ColorView.tsx b/app/packages/core/src/plugins/SchemaIO/components/ColorView.tsx index c790cfe9be..d5478caab3 100644 --- a/app/packages/core/src/plugins/SchemaIO/components/ColorView.tsx +++ b/app/packages/core/src/plugins/SchemaIO/components/ColorView.tsx @@ -1,25 +1,36 @@ import { Box, Popper, Stack, TextField } from "@mui/material"; -import React, { useEffect, useState } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import * as ColorPickers from "react-color"; import { colorPicker } from "./ColorView.module.css"; import HeaderView from "./HeaderView"; import autoFocus from "../utils/auto-focus"; import { getComponentProps } from "../utils"; +import { useKey } from "../hooks"; export default function ColorView(props) { const { onChange, path, schema, data } = props; const { view = {} } = schema; const { compact, variant, readOnly } = view; const [open, setOpen] = useState(false); - const [color, setColor] = useState(data ?? defaultColor); + const [color, setColor] = useState(data ?? fallbackColor); const [anchor, setAnchor] = React.useState(null); const Component = ColorPickers[variant] || ColorPickers.ChromePicker; const { bgColor, hexColor } = formatColor(color); + const [key, setUserChanged] = useKey(path, schema, data, true); + + const handleChange = useCallback( + (color) => { + setColor(color); + onChange(path, color); + setUserChanged(); + }, + [onChange, path, setUserChanged] + ); useEffect(() => { - onChange(path, color); - }, [color]); + setColor(data ?? fallbackColor); + }, [key]); return ( @@ -47,11 +58,12 @@ export default function ColorView(props) { /> {!compact && ( { - setColor({ hex: e.target.value }); + handleChange({ hex: e.target.value }); }} disabled={readOnly} {...getComponentProps(props, "field")} @@ -62,13 +74,12 @@ export default function ColorView(props) { open={open} anchorEl={anchor} placement="bottom-start" + sx={{ zIndex: (theme) => theme.zIndex.modal + 1 }} {...getComponentProps(props, "popper")} > { - setColor(color); - }} + onChange={handleChange} className={colorPicker} {...getComponentProps(props, "picker")} /> @@ -77,19 +88,17 @@ export default function ColorView(props) { ); } -function formatColor(color) { +function formatColor(color: ColorType) { const { hsl = {}, hex } = color; const { h, s, l, a } = hsl; - const bgColor = color.hsl - ? `hsla(${h},${s * 100}%,${l * 100}%,${a})` - : color.hex; + const bgColor = hsl ? `hsla(${h},${s * 100}%,${l * 100}%,${a})` : color.hex; const hexColor = (hex.startsWith("#") ? hex : `#${hex}`).toLowerCase(); return { ...color, bgColor, hexColor }; } -const defaultColor: defaultColorType = { hex: "#FF6D05" }; +const fallbackColor: ColorType = { hex: "#FF6D05" }; -type defaultColorType = { +type ColorType = { hex: string; hsl?: { h: number; diff --git a/app/packages/core/src/plugins/SchemaIO/components/DropdownView.tsx b/app/packages/core/src/plugins/SchemaIO/components/DropdownView.tsx index f6798e9482..426503283a 100644 --- a/app/packages/core/src/plugins/SchemaIO/components/DropdownView.tsx +++ b/app/packages/core/src/plugins/SchemaIO/components/DropdownView.tsx @@ -5,12 +5,13 @@ import autoFocus from "../utils/auto-focus"; import AlertView from "./AlertView"; import FieldWrapper from "./FieldWrapper"; import ChoiceMenuItemBody from "./ChoiceMenuItemBody"; +import { useKey } from "../hooks"; const MULTI_SELECT_TYPES = ["string", "array"]; export default function DropdownView(props) { const { onChange, schema, path, data } = props; - const { default: defaultValue, view = {}, type } = schema; + const { view = {}, type } = schema; const { choices, multiple: multiSelect, @@ -18,6 +19,7 @@ export default function DropdownView(props) { separator = ",", readOnly, } = view; + const [key, setUserChanged] = useKey(path, schema, data, true); if (multiSelect && !MULTI_SELECT_TYPES.includes(type)) return ( @@ -37,7 +39,7 @@ export default function DropdownView(props) { const isArrayType = type === "array"; const multiple = multiSelect || isArrayType; const fallbackDefaultValue = multiple ? [] : ""; - const rawDefaultValue = data ?? defaultValue ?? fallbackDefaultValue; + const rawDefaultValue = data ?? fallbackDefaultValue; const computedDefaultValue = multiple && !Array.isArray(rawDefaultValue) ? rawDefaultValue.toString().split(separator) @@ -51,6 +53,7 @@ export default function DropdownView(props) { return (