-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #45 from bcdev/forman-x-reorganising_components
Reorganising and enhancing components
- Loading branch information
Showing
16 changed files
with
267 additions
and
137 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <ActualComponent {...props} />; | ||
} else { | ||
console.error( | ||
`chartlets: invalid component type encountered: ${componentType}`, | ||
); | ||
return null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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([]); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
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<ComponentProps>, type?: string): () => void; | ||
|
||
/** | ||
* Lookup the component of the provided type. | ||
* | ||
* @param type The Chartlets component's type name. | ||
*/ | ||
lookup(type: string): FC<ComponentProps> | undefined; | ||
|
||
/** | ||
* Get the type names of all registered components. | ||
*/ | ||
types: string[]; | ||
} | ||
|
||
// export for testing only | ||
export class RegistryImpl implements Registry { | ||
private components = new Map<string, FC<ComponentProps>>(); | ||
|
||
register(component: FC<ComponentProps>, 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<ComponentProps> | undefined { | ||
return this.components.get(type); | ||
} | ||
|
||
get types(): string[] { | ||
return Array.from(this.components.keys()); | ||
} | ||
} | ||
|
||
/** | ||
* The Chartly component registry. | ||
* | ||
* Use `registry.register(C)` to register your own component `C`. | ||
* | ||
* `C` must be a functional React component with at least the following | ||
* two properties: | ||
* | ||
* - `type: string`: your component's type name. | ||
* - `onChange: ComponentChangeHandler`: an event handler | ||
* that your component may call to signal change events. | ||
*/ | ||
export const registry = new RegistryImpl(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,17 @@ | ||
import MuiBox from "@mui/material/Box"; | ||
|
||
import { type BoxState } 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 BoxProps extends Omit<BoxState, "type"> { | ||
onChange: ComponentChangeHandler; | ||
} | ||
interface BoxState extends ComponentState {} | ||
|
||
interface BoxProps extends ComponentProps, BoxState {} | ||
|
||
export function Box({ id, style, children, onChange }: BoxProps) { | ||
return ( | ||
<MuiBox id={id} style={style}> | ||
<ComponentChildren nodes={children} onChange={onChange} /> | ||
<Children nodes={children} onChange={onChange} /> | ||
</MuiBox> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.