From 99825ef636a6858e6210a1d026920b60aea3ea1d Mon Sep 17 00:00:00 2001 From: Norman Fomferra Date: Fri, 22 Nov 2024 13:56:56 +0100 Subject: [PATCH 1/5] Reorganising components; added CircularProgress --- .../helpers/applyStateChangeRequests.test.ts | 8 ++- .../actions/helpers/getInputValues.test.ts | 3 +- chartlets.js/src/lib/components/Box.tsx | 6 ++- chartlets.js/src/lib/components/Button.tsx | 7 ++- chartlets.js/src/lib/components/Checkbox.tsx | 8 ++- .../src/lib/components/CircularProgress.tsx | 31 +++++++++++ chartlets.js/src/lib/components/Component.tsx | 8 +++ chartlets.js/src/lib/components/Plot.tsx | 13 ++++- chartlets.js/src/lib/components/Select.tsx | 17 ++++-- .../src/lib/components/Typography.tsx | 25 +++++++-- chartlets.js/src/lib/index.ts | 5 +- chartlets.js/src/lib/types/state/component.ts | 53 +------------------ chartlets.js/src/lib/types/state/event.ts | 3 +- 13 files changed, 115 insertions(+), 72 deletions(-) create mode 100644 chartlets.js/src/lib/components/CircularProgress.tsx diff --git a/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts b/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts index 45db5b6b..bbe7fc23 100644 --- a/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts +++ b/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts @@ -1,12 +1,10 @@ import { describe, it, expect } from "vitest"; +import { type ComponentState } from "@/lib"; import { type ContribPoint } from "@/lib/types/model/extension"; import { type StateChangeRequest } from "@/lib/types/model/callback"; -import { - type BoxState, - type ComponentState, - type PlotState, -} from "@/lib/types/state/component"; +import { type BoxState } from "@/lib/components/Box"; +import { type PlotState } from "@/lib/components/Plot"; import { type ContributionState } from "@/lib/types/state/contribution"; import { applyComponentStateChange, diff --git a/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts b/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts index fbf314a3..19dd7d6a 100644 --- a/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts +++ b/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts @@ -1,6 +1,7 @@ import { describe, it, expect } from "vitest"; -import type { ComponentState, PlotState } from "@/lib/types/state/component"; +import type { ComponentState } from "@/lib"; +import type { PlotState } from "@/lib/components/Plot"; import { getInputValueFromComponent, getInputValueFromState, diff --git a/chartlets.js/src/lib/components/Box.tsx b/chartlets.js/src/lib/components/Box.tsx index 4ff83d48..c8b29283 100644 --- a/chartlets.js/src/lib/components/Box.tsx +++ b/chartlets.js/src/lib/components/Box.tsx @@ -1,9 +1,13 @@ import MuiBox from "@mui/material/Box"; -import { type BoxState } from "@/lib/types/state/component"; +import { type ContainerState } from "@/lib/types/state/component"; import { type ComponentChangeHandler } from "@/lib/types/state/event"; import { ComponentChildren } from "./ComponentChildren"; +export interface BoxState extends ContainerState { + type: "Box"; +} + export interface BoxProps extends Omit { onChange: ComponentChangeHandler; } diff --git a/chartlets.js/src/lib/components/Button.tsx b/chartlets.js/src/lib/components/Button.tsx index f444641e..83f0a0b9 100644 --- a/chartlets.js/src/lib/components/Button.tsx +++ b/chartlets.js/src/lib/components/Button.tsx @@ -1,9 +1,14 @@ import { type MouseEvent } from "react"; import MuiButton from "@mui/material/Button"; -import { type ButtonState } from "@/lib/types/state/component"; +import { type ComponentState } from "@/lib/types/state/component"; import { type ComponentChangeHandler } from "@/lib/types/state/event"; +export interface ButtonState extends ComponentState { + type: "Button"; + text: string; +} + export interface ButtonProps extends Omit { onChange: ComponentChangeHandler; } diff --git a/chartlets.js/src/lib/components/Checkbox.tsx b/chartlets.js/src/lib/components/Checkbox.tsx index 1f048277..548529cb 100644 --- a/chartlets.js/src/lib/components/Checkbox.tsx +++ b/chartlets.js/src/lib/components/Checkbox.tsx @@ -3,9 +3,15 @@ import MuiCheckbox from "@mui/material/Checkbox"; import MuiFormControl from "@mui/material/FormControl"; import MuiFormControlLabel from "@mui/material/FormControlLabel"; -import { type CheckboxState } from "@/lib/types/state/component"; +import { type ComponentState } from "@/lib/types/state/component"; import { type ComponentChangeHandler } from "@/lib/types/state/event"; +export interface CheckboxState extends ComponentState { + type: "Checkbox"; + label: string; + value?: boolean; +} + export interface CheckboxProps extends Omit { onChange: ComponentChangeHandler; } diff --git a/chartlets.js/src/lib/components/CircularProgress.tsx b/chartlets.js/src/lib/components/CircularProgress.tsx new file mode 100644 index 00000000..bc1c842b --- /dev/null +++ b/chartlets.js/src/lib/components/CircularProgress.tsx @@ -0,0 +1,31 @@ +import MuiCircularProgress from "@mui/material/CircularProgress"; + +import { type ComponentState } from "@/lib/types/state/component"; + +export interface CircularProgressState extends ComponentState { + type: "CircularProgress"; + size?: number | string; + value?: number; + variant?: "determinate" | "indeterminate"; +} + +export interface CircularProgressProps + extends Omit {} + +export function CircularProgress({ + id, + style, + size, + value, + variant, +}: CircularProgressProps) { + return ( + + ); +} diff --git a/chartlets.js/src/lib/components/Component.tsx b/chartlets.js/src/lib/components/Component.tsx index be06837a..0cfea9b0 100644 --- a/chartlets.js/src/lib/components/Component.tsx +++ b/chartlets.js/src/lib/components/Component.tsx @@ -6,6 +6,10 @@ import { Checkbox, type CheckboxProps } from "./Checkbox"; import { Select, type SelectProps } from "./Select"; import { Plot, type PlotProps } from "./Plot"; import { Typography, type TypographyProps } from "@/lib/components/Typography"; +import { + CircularProgress, + type CircularProgressProps, +} from "./CircularProgress"; export interface ComponentProps extends ComponentState { onChange: ComponentChangeHandler; @@ -28,7 +32,11 @@ export function Component({ type, ...props }: ComponentProps) { return ; } else if (type === "Checkbox") { return ; + } else if (type === "CircularProgress") { + return ; } else if (type === "Typography") { return ; + } else { + console.error(`Cannot render unknown component type ${type}`); } } diff --git a/chartlets.js/src/lib/components/Plot.tsx b/chartlets.js/src/lib/components/Plot.tsx index 62d939b7..4e909d0b 100644 --- a/chartlets.js/src/lib/components/Plot.tsx +++ b/chartlets.js/src/lib/components/Plot.tsx @@ -1,8 +1,17 @@ -import { VegaLite } from "react-vega"; +import { VegaLite, type VisualizationSpec } from "react-vega"; -import { type PlotState } from "@/lib/types/state/component"; +import { type ComponentState } from "@/lib/types/state/component"; import { type ComponentChangeHandler } from "@/lib/types/state/event"; +export interface PlotState extends ComponentState { + type: "Plot"; + chart: + | (VisualizationSpec & { + datasets?: Record; // Add the datasets property + }) + | null; +} + export interface PlotProps extends Omit { onChange: ComponentChangeHandler; } diff --git a/chartlets.js/src/lib/components/Select.tsx b/chartlets.js/src/lib/components/Select.tsx index 24610abd..9620d835 100644 --- a/chartlets.js/src/lib/components/Select.tsx +++ b/chartlets.js/src/lib/components/Select.tsx @@ -3,12 +3,21 @@ import MuiInputLabel from "@mui/material/InputLabel"; import MuiMenuItem from "@mui/material/MenuItem"; import MuiSelect, { type SelectChangeEvent } from "@mui/material/Select"; -import { - type SelectOption, - type SelectState, -} from "@/lib/types/state/component"; +import { type ComponentState } from "@/lib/types/state/component"; import { type ComponentChangeHandler } from "@/lib/types/state/event"; +export type SelectOption = + | string + | number + | [string, string] + | [number, string] + | { value: string | number; label?: string }; + +export interface SelectState extends ComponentState { + type: "Select"; + options: SelectOption[]; +} + export interface SelectProps extends Omit { onChange: ComponentChangeHandler; } diff --git a/chartlets.js/src/lib/components/Typography.tsx b/chartlets.js/src/lib/components/Typography.tsx index 47eb46e5..9276b8c8 100644 --- a/chartlets.js/src/lib/components/Typography.tsx +++ b/chartlets.js/src/lib/components/Typography.tsx @@ -1,8 +1,16 @@ import MuiTypography from "@mui/material/Typography"; +import { type TypographyVariant } from "@mui/material"; -import type { TypographyState } from "@/lib/types/state/component"; import { ComponentChildren } from "@/lib/components/ComponentChildren"; -import type { ComponentChangeHandler } from "@/lib"; +import type { ComponentChangeHandler, ContainerState } from "@/lib"; + +export interface TypographyState extends ContainerState { + type: "Typography"; + align?: "right" | "left" | "center" | "inherit" | "justify"; + gutterBottom?: boolean; + noWrap?: boolean; + variant?: TypographyVariant; +} export interface TypographyProps extends Omit { onChange: ComponentChangeHandler; @@ -11,11 +19,22 @@ export interface TypographyProps extends Omit { export function Typography({ id, style, + align, + gutterBottom, + noWrap, + variant, children: components, onChange, }: TypographyProps) { return ( - + ); diff --git a/chartlets.js/src/lib/index.ts b/chartlets.js/src/lib/index.ts index de27e62a..07984d09 100644 --- a/chartlets.js/src/lib/index.ts +++ b/chartlets.js/src/lib/index.ts @@ -1,7 +1,10 @@ // Types export { type Contribution } from "@/lib/types/model/contribution"; export { type ContributionState } from "@/lib/types/state/contribution"; -export { type ComponentState } from "@/lib/types/state/component"; +export type { + ComponentState, + ContainerState, +} from "@/lib/types/state/component"; export { type ComponentChangeEvent, type ComponentChangeHandler, diff --git a/chartlets.js/src/lib/types/state/component.ts b/chartlets.js/src/lib/types/state/component.ts index 8b6fd8e4..bb38dedb 100644 --- a/chartlets.js/src/lib/types/state/component.ts +++ b/chartlets.js/src/lib/types/state/component.ts @@ -1,23 +1,14 @@ import { type CSSProperties } from "react"; -import type { VisualizationSpec } from "react-vega"; import { isObject } from "@/lib/utils/isObject"; -export type ComponentType = - | "Box" - | "Button" - | "Checkbox" - | "Plot" - | "Select" - | "Typography"; - export interface ComponentState { - type: ComponentType; + type: string; label?: string; children?: ComponentItem[]; // common HTML attributes id?: string; name?: string; - value?: boolean | string | number; + value?: boolean | string | number | null | undefined; style?: CSSProperties; disabled?: boolean; } @@ -28,46 +19,6 @@ export interface ContainerState extends ComponentState { children: ComponentItem[]; } -export type SelectOption = - | string - | number - | [string, string] - | [number, string] - | { value: string | number; label?: string }; - -export interface SelectState extends ComponentState { - type: "Select"; - options: SelectOption[]; -} - -export interface ButtonState extends ComponentState { - type: "Button"; - text: string; -} - -export interface CheckboxState extends ComponentState { - type: "Checkbox"; - label: string; - value?: boolean; -} - -export interface PlotState extends ComponentState { - type: "Plot"; - chart: - | (VisualizationSpec & { - datasets?: Record; // Add the datasets property - }) - | null; -} - -export interface BoxState extends ContainerState { - type: "Box"; -} - -export interface TypographyState extends ContainerState { - type: "Typography"; -} - export function isComponentState(object: unknown): object is ComponentState { return isObject(object) && typeof object.type === "string"; } diff --git a/chartlets.js/src/lib/types/state/event.ts b/chartlets.js/src/lib/types/state/event.ts index 672e9ca3..a6766096 100644 --- a/chartlets.js/src/lib/types/state/event.ts +++ b/chartlets.js/src/lib/types/state/event.ts @@ -1,8 +1,7 @@ -import { type ComponentType } from "@/lib/types/state/component"; import type { ObjPathLike } from "@/lib/utils/objPath"; export interface ComponentChangeEvent { - componentType: ComponentType; + componentType: string; // See commonality with StateChange id: string; property: ObjPathLike; From b5b5dea3a130e9c403c34619d54de3248cf8f5c0 Mon Sep 17 00:00:00 2001 From: Norman Fomferra Date: Fri, 22 Nov 2024 15:30:53 +0100 Subject: [PATCH 2/5] Fixes after sync with main --- chartlets.js/src/lib/components/Typography.tsx | 4 ++-- chartlets.js/src/lib/types/state/component.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chartlets.js/src/lib/components/Typography.tsx b/chartlets.js/src/lib/components/Typography.tsx index 9276b8c8..8056e977 100644 --- a/chartlets.js/src/lib/components/Typography.tsx +++ b/chartlets.js/src/lib/components/Typography.tsx @@ -23,7 +23,7 @@ export function Typography({ gutterBottom, noWrap, variant, - children: components, + children: nodes, onChange, }: TypographyProps) { return ( @@ -35,7 +35,7 @@ export function Typography({ noWrap={noWrap} variant={variant} > - + ); } diff --git a/chartlets.js/src/lib/types/state/component.ts b/chartlets.js/src/lib/types/state/component.ts index 2e213557..85b20461 100644 --- a/chartlets.js/src/lib/types/state/component.ts +++ b/chartlets.js/src/lib/types/state/component.ts @@ -20,7 +20,7 @@ export type ComponentNode = export interface ComponentState { // TODO: Rename to tag, so we can also have // (Html)ElementState along with ComponentState - type: ComponentType; + type: string; children?: ComponentNode[]; // common HTML attributes id?: string; From bfd2707449adeb74815479b7a1046ebf5b2b83b3 Mon Sep 17 00:00:00 2001 From: Norman Fomferra Date: Fri, 22 Nov 2024 17:54:25 +0100 Subject: [PATCH 3/5] We now have a component registry --- .../helpers/applyStateChangeRequests.test.ts | 8 +-- .../actions/helpers/getInputValues.test.ts | 6 +- .../Children.tsx} | 4 +- chartlets.js/src/lib/component/Component.tsx | 20 +++++++ .../src/lib/component/Registry.test.ts | 53 ++++++++++++++++++ chartlets.js/src/lib/component/Registry.ts | 56 +++++++++++++++++++ chartlets.js/src/lib/components/Box.tsx | 16 ++---- chartlets.js/src/lib/components/Button.tsx | 14 ++--- chartlets.js/src/lib/components/Checkbox.tsx | 16 +++--- .../src/lib/components/CircularProgress.tsx | 7 +-- chartlets.js/src/lib/components/Component.tsx | 42 -------------- chartlets.js/src/lib/components/Plot.tsx | 18 +++--- chartlets.js/src/lib/components/Select.tsx | 15 ++--- .../src/lib/components/Typography.tsx | 14 ++--- chartlets.js/src/lib/index.ts | 33 ++++++++++- chartlets.js/src/lib/types/state/component.ts | 2 +- 16 files changed, 209 insertions(+), 115 deletions(-) rename chartlets.js/src/lib/{components/ComponentChildren.tsx => component/Children.tsx} (86%) create mode 100644 chartlets.js/src/lib/component/Component.tsx create mode 100644 chartlets.js/src/lib/component/Registry.test.ts create mode 100644 chartlets.js/src/lib/component/Registry.ts delete mode 100644 chartlets.js/src/lib/components/Component.tsx diff --git a/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts b/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts index bbe7fc23..b78a9ae7 100644 --- a/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts +++ b/chartlets.js/src/lib/actions/helpers/applyStateChangeRequests.test.ts @@ -3,19 +3,17 @@ import { describe, it, expect } from "vitest"; import { type ComponentState } from "@/lib"; import { type ContribPoint } from "@/lib/types/model/extension"; import { type StateChangeRequest } from "@/lib/types/model/callback"; -import { type BoxState } from "@/lib/components/Box"; -import { type PlotState } from "@/lib/components/Plot"; import { type ContributionState } from "@/lib/types/state/contribution"; import { applyComponentStateChange, applyContributionChangeRequests, } from "./applyStateChangeRequests"; -const componentTree: ComponentState = { +const componentTree = { type: "Box", id: "b1", children: [ - { type: "Plot", id: "p1", chart: null } as PlotState, + { type: "Plot", id: "p1", chart: null }, { type: "Box", id: "b2", @@ -113,7 +111,7 @@ describe("Test that applyComponentStateChange()", () => { }); it("replaces state if property is empty string", () => { - const value: BoxState = { + const value = { type: "Box", id: "b1", children: ["Hello", "World"], diff --git a/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts b/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts index 19dd7d6a..145643d1 100644 --- a/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts +++ b/chartlets.js/src/lib/actions/helpers/getInputValues.test.ts @@ -1,17 +1,15 @@ import { describe, it, expect } from "vitest"; -import type { ComponentState } from "@/lib"; -import type { PlotState } from "@/lib/components/Plot"; import { getInputValueFromComponent, getInputValueFromState, } from "./getInputValues"; -const componentState: ComponentState = { +const componentState = { type: "Box", id: "b1", children: [ - { type: "Plot", id: "p1", chart: null } as PlotState, + { type: "Plot", id: "p1", chart: null }, { type: "Box", id: "b2", diff --git a/chartlets.js/src/lib/components/ComponentChildren.tsx b/chartlets.js/src/lib/component/Children.tsx similarity index 86% rename from chartlets.js/src/lib/components/ComponentChildren.tsx rename to chartlets.js/src/lib/component/Children.tsx index 18ff8193..cbed58e4 100644 --- a/chartlets.js/src/lib/components/ComponentChildren.tsx +++ b/chartlets.js/src/lib/component/Children.tsx @@ -5,12 +5,12 @@ import { } from "@/lib/types/state/component"; import { Component } from "./Component"; -export interface ComponentChildrenProps { +export interface ChildrenProps { nodes?: ComponentNode[]; onChange: ComponentChangeHandler; } -export function ComponentChildren({ nodes, onChange }: ComponentChildrenProps) { +export function Children({ nodes, onChange }: ChildrenProps) { if (!nodes || nodes.length === 0) { return null; } diff --git a/chartlets.js/src/lib/component/Component.tsx b/chartlets.js/src/lib/component/Component.tsx new file mode 100644 index 00000000..2cad0537 --- /dev/null +++ b/chartlets.js/src/lib/component/Component.tsx @@ -0,0 +1,20 @@ +import { type ComponentChangeHandler } from "@/lib/types/state/event"; +import { registry } from "@/lib/component/Registry"; + +export interface ComponentProps { + type: string; + onChange: ComponentChangeHandler; +} + +export function Component(props: ComponentProps) { + const { type: componentType } = props; + const ActualComponent = registry.lookup(componentType); + if (typeof ActualComponent === "function") { + return ; + } else { + console.error( + `chartlets: invalid component type encountered: ${componentType}`, + ); + return null; + } +} diff --git a/chartlets.js/src/lib/component/Registry.test.ts b/chartlets.js/src/lib/component/Registry.test.ts new file mode 100644 index 00000000..bbbff336 --- /dev/null +++ b/chartlets.js/src/lib/component/Registry.test.ts @@ -0,0 +1,53 @@ +import { describe, it, expect } from "vitest"; + +import { RegistryImpl } from "@/lib/component/Registry"; + +describe("Test that RegistryImpl", () => { + it("works", () => { + const registry = new RegistryImpl(); + expect(registry.types).toEqual([]); + + const A = () => void 0; + const B = () => void 0; + const C = () => void 0; + const unregisterA = registry.register(A); + const unregisterB = registry.register(B); + const unregisterC = registry.register(C); + + expect(registry.lookup("A")).toBe(A); + expect(registry.lookup("B")).toBe(B); + expect(registry.lookup("C")).toBe(C); + expect(new Set(registry.types)).toEqual(new Set(["A", "B", "C"])); + + unregisterA(); + expect(registry.lookup("A")).toBeUndefined(); + expect(registry.lookup("B")).toBe(B); + expect(registry.lookup("C")).toBe(C); + expect(new Set(registry.types)).toEqual(new Set(["B", "C"])); + + unregisterB(); + expect(registry.lookup("A")).toBeUndefined(); + expect(registry.lookup("B")).toBeUndefined(); + expect(registry.lookup("C")).toBe(C); + expect(new Set(registry.types)).toEqual(new Set(["C"])); + + const C2 = () => void 0; + const unregisterC2 = registry.register(C2, "C"); + expect(registry.lookup("A")).toBeUndefined(); + expect(registry.lookup("B")).toBeUndefined(); + expect(registry.lookup("C")).toBe(C2); + expect(new Set(registry.types)).toEqual(new Set(["C"])); + + unregisterC2(); + expect(registry.lookup("A")).toBeUndefined(); + expect(registry.lookup("B")).toBeUndefined(); + expect(registry.lookup("C")).toBe(C); + expect(new Set(registry.types)).toEqual(new Set(["C"])); + + unregisterC(); + expect(registry.lookup("A")).toBeUndefined(); + expect(registry.lookup("B")).toBeUndefined(); + expect(registry.lookup("C")).toBeUndefined(); + expect(registry.types).toEqual([]); + }); +}); diff --git a/chartlets.js/src/lib/component/Registry.ts b/chartlets.js/src/lib/component/Registry.ts new file mode 100644 index 00000000..2c2f7d4f --- /dev/null +++ b/chartlets.js/src/lib/component/Registry.ts @@ -0,0 +1,56 @@ +import type { FC } from "react"; +import type { ComponentProps } from "@/lib/component/Component"; + +/** + * A registry for Chartlets components. + */ +export interface Registry { + /** + * Register a React component that renders a Chartlets component. + * + * @param component A functional React component. + * @param type The Chartlets component's type name. + * If not provided, `component.name` is used. + */ + register(component: FC, type?: string): () => void; + + /** + * Lookup the component of the provided type. + * + * @param type The Chartlets component's type name. + */ + lookup(type: string): FC | undefined; + + /** + * Get the type names of all registered components. + */ + types: string[]; +} + +// export for testing only +export class RegistryImpl implements Registry { + private components = new Map>(); + + register(component: FC, type?: string): () => void { + type = type || component.name; + const oldComponent = this.components.get(type); + this.components.set(type, component); + return () => { + if (typeof oldComponent === "function") { + this.components.set(type, oldComponent); + } else { + this.components.delete(type); + } + }; + } + + lookup(type: string): FC | undefined { + return this.components.get(type); + } + + get types(): string[] { + return Array.from(this.components.keys()); + } +} + +export const registry = new RegistryImpl(); diff --git a/chartlets.js/src/lib/components/Box.tsx b/chartlets.js/src/lib/components/Box.tsx index f63290b2..b6335544 100644 --- a/chartlets.js/src/lib/components/Box.tsx +++ b/chartlets.js/src/lib/components/Box.tsx @@ -1,21 +1,17 @@ import MuiBox from "@mui/material/Box"; -import { type ContainerState } from "@/lib/types/state/component"; -import { type ComponentChangeHandler } from "@/lib/types/state/event"; -import { ComponentChildren } from "./ComponentChildren"; +import type { ComponentState } from "@/lib/types/state/component"; +import { Children } from "../component/Children"; +import type { ComponentProps } from "@/lib/component/Component"; -export interface BoxState extends ContainerState { - type: "Box"; -} +interface BoxState extends ComponentState {} -export interface BoxProps extends Omit { - onChange: ComponentChangeHandler; -} +interface BoxProps extends ComponentProps, BoxState {} export function Box({ id, style, children, onChange }: BoxProps) { return ( - + ); } diff --git a/chartlets.js/src/lib/components/Button.tsx b/chartlets.js/src/lib/components/Button.tsx index 83f0a0b9..2f5f40a4 100644 --- a/chartlets.js/src/lib/components/Button.tsx +++ b/chartlets.js/src/lib/components/Button.tsx @@ -2,18 +2,16 @@ import { type MouseEvent } from "react"; import MuiButton from "@mui/material/Button"; import { type ComponentState } from "@/lib/types/state/component"; -import { type ComponentChangeHandler } from "@/lib/types/state/event"; +import type { ComponentProps } from "@/lib/component/Component"; -export interface ButtonState extends ComponentState { - type: "Button"; - text: string; +interface ButtonState extends ComponentState { + text?: string; } -export interface ButtonProps extends Omit { - onChange: ComponentChangeHandler; -} +interface ButtonProps extends ComponentProps, ButtonState {} export function Button({ + type, id, name, style, @@ -24,7 +22,7 @@ export function Button({ const handleClick = (_event: MouseEvent) => { if (id) { onChange({ - componentType: "Button", + componentType: type, id: id, property: "clicked", value: true, diff --git a/chartlets.js/src/lib/components/Checkbox.tsx b/chartlets.js/src/lib/components/Checkbox.tsx index 548529cb..140ef8fb 100644 --- a/chartlets.js/src/lib/components/Checkbox.tsx +++ b/chartlets.js/src/lib/components/Checkbox.tsx @@ -4,19 +4,17 @@ import MuiFormControl from "@mui/material/FormControl"; import MuiFormControlLabel from "@mui/material/FormControlLabel"; import { type ComponentState } from "@/lib/types/state/component"; -import { type ComponentChangeHandler } from "@/lib/types/state/event"; +import type { ComponentProps } from "@/lib/component/Component"; -export interface CheckboxState extends ComponentState { - type: "Checkbox"; - label: string; - value?: boolean; +interface CheckboxState extends ComponentState { + label?: string; + value?: boolean | undefined; } -export interface CheckboxProps extends Omit { - onChange: ComponentChangeHandler; -} +interface CheckboxProps extends ComponentProps, CheckboxState {} export function Checkbox({ + type, id, name, value, @@ -28,7 +26,7 @@ export function Checkbox({ const handleChange = (event: ChangeEvent) => { if (id) { return onChange({ - componentType: "Checkbox", + componentType: type, id: id, property: "value", value: event.currentTarget.checked, diff --git a/chartlets.js/src/lib/components/CircularProgress.tsx b/chartlets.js/src/lib/components/CircularProgress.tsx index bc1c842b..b75a80e6 100644 --- a/chartlets.js/src/lib/components/CircularProgress.tsx +++ b/chartlets.js/src/lib/components/CircularProgress.tsx @@ -1,16 +1,15 @@ import MuiCircularProgress from "@mui/material/CircularProgress"; import { type ComponentState } from "@/lib/types/state/component"; +import type { ComponentProps } from "@/lib/component/Component"; -export interface CircularProgressState extends ComponentState { - type: "CircularProgress"; +interface CircularProgressState extends ComponentState { size?: number | string; value?: number; variant?: "determinate" | "indeterminate"; } -export interface CircularProgressProps - extends Omit {} +interface CircularProgressProps extends ComponentProps, CircularProgressState {} export function CircularProgress({ id, diff --git a/chartlets.js/src/lib/components/Component.tsx b/chartlets.js/src/lib/components/Component.tsx deleted file mode 100644 index 0cfea9b0..00000000 --- a/chartlets.js/src/lib/components/Component.tsx +++ /dev/null @@ -1,42 +0,0 @@ -import { type ComponentState } from "@/lib/types/state/component"; -import { type ComponentChangeHandler } from "@/lib/types/state/event"; -import { Button, type ButtonProps } from "./Button"; -import { Box, type BoxProps } from "./Box"; -import { Checkbox, type CheckboxProps } from "./Checkbox"; -import { Select, type SelectProps } from "./Select"; -import { Plot, type PlotProps } from "./Plot"; -import { Typography, type TypographyProps } from "@/lib/components/Typography"; -import { - CircularProgress, - type CircularProgressProps, -} from "./CircularProgress"; - -export interface ComponentProps extends ComponentState { - onChange: ComponentChangeHandler; -} - -export function Component({ type, ...props }: ComponentProps) { - // TODO: allow for registering children via their types - // and make following code generic. - // - // const DashiComp = Registry.getComponent(link); - // return return ; - // - if (type === "Plot") { - return ; - } else if (type === "Select") { - return