Skip to content

Commit ef12fa6

Browse files
committed
stopping here
1 parent 53ae761 commit ef12fa6

File tree

8 files changed

+47
-33
lines changed

8 files changed

+47
-33
lines changed

chartlets.js/CHANGES.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
* Add `multiple` property for `Select` component to enable the selection
44
of multiple elements. The `default` mode is supported at the moment.
55

6+
* Relaxed requirements for adding new components to Chartlets.js via
7+
plugins. Implementing `ComponentProps` is now optional. (#115)
8+
69
* Static information about callbacks retrieved from API is not cached
710
reducing unnecessary processing and improving performance. (#113)
811

9-
* Relaxed requirements for adding new components to Chartlets.js via
10-
plugins. Implementing `ComponentProps` is now optional. (#115)
11-
1212
* Callbacks will now only be invoked when there’s an actual change in state,
1313
reducing unnecessary processing and improving performance. (#112)
1414

chartlets.js/packages/lib/src/actions/configureFramework.test.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import type { ComponentType, FC } from "react";
1+
import type { FC } from "react";
22
import { describe, it, expect, beforeEach, afterEach } from "vitest";
33
import { configureFramework, resolvePlugin } from "./configureFramework";
44
import { store } from "@/store";
5-
import { registry } from "@/components/registry";
5+
import { type ComponentRegistration, registry } from "@/components/registry";
66
import type { HostStore } from "@/types/state/host";
77
import type { Plugin } from "@/types/state/plugin";
8-
import type { ComponentProps } from "@/components/Component";
98

10-
function getComponents(): [string, ComponentType<ComponentProps>][] {
11-
interface DivProps extends ComponentProps {
9+
function getComponents(): [string, ComponentRegistration][] {
10+
interface DivProps {
1211
text: string;
1312
}
1413
const Div: FC<DivProps> = ({ text }) => <div>{text}</div>;
1514
return [
16-
["A", Div as FC<ComponentProps>],
17-
["B", Div as FC<ComponentProps>],
15+
["A", Div],
16+
["B", Div],
1817
];
1918
}
2019

@@ -61,6 +60,14 @@ describe("configureFramework", () => {
6160
});
6261
expect(registry.types.length).toBe(2);
6362
});
63+
64+
it("should allow adding plain components", () => {
65+
expect(registry.types.length).toBe(0);
66+
configureFramework({
67+
plugins: [{ components: getComponents() }],
68+
});
69+
expect(registry.types.length).toBe(2);
70+
});
6471
});
6572

6673
describe("resolvePlugin", () => {

chartlets.js/packages/lib/src/components/Children.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ describe("Children", () => {
3737
text: string;
3838
}
3939
const Div: FC<DivProps> = ({ text }) => <div>{text}</div>;
40-
registry.register("Div", Div as FC<ComponentProps>);
40+
registry.register("Div", Div);
4141
const divProps = {
4242
type: "Div",
4343
text: "Hello",

chartlets.js/packages/lib/src/components/Children.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { type FC } from "react";
12
import { type ComponentChangeHandler } from "@/types/state/event";
23
import { type ComponentNode, isComponentState } from "@/types/state/component";
34
import { Component } from "./Component";
@@ -7,7 +8,10 @@ export interface ChildrenProps {
78
onChange: ComponentChangeHandler;
89
}
910

10-
export function Children({ nodes, onChange }: ChildrenProps) {
11+
export const Children: FC<ChildrenProps> = ({
12+
nodes,
13+
onChange,
14+
}: ChildrenProps) => {
1115
if (!nodes || nodes.length === 0) {
1216
return null;
1317
}
@@ -27,4 +31,4 @@ export function Children({ nodes, onChange }: ChildrenProps) {
2731
})}
2832
</>
2933
);
30-
}
34+
};

chartlets.js/packages/lib/src/components/Component.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ describe("Component", () => {
3131
text: string;
3232
}
3333
const Div: FC<DivProps> = ({ text }) => <div>{text}</div>;
34-
registry.register("Div", Div as FC<ComponentProps>);
34+
registry.register("Div", Div);
3535
const divProps = {
3636
type: "Div",
3737
id: "root",
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
1+
import { type FC } from "react";
12
import { type ComponentChangeHandler } from "@/types/state/event";
3+
import { isString } from "@/utils/isString";
24
import { registry } from "@/components/registry";
35

46
export interface ComponentProps {
57
type: string;
68
onChange: ComponentChangeHandler;
79
}
810

9-
export function Component(props: ComponentProps) {
10-
const { type: componentType } = props;
11-
const ActualComponent = registry.lookup(componentType);
11+
export const Component: FC<ComponentProps> = (props: ComponentProps) => {
12+
const ActualComponent = isString(props.type) && registry.lookup(props.type);
1213
if (typeof ActualComponent === "function") {
1314
return <ActualComponent {...props} />;
1415
} else {
@@ -20,4 +21,4 @@ export function Component(props: ComponentProps) {
2021
// );
2122
return null;
2223
}
23-
}
24+
};

chartlets.js/packages/lib/src/components/registry.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@ import type { ComponentType } from "react";
22

33
import type { ComponentProps } from "@/components/Component";
44

5+
export type ComponentRegistration =
6+
| ComponentType<Record<string, unknown>>
7+
| ComponentType<ComponentProps>;
8+
59
/**
610
* A registry for Chartlets components.
711
*/
812
export interface Registry {
913
/**
1014
* Register a React component that renders a Chartlets component.
1115
*
12-
* `component` must be a functional React component with at
13-
* least the following two component props:
16+
* `component` can be any React component. However, if you want to register
17+
* a custom, reactive component, then `component` must be of type
18+
* `ComponentType<ComponentProps>` where a `ComponentProps` has at
19+
* least the following two properties:
1420
*
1521
* - `type: string`: your component's type name.
1622
* This will be the same as the `type` used for registration.
@@ -23,14 +29,14 @@ export interface Registry {
2329
* @param type The Chartlets component's unique type name.
2430
* @param component A functional React component.
2531
*/
26-
register(type: string, component: ComponentType<ComponentProps>): () => void;
32+
register(type: string, component: ComponentRegistration): () => void;
2733

2834
/**
2935
* Lookup the component of the provided type.
3036
*
3137
* @param type The Chartlets component's type name.
3238
*/
33-
lookup(type: string): ComponentType<ComponentProps> | undefined;
39+
lookup(type: string): ComponentRegistration | undefined;
3440

3541
/**
3642
* Clears the registry.
@@ -46,9 +52,9 @@ export interface Registry {
4652

4753
// export for testing only
4854
export class RegistryImpl implements Registry {
49-
private components = new Map<string, ComponentType<ComponentProps>>();
55+
private components = new Map<string, ComponentRegistration>();
5056

51-
register(type: string, component: ComponentType<ComponentProps>): () => void {
57+
register(type: string, component: ComponentRegistration): () => void {
5258
const oldComponent = this.components.get(type);
5359
this.components.set(type, component);
5460
return () => {
@@ -60,7 +66,7 @@ export class RegistryImpl implements Registry {
6066
};
6167
}
6268

63-
lookup(type: string): ComponentType<ComponentProps> | undefined {
69+
lookup(type: string): ComponentRegistration | undefined {
6470
return this.components.get(type);
6571
}
6672

@@ -77,12 +83,5 @@ export class RegistryImpl implements Registry {
7783
* The Chartlets component registry.
7884
*
7985
* Use `registry.register("C", C)` to register your own component `C`.
80-
*
81-
* `C` must be a functional React component with at least the following
82-
* two properties:
83-
*
84-
* - `type: string`: your component's type name.
85-
* - `onChange: ComponentChangeHandler`: an event handler
86-
* that your component may call to signal change events.
8786
*/
8887
export const registry = new RegistryImpl();

chartlets.js/packages/lib/src/types/state/plugin.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ import type { ComponentProps } from "@/components/Component";
55
* A component registration - a pair comprising the component type name
66
* and the React component.
77
*/
8-
export type ComponentRegistration = [string, ComponentType<ComponentProps>];
8+
export type ComponentRegistration = [
9+
string,
10+
ComponentType<ComponentProps> | ComponentType,
11+
];
912

1013
/**
1114
* A framework plugin.

0 commit comments

Comments
 (0)