diff --git a/code/CHANGELOG.md b/code/CHANGELOG.md index ace503d2a..5bcbd8e6b 100644 --- a/code/CHANGELOG.md +++ b/code/CHANGELOG.md @@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changes + +- [#287](https://github.com/InditexTech/weavejs/issues/287) Update create-app frontend + ## [0.16.2] - 2025-05-26 ### Fixed @@ -314,73 +318,38 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#18](https://github.com/InditexTech/weavejs/issues/18) Fix awareness not working on store-azure-web-pubsub [Unreleased]: https://github.com/InditexTech/weavejs/compare/0.16.2...HEAD - [0.16.2]: https://github.com/InditexTech/weavejs/compare/0.16.1...0.16.2 - [0.16.1]: https://github.com/InditexTech/weavejs/compare/0.16.0...0.16.1 - [0.16.0]: https://github.com/InditexTech/weavejs/compare/0.15.0...0.16.0 - [0.15.0]: https://github.com/InditexTech/weavejs/compare/0.14.3...0.15.0 - [0.14.3]: https://github.com/InditexTech/weavejs/compare/0.14.2...0.14.3 - [0.14.2]: https://github.com/InditexTech/weavejs/compare/0.14.1...0.14.2 - [0.14.1]: https://github.com/InditexTech/weavejs/compare/0.14.0...0.14.1 - [0.14.0]: https://github.com/InditexTech/weavejs/compare/0.13.1...0.14.0 - [0.13.1]: https://github.com/InditexTech/weavejs/compare/0.13.0...0.13.1 - [0.13.0]: https://github.com/InditexTech/weavejs/compare/0.12.1...0.13.0 - [0.12.1]: https://github.com/InditexTech/weavejs/compare/0.12.0...0.12.1 - [0.12.0]: https://github.com/InditexTech/weavejs/compare/0.11.0...0.12.0 - [0.11.0]: https://github.com/InditexTech/weavejs/compare/0.10.3...0.11.0 - [0.10.3]: https://github.com/InditexTech/weavejs/compare/0.10.2...0.10.3 - [0.10.2]: https://github.com/InditexTech/weavejs/compare/0.10.1...0.10.2 - [0.10.1]: https://github.com/InditexTech/weavejs/compare/0.10.0...0.10.1 - [0.10.0]: https://github.com/InditexTech/weavejs/compare/0.9.3...0.10.0 - [0.9.3]: https://github.com/InditexTech/weavejs/compare/0.9.2...0.9.3 - [0.9.2]: https://github.com/InditexTech/weavejs/compare/0.9.1...0.9.2 - [0.9.1]: https://github.com/InditexTech/weavejs/compare/0.9.0...0.9.1 - [0.9.0]: https://github.com/InditexTech/weavejs/compare/0.8.0...0.9.0 - [0.8.0]: https://github.com/InditexTech/weavejs/compare/0.7.1...0.8.0 - [0.7.1]: https://github.com/InditexTech/weavejs/compare/0.7.0...0.7.1 - [0.7.0]: https://github.com/InditexTech/weavejs/compare/0.6.0...0.7.0 - [0.6.0]: https://github.com/InditexTech/weavejs/compare/0.5.0...0.6.0 - [0.5.0]: https://github.com/InditexTech/weavejs/compare/0.4.0...0.5.0 - [0.4.0]: https://github.com/InditexTech/weavejs/compare/0.3.3...0.4.0 - [0.3.3]: https://github.com/InditexTech/weavejs/compare/0.3.2...0.3.3 - [0.3.2]: https://github.com/InditexTech/weavejs/compare/0.3.1...0.3.2 - [0.3.1]: https://github.com/InditexTech/weavejs/compare/0.3.0...0.3.1 - [0.3.0]: https://github.com/InditexTech/weavejs/compare/0.2.1...0.3.0 - [0.2.1]: https://github.com/InditexTech/weavejs/compare/0.2.0...0.2.1 - [0.2.0]: https://github.com/InditexTech/weavejs/compare/0.1.1...0.2.0 - [0.1.1]: https://github.com/InditexTech/weavejs/compare/0.1.0...0.1.1 - [0.1.0]: https://github.com/InditexTech/weavejs/releases/tag/0.1.0 diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-color.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-color.tsx index df6d603f5..c591179f3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-color.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-color.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { Input } from '@/components/ui/input'; import { ColorPicker, @@ -28,15 +28,36 @@ export const InputColor = ({ value, onChange, }: Readonly) => { - const [actualValue, setActualValue] = useState(value); + const editingRef = React.useRef(null); + const [enterPressed, setEnterPressed] = React.useState(false); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState(value); - useEffect(() => { - setActualValue(value); - }, [value]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + setEnterPressed(true); + } + }, + [] + ); + + const handleOnChange = React.useCallback( + (e: React.ChangeEvent) => { + setEditedValue(e.target.value); + }, + [] + ); - const handleInputChange = (e: React.ChangeEvent) => { - setActualValue(e.target.value); - }; + React.useEffect(() => { + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -49,8 +70,8 @@ export const InputColor = ({
{ - setActualValue(color as string); onChange(color as string); }} onFocus={() => { @@ -71,7 +91,6 @@ export const InputColor = ({ }} onBlurCapture={() => { window.weaveOnFieldFocus = false; - onChange(actualValue); }} > @@ -89,28 +108,39 @@ export const InputColor = ({ - - { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - onChange(actualValue); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - /> + {!editing && ( + ) => { + if (enterPressed) { + onChange?.(e.target.value); + setEnterPressed(false); + } + }} + onFocus={() => { + setEditing(true); + setEditedValue(value ?? '#000000ff'); + window.weaveOnFieldFocus = true; + }} + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + onChange(editedValue); + }} + onKeyDown={handleKeyDown} + /> + )}
); diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-font-family.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-font-family.tsx index 6829c9f34..5042c9e9f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-font-family.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-font-family.tsx @@ -14,7 +14,7 @@ import { import { Check, ChevronDown } from 'lucide-react'; import { Button } from '@/components/ui/button'; -import { useEffect, useRef, useState } from 'react'; +import React from 'react'; import { FONTS } from '@/components/utils/constants'; function InputFontFamily({ @@ -24,11 +24,11 @@ function InputFontFamily({ value: string; onChange: (value: string) => void; }) { - const [selectedFont, setSelectedFont] = useState(value); - const [open, setOpen] = useState(false); - const lastSelectedFontFamily = useRef(value); + const [selectedFont, setSelectedFont] = React.useState(value); + const [open, setOpen] = React.useState(false); + const lastSelectedFontFamily = React.useRef(value); - useEffect(() => { + React.useEffect(() => { if (onChange && selectedFont !== lastSelectedFontFamily.current) { lastSelectedFontFamily.current = selectedFont; onChange(selectedFont); diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-number.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-number.tsx index e3cb2577c..4b7b3f902 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-number.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-number.tsx @@ -20,20 +20,24 @@ export const InputNumber = ({ min = -Infinity, max = Infinity, }: Readonly) => { - const [actualValue, setActualValue] = React.useState(`${value}`); - - React.useEffect(() => { - setActualValue(`${value}`); - }, [value]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + } + }, + [] + ); - const handleBlur = () => { - let numberToSave = actualValue === '' ? '0' : actualValue; - numberToSave = numberToSave.replace(/^0+/, ''); - if (isNaN(parseFloat(numberToSave))) { - numberToSave = '0'; - } - onChange?.(parseFloat(actualValue)); - }; + const handleOnValueChange = React.useCallback( + (numberValue: number | undefined) => { + onChange?.(numberValue ?? 0); + }, + [onChange] + ); return ( { - setActualValue(e.target.value); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - onBlur={handleBlur} + value={Number(value)} + onValueChange={handleOnValueChange} + onKeyDown={handleKeyDown} /> ); }; diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-text.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-text.tsx index daad23ab5..2f8592f46 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-text.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/input-text.tsx @@ -14,11 +14,36 @@ export const InputText = ({ value, onChange, }: Readonly) => { - const [actualValue, setActualValue] = React.useState(`${value}`); + const editingRef = React.useRef(null); + const [enterPressed, setEnterPressed] = React.useState(false); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState(value); + + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + setEnterPressed(true); + } + }, + [] + ); + + const handleOnChange = React.useCallback( + (e: React.ChangeEvent) => { + setEditedValue(e.target.value); + }, + [] + ); React.useEffect(() => { - setActualValue(`${value}`); - }, [value]); + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -27,29 +52,39 @@ export const InputText = ({ {label}
)} - { - setActualValue(e.target.value); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - onFocus={() => { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - onChange(actualValue); - }} - /> + {!editing && ( + { + if (enterPressed) { + onChange(e.target.value); + setEnterPressed(false); + } + }} + onFocus={() => { + setEditing(true); + setEditedValue(value); + window.weaveOnFieldFocus = true; + }} + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + onChange(editedValue); + }} + /> + )} ); }; diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/number-input.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/number-input.tsx index 0e5f9d824..e4cd884a6 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/number-input.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/inputs/number-input.tsx @@ -31,46 +31,52 @@ export const NumberInput = React.forwardRef( onValueChange, fixedDecimalScale = false, decimalScale = 0, - value: controlledValue, + value, ...props }, ref ) => { - const [value, setValue] = React.useState( - controlledValue ?? defaultValue + const editingRef = React.useRef(null); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState( + defaultValue ); - React.useEffect(() => { - if (controlledValue !== undefined) { - setValue(controlledValue); - } - }, [controlledValue]); + const handleChange = React.useCallback( + (values: { value: string; floatValue: number | undefined }) => { + const newValue = + values.floatValue === undefined ? undefined : values.floatValue; - const handleChange = (values: { - value: string; - floatValue: number | undefined; - }) => { - const newValue = - values.floatValue === undefined ? undefined : values.floatValue; - setValue(newValue); - if (onValueChange) { - onValueChange(newValue); - } - }; + setEditedValue(newValue); + }, + [] + ); - const handleBlur = () => { - if (value !== undefined) { - if (value < min) { - setValue(min); + const handleBlur = React.useCallback(() => { + onValueChange?.(editedValue); + + if (editedValue !== undefined) { + if (editedValue < min) { + if (onValueChange) { + onValueChange(min); + } (ref as React.RefObject).current!.value = String(min); - } else if (value > max) { - setValue(max); + } else if (editedValue > max) { + if (onValueChange) { + onValueChange(max); + } (ref as React.RefObject).current!.value = String(max); } } - }; + }, [editedValue, onValueChange, min, max, ref]); + + React.useEffect(() => { + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -80,29 +86,52 @@ export const NumberInput = React.forwardRef(
)}
- { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - handleBlur(); - }} - max={max} - min={min} - customInput={Input} - placeholder={placeholder} - getInputRef={ref} - {...props} - className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" - /> + {!editing && ( + { + setEditing(true); + setEditedValue(value); + window.weaveOnFieldFocus = true; + }} + max={max} + min={min} + customInput={Input} + placeholder={placeholder} + getInputRef={ref} + {...props} + className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + handleBlur(); + }} + max={max} + min={min} + customInput={Input} + placeholder={placeholder} + getInputRef={editingRef} + {...props} + className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" + /> + )}
); diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/appearance-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/appearance-properties.tsx index 9b8f10f40..6ae35c825 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/appearance-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/appearance-properties.tsx @@ -20,28 +20,21 @@ export function AppearanceProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/color-token-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/color-token-properties.tsx index cb570253a..87a9f4d8d 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/color-token-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/color-token-properties.tsx @@ -1,10 +1,10 @@ -"use client"; +'use client'; -import React from "react"; -import { WeaveStateElement } from "@inditextech/weave-types"; -import { useWeave } from "@inditextech/weave-react"; -import { useCollaborationRoom } from "@/store/store"; -import { InputColor } from "../inputs/input-color"; +import React from 'react'; +import { WeaveStateElement } from '@inditextech/weave-types'; +import { useWeave } from '@inditextech/weave-react'; +import { useCollaborationRoom } from '@/store/store'; +import { InputColor } from '../inputs/input-color'; export function ColorTokenProperties() { const instance = useWeave((state) => state.instance); @@ -19,36 +19,29 @@ export function ColorTokenProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; - if (actualAction && nodePropertiesAction === "create") { - setActualNode({ - key: "creating", - type: "undefined", + const actualNode = React.useMemo(() => { + if (actualAction && nodePropertiesAction === 'create') { + return { + key: 'creating', + type: 'undefined', props: { ...nodeCreateProps, }, - }); - } - if (node && nodePropertiesAction === "update") { - setActualNode(node); + }; } - if (!actualAction && !node) { - setActualNode(undefined); + if (node && nodePropertiesAction === 'update') { + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { if (!instance) return; - if (actualAction && nodePropertiesAction === "create") { + if (actualAction && nodePropertiesAction === 'create') { instance.updatePropsAction(actualAction, updatedNode.props); } - if (nodePropertiesAction === "update") { + if (nodePropertiesAction === 'update') { instance.updateNode(updatedNode); } }, @@ -61,15 +54,15 @@ export function ColorTokenProperties() { if ( actualAction && - ["selectionTool"].includes(actualAction) && - !["color-token"].includes(actualNode.type) + ['selectionTool'].includes(actualAction) && + !['color-token'].includes(actualNode.type) ) { return null; } if ( actualAction && - !["selectionTool", "colorTokenTool"].includes(actualAction) + !['selectionTool', 'colorTokenTool'].includes(actualAction) ) return null; diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/crop-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/crop-properties.tsx index a7ec2155d..229f4215f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/crop-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/crop-properties.tsx @@ -11,26 +11,17 @@ import { InputNumber } from '../inputs/input-number'; export function CropProperties() { const instance = useWeave((state) => state.instance); const node = useWeave((state) => state.selection.node); - const actualAction = useWeave((state) => state.actions.actual); const nodePropertiesAction = useCollaborationRoom( (state) => state.nodeProperties.action ); - const nodeCreateProps = useCollaborationRoom( - (state) => state.nodeProperties.createProps - ); - - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (node && nodePropertiesAction === 'update') { - setActualNode(node); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [node, nodePropertiesAction]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/fill-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/fill-properties.tsx index 8ed4f3cb1..409a10cb4 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/fill-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/fill-properties.tsx @@ -21,28 +21,21 @@ export function FillProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/frame-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/frame-properties.tsx index 7daaff6c0..2461ab022 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/frame-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/frame-properties.tsx @@ -27,28 +27,21 @@ export function FrameProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/image-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/image-properties.tsx index fe5c9b5c0..4edb31ba3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/image-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/image-properties.tsx @@ -1,7 +1,6 @@ 'use client'; import React from 'react'; -import { WeaveStateElement } from '@inditextech/weave-types'; import { useWeave } from '@inditextech/weave-react'; import { useCollaborationRoom } from '@/store/store'; import { InputNumber } from '../inputs/input-number'; @@ -9,26 +8,17 @@ import { InputNumber } from '../inputs/input-number'; export function ImageProperties() { const instance = useWeave((state) => state.instance); const node = useWeave((state) => state.selection.node); - const actualAction = useWeave((state) => state.actions.actual); const nodePropertiesAction = useCollaborationRoom( (state) => state.nodeProperties.action ); - const nodeCreateProps = useCollaborationRoom( - (state) => state.nodeProperties.createProps - ); - - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (node && nodePropertiesAction === 'update') { - setActualNode(node); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [node, nodePropertiesAction]); if (!instance || !actualNode) return null; diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/meta-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/meta-properties.tsx index 0a7af201e..015847c5f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/meta-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/meta-properties.tsx @@ -19,28 +19,21 @@ export function MetaProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/size-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/size-properties.tsx index 2739a75b4..67f43a1e5 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/size-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/size-properties.tsx @@ -19,28 +19,21 @@ export function SizeProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/stroke-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/stroke-properties.tsx index 6cce2bb97..4de0877d3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/stroke-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/stroke-properties.tsx @@ -31,28 +31,21 @@ export function StrokeProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/text-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/text-properties.tsx index 2615a56cc..99c78454d 100644 --- a/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/text-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+azure-web-pubsub/components/room-components/node-properties/text-properties.tsx @@ -37,28 +37,21 @@ export function TextProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodeCreateProps, nodePropertiesAction]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { @@ -267,7 +260,10 @@ export function TextProperties() { } - pressed={actualNode.props.fontVariant === 'normal'} + pressed={ + !actualNode.props.fontVariant || + actualNode.props.fontVariant === 'normal' + } onClick={() => { const updatedNode: WeaveStateElement = { ...actualNode, diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-color.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-color.tsx index df6d603f5..c591179f3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-color.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-color.tsx @@ -1,6 +1,6 @@ 'use client'; -import React, { useState, useEffect } from 'react'; +import React from 'react'; import { Input } from '@/components/ui/input'; import { ColorPicker, @@ -28,15 +28,36 @@ export const InputColor = ({ value, onChange, }: Readonly) => { - const [actualValue, setActualValue] = useState(value); + const editingRef = React.useRef(null); + const [enterPressed, setEnterPressed] = React.useState(false); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState(value); - useEffect(() => { - setActualValue(value); - }, [value]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + setEnterPressed(true); + } + }, + [] + ); + + const handleOnChange = React.useCallback( + (e: React.ChangeEvent) => { + setEditedValue(e.target.value); + }, + [] + ); - const handleInputChange = (e: React.ChangeEvent) => { - setActualValue(e.target.value); - }; + React.useEffect(() => { + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -49,8 +70,8 @@ export const InputColor = ({
{ - setActualValue(color as string); onChange(color as string); }} onFocus={() => { @@ -71,7 +91,6 @@ export const InputColor = ({ }} onBlurCapture={() => { window.weaveOnFieldFocus = false; - onChange(actualValue); }} > @@ -89,28 +108,39 @@ export const InputColor = ({ - - { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - onChange(actualValue); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - /> + {!editing && ( + ) => { + if (enterPressed) { + onChange?.(e.target.value); + setEnterPressed(false); + } + }} + onFocus={() => { + setEditing(true); + setEditedValue(value ?? '#000000ff'); + window.weaveOnFieldFocus = true; + }} + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + onChange(editedValue); + }} + onKeyDown={handleKeyDown} + /> + )}
); diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-font-family.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-font-family.tsx index 6829c9f34..5042c9e9f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-font-family.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-font-family.tsx @@ -14,7 +14,7 @@ import { import { Check, ChevronDown } from 'lucide-react'; import { Button } from '@/components/ui/button'; -import { useEffect, useRef, useState } from 'react'; +import React from 'react'; import { FONTS } from '@/components/utils/constants'; function InputFontFamily({ @@ -24,11 +24,11 @@ function InputFontFamily({ value: string; onChange: (value: string) => void; }) { - const [selectedFont, setSelectedFont] = useState(value); - const [open, setOpen] = useState(false); - const lastSelectedFontFamily = useRef(value); + const [selectedFont, setSelectedFont] = React.useState(value); + const [open, setOpen] = React.useState(false); + const lastSelectedFontFamily = React.useRef(value); - useEffect(() => { + React.useEffect(() => { if (onChange && selectedFont !== lastSelectedFontFamily.current) { lastSelectedFontFamily.current = selectedFont; onChange(selectedFont); diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-number.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-number.tsx index e3cb2577c..4b7b3f902 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-number.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-number.tsx @@ -20,20 +20,24 @@ export const InputNumber = ({ min = -Infinity, max = Infinity, }: Readonly) => { - const [actualValue, setActualValue] = React.useState(`${value}`); - - React.useEffect(() => { - setActualValue(`${value}`); - }, [value]); + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + } + }, + [] + ); - const handleBlur = () => { - let numberToSave = actualValue === '' ? '0' : actualValue; - numberToSave = numberToSave.replace(/^0+/, ''); - if (isNaN(parseFloat(numberToSave))) { - numberToSave = '0'; - } - onChange?.(parseFloat(actualValue)); - }; + const handleOnValueChange = React.useCallback( + (numberValue: number | undefined) => { + onChange?.(numberValue ?? 0); + }, + [onChange] + ); return ( { - setActualValue(e.target.value); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - onBlur={handleBlur} + value={Number(value)} + onValueChange={handleOnValueChange} + onKeyDown={handleKeyDown} /> ); }; diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-text.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-text.tsx index daad23ab5..2f8592f46 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-text.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/input-text.tsx @@ -14,11 +14,36 @@ export const InputText = ({ value, onChange, }: Readonly) => { - const [actualValue, setActualValue] = React.useState(`${value}`); + const editingRef = React.useRef(null); + const [enterPressed, setEnterPressed] = React.useState(false); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState(value); + + const handleKeyDown = React.useCallback( + (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + e.preventDefault(); + e.stopPropagation(); + const input = e.target as HTMLInputElement; + input.blur(); + setEnterPressed(true); + } + }, + [] + ); + + const handleOnChange = React.useCallback( + (e: React.ChangeEvent) => { + setEditedValue(e.target.value); + }, + [] + ); React.useEffect(() => { - setActualValue(`${value}`); - }, [value]); + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -27,29 +52,39 @@ export const InputText = ({ {label}
)} - { - setActualValue(e.target.value); - }} - onKeyDown={(e) => { - if (e.key === 'Enter') { - e.preventDefault(); - e.stopPropagation(); - const input = e.target as HTMLInputElement; - input.blur(); - } - }} - onFocus={() => { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - onChange(actualValue); - }} - /> + {!editing && ( + { + if (enterPressed) { + onChange(e.target.value); + setEnterPressed(false); + } + }} + onFocus={() => { + setEditing(true); + setEditedValue(value); + window.weaveOnFieldFocus = true; + }} + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + onChange(editedValue); + }} + /> + )} ); }; diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/number-input.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/number-input.tsx index 0e5f9d824..e4cd884a6 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/number-input.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/inputs/number-input.tsx @@ -31,46 +31,52 @@ export const NumberInput = React.forwardRef( onValueChange, fixedDecimalScale = false, decimalScale = 0, - value: controlledValue, + value, ...props }, ref ) => { - const [value, setValue] = React.useState( - controlledValue ?? defaultValue + const editingRef = React.useRef(null); + const [editing, setEditing] = React.useState(false); + const [editedValue, setEditedValue] = React.useState( + defaultValue ); - React.useEffect(() => { - if (controlledValue !== undefined) { - setValue(controlledValue); - } - }, [controlledValue]); + const handleChange = React.useCallback( + (values: { value: string; floatValue: number | undefined }) => { + const newValue = + values.floatValue === undefined ? undefined : values.floatValue; - const handleChange = (values: { - value: string; - floatValue: number | undefined; - }) => { - const newValue = - values.floatValue === undefined ? undefined : values.floatValue; - setValue(newValue); - if (onValueChange) { - onValueChange(newValue); - } - }; + setEditedValue(newValue); + }, + [] + ); - const handleBlur = () => { - if (value !== undefined) { - if (value < min) { - setValue(min); + const handleBlur = React.useCallback(() => { + onValueChange?.(editedValue); + + if (editedValue !== undefined) { + if (editedValue < min) { + if (onValueChange) { + onValueChange(min); + } (ref as React.RefObject).current!.value = String(min); - } else if (value > max) { - setValue(max); + } else if (editedValue > max) { + if (onValueChange) { + onValueChange(max); + } (ref as React.RefObject).current!.value = String(max); } } - }; + }, [editedValue, onValueChange, min, max, ref]); + + React.useEffect(() => { + if (editingRef.current) { + editingRef.current.focus(); + } + }, [editing]); return (
@@ -80,29 +86,52 @@ export const NumberInput = React.forwardRef(
)}
- { - window.weaveOnFieldFocus = true; - }} - onBlurCapture={() => { - window.weaveOnFieldFocus = false; - handleBlur(); - }} - max={max} - min={min} - customInput={Input} - placeholder={placeholder} - getInputRef={ref} - {...props} - className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" - /> + {!editing && ( + { + setEditing(true); + setEditedValue(value); + window.weaveOnFieldFocus = true; + }} + max={max} + min={min} + customInput={Input} + placeholder={placeholder} + getInputRef={ref} + {...props} + className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" + /> + )} + {editing && ( + { + window.weaveOnFieldFocus = false; + setEditing(false); + handleBlur(); + }} + max={max} + min={min} + customInput={Input} + placeholder={placeholder} + getInputRef={editingRef} + {...props} + className="w-full py-0 h-[40px] rounded-none !text-[14px] !border-black font-normal text-black text-right focus:outline-none bg-transparent shadow-none" + /> + )}
); diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/appearance-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/appearance-properties.tsx index 9b8f10f40..6ae35c825 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/appearance-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/appearance-properties.tsx @@ -20,28 +20,21 @@ export function AppearanceProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/color-token-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/color-token-properties.tsx index cb570253a..87a9f4d8d 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/color-token-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/color-token-properties.tsx @@ -1,10 +1,10 @@ -"use client"; +'use client'; -import React from "react"; -import { WeaveStateElement } from "@inditextech/weave-types"; -import { useWeave } from "@inditextech/weave-react"; -import { useCollaborationRoom } from "@/store/store"; -import { InputColor } from "../inputs/input-color"; +import React from 'react'; +import { WeaveStateElement } from '@inditextech/weave-types'; +import { useWeave } from '@inditextech/weave-react'; +import { useCollaborationRoom } from '@/store/store'; +import { InputColor } from '../inputs/input-color'; export function ColorTokenProperties() { const instance = useWeave((state) => state.instance); @@ -19,36 +19,29 @@ export function ColorTokenProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; - if (actualAction && nodePropertiesAction === "create") { - setActualNode({ - key: "creating", - type: "undefined", + const actualNode = React.useMemo(() => { + if (actualAction && nodePropertiesAction === 'create') { + return { + key: 'creating', + type: 'undefined', props: { ...nodeCreateProps, }, - }); - } - if (node && nodePropertiesAction === "update") { - setActualNode(node); + }; } - if (!actualAction && !node) { - setActualNode(undefined); + if (node && nodePropertiesAction === 'update') { + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { if (!instance) return; - if (actualAction && nodePropertiesAction === "create") { + if (actualAction && nodePropertiesAction === 'create') { instance.updatePropsAction(actualAction, updatedNode.props); } - if (nodePropertiesAction === "update") { + if (nodePropertiesAction === 'update') { instance.updateNode(updatedNode); } }, @@ -61,15 +54,15 @@ export function ColorTokenProperties() { if ( actualAction && - ["selectionTool"].includes(actualAction) && - !["color-token"].includes(actualNode.type) + ['selectionTool'].includes(actualAction) && + !['color-token'].includes(actualNode.type) ) { return null; } if ( actualAction && - !["selectionTool", "colorTokenTool"].includes(actualAction) + !['selectionTool', 'colorTokenTool'].includes(actualAction) ) return null; diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/crop-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/crop-properties.tsx index a7ec2155d..229f4215f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/crop-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/crop-properties.tsx @@ -11,26 +11,17 @@ import { InputNumber } from '../inputs/input-number'; export function CropProperties() { const instance = useWeave((state) => state.instance); const node = useWeave((state) => state.selection.node); - const actualAction = useWeave((state) => state.actions.actual); const nodePropertiesAction = useCollaborationRoom( (state) => state.nodeProperties.action ); - const nodeCreateProps = useCollaborationRoom( - (state) => state.nodeProperties.createProps - ); - - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (node && nodePropertiesAction === 'update') { - setActualNode(node); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [node, nodePropertiesAction]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/fill-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/fill-properties.tsx index 8ed4f3cb1..409a10cb4 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/fill-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/fill-properties.tsx @@ -21,28 +21,21 @@ export function FillProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/frame-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/frame-properties.tsx index 7daaff6c0..2461ab022 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/frame-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/frame-properties.tsx @@ -27,28 +27,21 @@ export function FrameProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/image-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/image-properties.tsx index fe5c9b5c0..4edb31ba3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/image-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/image-properties.tsx @@ -1,7 +1,6 @@ 'use client'; import React from 'react'; -import { WeaveStateElement } from '@inditextech/weave-types'; import { useWeave } from '@inditextech/weave-react'; import { useCollaborationRoom } from '@/store/store'; import { InputNumber } from '../inputs/input-number'; @@ -9,26 +8,17 @@ import { InputNumber } from '../inputs/input-number'; export function ImageProperties() { const instance = useWeave((state) => state.instance); const node = useWeave((state) => state.selection.node); - const actualAction = useWeave((state) => state.actions.actual); const nodePropertiesAction = useCollaborationRoom( (state) => state.nodeProperties.action ); - const nodeCreateProps = useCollaborationRoom( - (state) => state.nodeProperties.createProps - ); - - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (node && nodePropertiesAction === 'update') { - setActualNode(node); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [node, nodePropertiesAction]); if (!instance || !actualNode) return null; diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/meta-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/meta-properties.tsx index 0a7af201e..015847c5f 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/meta-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/meta-properties.tsx @@ -19,28 +19,21 @@ export function MetaProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/size-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/size-properties.tsx index 2739a75b4..67f43a1e5 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/size-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/size-properties.tsx @@ -19,28 +19,21 @@ export function SizeProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/stroke-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/stroke-properties.tsx index 6cce2bb97..4de0877d3 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/stroke-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/stroke-properties.tsx @@ -31,28 +31,21 @@ export function StrokeProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodePropertiesAction, nodeCreateProps]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { diff --git a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/text-properties.tsx b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/text-properties.tsx index 2615a56cc..99c78454d 100644 --- a/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/text-properties.tsx +++ b/code/packages/create-frontend-app/template/+nextjs+websockets/components/room-components/node-properties/text-properties.tsx @@ -37,28 +37,21 @@ export function TextProperties() { (state) => state.nodeProperties.createProps ); - const [actualNode, setActualNode] = React.useState< - WeaveStateElement | undefined - >(node); - - React.useEffect(() => { - if (!instance) return; + const actualNode = React.useMemo(() => { if (actualAction && nodePropertiesAction === 'create') { - setActualNode({ + return { key: 'creating', type: 'undefined', props: { ...nodeCreateProps, }, - }); + }; } if (node && nodePropertiesAction === 'update') { - setActualNode(node); - } - if (!actualAction && !node) { - setActualNode(undefined); + return node; } - }, [instance, actualAction, node, nodeCreateProps, nodePropertiesAction]); + return undefined; + }, [actualAction, node, nodePropertiesAction, nodeCreateProps]); const updateElement = React.useCallback( (updatedNode: WeaveStateElement) => { @@ -267,7 +260,10 @@ export function TextProperties() { } - pressed={actualNode.props.fontVariant === 'normal'} + pressed={ + !actualNode.props.fontVariant || + actualNode.props.fontVariant === 'normal' + } onClick={() => { const updatedNode: WeaveStateElement = { ...actualNode, diff --git a/docs/content/docs/main/changelog/index.mdx b/docs/content/docs/main/changelog/index.mdx index a5d74d700..c0c4d57d5 100644 --- a/docs/content/docs/main/changelog/index.mdx +++ b/docs/content/docs/main/changelog/index.mdx @@ -9,6 +9,7 @@ description: Check out the latest changes to Weave.js. ## Pre-release versions +- [**0.17.0**](/docs/main/changelog/prerelease/0.17.0) - [**0.16.2**](/docs/main/changelog/prerelease/0.16.2) - [**0.16.1**](/docs/main/changelog/prerelease/0.16.1) - [**0.16.0**](/docs/main/changelog/prerelease/0.16.0) diff --git a/docs/content/docs/main/changelog/prerelease/0.17.0.mdx b/docs/content/docs/main/changelog/prerelease/0.17.0.mdx new file mode 100644 index 000000000..b7d4e7d1d --- /dev/null +++ b/docs/content/docs/main/changelog/prerelease/0.17.0.mdx @@ -0,0 +1,12 @@ +--- +title: v0.17.0 +description: Improvements on create-app frontend +--- + +## Metadata + +- **Release date**: 2025-05-26 + +### Changes + +- [#287](https://github.com/InditexTech/weavejs/issues/287) Update create-app frontend diff --git a/docs/content/docs/main/changelog/prerelease/meta.json b/docs/content/docs/main/changelog/prerelease/meta.json index 665c99bdc..dd291120e 100644 --- a/docs/content/docs/main/changelog/prerelease/meta.json +++ b/docs/content/docs/main/changelog/prerelease/meta.json @@ -2,6 +2,7 @@ "title": "Prerelease versions", "description": "Detailed changelog for Weave.js pre-release versions", "pages": [ + "0.17.0", "0.16.2", "0.16.1", "0.16.0",