Skip to content
Merged
4 changes: 2 additions & 2 deletions dashi/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dashi/package.json
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "dashipopashi",
"version": "0.0.7",
"version": "0.0.8",
"description": "An experimental library for integrating interactive charts into existing JavaScript applications.",
"type": "module",
"files": [
Expand Down
6 changes: 4 additions & 2 deletions dashi/src/demo/actions/hidePanel.ts
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
import { updateContributionState } from "@/lib";
import { updateContributionContainer } from "@/lib";
import type { PanelState } from "@/demo/types";

export function hidePanel(panelIndex: number) {
updateContributionState<PanelState>("panels", panelIndex, { visible: false });
updateContributionContainer<PanelState>("panels", panelIndex, {
visible: false,
});
}
6 changes: 4 additions & 2 deletions dashi/src/demo/actions/showPanel.ts
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
import { updateContributionState } from "@/lib";
import { updateContributionContainer } from "@/lib";
import type { PanelState } from "@/demo/types";

export function showPanel(panelIndex: number) {
updateContributionState<PanelState>("panels", panelIndex, { visible: true });
updateContributionContainer<PanelState>("panels", panelIndex, {
visible: true,
});
}
38 changes: 19 additions & 19 deletions dashi/src/demo/components/Panel.tsx
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
import type { CSSProperties, ReactElement } from "react";
import CircularProgress from "@mui/material/CircularProgress";

import {
type ComponentChangeHandler,
type ContributionState,
Component,
} from "@/lib";
import { Component } from "@/lib";
import type { ComponentState, ComponentChangeHandler } from "@/lib";
import type { PanelState } from "@/demo/types";

const panelContainerStyle: CSSProperties = {
Expand All@@ -32,39 +28,43 @@ const panelContentStyle: CSSProperties = {
padding: 2,
};

interface PanelProps extends ContributionState<PanelState> {
interface PanelProps extends PanelState {
componentProps?: ComponentState;
componentStatus?: string;
componentError?: { message: string };
onChange: ComponentChangeHandler;
}

function Panel({
name,
state,
component,
componentResult,
title,
visible,
componentProps,
componentStatus,
componentError,
onChange,
}: PanelProps) {
if (!state.visible) {
if (!visible) {
return null;
}
let panelElement: ReactElement | null = null;
if (component) {
panelElement = <Component {...component} onChange={onChange} />;
} else if (componentResult.error) {
if (componentProps) {
panelElement = <Component {...componentProps} onChange={onChange} />;
} else if (componentError) {
panelElement = (
<span>
Error loading {name}: {componentResult.error.message}
Error loading panel {title}: {componentError.message}
</span>
);
} else if (componentResult.status === "pending") {
} else if (componentStatus === "pending") {
panelElement = (
<span>
<CircularProgress size={30} color="secondary" /> Loading {name}...
<CircularProgress size={30} color="secondary" /> Loading {title}...
</span>
);
}
return (
<div style={panelContainerStyle}>
<div style={panelHeaderStyle}>{state.title}</div>
<div style={panelHeaderStyle}>{title}</div>
<div style={panelContentStyle}>{panelElement}</div>
</div>
);
Expand Down
5 changes: 3 additions & 2 deletions dashi/src/demo/components/PanelsControl.tsx
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,15 +17,16 @@ function PanelsControl() {
<FormGroup sx={{ display: "flex", flexDirection: "row" }}>
{panelStates.map((panelState, panelIndex) => {
const id = `panels.${panelIndex}`;
const { title, visible } = panelState.container;
return (
<FormControlLabel
key={panelIndex}
label={panelState.state.title}
label={title}
control={
<Checkbox
color="secondary"
id={id}
checked={panelState.state.visible || false}
checked={visible || false}
value={panelIndex}
onChange={(e) => {
if (e.currentTarget.checked) {
Expand Down
30 changes: 13 additions & 17 deletions dashi/src/demo/components/PanelsRow.tsx
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
import type { JSX } from "react";

import { type ComponentChangeEvent, handleComponentChange } from "@/lib";
import { usePanelStates } from "@/demo/hooks";
import Panel from "./Panel";
Expand All@@ -17,23 +15,21 @@ function PanelsRow() {
) => {
handleComponentChange("panels", panelIndex, panelEvent);
};
const visiblePanels: JSX.Element[] = [];
panelStates.forEach((panelState, panelIndex) => {
if (panelState.state.visible) {
visiblePanels.push(
<Panel
key={panelIndex}
{...panelState}
onChange={(e) => handlePanelChange(panelIndex, e)}
/>,
);
}
const panels = panelStates.map((panelState, panelIndex) => {
const { container, component, componentResult } = panelState;
return (
<Panel
key={panelIndex}
{...container}
componentProps={component}
componentStatus={componentResult.status}
componentError={componentResult.error}
onChange={(e) => handlePanelChange(panelIndex, e)}
/>
);
});
const panelElements = <>{visiblePanels}</>;
return (
<div style={{ display: "flex", gap: 5, paddingTop: 10 }}>
{panelElements}
</div>
<div style={{ display: "flex", gap: 5, paddingTop: 10 }}>{panels}</div>
);
}

Expand Down
2 changes: 1 addition & 1 deletion dashi/src/lib/actions/configureFramework.ts
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
import { store } from "@/lib/store";
import type { FrameworkOptions } from "@/lib/types/state/store";
import { configureLogging } from "@/lib/utils/configureLogging";
import { configureLogging } from "@/lib/actions/helpers/configureLogging";
import { handleHostStoreChange } from "./handleHostStoreChange";

export function configureFramework<S extends object = object>(
Expand Down
5 changes: 3 additions & 2 deletions dashi/src/lib/actions/handleComponentChange.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,7 +17,7 @@ export function handleComponentChange(
contribIndex,
stateChanges: [
{
kind: "Component",
link: "component",
id: changeEvent.componentId,
property: changeEvent.propertyName,
value: changeEvent.propertyValue,
Expand DownExpand Up@@ -57,7 +57,8 @@ function getCallbackRequests(
const inputs = callback.inputs;
const inputIndex = inputs.findIndex(
(input) =>
(!input.kind || input.kind === "Component") &&
!input.noTrigger &&
(!input.link || input.link === "component") &&
input.id === changeEvent.componentId &&
input.property === changeEvent.propertyName,
);
Expand Down
9 changes: 6 additions & 3 deletions dashi/src/lib/actions/handleHostStoreChange.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,9 +5,9 @@ import type {
CallbackRef,
CallbackRequest,
ContribRef,
Input,
InputRef,
} from "@/lib/types/model/callback";
import type { Input } from "@/lib/types/model/channel";
import { getInputValues } from "@/lib/actions/helpers/getInputValues";
import { getValue, type PropertyPath } from "@/lib/utils/getValue";
import { invokeCallbacks } from "@/lib/actions/helpers/invokeCallbacks";
Expand DownExpand Up@@ -59,6 +59,9 @@ function getCallbackRequests<S extends object = object>(

const getHostStorePropertyRefs = memoizeOne(_getHostStorePropertyRefs);

/**
* Get the static list of host state property references for all contributions.
*/
function _getHostStorePropertyRefs(): PropertyRef[] {
const { contributionsRecord } = store.getState();
const propertyRefs: PropertyRef[] = [];
Expand All@@ -68,13 +71,13 @@ function _getHostStorePropertyRefs(): PropertyRef[] {
(contribution.callbacks || []).forEach(
(callback, callbackIndex) =>
(callback.inputs || []).forEach((input, inputIndex) => {
if (input.kind === "AppState") {
if (!input.noTrigger && input.link === "app") {
propertyRefs.push({
contribPoint,
contribIndex,
callbackIndex,
inputIndex,
propertyPath: input.property.split("."),
propertyPath: input.property!.split("."),
});
}
}),
Expand Down
10 changes: 5 additions & 5 deletions dashi/src/lib/actions/helpers/applyStateChangeRequests.test.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -35,7 +35,7 @@ describe("Test that applyContributionChangeRequests()", () => {
name: "",
extension: "",
componentResult: { status: "ok" },
state: { visible: true },
container: { visible: true },
component: componentTree,
},
],
Expand All@@ -46,7 +46,7 @@ describe("Test that applyContributionChangeRequests()", () => {
contribIndex: 0,
stateChanges: [
{
kind: "Component",
link: "component",
id: "dd1",
property: "value",
value: 14,
Expand All@@ -59,7 +59,7 @@ describe("Test that applyContributionChangeRequests()", () => {
contribIndex: 0,
stateChanges: [
{
kind: "Component",
link: "component",
id: "dd1",
property: "value",
value: 13,
Expand DownExpand Up@@ -88,7 +88,7 @@ describe("Test that applyContributionChangeRequests()", () => {
describe("Test that applyComponentStateChange()", () => {
it("changes state if values are different", () => {
const newState = applyComponentStateChange(componentTree, {
kind: "Component",
link: "component",
id: "cb1",
property: "value",
value: false,
Expand All@@ -99,7 +99,7 @@ describe("Test that applyComponentStateChange()", () => {

it("doesn't change the state if value stays the same", () => {
const newState = applyComponentStateChange(componentTree, {
kind: "Component",
link: "component",
id: "cb1",
property: "value",
value: true,
Expand Down
41 changes: 19 additions & 22 deletions dashi/src/lib/actions/helpers/applyStateChangeRequests.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,7 +10,7 @@ import type {
import type { ContribPoint } from "@/lib/types/model/extension";
import type { ContributionState } from "@/lib";
import { updateArray } from "@/lib/utils/updateArray";
import { isContainerState } from "@/lib/utils/isContainerState";
import { isContainerState } from "@/lib/actions/helpers/isContainerState";

export function applyStateChangeRequests(
stateChangeRequests: StateChangeRequest[],
Expand All@@ -37,8 +37,9 @@ function applyHostStateChanges(stateChangeRequests: StateChangeRequest[]) {
stateChangeRequests.forEach((stateChangeRequest) => {
hostState = applyStateChanges(
hostState,
stateChangeRequest.stateChanges,
"AppState",
stateChangeRequest.stateChanges.filter(
(stateChange) => stateChange.link === "app",
),
);
});
if (hostState !== hostStateOld) {
Expand All@@ -53,13 +54,9 @@ function applyComponentStateChanges(
) {
let component = componentOld;
if (component) {
stateChanges
.filter(
(stateChange) => !stateChange.kind || stateChange.kind === "Component",
)
.forEach((stateChange) => {
component = applyComponentStateChange(component!, stateChange);
});
stateChanges.forEach((stateChange) => {
component = applyComponentStateChange(component!, stateChange);
});
}
return component;
}
Expand All@@ -72,25 +69,27 @@ export function applyContributionChangeRequests(
stateChangeRequests.forEach(
({ contribPoint, contribIndex, stateChanges }) => {
const contribution = contributionsRecord[contribPoint][contribIndex];
const state = applyStateChanges(
contribution.state,
stateChanges,
"State",
const container = applyStateChanges(
contribution.container,
stateChanges.filter((stateChange) => stateChange.link === "container"),
);
const component = applyComponentStateChanges(
contribution.component,
stateChanges,
stateChanges.filter(
(stateChange) =>
!stateChange.link || stateChange.link === "component",
),
);
if (
state !== contribution.state ||
container !== contribution.container ||
component !== contribution.component
) {
contributionsRecord = {
...contributionsRecord,
[contribPoint]: updateArray<ContributionState>(
contributionsRecord[contribPoint],
contribIndex,
{ ...contribution, state, component },
{ ...contribution, container, component },
),
};
}
Expand DownExpand Up@@ -139,14 +138,12 @@ export function applyComponentStateChange(
export function applyStateChanges<S extends object>(
state: S | undefined,
stateChanges: StateChange[],
kind: "State" | "AppState",
): S | undefined {
stateChanges.forEach((stateChange) => {
if (
stateChange.kind === kind &&
(!state ||
(state as unknown as Record<string, unknown>)[stateChange.property] !==
stateChange.value)
!state ||
(state as unknown as Record<string, unknown>)[stateChange.property] !==
stateChange.value
) {
state = { ...state, [stateChange.property]: stateChange.value } as S;
}
Expand Down
Loading