From 14d509f2e18b542245e1b4139d10c7ab6f271bc2 Mon Sep 17 00:00:00 2001 From: Emiliano Bonilla <56323762+emilbon99@users.noreply.github.com> Date: Sun, 18 Aug 2024 09:54:30 -0700 Subject: [PATCH 01/20] [console] - updated additional symbols --- pluto/src/input/Text.tsx | 14 +++- pluto/src/vis/diagram/Diagram.css | 12 ++- pluto/src/vis/schematic/Symbols.tsx | 80 +++++++++++++++++++ .../vis/schematic/primitives/Primitives.tsx | 63 ++++++++++++++- pluto/src/vis/schematic/registry.ts | 38 +++++++++ 5 files changed, 193 insertions(+), 14 deletions(-) diff --git a/pluto/src/input/Text.tsx b/pluto/src/input/Text.tsx index 3378ea169..3029a64e2 100644 --- a/pluto/src/input/Text.tsx +++ b/pluto/src/input/Text.tsx @@ -73,8 +73,11 @@ export const Text = forwardRef( ) => { const cachedFocusRef = useRef(""); const [tempValue, setTempValue] = useState(null); + const internalRef = useRef(null); + const focusedRef = useRef(false); const handleBlur = (e: React.FocusEvent): void => { + focusedRef.current = false; if (resetOnBlurIfEmpty && e.target.value === "") onChange?.(cachedFocusRef.current); else if (onlyChangeOnBlur) { @@ -93,11 +96,14 @@ export const Text = forwardRef( if (onlyChangeOnBlur) setTempValue(value); onFocus?.(e); cachedFocusRef.current = e.target.value; + }; + + const handleMouseUp = (): void => { // This looks hacky, but it's the only way to consistently select the text // after the focus event. - if (!selectOnFocus) return; - const interval = setInterval(() => e.target.select(), 2); - setTimeout(() => clearInterval(interval), 50); + if (!selectOnFocus || focusedRef.current) return; + focusedRef.current = true; + internalRef.current?.select(); }; const handleKeyDown = (e: React.KeyboardEvent): void => { @@ -105,7 +111,6 @@ export const Text = forwardRef( if (e.key === "Enter") e.currentTarget.blur(); }; - const internalRef = useRef(null); const combinedRef = useCombinedRefs(ref, internalRef); return ( @@ -148,6 +153,7 @@ export const Text = forwardRef( autoCorrect="off" onFocus={handleFocus} onKeyDown={handleKeyDown} + onMouseUp={handleMouseUp} onBlur={handleBlur} className={CSS(CSS.visible(false), level != null && CSS.BM("text", level))} disabled={disabled} diff --git a/pluto/src/vis/diagram/Diagram.css b/pluto/src/vis/diagram/Diagram.css index 5a6e908b3..084b92654 100644 --- a/pluto/src/vis/diagram/Diagram.css +++ b/pluto/src/vis/diagram/Diagram.css @@ -31,17 +31,15 @@ } } - .react-flow__resize-control { display: none; } - .react-flow__handle { background: none !important; border: var(--pluto-border) !important; border-color: transparent !important; - pointer-events: none !important;; + pointer-events: none !important; } .react-flow__background circle { @@ -60,12 +58,13 @@ } .react-flow__edges { - z-index: 6 !important; + z-index: 6 !important; } .pluto-diagram { &.pluto--editable { - & .pluto-symbol-primitive,.pluto-control-chip { + & .pluto-symbol-primitive, + .pluto-control-chip { pointer-events: none; } @@ -77,6 +76,7 @@ width: 1.4rem !important; height: 1.4rem !important; pointer-events: all !important; + z-index: 1; } & .pluto-symbol { &:hover { @@ -100,6 +100,4 @@ } } } - - } diff --git a/pluto/src/vis/schematic/Symbols.tsx b/pluto/src/vis/schematic/Symbols.tsx index beb943470..403854876 100644 --- a/pluto/src/vis/schematic/Symbols.tsx +++ b/pluto/src/vis/schematic/Symbols.tsx @@ -1073,3 +1073,83 @@ export const Light = Aether.wrap>( export const LightPreview = (props: LightProps): ReactElement => ( ); + +export interface AgitatorProps + extends Primitives.AgitatorProps, + Omit { + label?: LabelExtensionProps; + control?: ControlStateProps; +} + +export const Agitator = Aether.wrap>( + "agitator", + ({ + aetherKey, + label, + orientation = "left", + color, + source, + sink, + onChange, + control, + }): ReactElement => { + const { enabled, triggered, toggle } = Toggle.use({ aetherKey, source, sink }); + return ( + + + + + + ); + }, +); + +export const AgitatorPreview = (props: AgitatorProps): ReactElement => ( + +); + +export interface PropellerAgitatorProps + extends Primitives.PropellerAgitatorProps, + Omit { + label?: LabelExtensionProps; + control?: ControlStateProps; +} + +export const PropellerAgitator = Aether.wrap>( + "propellerAgitator", + ({ + aetherKey, + label, + orientation = "left", + color, + source, + sink, + onChange, + control, + }): ReactElement => { + const { enabled, triggered, toggle } = Toggle.use({ aetherKey, source, sink }); + return ( + + + + + + ); + }, +); + +export const PropellerAgitatorPreview = ( + props: PropellerAgitatorProps, +): ReactElement => ; diff --git a/pluto/src/vis/schematic/primitives/Primitives.tsx b/pluto/src/vis/schematic/primitives/Primitives.tsx index 6463cb3b3..60f91b34c 100644 --- a/pluto/src/vis/schematic/primitives/Primitives.tsx +++ b/pluto/src/vis/schematic/primitives/Primitives.tsx @@ -1004,8 +1004,8 @@ export const Setpoint = ({ {...props} > - - + + ( +}: ElectricRegulatorProps): ReactElement => (
@@ -1374,3 +1374,60 @@ export const ElectricRegulator = ({
); + +export interface AgitatorProps extends ToggleProps, SVGBasedPrimitiveProps { + height?: number; +} + +export const Agitator = ({ + height = 86, + orientation = "left", + color, + scale, + ...props +}: AgitatorProps): ReactElement => ( + + + + + + + + + +); + +export interface PropellerAgitatorProps extends ToggleProps, SVGBasedPrimitiveProps { + height?: number; +} + +export const PropellerAgitator = ({ + height = 86, + orientation = "left", + color, + scale, + ...props +}: PropellerAgitatorProps): ReactElement => ( + + + + + + + + + +); diff --git a/pluto/src/vis/schematic/registry.ts b/pluto/src/vis/schematic/registry.ts index af7c9eaa5..685f8d52a 100644 --- a/pluto/src/vis/schematic/registry.ts +++ b/pluto/src/vis/schematic/registry.ts @@ -26,6 +26,9 @@ import { } from "@/vis/schematic/Forms"; import { type LabelExtensionProps } from "@/vis/schematic/Labeled"; import { + Agitator, + AgitatorPreview, + AgitatorProps, AngledReliefValve, AngledReliefValvePreview, AngledValve, @@ -67,6 +70,9 @@ import { PistonPump, PistonPumpPreview, type PistonPumpProps, + PropellerAgitator, + PropellerAgitatorPreview, + PropellerAgitatorProps, Pump, PumpPreview, type PumpProps, @@ -155,6 +161,8 @@ const VARIANTS = [ "vacuumPump", "value", "valve", + "agitator", + "propellerAgitator", ] as const; export const typeZ = z.enum(VARIANTS); @@ -672,6 +680,34 @@ const setpoint: Spec = { zIndex: Z_INDEX_UPPER, }; +const agitator: Spec = { + name: "Agitator", + key: "agitator", + Symbol: Agitator, + Form: CommonToggleForm, + defaultProps: (t) => ({ + color: t.colors.gray.l9.rgba255, + ...zeroLabel("Agitator"), + ...ZERO_TOGGLE_PROPS, + }), + Preview: AgitatorPreview, + zIndex: Z_INDEX_UPPER, +}; + +const propellerAgitator: Spec = { + name: "Propeller Agitator", + key: "propellerAgitator", + Symbol: PropellerAgitator, + Form: CommonToggleForm, + defaultProps: (t) => ({ + color: t.colors.gray.l9.rgba255, + ...zeroLabel("Propeller Agitator"), + ...ZERO_TOGGLE_PROPS, + }), + Preview: PropellerAgitatorPreview, + zIndex: Z_INDEX_UPPER, +}; + export const SYMBOLS: Record> = { value, light, @@ -702,4 +738,6 @@ export const SYMBOLS: Record> = { cap, filter, orifice, + agitator, + propellerAgitator, }; From da6cd066767baca90ce209bfecf757a81d075778 Mon Sep 17 00:00:00 2001 From: pjdotson Date: Sat, 14 Sep 2024 14:44:14 -0700 Subject: [PATCH 02/20] fix(console): Fix nested + ); +}; diff --git a/pluto/src/select/external.ts b/pluto/src/select/external.ts index 452e16a43..887cdacf0 100644 --- a/pluto/src/select/external.ts +++ b/pluto/src/select/external.ts @@ -7,6 +7,7 @@ // License, use of this software will be governed by the Apache License, Version 2.0, // included in the file licenses/APL.txt. +export * from "@/select/Alignment"; export * from "@/select/Button"; export * from "@/select/DataType"; export * from "@/select/Direction"; diff --git a/pluto/src/vis/diagram/Diagram.css b/pluto/src/vis/diagram/Diagram.css index 10549fc0f..29f2f5460 100644 --- a/pluto/src/vis/diagram/Diagram.css +++ b/pluto/src/vis/diagram/Diagram.css @@ -24,7 +24,7 @@ .react-flow__node.selected .pluto-symbol-primitive { /* make an inset box shadow to simulate a background */ - box-shadow: 0 0 0 1000px var(--pluto-primary-z) inset !important; + box-shadow: 0 0 0 1000px var(--pluto-primary-z-20) inset !important; & .react-flow__resize-control { display: block; diff --git a/pluto/src/vis/diagram/aether/types.ts b/pluto/src/vis/diagram/aether/types.ts index 1d3974ea7..6900c7c34 100644 --- a/pluto/src/vis/diagram/aether/types.ts +++ b/pluto/src/vis/diagram/aether/types.ts @@ -155,7 +155,7 @@ export const translateNodesForward = (nodes: Node[]): rf.Node[] => ...node, id: node.key, type: "custom", - zIndex: 8, + zIndex: node.zIndex, data: {}, })); diff --git a/pluto/src/vis/schematic/Forms.tsx b/pluto/src/vis/schematic/Forms.tsx index d1de14f33..c41aa34e5 100644 --- a/pluto/src/vis/schematic/Forms.tsx +++ b/pluto/src/vis/schematic/Forms.tsx @@ -19,6 +19,7 @@ import { Color } from "@/color"; import { CSS } from "@/css"; import { Form } from "@/form"; import { Input } from "@/input"; +import { Select } from "@/select"; import { Tabs } from "@/tabs"; import { telem } from "@/telem/aether"; import { control } from "@/telem/control/aether"; @@ -53,7 +54,10 @@ interface SymbolOrientation { orientation?: location.Outer; } -const OrientationControl: Form.FieldT = (props): ReactElement => ( +const OrientationControl = ({ + showOuter, + ...props +}: Form.FieldProps & { showOuter?: boolean }): ReactElement => ( label="Orientation" padHelpText={false} {...props}> {({ value, onChange }) => ( = (props): ReactElement inner: value.orientation ?? "top", outer: value.label?.orientation ?? "top", }} + showOuter={showOuter} onChange={(v) => onChange({ ...value, @@ -81,6 +86,12 @@ const LabelControls = ({ path }: { path: string }): ReactElement => ( path={path + ".label"} label="Label" padHelpText={false} grow> {(p) => } + path={path + ".level"} label="Label Size" @@ -88,6 +99,14 @@ const LabelControls = ({ path }: { path: string }): ReactElement => ( > {(p) => } + + path={path + ".align"} + label="Label Alignment" + padHelpText={false} + hideIfNull + > + {(p) => } + ); @@ -191,13 +210,13 @@ const ToggleControlForm = ({ path }: { path: string }): ReactElement => { ...value, sink: t, control: { - ...value.control, showChip: true, + showIndicator: true, + ...value.control, chip: { sink: controlChipSink, source: authSource, }, - showIndicator: true, indicator: { statusSource: authSource, }, @@ -216,6 +235,12 @@ const ToggleControlForm = ({ path }: { path: string }): ReactElement => { + ); }; @@ -333,7 +358,7 @@ export const TankForm = ({ - + ); @@ -488,7 +513,7 @@ export const ValueForm = (): ReactElement => { - + ); } @@ -746,7 +771,7 @@ export const TextBoxForm = (): ReactElement => ( - path="width" label="Width" padHelpText={false}> + path="width" label="Label Width" padHelpText={false}> {(p) => ( )} diff --git a/pluto/src/vis/schematic/Labeled.tsx b/pluto/src/vis/schematic/Labeled.tsx index a3d50d94a..82e277db4 100644 --- a/pluto/src/vis/schematic/Labeled.tsx +++ b/pluto/src/vis/schematic/Labeled.tsx @@ -8,7 +8,7 @@ // included in the file licenses/APL.txt. import { type location } from "@synnaxlabs/x"; -import { forwardRef,useCallback } from "react"; +import { forwardRef, useCallback } from "react"; import { Align } from "@/align"; import { CSS } from "@/css"; @@ -18,6 +18,8 @@ export interface LabelExtensionProps { label?: string; level?: Text.Level; orientation?: location.Outer; + maxInlineSize?: number; + align?: Align.Alignment; } export interface LabeledProps @@ -36,6 +38,7 @@ export const Labeled = forwardRef( orientation = "top", style, className, + maxInlineSize = 150, ...props }, ref, @@ -64,6 +67,7 @@ export const Labeled = forwardRef( onChange({ diff --git a/pluto/src/vis/schematic/OrientationControl.css b/pluto/src/vis/schematic/OrientationControl.css index e29bdf615..98b630884 100644 --- a/pluto/src/vis/schematic/OrientationControl.css +++ b/pluto/src/vis/schematic/OrientationControl.css @@ -11,16 +11,22 @@ .pluto-orientation-control { position: relative; - width: 100px; + &:not(.pluto-value) { + width: 100px; + } aspect-ratio: 1; .symbol { height: 2px; - width: calc(100% - 1rem); + width: calc(100% - 9px); background-color: var(--pluto-gray-l8); border-radius: var(--pluto-border-radius); } + &.pluto-value { + border: none; + } + .pluto-value { border: var(--pluto-border); border-radius: var(--pluto-border-radius); @@ -35,6 +41,9 @@ justify-content: center; &.pluto--selected { background-color: var(--pluto-primary-z) !important; + & .symbol { + background-color: var(--pluto-text-on-primary) !important; + } } &.pluto--y { diff --git a/pluto/src/vis/schematic/SelectOrientation.tsx b/pluto/src/vis/schematic/SelectOrientation.tsx index f75041cda..74eb1a976 100644 --- a/pluto/src/vis/schematic/SelectOrientation.tsx +++ b/pluto/src/vis/schematic/SelectOrientation.tsx @@ -22,16 +22,30 @@ export interface OrientationValue { outer: location.Outer; } -export interface SelectOrientationProps extends Input.Control {} +export interface SelectOrientationProps + extends Input.Control, + Omit { + showOuter?: boolean; +} export const SelectOrientation = ({ value, + showOuter = true, onChange, }: SelectOrientationProps): ReactElement => { - const { inner, outer } = value; + const { outer } = value; const handleChange = (next: Partial) => () => onChange({ ...value, ...next }); + if (!showOuter) + return ( + + ); + return (