Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 number Diff line number Diff 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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 number Diff line number Diff 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 Down Expand 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