@smwb/ui-solid 1.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +115 -0
- package/dist/assets/styles/less/components/appBar/appBar.entry.css +1 -1
- package/dist/assets/styles/less/components/avatar/avatar.entry.css +1 -1
- package/dist/assets/styles/less/components/badge/badge.entry.css +1 -1
- package/dist/assets/styles/less/components/breadcrumbs/breadcrumbs.entry.css +1 -1
- package/dist/assets/styles/less/components/button/button.entry.css +1 -1
- package/dist/assets/styles/less/components/buttonGroup/buttonGroup.entry.css +1 -1
- package/dist/assets/styles/less/components/dagView/dagView.entry.css +1 -1
- package/dist/assets/styles/less/components/meter/meter.entry.css +1 -1
- package/dist/assets/styles/less/components/screenDivider/screenDivider.entry.css +1 -1
- package/dist/assets/styles/less/components/sheet/sheet.entry.css +1 -1
- package/dist/assets/styles/less/components/statusDot/statusDot.entry.css +1 -1
- package/dist/assets/styles/less/components/tabGroups/tabGroups.entry.css +1 -1
- package/dist/assets/styles/less/components/tabs/tab/tab.entry.css +1 -1
- package/dist/assets/styles/less/components/toggle/toggle.entry.css +1 -1
- package/dist/assets/styles/less/components/treeView/treeView.entry.css +1 -1
- package/dist/assets/styles/less/tokens.entry.css +1 -1
- package/dist/components/dataDisplay/avatar/avatar.d.ts +5 -2
- package/dist/components/dataDisplay/avatar/avatar.js +9 -9
- package/dist/components/dataDisplay/avatar/avatar.js.map +1 -1
- package/dist/components/dataDisplay/badge/badge.d.ts +2 -1
- package/dist/components/dataDisplay/badge/badge.js.map +1 -1
- package/dist/components/dataDisplay/chart/chart.d.ts +16 -8
- package/dist/components/dataDisplay/chart/chartFull.d.ts +14 -0
- package/dist/components/dataDisplay/chart/core.d.ts +19 -0
- package/dist/components/dataDisplay/chart/index.d.ts +1 -1
- package/dist/components/dataDisplay/dagView/dagView.d.ts +4 -0
- package/dist/components/dataDisplay/dagView/dagView.js +124 -123
- package/dist/components/dataDisplay/dagView/dagView.js.map +1 -1
- package/dist/components/dataDisplay/dagView/index.d.ts +1 -1
- package/dist/components/dataDisplay/meter/index.d.ts +1 -1
- package/dist/components/dataDisplay/meter/meter.d.ts +14 -0
- package/dist/components/dataDisplay/meter/meter.js +32 -30
- package/dist/components/dataDisplay/meter/meter.js.map +1 -1
- package/dist/components/dataDisplay/statusDot/index.d.ts +1 -1
- package/dist/components/dataDisplay/statusDot/statusDot.d.ts +10 -1
- package/dist/components/dataDisplay/statusDot/statusDot.js +20 -11
- package/dist/components/dataDisplay/statusDot/statusDot.js.map +1 -1
- package/dist/components/dataDisplay/treeView/treeView.d.ts +18 -2
- package/dist/components/dataDisplay/treeView/treeView.js +140 -121
- package/dist/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/components/inputs/button/button.d.ts +7 -0
- package/dist/components/inputs/button/button.js +57 -51
- package/dist/components/inputs/button/button.js.map +1 -1
- package/dist/components/inputs/toggle/toggle.d.ts +6 -0
- package/dist/components/inputs/toggle/toggle.js +23 -23
- package/dist/components/inputs/toggle/toggle.js.map +1 -1
- package/dist/components/layout/appLayout/appLayout.d.ts +6 -1
- package/dist/components/layout/appLayout/appLayout.js +49 -42
- package/dist/components/layout/appLayout/appLayout.js.map +1 -1
- package/dist/components/layout/screenDivider/screenDivider.d.ts +12 -0
- package/dist/components/layout/screenDivider/screenDivider.js +87 -46
- package/dist/components/layout/screenDivider/screenDivider.js.map +1 -1
- package/dist/components/layout/sheet/sheet.d.ts +11 -0
- package/dist/components/layout/sheet/sheet.js +122 -102
- package/dist/components/layout/sheet/sheet.js.map +1 -1
- package/dist/components/layout/tabGroups/index.d.ts +1 -1
- package/dist/components/layout/tabGroups/tabGroups.d.ts +44 -1
- package/dist/components/layout/tabGroups/tabGroups.js +500 -460
- package/dist/components/layout/tabGroups/tabGroups.js.map +1 -1
- package/dist/components/layout/tabGroups/tabGroupsFocus.d.ts +16 -0
- package/dist/components/layout/tabGroups/tabGroupsFocus.js +102 -70
- package/dist/components/layout/tabGroups/tabGroupsFocus.js.map +1 -1
- package/dist/components/navigation/appBar/appBar.d.ts +12 -0
- package/dist/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/components/navigation/breadcrumbs/breadcrumbs.d.ts +9 -0
- package/dist/components/navigation/breadcrumbs/breadcrumbs.js +47 -31
- package/dist/components/navigation/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/components/navigation/tabs/tab/tab.js +71 -68
- package/dist/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/components/navigation/tabs/tabs.d.ts +15 -1
- package/dist/components/navigation/tabs/tabs.js +19 -16
- package/dist/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/components/navigation/tabs/tabsContext.d.ts +2 -0
- package/dist/components/navigation/tabs/tabsContext.js.map +1 -1
- package/dist/headless/components/dataDisplay/avatar/avatar.js +9 -9
- package/dist/headless/components/dataDisplay/avatar/avatar.js.map +1 -1
- package/dist/headless/components/dataDisplay/badge/badge.js.map +1 -1
- package/dist/headless/components/dataDisplay/dagView/dagView.js +133 -132
- package/dist/headless/components/dataDisplay/dagView/dagView.js.map +1 -1
- package/dist/headless/components/dataDisplay/meter/meter.js +32 -30
- package/dist/headless/components/dataDisplay/meter/meter.js.map +1 -1
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js +19 -10
- package/dist/headless/components/dataDisplay/statusDot/statusDot.js.map +1 -1
- package/dist/headless/components/dataDisplay/treeView/treeView.js +139 -120
- package/dist/headless/components/dataDisplay/treeView/treeView.js.map +1 -1
- package/dist/headless/components/inputs/button/button.js +57 -51
- package/dist/headless/components/inputs/button/button.js.map +1 -1
- package/dist/headless/components/inputs/toggle/toggle.js +23 -23
- package/dist/headless/components/inputs/toggle/toggle.js.map +1 -1
- package/dist/headless/components/layout/appLayout/appLayout.js +52 -45
- package/dist/headless/components/layout/appLayout/appLayout.js.map +1 -1
- package/dist/headless/components/layout/screenDivider/screenDivider.js +88 -47
- package/dist/headless/components/layout/screenDivider/screenDivider.js.map +1 -1
- package/dist/headless/components/layout/sheet/sheet.js +124 -104
- package/dist/headless/components/layout/sheet/sheet.js.map +1 -1
- package/dist/headless/components/layout/tabGroups/tabGroups.js +500 -460
- package/dist/headless/components/layout/tabGroups/tabGroups.js.map +1 -1
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js +102 -70
- package/dist/headless/components/layout/tabGroups/tabGroupsFocus.js.map +1 -1
- package/dist/headless/components/navigation/appBar/appBar.js.map +1 -1
- package/dist/headless/components/navigation/breadcrumbs/breadcrumbs.js +46 -30
- package/dist/headless/components/navigation/breadcrumbs/breadcrumbs.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tab/tab.js +70 -67
- package/dist/headless/components/navigation/tabs/tab/tab.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabs.js +19 -16
- package/dist/headless/components/navigation/tabs/tabs.js.map +1 -1
- package/dist/headless/components/navigation/tabs/tabsContext.js.map +1 -1
- package/dist/headless/primitives/publishHeaderOffset.js +19 -0
- package/dist/headless/primitives/publishHeaderOffset.js.map +1 -0
- package/dist/headless/source/components/dataDisplay/avatar/avatar.jsx +1 -0
- package/dist/headless/source/components/dataDisplay/avatar/avatar.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/badge/badge.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/chart/chart.jsx +14 -12
- package/dist/headless/source/components/dataDisplay/chart/chart.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/chart/chartFull.js +12 -0
- package/dist/headless/source/components/dataDisplay/chart/chartFull.js.map +7 -0
- package/dist/headless/source/components/dataDisplay/chart/core.js +11 -0
- package/dist/headless/source/components/dataDisplay/chart/core.js.map +7 -0
- package/dist/headless/source/components/dataDisplay/chart/index.js +1 -1
- package/dist/headless/source/components/dataDisplay/chart/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/dagView/dagView.jsx +2 -1
- package/dist/headless/source/components/dataDisplay/dagView/dagView.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/dagView/index.js.map +2 -2
- package/dist/headless/source/components/dataDisplay/meter/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/meter/meter.jsx +14 -2
- package/dist/headless/source/components/dataDisplay/meter/meter.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/statusDot/index.js.map +1 -1
- package/dist/headless/source/components/dataDisplay/statusDot/statusDot.jsx +13 -1
- package/dist/headless/source/components/dataDisplay/statusDot/statusDot.jsx.map +1 -1
- package/dist/headless/source/components/dataDisplay/treeView/treeView.jsx +16 -3
- package/dist/headless/source/components/dataDisplay/treeView/treeView.jsx.map +1 -1
- package/dist/headless/source/components/inputs/button/button.jsx +26 -1
- package/dist/headless/source/components/inputs/button/button.jsx.map +1 -1
- package/dist/headless/source/components/inputs/toggle/toggle.jsx +9 -2
- package/dist/headless/source/components/inputs/toggle/toggle.jsx.map +1 -1
- package/dist/headless/source/components/layout/appLayout/appLayout.jsx +14 -2
- package/dist/headless/source/components/layout/appLayout/appLayout.jsx.map +1 -1
- package/dist/headless/source/components/layout/screenDivider/screenDivider.jsx +102 -18
- package/dist/headless/source/components/layout/screenDivider/screenDivider.jsx.map +1 -1
- package/dist/headless/source/components/layout/sheet/sheet.jsx +14 -1
- package/dist/headless/source/components/layout/sheet/sheet.jsx.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/index.js.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroups.jsx +55 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroups.jsx.map +1 -1
- package/dist/headless/source/components/layout/tabGroups/tabGroupsFocus.js +42 -0
- package/dist/headless/source/components/layout/tabGroups/tabGroupsFocus.js.map +2 -2
- package/dist/headless/source/components/navigation/appBar/appBar.jsx.map +1 -1
- package/dist/headless/source/components/navigation/breadcrumbs/breadcrumbs.jsx +39 -4
- package/dist/headless/source/components/navigation/breadcrumbs/breadcrumbs.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tab/tab.jsx +7 -1
- package/dist/headless/source/components/navigation/tabs/tab/tab.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tabs.jsx +5 -1
- package/dist/headless/source/components/navigation/tabs/tabs.jsx.map +1 -1
- package/dist/headless/source/components/navigation/tabs/tabsContext.js.map +2 -2
- package/dist/headless/source/index.js +8 -1
- package/dist/headless/source/index.js.map +2 -2
- package/dist/headless/source/primitives/publishHeaderOffset.js +34 -0
- package/dist/headless/source/primitives/publishHeaderOffset.js.map +7 -0
- package/dist/index.d.ts +5 -5
- package/dist/primitives/publishHeaderOffset.d.ts +7 -0
- package/dist/primitives/publishHeaderOffset.js +19 -0
- package/dist/primitives/publishHeaderOffset.js.map +1 -0
- package/dist/source/components/dataDisplay/avatar/avatar.jsx +1 -0
- package/dist/source/components/dataDisplay/avatar/avatar.jsx.map +1 -1
- package/dist/source/components/dataDisplay/badge/badge.jsx.map +1 -1
- package/dist/source/components/dataDisplay/chart/chart.jsx +14 -12
- package/dist/source/components/dataDisplay/chart/chart.jsx.map +1 -1
- package/dist/source/components/dataDisplay/chart/chartFull.js +12 -0
- package/dist/source/components/dataDisplay/chart/chartFull.js.map +7 -0
- package/dist/source/components/dataDisplay/chart/core.js +11 -0
- package/dist/source/components/dataDisplay/chart/core.js.map +7 -0
- package/dist/source/components/dataDisplay/chart/index.js +1 -1
- package/dist/source/components/dataDisplay/chart/index.js.map +1 -1
- package/dist/source/components/dataDisplay/dagView/dagView.jsx +2 -1
- package/dist/source/components/dataDisplay/dagView/dagView.jsx.map +1 -1
- package/dist/source/components/dataDisplay/dagView/index.js.map +2 -2
- package/dist/source/components/dataDisplay/meter/index.js.map +1 -1
- package/dist/source/components/dataDisplay/meter/meter.jsx +14 -2
- package/dist/source/components/dataDisplay/meter/meter.jsx.map +1 -1
- package/dist/source/components/dataDisplay/statusDot/index.js.map +1 -1
- package/dist/source/components/dataDisplay/statusDot/statusDot.jsx +13 -1
- package/dist/source/components/dataDisplay/statusDot/statusDot.jsx.map +1 -1
- package/dist/source/components/dataDisplay/treeView/treeView.jsx +16 -3
- package/dist/source/components/dataDisplay/treeView/treeView.jsx.map +1 -1
- package/dist/source/components/inputs/button/button.jsx +26 -1
- package/dist/source/components/inputs/button/button.jsx.map +1 -1
- package/dist/source/components/inputs/toggle/toggle.jsx +9 -2
- package/dist/source/components/inputs/toggle/toggle.jsx.map +1 -1
- package/dist/source/components/layout/appLayout/appLayout.jsx +14 -2
- package/dist/source/components/layout/appLayout/appLayout.jsx.map +1 -1
- package/dist/source/components/layout/screenDivider/screenDivider.jsx +102 -18
- package/dist/source/components/layout/screenDivider/screenDivider.jsx.map +1 -1
- package/dist/source/components/layout/sheet/sheet.jsx +14 -1
- package/dist/source/components/layout/sheet/sheet.jsx.map +1 -1
- package/dist/source/components/layout/tabGroups/index.js.map +1 -1
- package/dist/source/components/layout/tabGroups/tabGroups.jsx +55 -1
- package/dist/source/components/layout/tabGroups/tabGroups.jsx.map +1 -1
- package/dist/source/components/layout/tabGroups/tabGroupsFocus.js +42 -0
- package/dist/source/components/layout/tabGroups/tabGroupsFocus.js.map +2 -2
- package/dist/source/components/navigation/appBar/appBar.jsx.map +1 -1
- package/dist/source/components/navigation/breadcrumbs/breadcrumbs.jsx +39 -4
- package/dist/source/components/navigation/breadcrumbs/breadcrumbs.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tab/tab.jsx +7 -1
- package/dist/source/components/navigation/tabs/tab/tab.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tabs.jsx +5 -1
- package/dist/source/components/navigation/tabs/tabs.jsx.map +1 -1
- package/dist/source/components/navigation/tabs/tabsContext.js.map +2 -2
- package/dist/source/index.js +8 -1
- package/dist/source/index.js.map +2 -2
- package/dist/source/primitives/publishHeaderOffset.js +34 -0
- package/dist/source/primitives/publishHeaderOffset.js.map +7 -0
- package/package.json +9 -3
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../../src/components/dataDisplay/chart/core.ts"],
|
|
4
|
+
"sourcesContent": ["// The `@smwb/ui-solid/chart/core` entry: the chart with no default loader.\n// Nothing here reaches `echarts` at run time, so an app that gives `Chart` its\n// own `loader` (a module built on `echarts/core`) gets no copy of the whole\n// library in its bundle.\nimport type { JSX } from \"solid-js\";\nimport { ChartCore, type ChartModule, type ChartProps as ChartPropsWithDefaultLoader } from \"./chart\";\n\n/** The props of `Chart`, with `loader` required: there is no default to fall back on. */\nexport type ChartProps = Omit<ChartPropsWithDefaultLoader, \"loader\"> & {\n /**\n * Loads ECharts in the browser: `() => import(\"./my-echarts\")`, a module that\n * registers only the charts you use with `echarts/core` and exports its `init`.\n */\n loader: () => Promise<ChartModule>;\n};\n\n/**\n * An ECharts chart in the theme's palette, with no built-in ECharts: `loader`\n * is required, and the whole library is never part of your bundle.\n */\nexport const Chart: (props: ChartProps) => JSX.Element = ChartCore;\n\nexport default Chart;\nexport type { ChartEventParams, ChartInstance, ChartModule } from \"./chart\";\nexport { chartTheme, readChartPalette } from \"./chartTheme\";\nexport type { ChartOption, ChartPalette } from \"./chartTheme\";\n"],
|
|
5
|
+
"mappings": "AAKA,SAAS,iBAAmF;AAerF,MAAM,QAA4C;AAEzD,IAAO,eAAQ;AAEf,SAAS,YAAY,wBAAwB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/components/dataDisplay/chart/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { Chart, default } from \"./
|
|
4
|
+
"sourcesContent": ["export { Chart, default } from \"./chartFull\";\nexport type { ChartProps, ChartEventParams, ChartInstance, ChartModule } from \"./chart\";\nexport { chartTheme, readChartPalette } from \"./chartTheme\";\nexport type { ChartOption, ChartPalette } from \"./chartTheme\";\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,WAAAA,gBAAe;AAE/B,SAAS,YAAY,wBAAwB;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -43,7 +43,7 @@ const DEFAULT_LABELS = {
|
|
|
43
43
|
fitView: "Fit to view",
|
|
44
44
|
controls: "Zoom"
|
|
45
45
|
};
|
|
46
|
-
const NODE_KEYS = ["label", "status", "accent", "width", "height", "data", "disabled"];
|
|
46
|
+
const NODE_KEYS = ["label", "status", "accent", "variant", "width", "height", "data", "disabled"];
|
|
47
47
|
const INNER_FOCUSABLE = 'a[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [tabindex], [contenteditable]:not([contenteditable="false"])';
|
|
48
48
|
const cssLength = (value) => typeof value === "number" ? `${value}px` : value;
|
|
49
49
|
const sameList = (a, b) => a.length === b.length && a.every((value, i) => value === b[i]);
|
|
@@ -523,6 +523,7 @@ function DagView(props) {
|
|
|
523
523
|
"smwb-dag-view__node--disabled": Boolean(node()?.disabled)
|
|
524
524
|
})}
|
|
525
525
|
data-status={node()?.status}
|
|
526
|
+
data-variant={node()?.variant}
|
|
526
527
|
aria-selected={state.selected ? "true" : "false"}
|
|
527
528
|
aria-disabled={node()?.disabled ? "true" : void 0}
|
|
528
529
|
aria-describedby={description(id) ? descriptionId() : void 0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/components/dataDisplay/dagView/dagView.tsx"],"sourcesContent":["import {\n DEV,\n For,\n type JSX,\n Show,\n createEffect,\n createMemo,\n createSelector,\n createSignal,\n createUniqueId,\n mergeProps,\n on,\n onCleanup,\n onMount,\n splitProps,\n untrack,\n} from \"solid-js\";\nimport cn from \"clsx\";\nimport { createControllableState } from \"../../../primitives/createControllableState\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\nimport { mergeStyle } from \"../../../primitives/mergeStyle\";\nimport {\n type DagDirection,\n type DagLayoutEdge,\n type DagLayoutInput,\n type DagLayoutNode,\n type DagLayoutResult,\n dagEdgePath,\n dagLayout,\n} from \"./dagLayout\";\nimport { type Viewport, centerOn, createPanZoom, fitBounds, isVisible, viewportTransform, zoomAt } from \"./panZoom\";\n\n/** A node's status: a built-in one, coloured by the theme, or any word of the app's, styled by `[data-status]`. */\nexport type DagViewStatus =\n | \"idle\"\n | \"pending\"\n | \"running\"\n | \"success\"\n | \"warning\"\n | \"error\"\n | \"skipped\"\n | (string & {});\n\nexport interface DagViewNode<T = unknown> {\n /** Unique among the nodes; edges name nodes by it. */\n id: string;\n /** What the default node shows, and its accessible name; the id unless given. */\n label?: JSX.Element;\n /** Colours the node's accent from the theme. */\n status?: DagViewStatus | undefined;\n /** The node's accent colour, over its status colour: any CSS colour. */\n accent?: string | undefined;\n /** The node's width in pixels; `nodeWidth` unless given. */\n width?: number | undefined;\n /** The node's height in pixels; `nodeHeight` unless given. */\n height?: number | undefined;\n /** Anything of the app's, handed back to `renderNode` and `onNodeClick`. */\n data?: T;\n /** Shown, focusable, but not selectable. */\n disabled?: boolean | undefined;\n}\n\nexport interface DagViewEdge {\n /** `source->target` unless given. */\n id?: string | undefined;\n /** The id of the node the edge starts from: the one depended on. */\n source: string;\n /** The id of the node the edge points to: the one that depends on `source`. */\n target: string;\n}\n\n/** A node's state for `renderNode`. Its fields are reactive: read them in JSX or an effect. */\nexport interface DagViewNodeState {\n readonly selected: boolean;\n /** Next to the selected node: \"upstream\" feeds it, \"downstream\" depends on it. */\n readonly related: \"upstream\" | \"downstream\" | null;\n /** Set apart from the selected node and its neighbours, with `dimUnrelated`. */\n readonly dimmed: boolean;\n /** Has keyboard focus. */\n readonly focused: boolean;\n}\n\n/** Where the graph is: moved by x, y (pixels) and scaled by zoom. */\nexport type DagViewViewport = Viewport;\n\n/** Moves the view from outside; handed over by `apiRef` once the graph is in the page. */\nexport interface DagViewApi {\n /** Fits the whole graph in view. */\n fitView(): void;\n /** Zooms to `zoom` around the middle of the view. */\n zoomTo(zoom: number): void;\n /** Zooms by `factor` around the middle of the view. */\n zoomBy(factor: number): void;\n /** Moves the node with this id to the middle of the view. */\n centerNode(id: string): void;\n}\n\n/** Texts for assistive technology and the zoom buttons, English by default. */\nexport interface DagViewLabels {\n /** What the graph is called as a widget: \"dependency graph\". */\n roleDescription: string;\n /** \"Status\", before a node's status word. */\n status: string;\n /** \"Depends on\", before the names of the nodes a node's edges come from. */\n dependsOn: string;\n /** \"Required by\", before the names of the nodes a node's edges go to. */\n requiredBy: string;\n /** Status words, shown on the default nodes and read out: { running: \"Running\", … }. */\n statuses: Record<string, string>;\n zoomIn: string;\n zoomOut: string;\n fitView: string;\n /** The name of the group of zoom buttons. */\n controls: string;\n}\n\nexport interface DagViewProps<T = unknown> extends Omit<JSX.HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n /** What the graph shows: its accessible name. */\n label: string;\n /** The graph in words, for screen readers; it is there on the server too. */\n summary?: string | undefined;\n /** The nodes. A change of status, label or data alone does not lay the graph out again. */\n nodes: readonly DagViewNode<T>[];\n /** The edges, from the node depended on to the node that depends on it. */\n edges: readonly DagViewEdge[];\n /**\n * Draws a node's content inside its box; the default shows a status dot,\n * the label and the status word. Called once per node: `node` and `state`\n * are reactive, so read their fields in JSX. Keep the content\n * non-interactive where you can: a node is an ARIA option, whose content\n * assistive technology may read as plain text, and a click in it also\n * selects the node. Links and buttons in it are left out of the Tab order\n * except in the node that is the graph's Tab stop.\n */\n renderNode?: ((node: DagViewNode<T>, state: DagViewNodeState) => JSX.Element) | undefined;\n /** Which way the layers run: \"LR\" (left to right, default) or \"TB\" (top to bottom). */\n direction?: DagDirection | undefined;\n /** A node's width in pixels, unless the node sets its own; 180 by default. */\n nodeWidth?: number | undefined;\n /** A node's height in pixels, unless the node sets its own; 56 by default. */\n nodeHeight?: number | undefined;\n /** The space between layers in pixels; 64 by default. */\n rankGap?: number | undefined;\n /** The space between nodes in a layer in pixels; 24 by default. */\n nodeGap?: number | undefined;\n /** Lays the graph out in place of the built-in layout, e.g. with dagre or elk. It must be synchronous. */\n layout?: ((input: DagLayoutInput) => DagLayoutResult) | undefined;\n /** The selected node's id (controlled); null selects nothing. */\n selectedId?: string | null | undefined;\n /** The node selected at first (uncontrolled). */\n defaultSelectedId?: string | null | undefined;\n /** A node was selected (its id) or the selection was cleared (null). */\n onSelectedChange?: ((id: string | null) => void) | undefined;\n /** A node was clicked, or chosen with Enter or Space. Not called for a disabled node. */\n onNodeClick?: ((node: DagViewNode<T>, event: MouseEvent | KeyboardEvent) => void) | undefined;\n /** Fades the nodes and edges that are not next to the selected node. */\n dimUnrelated?: boolean | undefined;\n /** Where the graph is (controlled). */\n viewport?: DagViewViewport | undefined;\n /** Where the graph is at first (uncontrolled); with `fit={false}` the page does not move after it loads. */\n defaultViewport?: DagViewViewport | undefined;\n /** The view moved or zoomed: at most once per frame during a gesture. */\n onViewportChange?: ((viewport: DagViewViewport) => void) | undefined;\n /** Fits the graph in view once it is in the page, and again when its nodes or edges change; true by default. */\n fit?: boolean | undefined;\n /** The smallest zoom; 0.1 by default. */\n minZoom?: number | undefined;\n /** The largest zoom; 2 by default. */\n maxZoom?: number | undefined;\n /** What a plain mouse wheel does: \"zoom\" (default), \"pan\", or \"none\" (the page scrolls). Ctrl+wheel and a trackpad pinch always zoom. */\n wheel?: \"zoom\" | \"pan\" | \"none\" | undefined;\n /** Shows the zoom in, zoom out and fit buttons; true by default. */\n controls?: boolean | undefined;\n /** Texts for assistive technology and the buttons, over the English defaults. */\n labels?: Partial<DagViewLabels> | undefined;\n /**\n * The graph's height: a number of pixels or any CSS length; 480 by default,\n * from the stylesheet, so a height in `style` works too. It fills the width.\n */\n height?: number | string | undefined;\n /** Gets the functions that move the view from outside. */\n apiRef?: ((api: DagViewApi) => void) | undefined;\n /** Test id of the root `<div>`; `dag-view` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLDivElement>;\n}\n\n/** Room around the graph inside its world, in pixels. */\nconst PADDING = 24;\n\nconst DEFAULT_LABELS: DagViewLabels = {\n roleDescription: \"dependency graph\",\n status: \"Status\",\n dependsOn: \"Depends on\",\n requiredBy: \"Required by\",\n statuses: {\n idle: \"Idle\",\n pending: \"Pending\",\n running: \"Running\",\n success: \"Success\",\n warning: \"Warning\",\n error: \"Error\",\n skipped: \"Skipped\",\n },\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n fitView: \"Fit to view\",\n controls: \"Zoom\",\n};\n\nconst NODE_KEYS = [\"label\", \"status\", \"accent\", \"width\", \"height\", \"data\", \"disabled\"] as const;\n\n/** What can take focus inside a node's own content. */\nconst INNER_FOCUSABLE =\n 'a[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [tabindex], [contenteditable]:not([contenteditable=\"false\"])';\n\nconst cssLength = (value: number | string): string => (typeof value === \"number\" ? `${value}px` : value);\n\nconst sameList = (a: readonly string[], b: readonly string[]): boolean =>\n a.length === b.length && a.every((value, i) => value === b[i]);\n\n/** A node's name in words, for descriptions: its label when that is text, else its id. */\nconst nameOf = (node: DagViewNode<unknown> | undefined, id: string): string => {\n const label = node?.label;\n return typeof label === \"string\" || typeof label === \"number\" ? String(label) : id;\n};\n\nconst warn = DEV ? (message: string): void => console.warn(`[smwb] DagView: ${message}`) : undefined;\n\n/**\n * A directed graph of dependencies: nodes in layers, left to right or top to\n * bottom, joined by arrows. A node is selected by a click or the keyboard, and\n * the edges into and out of it light up; the view pans and zooms with a mouse,\n * a trackpad, touch or the keyboard.\n */\nexport function DagView<T = unknown>(props: DagViewProps<T>): JSX.Element {\n const merged = mergeProps(\n {\n direction: \"LR\" as DagDirection,\n nodeWidth: 180,\n nodeHeight: 56,\n rankGap: 64,\n nodeGap: 24,\n fit: true,\n minZoom: 0.1,\n maxZoom: 2,\n wheel: \"zoom\" as \"zoom\" | \"pan\" | \"none\",\n controls: true,\n },\n props\n );\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"style\",\n \"label\",\n \"summary\",\n \"nodes\",\n \"edges\",\n \"renderNode\",\n \"direction\",\n \"nodeWidth\",\n \"nodeHeight\",\n \"rankGap\",\n \"nodeGap\",\n \"layout\",\n \"selectedId\",\n \"defaultSelectedId\",\n \"onSelectedChange\",\n \"onNodeClick\",\n \"dimUnrelated\",\n \"viewport\",\n \"defaultViewport\",\n \"onViewportChange\",\n \"fit\",\n \"minZoom\",\n \"maxZoom\",\n \"wheel\",\n \"controls\",\n \"labels\",\n \"height\",\n \"apiRef\",\n \"ref\",\n \"data-testid\",\n ]);\n\n const uid = createUniqueId();\n const arrowId = `${uid}-arrow`;\n const activeArrowId = `${uid}-arrow-active`;\n const summaryId = `${uid}-summary`;\n let root!: HTMLDivElement;\n const elements = new Map<string, HTMLElement>();\n\n const labels = createMemo(\n (): DagViewLabels => ({\n ...DEFAULT_LABELS,\n ...local.labels,\n statuses: { ...DEFAULT_LABELS.statuses, ...local.labels?.statuses },\n })\n );\n const statusWord = (status: string): string => labels().statuses[status] ?? status;\n\n // ---- Nodes and layout ----\n\n const byId = createMemo(() => {\n const map = new Map<string, DagViewNode<T>>();\n for (const node of local.nodes) if (!map.has(node.id)) map.set(node.id, node);\n return map;\n });\n // Nodes are drawn by id, so content stays mounted when the app replaces a\n // node object to change its status.\n const ids = createMemo(() => [...byId().keys()], [], { equals: sameList });\n\n // The layout depends only on the graph's shape; a status change leaves it be.\n const structure = createMemo(\n () => {\n const nodes = [...byId().values()].map((node) => ({\n id: node.id,\n width: node.width ?? local.nodeWidth,\n height: node.height ?? local.nodeHeight,\n }));\n const edges = local.edges.map((edge) => ({ id: edge.id, source: edge.source, target: edge.target }));\n const input: DagLayoutInput = {\n nodes,\n edges,\n direction: local.direction,\n rankGap: local.rankGap,\n nodeGap: local.nodeGap,\n warn,\n };\n const key = JSON.stringify([\n local.direction,\n local.rankGap,\n local.nodeGap,\n nodes.map((n) => [n.id, n.width, n.height]),\n edges.map((e) => [e.id ?? null, e.source, e.target]),\n ]);\n return { key, input };\n },\n undefined,\n { equals: (a, b) => a.key === b.key }\n );\n const layout = createMemo(() => (local.layout ?? dagLayout)(structure().input));\n\n // The flow of a layer runs along x in LR and along y in TB; across it is the other one.\n const across = (node: DagLayoutNode): number => (local.direction === \"TB\" ? node.x : node.y);\n\n const graph = createMemo(() => {\n const result = layout();\n const incoming = new Map<string, DagLayoutEdge[]>();\n const outgoing = new Map<string, DagLayoutEdge[]>();\n for (const edge of result.edges) {\n if (!incoming.has(edge.target)) incoming.set(edge.target, []);\n if (!outgoing.has(edge.source)) outgoing.set(edge.source, []);\n incoming.get(edge.target)!.push(edge);\n outgoing.get(edge.source)!.push(edge);\n }\n const ordered = [...result.nodes.values()].sort((a, b) => a.layer - b.layer || across(a) - across(b));\n const layers = new Map<number, DagLayoutNode[]>();\n for (const node of ordered) {\n if (!layers.has(node.layer)) layers.set(node.layer, []);\n layers.get(node.layer)!.push(node);\n }\n return { incoming, outgoing, ordered, layers };\n });\n\n // ---- Selection ----\n\n const [selected, setSelected] = createControllableState<string | null>({\n value: () => local.selectedId,\n defaultValue: untrack(() => local.defaultSelectedId) ?? null,\n onChange: (id) => local.onSelectedChange?.(id),\n });\n const isSelected = createSelector(selected);\n\n const relations = createMemo(() => {\n const id = selected();\n const edges = new Map<string, \"upstream\" | \"downstream\">();\n const nodes = new Map<string, \"upstream\" | \"downstream\">();\n if (id === null || !layout().nodes.has(id)) return { active: false, edges, nodes };\n const { incoming, outgoing } = graph();\n for (const edge of incoming.get(id) ?? []) {\n edges.set(edge.id, \"upstream\");\n nodes.set(edge.source, \"upstream\");\n }\n for (const edge of outgoing.get(id) ?? []) {\n edges.set(edge.id, \"downstream\");\n nodes.set(edge.target, \"downstream\");\n }\n return { active: true, edges, nodes };\n });\n\n // ---- Focus: one tab stop, on the last focused node, else the selected one, else the first ----\n\n const [active, setActive] = createSignal<string | null>(null);\n const [focused, setFocused] = createSignal<string | null>(null);\n const tabStop = createMemo(() => {\n const nodes = layout().nodes;\n const last = active();\n if (last !== null && nodes.has(last)) return last;\n const chosen = selected();\n if (chosen !== null && nodes.has(chosen)) return chosen;\n return graph().ordered[0]?.id ?? null;\n });\n\n // ---- Viewport ----\n\n const [viewport, setViewport] = createControllableState<Viewport>({\n value: () => local.viewport,\n defaultValue: untrack(() => local.defaultViewport) ?? { x: 0, y: 0, zoom: 1 },\n onChange: (next) => local.onViewportChange?.(next),\n });\n const [interacting, setInteracting] = createSignal(false);\n const far = createMemo(() => viewport().zoom < 0.45);\n\n const size = (): { width: number; height: number } => ({\n width: root?.clientWidth ?? 0,\n height: root?.clientHeight ?? 0,\n });\n const hasSize = (): boolean => {\n const { width, height } = size();\n return width > 0 && height > 0;\n };\n const worldSize = (): { width: number; height: number } => ({\n width: layout().width + PADDING * 2,\n height: layout().height + PADDING * 2,\n });\n const nodeRect = (id: string): { x: number; y: number; width: number; height: number } | undefined => {\n const box = layout().nodes.get(id);\n return box && { x: box.x + PADDING, y: box.y + PADDING, width: box.width, height: box.height };\n };\n\n const api: DagViewApi = {\n fitView() {\n if (!hasSize()) return;\n const world = worldSize();\n setViewport(\n fitBounds(\n { x: 0, y: 0, ...world },\n size(),\n 0,\n local.minZoom,\n Math.max(local.minZoom, Math.min(1, local.maxZoom))\n )\n );\n },\n zoomTo(zoom) {\n api.zoomBy(zoom / viewport().zoom);\n },\n zoomBy(factor) {\n const { width, height } = size();\n setViewport(zoomAt(viewport(), { x: width / 2, y: height / 2 }, factor, local.minZoom, local.maxZoom));\n },\n centerNode(id) {\n const rect = nodeRect(id);\n if (!rect) return;\n setViewport(centerOn(viewport(), { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 }, size()));\n },\n };\n\n const ensureVisible = (id: string): void => {\n const rect = nodeRect(id);\n if (rect && hasSize() && !isVisible(viewport(), rect, size(), 8)) api.centerNode(id);\n };\n\n // Fit once the graph has a size, and again when its shape changes. At zero\n // size (a hidden tab) the fit waits for the first resize that gives one.\n let fitPending = false;\n const tryFit = (): void => {\n if (!fitPending || !hasSize()) return;\n fitPending = false;\n api.fitView();\n };\n createEffect(\n on(\n layout,\n () => {\n if (!untrack(() => local.fit)) return;\n fitPending = true;\n tryFit();\n },\n { defer: true }\n )\n );\n\n onMount(() => {\n const dispose = createPanZoom(root, {\n viewport,\n write: setViewport,\n minZoom: () => local.minZoom,\n maxZoom: () => local.maxZoom,\n wheel: () => local.wheel,\n onInteracting: setInteracting,\n });\n let frame = 0;\n const resizeObserver =\n typeof ResizeObserver === \"function\"\n ? new ResizeObserver(() => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(tryFit);\n })\n : undefined;\n resizeObserver?.observe(root);\n onCleanup(() => {\n dispose();\n resizeObserver?.disconnect();\n cancelAnimationFrame(frame);\n });\n fitPending = local.fit;\n tryFit();\n local.apiRef?.(api);\n });\n\n // ---- Interaction ----\n\n const choose = (id: string, event: MouseEvent | KeyboardEvent): void => {\n const node = byId().get(id);\n if (!node || node.disabled) return;\n setSelected(id);\n local.onNodeClick?.(node, event);\n };\n\n const focusNode = (id: string | undefined): void => {\n if (id === undefined) return;\n setActive(id);\n elements.get(id)?.focus({ preventScroll: true });\n ensureVisible(id);\n };\n\n // A node that goes away takes its selection with it, and focus moves to the\n // Tab stop rather than dropping to the page. Only a node that was there\n // counts: a selection given before its node loads is kept.\n createEffect<readonly string[] | undefined>((before) => {\n const now = ids();\n if (before) {\n untrack(() => {\n const present = new Set(now);\n const chosen = selected();\n if (chosen !== null && !present.has(chosen) && before.includes(chosen)) setSelected(null);\n const had = focused();\n if (had === null || present.has(had)) return;\n setFocused(null);\n const doc = root?.ownerDocument;\n const stop = tabStop();\n if (doc && (doc.activeElement === null || doc.activeElement === doc.body) && stop !== null)\n elements.get(stop)?.focus({ preventScroll: true });\n });\n }\n return now;\n });\n\n // One Tab stop: focusables in `renderNode` content (a link, a button) are\n // taken out of the Tab order, except in the node that is the Tab stop. Their\n // own tabindex comes back when their node becomes it.\n const ownTabIndex = new WeakMap<Element, string | null>();\n // The value the component wrote last, so its own writes can be told apart\n // from the caller's in the attribute records below.\n const writtenTabIndex = new WeakMap<Element, string | null>();\n const syncInnerTabStops = (): void => {\n const stop = untrack(tabStop);\n for (const [id, el] of elements) {\n for (const inner of el.querySelectorAll(INNER_FOCUSABLE)) {\n if (!ownTabIndex.has(inner)) ownTabIndex.set(inner, inner.getAttribute(\"tabindex\"));\n const own = ownTabIndex.get(inner) ?? null;\n const next = id === stop ? own : \"-1\";\n if (inner.getAttribute(\"tabindex\") === next) continue;\n if (next === null) inner.removeAttribute(\"tabindex\");\n else inner.setAttribute(\"tabindex\", next);\n writtenTabIndex.set(inner, next);\n }\n }\n };\n onMount(() => {\n if (!local.renderNode) return;\n createEffect(on(tabStop, syncInnerTabStops));\n if (typeof MutationObserver !== \"function\") return;\n // Content that changes later (a link that shows up with a status) is caught\n // too, and so is a tabindex the caller writes from a signal: that write is\n // taken as the content's own value, then the Tab order is restored over it.\n const observer = new MutationObserver((records) => {\n let sync = false;\n for (const record of records) {\n if (record.type !== \"attributes\") {\n sync = true;\n continue;\n }\n const target = record.target as Element;\n // A node's own roving tabindex is the component's, not its content's.\n if (target.classList.contains(\"smwb-dag-view__node\")) continue;\n const now = target.getAttribute(\"tabindex\");\n if (writtenTabIndex.has(target) && writtenTabIndex.get(target) === now) continue;\n ownTabIndex.set(target, now);\n sync = true;\n }\n if (sync) syncInnerTabStops();\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"tabindex\"],\n });\n onCleanup(() => observer.disconnect());\n });\n\n /** The node an arrow key leads to from `id`: along the edges, or to a neighbour in the layer. */\n const neighbour = (id: string, key: string): string | undefined => {\n const tb = local.direction === \"TB\";\n const forward = tb ? \"ArrowDown\" : \"ArrowRight\";\n const back = tb ? \"ArrowUp\" : \"ArrowLeft\";\n const before = tb ? \"ArrowLeft\" : \"ArrowUp\";\n const after = tb ? \"ArrowRight\" : \"ArrowDown\";\n const nodes = layout().nodes;\n const first = (list: string[]): string | undefined =>\n list\n .map((other) => nodes.get(other))\n .filter((node): node is DagLayoutNode => node !== undefined)\n .sort((a, b) => across(a) - across(b))[0]?.id;\n if (key === forward) return first((graph().outgoing.get(id) ?? []).map((e) => e.target));\n if (key === back) return first((graph().incoming.get(id) ?? []).map((e) => e.source));\n const self = nodes.get(id);\n if (!self) return undefined;\n const layer = graph().layers.get(self.layer) ?? [];\n const index = layer.findIndex((node) => node.id === id);\n if (key === before) return layer[index - 1]?.id;\n if (key === after) return layer[index + 1]?.id;\n return undefined;\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n const target = event.target as HTMLElement;\n const id = target.dataset?.[\"dagId\"];\n // Keys pressed in a node's own content (a link, a field) are its own.\n if (id === undefined || !target.classList.contains(\"smwb-dag-view__node\")) return;\n // Ctrl, Cmd and Alt shortcuts are the browser's: page zoom, history, tabs.\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const key = event.key;\n if (key.startsWith(\"Arrow\") && event.shiftKey) {\n const step = 48;\n const v = viewport();\n const dx = key === \"ArrowLeft\" ? step : key === \"ArrowRight\" ? -step : 0;\n const dy = key === \"ArrowUp\" ? step : key === \"ArrowDown\" ? -step : 0;\n setViewport({ x: v.x + dx, y: v.y + dy, zoom: v.zoom });\n event.preventDefault();\n return;\n }\n if (key.startsWith(\"Arrow\")) {\n event.preventDefault();\n focusNode(neighbour(id, key));\n return;\n }\n switch (key) {\n case \"Home\":\n event.preventDefault();\n focusNode(graph().ordered[0]?.id);\n return;\n case \"End\":\n event.preventDefault();\n focusNode(graph().ordered[graph().ordered.length - 1]?.id);\n return;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n choose(id, event);\n return;\n case \"Escape\":\n // Handled only when there was a selection, so an enclosing dialog still gets it otherwise.\n if (selected() === null) return;\n event.preventDefault();\n setSelected(null);\n return;\n case \"+\":\n case \"=\":\n event.preventDefault();\n api.zoomBy(1.25);\n return;\n case \"-\":\n case \"_\":\n event.preventDefault();\n api.zoomBy(0.8);\n return;\n case \"0\":\n event.preventDefault();\n api.fitView();\n return;\n }\n };\n\n const defaultRender = (node: DagViewNode<T>): JSX.Element => (\n <>\n <span class=\"smwb-dag-view__dot\" aria-hidden=\"true\" />\n <span class=\"smwb-dag-view__label\">{node.label ?? node.id}</span>\n <Show when={node.status}>{(status) => <span class=\"smwb-dag-view__status\">{statusWord(status())}</span>}</Show>\n </>\n );\n\n const description = (id: string): string => {\n const node = byId().get(id);\n const parts: string[] = [];\n if (node?.status) parts.push(`${labels().status}: ${statusWord(node.status)}.`);\n const names = (list: string[]): string => list.map((other) => nameOf(byId().get(other), other)).join(\", \");\n const from = (graph().incoming.get(id) ?? []).map((e) => e.source);\n const to = (graph().outgoing.get(id) ?? []).map((e) => e.target);\n if (from.length) parts.push(`${labels().dependsOn}: ${names(from)}.`);\n if (to.length) parts.push(`${labels().requiredBy}: ${names(to)}.`);\n return parts.join(\" \");\n };\n\n const renderNodeFor = (id: string, index: () => number): JSX.Element => {\n const node = (): DagViewNode<T> | undefined => byId().get(id);\n // The node as `renderNode` sees it: its fields read the app's latest object.\n const view = { id } as DagViewNode<T>;\n for (const key of NODE_KEYS) Object.defineProperty(view, key, { enumerable: true, get: () => node()?.[key] });\n const state: DagViewNodeState = {\n get selected() {\n return isSelected(id);\n },\n get related() {\n return relations().nodes.get(id) ?? null;\n },\n get dimmed() {\n const r = relations();\n return Boolean(local.dimUnrelated) && r.active && !isSelected(id) && !r.nodes.has(id);\n },\n get focused() {\n return focused() === id;\n },\n };\n const descriptionId = (): string => `${uid}-node-${index()}`;\n const style = (): JSX.CSSProperties => {\n const box = layout().nodes.get(id);\n const css: JSX.CSSProperties = box\n ? {\n left: `${box.x + PADDING}px`,\n top: `${box.y + PADDING}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n }\n : { display: \"none\" };\n const accent = node()?.accent;\n if (accent) css[\"--smwb-dag-view-node-accent\"] = accent;\n return css;\n };\n const onFocus = (event: FocusEvent): void => {\n if (event.target !== event.currentTarget) return;\n setActive(id);\n setFocused(id);\n let keyboard = true;\n try {\n keyboard = (event.currentTarget as HTMLElement).matches(\":focus-visible\");\n } catch {\n // An engine without :focus-visible: treat it as the keyboard.\n }\n if (keyboard) ensureVisible(id);\n };\n const onBlur = (event: FocusEvent): void => {\n if (event.target !== event.currentTarget || focused() !== id) return;\n // A browser blurs a node while it is being removed, before the removal\n // effect below runs. Clearing `focused` there would leave the effect\n // nothing to move on, and focus would fall to the page.\n if (!ids().includes(id)) return;\n setFocused(null);\n };\n const content = untrack(() => (local.renderNode ?? defaultRender)(view, state));\n return (\n <div\n role=\"option\"\n data-dag-id={id}\n ref={(el) => {\n elements.set(id, el);\n onCleanup(() => elements.get(id) === el && elements.delete(id));\n }}\n class={cn(\"smwb-dag-view__node\", {\n \"smwb-dag-view__node--selected\": state.selected,\n \"smwb-dag-view__node--upstream\": state.related === \"upstream\",\n \"smwb-dag-view__node--downstream\": state.related === \"downstream\",\n \"smwb-dag-view__node--dimmed\": state.dimmed,\n \"smwb-dag-view__node--disabled\": Boolean(node()?.disabled),\n })}\n data-status={node()?.status}\n aria-selected={state.selected ? \"true\" : \"false\"}\n aria-disabled={node()?.disabled ? \"true\" : undefined}\n aria-describedby={description(id) ? descriptionId() : undefined}\n tabIndex={tabStop() === id ? 0 : -1}\n style={style()}\n onClick={(event) => choose(id, event)}\n onFocus={onFocus}\n onBlur={onBlur}\n >\n {content}\n <span id={descriptionId()} hidden>\n {description(id)}\n </span>\n </div>\n );\n };\n\n const edgeClass = (edge: DagLayoutEdge): string => {\n const r = relations();\n const relation = r.edges.get(edge.id);\n return cn(\"smwb-dag-view__edge\", {\n \"smwb-dag-view__edge--active\": relation !== undefined,\n \"smwb-dag-view__edge--upstream\": relation === \"upstream\",\n \"smwb-dag-view__edge--downstream\": relation === \"downstream\",\n \"smwb-dag-view__edge--dimmed\": Boolean(local.dimUnrelated) && r.active && relation === undefined,\n \"smwb-dag-view__edge--reversed\": edge.reversed,\n });\n };\n\n // The default height is the stylesheet's, so a height in the caller's style is not overridden.\n const rootStyle = (): JSX.CSSProperties | string | undefined =>\n mergeStyle(local.style, { height: local.height === undefined ? undefined : cssLength(local.height) });\n\n return (\n <div\n data-testid={local[\"data-testid\"] ?? \"dag-view\"}\n {...rest}\n ref={mergeRefs(local.ref, (el) => (root = el))}\n class={cn(\"smwb-dag-view\", local.class)}\n // Only when there is one: the server would print an empty style=\"\".\n {...(rootStyle() === undefined ? {} : { style: rootStyle() })}\n data-direction={local.direction}\n data-zoom={far() ? \"far\" : undefined}\n data-interacting={interacting() ? \"\" : undefined}\n >\n <div\n class=\"smwb-dag-view__world\"\n role=\"listbox\"\n aria-label={local.label}\n aria-roledescription={labels().roleDescription}\n aria-describedby={local.summary ? summaryId : undefined}\n style={{\n width: `${worldSize().width}px`,\n height: `${worldSize().height}px`,\n transform: viewportTransform(viewport()),\n }}\n onKeyDown={onKeyDown}\n >\n <svg class=\"smwb-dag-view__edges\" width={worldSize().width} height={worldSize().height} aria-hidden=\"true\">\n <defs>\n <marker\n id={arrowId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n <path class=\"smwb-dag-view__arrow\" d=\"M0,1 L9,5 L0,9 z\" />\n </marker>\n <marker\n id={activeArrowId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n <path class=\"smwb-dag-view__arrow smwb-dag-view__arrow--active\" d=\"M0,1 L9,5 L0,9 z\" />\n </marker>\n </defs>\n <g transform={`translate(${PADDING} ${PADDING})`}>\n <For each={layout().edges}>\n {(edge) => (\n <path\n class={edgeClass(edge)}\n data-source={edge.source}\n data-target={edge.target}\n d={dagEdgePath(edge.points, local.direction)}\n marker-end={`url(#${relations().edges.has(edge.id) ? activeArrowId : arrowId})`}\n />\n )}\n </For>\n </g>\n </svg>\n <For each={ids()}>{(id, index) => renderNodeFor(id, index)}</For>\n </div>\n <Show when={local.summary}>\n <p id={summaryId} class=\"smwb-dag-view__summary\">\n {local.summary}\n </p>\n </Show>\n <Show when={local.controls}>\n <div class=\"smwb-dag-view__controls\" role=\"group\" aria-label={labels().controls}>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().zoomIn} onClick={() => api.zoomBy(1.25)}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n </button>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().zoomOut} onClick={() => api.zoomBy(0.8)}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M5 12h14\" />\n </svg>\n </button>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().fitView} onClick={() => api.fitView()}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5\" />\n </svg>\n </button>\n </div>\n </Show>\n </div>\n );\n}\n\nexport default DagView;\n"],"mappings":"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","names":[],"file":"dagView.jsx"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/dataDisplay/dagView/dagView.tsx"],"sourcesContent":["import {\n DEV,\n For,\n type JSX,\n Show,\n createEffect,\n createMemo,\n createSelector,\n createSignal,\n createUniqueId,\n mergeProps,\n on,\n onCleanup,\n onMount,\n splitProps,\n untrack,\n} from \"solid-js\";\nimport cn from \"clsx\";\nimport { createControllableState } from \"../../../primitives/createControllableState\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\nimport { mergeStyle } from \"../../../primitives/mergeStyle\";\nimport {\n type DagDirection,\n type DagLayoutEdge,\n type DagLayoutInput,\n type DagLayoutNode,\n type DagLayoutResult,\n dagEdgePath,\n dagLayout,\n} from \"./dagLayout\";\nimport { type Viewport, centerOn, createPanZoom, fitBounds, isVisible, viewportTransform, zoomAt } from \"./panZoom\";\n\n/** A node's status: a built-in one, coloured by the theme, or any word of the app's, styled by `[data-status]`. */\nexport type DagViewStatus =\n | \"idle\"\n | \"pending\"\n | \"running\"\n | \"success\"\n | \"warning\"\n | \"error\"\n | \"skipped\"\n | (string & {});\n\n/** The line style of a node's frame: dashed or solid, over its status and the theme's `--smwb-dag-view-node-border-style`. */\nexport type DagViewNodeVariant = \"solid\" | \"dashed\";\n\nexport interface DagViewNode<T = unknown> {\n /** Unique among the nodes; edges name nodes by it. */\n id: string;\n /** What the default node shows, and its accessible name; the id unless given. */\n label?: JSX.Element;\n /** Colours the node's accent from the theme. */\n status?: DagViewStatus | undefined;\n /** The node's accent colour, over its status colour: any CSS colour. */\n accent?: string | undefined;\n /** The line style of the node's frame, over its status and the theme; the theme's unless given. */\n variant?: DagViewNodeVariant | undefined;\n /** The node's width in pixels; `nodeWidth` unless given. */\n width?: number | undefined;\n /** The node's height in pixels; `nodeHeight` unless given. */\n height?: number | undefined;\n /** Anything of the app's, handed back to `renderNode` and `onNodeClick`. */\n data?: T;\n /** Shown, focusable, but not selectable. */\n disabled?: boolean | undefined;\n}\n\nexport interface DagViewEdge {\n /** `source->target` unless given. */\n id?: string | undefined;\n /** The id of the node the edge starts from: the one depended on. */\n source: string;\n /** The id of the node the edge points to: the one that depends on `source`. */\n target: string;\n}\n\n/** A node's state for `renderNode`. Its fields are reactive: read them in JSX or an effect. */\nexport interface DagViewNodeState {\n readonly selected: boolean;\n /** Next to the selected node: \"upstream\" feeds it, \"downstream\" depends on it. */\n readonly related: \"upstream\" | \"downstream\" | null;\n /** Set apart from the selected node and its neighbours, with `dimUnrelated`. */\n readonly dimmed: boolean;\n /** Has keyboard focus. */\n readonly focused: boolean;\n}\n\n/** Where the graph is: moved by x, y (pixels) and scaled by zoom. */\nexport type DagViewViewport = Viewport;\n\n/** Moves the view from outside; handed over by `apiRef` once the graph is in the page. */\nexport interface DagViewApi {\n /** Fits the whole graph in view. */\n fitView(): void;\n /** Zooms to `zoom` around the middle of the view. */\n zoomTo(zoom: number): void;\n /** Zooms by `factor` around the middle of the view. */\n zoomBy(factor: number): void;\n /** Moves the node with this id to the middle of the view. */\n centerNode(id: string): void;\n}\n\n/** Texts for assistive technology and the zoom buttons, English by default. */\nexport interface DagViewLabels {\n /** What the graph is called as a widget: \"dependency graph\". */\n roleDescription: string;\n /** \"Status\", before a node's status word. */\n status: string;\n /** \"Depends on\", before the names of the nodes a node's edges come from. */\n dependsOn: string;\n /** \"Required by\", before the names of the nodes a node's edges go to. */\n requiredBy: string;\n /** Status words, shown on the default nodes and read out: { running: \"Running\", … }. */\n statuses: Record<string, string>;\n zoomIn: string;\n zoomOut: string;\n fitView: string;\n /** The name of the group of zoom buttons. */\n controls: string;\n}\n\nexport interface DagViewProps<T = unknown> extends Omit<JSX.HTMLAttributes<HTMLDivElement>, \"onClick\"> {\n /** What the graph shows: its accessible name. */\n label: string;\n /** The graph in words, for screen readers; it is there on the server too. */\n summary?: string | undefined;\n /** The nodes. A change of status, label or data alone does not lay the graph out again. */\n nodes: readonly DagViewNode<T>[];\n /** The edges, from the node depended on to the node that depends on it. */\n edges: readonly DagViewEdge[];\n /**\n * Draws a node's content inside its box; the default shows a status dot,\n * the label and the status word. Called once per node: `node` and `state`\n * are reactive, so read their fields in JSX. Keep the content\n * non-interactive where you can: a node is an ARIA option, whose content\n * assistive technology may read as plain text, and a click in it also\n * selects the node. Links and buttons in it are left out of the Tab order\n * except in the node that is the graph's Tab stop.\n */\n renderNode?: ((node: DagViewNode<T>, state: DagViewNodeState) => JSX.Element) | undefined;\n /** Which way the layers run: \"LR\" (left to right, default) or \"TB\" (top to bottom). */\n direction?: DagDirection | undefined;\n /** A node's width in pixels, unless the node sets its own; 180 by default. */\n nodeWidth?: number | undefined;\n /** A node's height in pixels, unless the node sets its own; 56 by default. */\n nodeHeight?: number | undefined;\n /** The space between layers in pixels; 64 by default. */\n rankGap?: number | undefined;\n /** The space between nodes in a layer in pixels; 24 by default. */\n nodeGap?: number | undefined;\n /** Lays the graph out in place of the built-in layout, e.g. with dagre or elk. It must be synchronous. */\n layout?: ((input: DagLayoutInput) => DagLayoutResult) | undefined;\n /** The selected node's id (controlled); null selects nothing. */\n selectedId?: string | null | undefined;\n /** The node selected at first (uncontrolled). */\n defaultSelectedId?: string | null | undefined;\n /** A node was selected (its id) or the selection was cleared (null). */\n onSelectedChange?: ((id: string | null) => void) | undefined;\n /** A node was clicked, or chosen with Enter or Space. Not called for a disabled node. */\n onNodeClick?: ((node: DagViewNode<T>, event: MouseEvent | KeyboardEvent) => void) | undefined;\n /** Fades the nodes and edges that are not next to the selected node. */\n dimUnrelated?: boolean | undefined;\n /** Where the graph is (controlled). */\n viewport?: DagViewViewport | undefined;\n /** Where the graph is at first (uncontrolled); with `fit={false}` the page does not move after it loads. */\n defaultViewport?: DagViewViewport | undefined;\n /** The view moved or zoomed: at most once per frame during a gesture. */\n onViewportChange?: ((viewport: DagViewViewport) => void) | undefined;\n /** Fits the graph in view once it is in the page, and again when its nodes or edges change; true by default. */\n fit?: boolean | undefined;\n /** The smallest zoom; 0.1 by default. */\n minZoom?: number | undefined;\n /** The largest zoom; 2 by default. */\n maxZoom?: number | undefined;\n /** What a plain mouse wheel does: \"zoom\" (default), \"pan\", or \"none\" (the page scrolls). Ctrl+wheel and a trackpad pinch always zoom. */\n wheel?: \"zoom\" | \"pan\" | \"none\" | undefined;\n /** Shows the zoom in, zoom out and fit buttons; true by default. */\n controls?: boolean | undefined;\n /** Texts for assistive technology and the buttons, over the English defaults. */\n labels?: Partial<DagViewLabels> | undefined;\n /**\n * The graph's height: a number of pixels or any CSS length; 480 by default,\n * from the stylesheet, so a height in `style` works too. It fills the width.\n */\n height?: number | string | undefined;\n /** Gets the functions that move the view from outside. */\n apiRef?: ((api: DagViewApi) => void) | undefined;\n /** Test id of the root `<div>`; `dag-view` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLDivElement>;\n}\n\n/** Room around the graph inside its world, in pixels. */\nconst PADDING = 24;\n\nconst DEFAULT_LABELS: DagViewLabels = {\n roleDescription: \"dependency graph\",\n status: \"Status\",\n dependsOn: \"Depends on\",\n requiredBy: \"Required by\",\n statuses: {\n idle: \"Idle\",\n pending: \"Pending\",\n running: \"Running\",\n success: \"Success\",\n warning: \"Warning\",\n error: \"Error\",\n skipped: \"Skipped\",\n },\n zoomIn: \"Zoom in\",\n zoomOut: \"Zoom out\",\n fitView: \"Fit to view\",\n controls: \"Zoom\",\n};\n\nconst NODE_KEYS = [\"label\", \"status\", \"accent\", \"variant\", \"width\", \"height\", \"data\", \"disabled\"] as const;\n\n/** What can take focus inside a node's own content. */\nconst INNER_FOCUSABLE =\n 'a[href], button, input, select, textarea, iframe, summary, audio[controls], video[controls], [tabindex], [contenteditable]:not([contenteditable=\"false\"])';\n\nconst cssLength = (value: number | string): string => (typeof value === \"number\" ? `${value}px` : value);\n\nconst sameList = (a: readonly string[], b: readonly string[]): boolean =>\n a.length === b.length && a.every((value, i) => value === b[i]);\n\n/** A node's name in words, for descriptions: its label when that is text, else its id. */\nconst nameOf = (node: DagViewNode<unknown> | undefined, id: string): string => {\n const label = node?.label;\n return typeof label === \"string\" || typeof label === \"number\" ? String(label) : id;\n};\n\nconst warn = DEV ? (message: string): void => console.warn(`[smwb] DagView: ${message}`) : undefined;\n\n/**\n * A directed graph of dependencies: nodes in layers, left to right or top to\n * bottom, joined by arrows. A node is selected by a click or the keyboard, and\n * the edges into and out of it light up; the view pans and zooms with a mouse,\n * a trackpad, touch or the keyboard.\n */\nexport function DagView<T = unknown>(props: DagViewProps<T>): JSX.Element {\n const merged = mergeProps(\n {\n direction: \"LR\" as DagDirection,\n nodeWidth: 180,\n nodeHeight: 56,\n rankGap: 64,\n nodeGap: 24,\n fit: true,\n minZoom: 0.1,\n maxZoom: 2,\n wheel: \"zoom\" as \"zoom\" | \"pan\" | \"none\",\n controls: true,\n },\n props\n );\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"style\",\n \"label\",\n \"summary\",\n \"nodes\",\n \"edges\",\n \"renderNode\",\n \"direction\",\n \"nodeWidth\",\n \"nodeHeight\",\n \"rankGap\",\n \"nodeGap\",\n \"layout\",\n \"selectedId\",\n \"defaultSelectedId\",\n \"onSelectedChange\",\n \"onNodeClick\",\n \"dimUnrelated\",\n \"viewport\",\n \"defaultViewport\",\n \"onViewportChange\",\n \"fit\",\n \"minZoom\",\n \"maxZoom\",\n \"wheel\",\n \"controls\",\n \"labels\",\n \"height\",\n \"apiRef\",\n \"ref\",\n \"data-testid\",\n ]);\n\n const uid = createUniqueId();\n const arrowId = `${uid}-arrow`;\n const activeArrowId = `${uid}-arrow-active`;\n const summaryId = `${uid}-summary`;\n let root!: HTMLDivElement;\n const elements = new Map<string, HTMLElement>();\n\n const labels = createMemo(\n (): DagViewLabels => ({\n ...DEFAULT_LABELS,\n ...local.labels,\n statuses: { ...DEFAULT_LABELS.statuses, ...local.labels?.statuses },\n })\n );\n const statusWord = (status: string): string => labels().statuses[status] ?? status;\n\n // ---- Nodes and layout ----\n\n const byId = createMemo(() => {\n const map = new Map<string, DagViewNode<T>>();\n for (const node of local.nodes) if (!map.has(node.id)) map.set(node.id, node);\n return map;\n });\n // Nodes are drawn by id, so content stays mounted when the app replaces a\n // node object to change its status.\n const ids = createMemo(() => [...byId().keys()], [], { equals: sameList });\n\n // The layout depends only on the graph's shape; a status change leaves it be.\n const structure = createMemo(\n () => {\n const nodes = [...byId().values()].map((node) => ({\n id: node.id,\n width: node.width ?? local.nodeWidth,\n height: node.height ?? local.nodeHeight,\n }));\n const edges = local.edges.map((edge) => ({ id: edge.id, source: edge.source, target: edge.target }));\n const input: DagLayoutInput = {\n nodes,\n edges,\n direction: local.direction,\n rankGap: local.rankGap,\n nodeGap: local.nodeGap,\n warn,\n };\n const key = JSON.stringify([\n local.direction,\n local.rankGap,\n local.nodeGap,\n nodes.map((n) => [n.id, n.width, n.height]),\n edges.map((e) => [e.id ?? null, e.source, e.target]),\n ]);\n return { key, input };\n },\n undefined,\n { equals: (a, b) => a.key === b.key }\n );\n const layout = createMemo(() => (local.layout ?? dagLayout)(structure().input));\n\n // The flow of a layer runs along x in LR and along y in TB; across it is the other one.\n const across = (node: DagLayoutNode): number => (local.direction === \"TB\" ? node.x : node.y);\n\n const graph = createMemo(() => {\n const result = layout();\n const incoming = new Map<string, DagLayoutEdge[]>();\n const outgoing = new Map<string, DagLayoutEdge[]>();\n for (const edge of result.edges) {\n if (!incoming.has(edge.target)) incoming.set(edge.target, []);\n if (!outgoing.has(edge.source)) outgoing.set(edge.source, []);\n incoming.get(edge.target)!.push(edge);\n outgoing.get(edge.source)!.push(edge);\n }\n const ordered = [...result.nodes.values()].sort((a, b) => a.layer - b.layer || across(a) - across(b));\n const layers = new Map<number, DagLayoutNode[]>();\n for (const node of ordered) {\n if (!layers.has(node.layer)) layers.set(node.layer, []);\n layers.get(node.layer)!.push(node);\n }\n return { incoming, outgoing, ordered, layers };\n });\n\n // ---- Selection ----\n\n const [selected, setSelected] = createControllableState<string | null>({\n value: () => local.selectedId,\n defaultValue: untrack(() => local.defaultSelectedId) ?? null,\n onChange: (id) => local.onSelectedChange?.(id),\n });\n const isSelected = createSelector(selected);\n\n const relations = createMemo(() => {\n const id = selected();\n const edges = new Map<string, \"upstream\" | \"downstream\">();\n const nodes = new Map<string, \"upstream\" | \"downstream\">();\n if (id === null || !layout().nodes.has(id)) return { active: false, edges, nodes };\n const { incoming, outgoing } = graph();\n for (const edge of incoming.get(id) ?? []) {\n edges.set(edge.id, \"upstream\");\n nodes.set(edge.source, \"upstream\");\n }\n for (const edge of outgoing.get(id) ?? []) {\n edges.set(edge.id, \"downstream\");\n nodes.set(edge.target, \"downstream\");\n }\n return { active: true, edges, nodes };\n });\n\n // ---- Focus: one tab stop, on the last focused node, else the selected one, else the first ----\n\n const [active, setActive] = createSignal<string | null>(null);\n const [focused, setFocused] = createSignal<string | null>(null);\n const tabStop = createMemo(() => {\n const nodes = layout().nodes;\n const last = active();\n if (last !== null && nodes.has(last)) return last;\n const chosen = selected();\n if (chosen !== null && nodes.has(chosen)) return chosen;\n return graph().ordered[0]?.id ?? null;\n });\n\n // ---- Viewport ----\n\n const [viewport, setViewport] = createControllableState<Viewport>({\n value: () => local.viewport,\n defaultValue: untrack(() => local.defaultViewport) ?? { x: 0, y: 0, zoom: 1 },\n onChange: (next) => local.onViewportChange?.(next),\n });\n const [interacting, setInteracting] = createSignal(false);\n const far = createMemo(() => viewport().zoom < 0.45);\n\n const size = (): { width: number; height: number } => ({\n width: root?.clientWidth ?? 0,\n height: root?.clientHeight ?? 0,\n });\n const hasSize = (): boolean => {\n const { width, height } = size();\n return width > 0 && height > 0;\n };\n const worldSize = (): { width: number; height: number } => ({\n width: layout().width + PADDING * 2,\n height: layout().height + PADDING * 2,\n });\n const nodeRect = (id: string): { x: number; y: number; width: number; height: number } | undefined => {\n const box = layout().nodes.get(id);\n return box && { x: box.x + PADDING, y: box.y + PADDING, width: box.width, height: box.height };\n };\n\n const api: DagViewApi = {\n fitView() {\n if (!hasSize()) return;\n const world = worldSize();\n setViewport(\n fitBounds(\n { x: 0, y: 0, ...world },\n size(),\n 0,\n local.minZoom,\n Math.max(local.minZoom, Math.min(1, local.maxZoom))\n )\n );\n },\n zoomTo(zoom) {\n api.zoomBy(zoom / viewport().zoom);\n },\n zoomBy(factor) {\n const { width, height } = size();\n setViewport(zoomAt(viewport(), { x: width / 2, y: height / 2 }, factor, local.minZoom, local.maxZoom));\n },\n centerNode(id) {\n const rect = nodeRect(id);\n if (!rect) return;\n setViewport(centerOn(viewport(), { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 }, size()));\n },\n };\n\n const ensureVisible = (id: string): void => {\n const rect = nodeRect(id);\n if (rect && hasSize() && !isVisible(viewport(), rect, size(), 8)) api.centerNode(id);\n };\n\n // Fit once the graph has a size, and again when its shape changes. At zero\n // size (a hidden tab) the fit waits for the first resize that gives one.\n let fitPending = false;\n const tryFit = (): void => {\n if (!fitPending || !hasSize()) return;\n fitPending = false;\n api.fitView();\n };\n createEffect(\n on(\n layout,\n () => {\n if (!untrack(() => local.fit)) return;\n fitPending = true;\n tryFit();\n },\n { defer: true }\n )\n );\n\n onMount(() => {\n const dispose = createPanZoom(root, {\n viewport,\n write: setViewport,\n minZoom: () => local.minZoom,\n maxZoom: () => local.maxZoom,\n wheel: () => local.wheel,\n onInteracting: setInteracting,\n });\n let frame = 0;\n const resizeObserver =\n typeof ResizeObserver === \"function\"\n ? new ResizeObserver(() => {\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(tryFit);\n })\n : undefined;\n resizeObserver?.observe(root);\n onCleanup(() => {\n dispose();\n resizeObserver?.disconnect();\n cancelAnimationFrame(frame);\n });\n fitPending = local.fit;\n tryFit();\n local.apiRef?.(api);\n });\n\n // ---- Interaction ----\n\n const choose = (id: string, event: MouseEvent | KeyboardEvent): void => {\n const node = byId().get(id);\n if (!node || node.disabled) return;\n setSelected(id);\n local.onNodeClick?.(node, event);\n };\n\n const focusNode = (id: string | undefined): void => {\n if (id === undefined) return;\n setActive(id);\n elements.get(id)?.focus({ preventScroll: true });\n ensureVisible(id);\n };\n\n // A node that goes away takes its selection with it, and focus moves to the\n // Tab stop rather than dropping to the page. Only a node that was there\n // counts: a selection given before its node loads is kept.\n createEffect<readonly string[] | undefined>((before) => {\n const now = ids();\n if (before) {\n untrack(() => {\n const present = new Set(now);\n const chosen = selected();\n if (chosen !== null && !present.has(chosen) && before.includes(chosen)) setSelected(null);\n const had = focused();\n if (had === null || present.has(had)) return;\n setFocused(null);\n const doc = root?.ownerDocument;\n const stop = tabStop();\n if (doc && (doc.activeElement === null || doc.activeElement === doc.body) && stop !== null)\n elements.get(stop)?.focus({ preventScroll: true });\n });\n }\n return now;\n });\n\n // One Tab stop: focusables in `renderNode` content (a link, a button) are\n // taken out of the Tab order, except in the node that is the Tab stop. Their\n // own tabindex comes back when their node becomes it.\n const ownTabIndex = new WeakMap<Element, string | null>();\n // The value the component wrote last, so its own writes can be told apart\n // from the caller's in the attribute records below.\n const writtenTabIndex = new WeakMap<Element, string | null>();\n const syncInnerTabStops = (): void => {\n const stop = untrack(tabStop);\n for (const [id, el] of elements) {\n for (const inner of el.querySelectorAll(INNER_FOCUSABLE)) {\n if (!ownTabIndex.has(inner)) ownTabIndex.set(inner, inner.getAttribute(\"tabindex\"));\n const own = ownTabIndex.get(inner) ?? null;\n const next = id === stop ? own : \"-1\";\n if (inner.getAttribute(\"tabindex\") === next) continue;\n if (next === null) inner.removeAttribute(\"tabindex\");\n else inner.setAttribute(\"tabindex\", next);\n writtenTabIndex.set(inner, next);\n }\n }\n };\n onMount(() => {\n if (!local.renderNode) return;\n createEffect(on(tabStop, syncInnerTabStops));\n if (typeof MutationObserver !== \"function\") return;\n // Content that changes later (a link that shows up with a status) is caught\n // too, and so is a tabindex the caller writes from a signal: that write is\n // taken as the content's own value, then the Tab order is restored over it.\n const observer = new MutationObserver((records) => {\n let sync = false;\n for (const record of records) {\n if (record.type !== \"attributes\") {\n sync = true;\n continue;\n }\n const target = record.target as Element;\n // A node's own roving tabindex is the component's, not its content's.\n if (target.classList.contains(\"smwb-dag-view__node\")) continue;\n const now = target.getAttribute(\"tabindex\");\n if (writtenTabIndex.has(target) && writtenTabIndex.get(target) === now) continue;\n ownTabIndex.set(target, now);\n sync = true;\n }\n if (sync) syncInnerTabStops();\n });\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: [\"tabindex\"],\n });\n onCleanup(() => observer.disconnect());\n });\n\n /** The node an arrow key leads to from `id`: along the edges, or to a neighbour in the layer. */\n const neighbour = (id: string, key: string): string | undefined => {\n const tb = local.direction === \"TB\";\n const forward = tb ? \"ArrowDown\" : \"ArrowRight\";\n const back = tb ? \"ArrowUp\" : \"ArrowLeft\";\n const before = tb ? \"ArrowLeft\" : \"ArrowUp\";\n const after = tb ? \"ArrowRight\" : \"ArrowDown\";\n const nodes = layout().nodes;\n const first = (list: string[]): string | undefined =>\n list\n .map((other) => nodes.get(other))\n .filter((node): node is DagLayoutNode => node !== undefined)\n .sort((a, b) => across(a) - across(b))[0]?.id;\n if (key === forward) return first((graph().outgoing.get(id) ?? []).map((e) => e.target));\n if (key === back) return first((graph().incoming.get(id) ?? []).map((e) => e.source));\n const self = nodes.get(id);\n if (!self) return undefined;\n const layer = graph().layers.get(self.layer) ?? [];\n const index = layer.findIndex((node) => node.id === id);\n if (key === before) return layer[index - 1]?.id;\n if (key === after) return layer[index + 1]?.id;\n return undefined;\n };\n\n const onKeyDown = (event: KeyboardEvent): void => {\n const target = event.target as HTMLElement;\n const id = target.dataset?.[\"dagId\"];\n // Keys pressed in a node's own content (a link, a field) are its own.\n if (id === undefined || !target.classList.contains(\"smwb-dag-view__node\")) return;\n // Ctrl, Cmd and Alt shortcuts are the browser's: page zoom, history, tabs.\n if (event.ctrlKey || event.metaKey || event.altKey) return;\n const key = event.key;\n if (key.startsWith(\"Arrow\") && event.shiftKey) {\n const step = 48;\n const v = viewport();\n const dx = key === \"ArrowLeft\" ? step : key === \"ArrowRight\" ? -step : 0;\n const dy = key === \"ArrowUp\" ? step : key === \"ArrowDown\" ? -step : 0;\n setViewport({ x: v.x + dx, y: v.y + dy, zoom: v.zoom });\n event.preventDefault();\n return;\n }\n if (key.startsWith(\"Arrow\")) {\n event.preventDefault();\n focusNode(neighbour(id, key));\n return;\n }\n switch (key) {\n case \"Home\":\n event.preventDefault();\n focusNode(graph().ordered[0]?.id);\n return;\n case \"End\":\n event.preventDefault();\n focusNode(graph().ordered[graph().ordered.length - 1]?.id);\n return;\n case \"Enter\":\n case \" \":\n event.preventDefault();\n choose(id, event);\n return;\n case \"Escape\":\n // Handled only when there was a selection, so an enclosing dialog still gets it otherwise.\n if (selected() === null) return;\n event.preventDefault();\n setSelected(null);\n return;\n case \"+\":\n case \"=\":\n event.preventDefault();\n api.zoomBy(1.25);\n return;\n case \"-\":\n case \"_\":\n event.preventDefault();\n api.zoomBy(0.8);\n return;\n case \"0\":\n event.preventDefault();\n api.fitView();\n return;\n }\n };\n\n const defaultRender = (node: DagViewNode<T>): JSX.Element => (\n <>\n <span class=\"smwb-dag-view__dot\" aria-hidden=\"true\" />\n <span class=\"smwb-dag-view__label\">{node.label ?? node.id}</span>\n <Show when={node.status}>{(status) => <span class=\"smwb-dag-view__status\">{statusWord(status())}</span>}</Show>\n </>\n );\n\n const description = (id: string): string => {\n const node = byId().get(id);\n const parts: string[] = [];\n if (node?.status) parts.push(`${labels().status}: ${statusWord(node.status)}.`);\n const names = (list: string[]): string => list.map((other) => nameOf(byId().get(other), other)).join(\", \");\n const from = (graph().incoming.get(id) ?? []).map((e) => e.source);\n const to = (graph().outgoing.get(id) ?? []).map((e) => e.target);\n if (from.length) parts.push(`${labels().dependsOn}: ${names(from)}.`);\n if (to.length) parts.push(`${labels().requiredBy}: ${names(to)}.`);\n return parts.join(\" \");\n };\n\n const renderNodeFor = (id: string, index: () => number): JSX.Element => {\n const node = (): DagViewNode<T> | undefined => byId().get(id);\n // The node as `renderNode` sees it: its fields read the app's latest object.\n const view = { id } as DagViewNode<T>;\n for (const key of NODE_KEYS) Object.defineProperty(view, key, { enumerable: true, get: () => node()?.[key] });\n const state: DagViewNodeState = {\n get selected() {\n return isSelected(id);\n },\n get related() {\n return relations().nodes.get(id) ?? null;\n },\n get dimmed() {\n const r = relations();\n return Boolean(local.dimUnrelated) && r.active && !isSelected(id) && !r.nodes.has(id);\n },\n get focused() {\n return focused() === id;\n },\n };\n const descriptionId = (): string => `${uid}-node-${index()}`;\n const style = (): JSX.CSSProperties => {\n const box = layout().nodes.get(id);\n const css: JSX.CSSProperties = box\n ? {\n left: `${box.x + PADDING}px`,\n top: `${box.y + PADDING}px`,\n width: `${box.width}px`,\n height: `${box.height}px`,\n }\n : { display: \"none\" };\n const accent = node()?.accent;\n if (accent) css[\"--smwb-dag-view-node-accent\"] = accent;\n return css;\n };\n const onFocus = (event: FocusEvent): void => {\n if (event.target !== event.currentTarget) return;\n setActive(id);\n setFocused(id);\n let keyboard = true;\n try {\n keyboard = (event.currentTarget as HTMLElement).matches(\":focus-visible\");\n } catch {\n // An engine without :focus-visible: treat it as the keyboard.\n }\n if (keyboard) ensureVisible(id);\n };\n const onBlur = (event: FocusEvent): void => {\n if (event.target !== event.currentTarget || focused() !== id) return;\n // A browser blurs a node while it is being removed, before the removal\n // effect below runs. Clearing `focused` there would leave the effect\n // nothing to move on, and focus would fall to the page.\n if (!ids().includes(id)) return;\n setFocused(null);\n };\n const content = untrack(() => (local.renderNode ?? defaultRender)(view, state));\n return (\n <div\n role=\"option\"\n data-dag-id={id}\n ref={(el) => {\n elements.set(id, el);\n onCleanup(() => elements.get(id) === el && elements.delete(id));\n }}\n class={cn(\"smwb-dag-view__node\", {\n \"smwb-dag-view__node--selected\": state.selected,\n \"smwb-dag-view__node--upstream\": state.related === \"upstream\",\n \"smwb-dag-view__node--downstream\": state.related === \"downstream\",\n \"smwb-dag-view__node--dimmed\": state.dimmed,\n \"smwb-dag-view__node--disabled\": Boolean(node()?.disabled),\n })}\n data-status={node()?.status}\n data-variant={node()?.variant}\n aria-selected={state.selected ? \"true\" : \"false\"}\n aria-disabled={node()?.disabled ? \"true\" : undefined}\n aria-describedby={description(id) ? descriptionId() : undefined}\n tabIndex={tabStop() === id ? 0 : -1}\n style={style()}\n onClick={(event) => choose(id, event)}\n onFocus={onFocus}\n onBlur={onBlur}\n >\n {content}\n <span id={descriptionId()} hidden>\n {description(id)}\n </span>\n </div>\n );\n };\n\n const edgeClass = (edge: DagLayoutEdge): string => {\n const r = relations();\n const relation = r.edges.get(edge.id);\n return cn(\"smwb-dag-view__edge\", {\n \"smwb-dag-view__edge--active\": relation !== undefined,\n \"smwb-dag-view__edge--upstream\": relation === \"upstream\",\n \"smwb-dag-view__edge--downstream\": relation === \"downstream\",\n \"smwb-dag-view__edge--dimmed\": Boolean(local.dimUnrelated) && r.active && relation === undefined,\n \"smwb-dag-view__edge--reversed\": edge.reversed,\n });\n };\n\n // The default height is the stylesheet's, so a height in the caller's style is not overridden.\n const rootStyle = (): JSX.CSSProperties | string | undefined =>\n mergeStyle(local.style, { height: local.height === undefined ? undefined : cssLength(local.height) });\n\n return (\n <div\n data-testid={local[\"data-testid\"] ?? \"dag-view\"}\n {...rest}\n ref={mergeRefs(local.ref, (el) => (root = el))}\n class={cn(\"smwb-dag-view\", local.class)}\n // Only when there is one: the server would print an empty style=\"\".\n {...(rootStyle() === undefined ? {} : { style: rootStyle() })}\n data-direction={local.direction}\n data-zoom={far() ? \"far\" : undefined}\n data-interacting={interacting() ? \"\" : undefined}\n >\n <div\n class=\"smwb-dag-view__world\"\n role=\"listbox\"\n aria-label={local.label}\n aria-roledescription={labels().roleDescription}\n aria-describedby={local.summary ? summaryId : undefined}\n style={{\n width: `${worldSize().width}px`,\n height: `${worldSize().height}px`,\n transform: viewportTransform(viewport()),\n }}\n onKeyDown={onKeyDown}\n >\n <svg class=\"smwb-dag-view__edges\" width={worldSize().width} height={worldSize().height} aria-hidden=\"true\">\n <defs>\n <marker\n id={arrowId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n <path class=\"smwb-dag-view__arrow\" d=\"M0,1 L9,5 L0,9 z\" />\n </marker>\n <marker\n id={activeArrowId}\n viewBox=\"0 0 10 10\"\n refX=\"9\"\n refY=\"5\"\n markerWidth=\"10\"\n markerHeight=\"10\"\n markerUnits=\"userSpaceOnUse\"\n orient=\"auto-start-reverse\"\n >\n <path class=\"smwb-dag-view__arrow smwb-dag-view__arrow--active\" d=\"M0,1 L9,5 L0,9 z\" />\n </marker>\n </defs>\n <g transform={`translate(${PADDING} ${PADDING})`}>\n <For each={layout().edges}>\n {(edge) => (\n <path\n class={edgeClass(edge)}\n data-source={edge.source}\n data-target={edge.target}\n d={dagEdgePath(edge.points, local.direction)}\n marker-end={`url(#${relations().edges.has(edge.id) ? activeArrowId : arrowId})`}\n />\n )}\n </For>\n </g>\n </svg>\n <For each={ids()}>{(id, index) => renderNodeFor(id, index)}</For>\n </div>\n <Show when={local.summary}>\n <p id={summaryId} class=\"smwb-dag-view__summary\">\n {local.summary}\n </p>\n </Show>\n <Show when={local.controls}>\n <div class=\"smwb-dag-view__controls\" role=\"group\" aria-label={labels().controls}>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().zoomIn} onClick={() => api.zoomBy(1.25)}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M12 5v14M5 12h14\" />\n </svg>\n </button>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().zoomOut} onClick={() => api.zoomBy(0.8)}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M5 12h14\" />\n </svg>\n </button>\n <button type=\"button\" class=\"smwb-dag-view__control\" title={labels().fitView} onClick={() => api.fitView()}>\n <svg viewBox=\"0 0 24 24\" aria-hidden=\"true\">\n <path d=\"M4 9V4h5M20 9V4h-5M4 15v5h5M20 15v5h-5\" />\n </svg>\n </button>\n </div>\n </Show>\n </div>\n );\n}\n\nexport default DagView;\n"],"mappings":"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","names":[],"file":"dagView.jsx"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/components/dataDisplay/dagView/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { DagView, default } from \"./dagView\";\nexport type {\n DagViewProps,\n DagViewNode,\n DagViewEdge,\n DagViewStatus,\n DagViewViewport,\n DagViewApi,\n DagViewNodeState,\n DagViewLabels,\n} from \"./dagView\";\nexport { dagLayout, dagEdgePath, dagEdgeId } from \"./dagLayout\";\nexport type {\n DagDirection,\n DagLayoutInput,\n DagLayoutInputNode,\n DagLayoutInputEdge,\n DagLayoutResult,\n DagLayoutNode,\n DagLayoutEdge,\n DagPoint,\n} from \"./dagLayout\";\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,SAAS,WAAAA,gBAAe;
|
|
4
|
+
"sourcesContent": ["export { DagView, default } from \"./dagView\";\nexport type {\n DagViewProps,\n DagViewNode,\n DagViewEdge,\n DagViewStatus,\n DagViewNodeVariant,\n DagViewViewport,\n DagViewApi,\n DagViewNodeState,\n DagViewLabels,\n} from \"./dagView\";\nexport { dagLayout, dagEdgePath, dagEdgeId } from \"./dagLayout\";\nexport type {\n DagDirection,\n DagLayoutInput,\n DagLayoutInputNode,\n DagLayoutInputEdge,\n DagLayoutResult,\n DagLayoutNode,\n DagLayoutEdge,\n DagPoint,\n} from \"./dagLayout\";\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS,WAAAA,gBAAe;AAYjC,SAAS,WAAW,aAAa,iBAAiB;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/components/dataDisplay/meter/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { Meter, meterColor, DEFAULT_METER_THRESHOLDS, default } from \"./meter\";\nexport type { MeterProps, MeterColor, MeterThreshold } from \"./meter\";\n"],
|
|
4
|
+
"sourcesContent": ["export { Meter, meterColor, DEFAULT_METER_THRESHOLDS, default } from \"./meter\";\nexport type { MeterProps, MeterColor, MeterThreshold, MeterTextPosition, MeterSize } from \"./meter\";\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,OAAO,YAAY,0BAA0B,WAAAA,gBAAe;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -28,6 +28,9 @@ function Meter(props) {
|
|
|
28
28
|
"thresholds",
|
|
29
29
|
"color",
|
|
30
30
|
"hideText",
|
|
31
|
+
"textPosition",
|
|
32
|
+
"size",
|
|
33
|
+
"aria-valuetext",
|
|
31
34
|
"ref",
|
|
32
35
|
"data-testid"
|
|
33
36
|
]);
|
|
@@ -46,9 +49,18 @@ function Meter(props) {
|
|
|
46
49
|
aria-valuenow={local.value}
|
|
47
50
|
aria-valuemin={0}
|
|
48
51
|
aria-valuemax={local.max}
|
|
49
|
-
aria-valuetext={`${local.value} ${local.ofLabel} ${local.max}`}
|
|
52
|
+
aria-valuetext={local["aria-valuetext"] ?? `${local.value} ${local.ofLabel} ${local.max}`}
|
|
50
53
|
data-testid={local["data-testid"] ?? "meter"}
|
|
51
|
-
class={cn(
|
|
54
|
+
class={cn(
|
|
55
|
+
"smwb-meter",
|
|
56
|
+
`smwb-meter_color-${color()}`,
|
|
57
|
+
{
|
|
58
|
+
"smwb-meter_bar-only": local.hideText,
|
|
59
|
+
"smwb-meter_text-before": local.textPosition === "before",
|
|
60
|
+
"smwb-meter_compact": local.size === "compact"
|
|
61
|
+
},
|
|
62
|
+
local.class
|
|
63
|
+
)}
|
|
52
64
|
>
|
|
53
65
|
<span class="smwb-meter__track" aria-hidden="true">
|
|
54
66
|
<span class="smwb-meter__fill" style={{ width: `${share() * 100}%` }} />
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/components/dataDisplay/meter/meter.tsx"],"sourcesContent":["import { type JSX, Show, children, mergeProps, splitProps } from \"solid-js\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\nexport type MeterColor = \"neutral\" | \"primary\" | \"info\" | \"success\" | \"warning\" | \"error\";\n\n/** From this share of `max` (0–1) on, the meter takes `color`. */\nexport interface MeterThreshold {\n from: number;\n color: MeterColor;\n}\n\n/** Info while under way, success when complete. */\nexport const DEFAULT_METER_THRESHOLDS: readonly MeterThreshold[] = [\n { from: 0, color: \"info\" },\n { from: 1, color: \"success\" },\n];\n\nexport interface MeterProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, \"role\"> {\n /** How many are done (X of Y). */\n value: number;\n /** How many there are in all (X of Y). */\n max: number;\n /** What is measured — the accessible name, e.g. \"Requirements accepted\". */\n label: string;\n /** Visible text instead of \"X of Y\": markup, or a function of (value, max). */\n text?: JSX.Element | ((value: number, max: number) => JSX.Element);\n /** The word between the figures in the default text and in aria-valuetext. */\n ofLabel?: string;\n /** Colour by share of `max`: the last threshold the share reaches wins. */\n thresholds?: readonly MeterThreshold[];\n /** A fixed colour, instead of the thresholds. */\n color?: MeterColor;\n /** The bar only; the text stays available to assistive technology. */\n hideText?: boolean;\n /** Test id of the root `<div>`; `meter` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLDivElement>;\n}\n\n/** The colour for a share of the whole: the last threshold (by `from`) the share reaches. */\nexport function meterColor(share: number, thresholds: readonly MeterThreshold[]): MeterColor {\n let color: MeterColor = \"neutral\";\n let from = -Infinity;\n for (const threshold of thresholds) {\n if (share >= threshold.from && threshold.from >= from) {\n color = threshold.color;\n from = threshold.from;\n }\n }\n return color;\n}\n\n/** A share of a whole, \"X of Y\": a bar and the figures beside it, coloured by thresholds. */\nexport function Meter(props: MeterProps): JSX.Element {\n const merged = mergeProps({ ofLabel: \"of\", thresholds: DEFAULT_METER_THRESHOLDS }, props);\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"value\",\n \"max\",\n \"label\",\n \"text\",\n \"ofLabel\",\n \"thresholds\",\n \"color\",\n \"hideText\",\n \"ref\",\n \"data-testid\",\n ]);\n\n const share = (): number => (local.max > 0 ? Math.min(1, Math.max(0, local.value / local.max)) : 0);\n const color = (): MeterColor => local.color ?? meterColor(share(), local.thresholds);\n // Read the text once: markup passed as a prop is created anew on every read,\n // and during hydration a copy made only to test it has no server DOM node. A\n // function of (value, max) is kept as it is and called where the text renders.\n const custom = children(() => local.text as JSX.Element);\n const text = (): JSX.Element => {\n const resolved = custom() as JSX.Element | ((value: number, max: number) => JSX.Element);\n return typeof resolved === \"function\" ? resolved(local.value, local.max) : resolved;\n };\n\n return (\n <div\n {...rest}\n ref={mergeRefs(local.ref)}\n role=\"meter\"\n aria-label={local.label}\n aria-valuenow={local.value}\n aria-valuemin={0}\n aria-valuemax={local.max}\n aria-valuetext={`${local.value} ${local.ofLabel} ${local.max}`}\n data-testid={local[\"data-testid\"] ?? \"meter\"}\n class={cn(\"smwb-meter\"
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/dataDisplay/meter/meter.tsx"],"sourcesContent":["import { type JSX, Show, children, mergeProps, splitProps } from \"solid-js\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\nexport type MeterColor = \"neutral\" | \"primary\" | \"info\" | \"success\" | \"warning\" | \"error\";\nexport type MeterTextPosition = \"after\" | \"before\";\nexport type MeterSize = \"medium\" | \"compact\";\n\n/** From this share of `max` (0–1) on, the meter takes `color`. */\nexport interface MeterThreshold {\n from: number;\n color: MeterColor;\n}\n\n/** Info while under way, success when complete. */\nexport const DEFAULT_METER_THRESHOLDS: readonly MeterThreshold[] = [\n { from: 0, color: \"info\" },\n { from: 1, color: \"success\" },\n];\n\nexport interface MeterProps extends Omit<JSX.HTMLAttributes<HTMLDivElement>, \"role\"> {\n /** How many are done (X of Y). */\n value: number;\n /** How many there are in all (X of Y). */\n max: number;\n /** What is measured — the accessible name, e.g. \"Requirements accepted\". */\n label: string;\n /** Visible text instead of \"X of Y\": markup, or a function of (value, max). */\n text?: JSX.Element | ((value: number, max: number) => JSX.Element);\n /** The word between the figures in the default text and in aria-valuetext. */\n ofLabel?: string;\n /** Colour by share of `max`: the last threshold the share reaches wins. */\n thresholds?: readonly MeterThreshold[];\n /** A fixed colour, instead of the thresholds. */\n color?: MeterColor;\n /** The bar only; the text stays available to assistive technology. */\n hideText?: boolean;\n /** Where the text sits against the bar: `after` it (the default) or `before` it. */\n textPosition?: MeterTextPosition;\n /**\n * `compact`: a fixed-width bar and small secondary text, and the block shrinks to its\n * content instead of filling the parent. `medium` (the default) fills the parent.\n */\n size?: MeterSize;\n /**\n * What assistive technology reads as the value, e.g. the text you format for the\n * eye (\"$4.18 / $20\"); \"X of Y\" built from `value`, `ofLabel` and `max` unless given.\n */\n \"aria-valuetext\"?: string | undefined;\n /** Test id of the root `<div>`; `meter` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLDivElement>;\n}\n\n/** The colour for a share of the whole: the last threshold (by `from`) the share reaches. */\nexport function meterColor(share: number, thresholds: readonly MeterThreshold[]): MeterColor {\n let color: MeterColor = \"neutral\";\n let from = -Infinity;\n for (const threshold of thresholds) {\n if (share >= threshold.from && threshold.from >= from) {\n color = threshold.color;\n from = threshold.from;\n }\n }\n return color;\n}\n\n/** A share of a whole, \"X of Y\": a bar and the figures beside it, coloured by thresholds. */\nexport function Meter(props: MeterProps): JSX.Element {\n const merged = mergeProps({ ofLabel: \"of\", thresholds: DEFAULT_METER_THRESHOLDS }, props);\n const [local, rest] = splitProps(merged, [\n \"class\",\n \"value\",\n \"max\",\n \"label\",\n \"text\",\n \"ofLabel\",\n \"thresholds\",\n \"color\",\n \"hideText\",\n \"textPosition\",\n \"size\",\n \"aria-valuetext\",\n \"ref\",\n \"data-testid\",\n ]);\n\n const share = (): number => (local.max > 0 ? Math.min(1, Math.max(0, local.value / local.max)) : 0);\n const color = (): MeterColor => local.color ?? meterColor(share(), local.thresholds);\n // Read the text once: markup passed as a prop is created anew on every read,\n // and during hydration a copy made only to test it has no server DOM node. A\n // function of (value, max) is kept as it is and called where the text renders.\n const custom = children(() => local.text as JSX.Element);\n const text = (): JSX.Element => {\n const resolved = custom() as JSX.Element | ((value: number, max: number) => JSX.Element);\n return typeof resolved === \"function\" ? resolved(local.value, local.max) : resolved;\n };\n\n return (\n <div\n {...rest}\n ref={mergeRefs(local.ref)}\n role=\"meter\"\n aria-label={local.label}\n aria-valuenow={local.value}\n aria-valuemin={0}\n aria-valuemax={local.max}\n aria-valuetext={local[\"aria-valuetext\"] ?? `${local.value} ${local.ofLabel} ${local.max}`}\n data-testid={local[\"data-testid\"] ?? \"meter\"}\n class={cn(\n \"smwb-meter\",\n `smwb-meter_color-${color()}`,\n {\n \"smwb-meter_bar-only\": local.hideText,\n \"smwb-meter_text-before\": local.textPosition === \"before\",\n \"smwb-meter_compact\": local.size === \"compact\",\n },\n local.class\n )}\n >\n <span class=\"smwb-meter__track\" aria-hidden=\"true\">\n <span class=\"smwb-meter__fill\" style={{ width: `${share() * 100}%` }} />\n </span>\n <Show when={!local.hideText}>\n <span class=\"smwb-meter__text\" aria-hidden=\"true\">\n <Show\n when={custom() !== undefined}\n fallback={\n <>\n <b class=\"smwb-meter__value\">{local.value}</b>\n <span class=\"smwb-meter__of\">\n {\" \"}\n {local.ofLabel} {local.max}\n </span>\n </>\n }\n >\n {text()}\n </Show>\n </span>\n </Show>\n </div>\n );\n}\n\nexport default Meter;\n"],"mappings":"AAAA,SAAmB,MAAM,UAAU,YAAY,kBAAkB;AACjE,OAAO,QAAQ;AACf,SAAS,iBAA2B;AAa7B,MAAM,2BAAsD;AAAA,EACjE,EAAE,MAAM,GAAG,OAAO,OAAO;AAAA,EACzB,EAAE,MAAM,GAAG,OAAO,UAAU;AAC9B;AAqCO,SAAS,WAAW,OAAe,YAAmD;AAC3F,MAAI,QAAoB;AACxB,MAAI,OAAO;AACX,aAAW,aAAa,YAAY;AAClC,QAAI,SAAS,UAAU,QAAQ,UAAU,QAAQ,MAAM;AACrD,cAAQ,UAAU;AAClB,aAAO,UAAU;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,MAAM,OAAgC;AACpD,QAAM,SAAS,WAAW,EAAE,SAAS,MAAM,YAAY,yBAAyB,GAAG,KAAK;AACxF,QAAM,CAAC,OAAO,IAAI,IAAI,WAAW,QAAQ;AAAA,IACvC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,QAAQ,MAAe,MAAM,MAAM,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,MAAM,QAAQ,MAAM,GAAG,CAAC,IAAI;AACjG,QAAM,QAAQ,MAAkB,MAAM,SAAS,WAAW,MAAM,GAAG,MAAM,UAAU;AAInF,QAAM,SAAS,SAAS,MAAM,MAAM,IAAmB;AACvD,QAAM,OAAO,MAAmB;AAC9B,UAAM,WAAW,OAAO;AACxB,WAAO,OAAO,aAAa,aAAa,SAAS,MAAM,OAAO,MAAM,GAAG,IAAI;AAAA,EAC7E;AAEA,SACE,CAAC;AAAA,QACK;AAAA,IACJ,KAAK,UAAU,MAAM,GAAG;AAAA,IACxB,KAAK;AAAA,IACL,YAAY,MAAM;AAAA,IAClB,eAAe,MAAM;AAAA,IACrB,eAAe;AAAA,IACf,eAAe,MAAM;AAAA,IACrB,gBAAgB,MAAM,gBAAgB,KAAK,GAAG,MAAM,KAAK,IAAI,MAAM,OAAO,IAAI,MAAM,GAAG;AAAA,IACvF,aAAa,MAAM,aAAa,KAAK;AAAA,IACrC,OAAO;AAAA,MACL;AAAA,MACA,oBAAoB,MAAM,CAAC;AAAA,MAC3B;AAAA,QACE,uBAAuB,MAAM;AAAA,QAC7B,0BAA0B,MAAM,iBAAiB;AAAA,QACjD,sBAAsB,MAAM,SAAS;AAAA,MACvC;AAAA,MACA,MAAM;AAAA,IACR;AAAA,GACD;AAAA,MACC,CAAC,KAAK,MAAM,oBAAoB,YAAY,OAAO;AAAA,QACjD,CAAC,KAAK,MAAM,mBAAmB,OAAO,EAAE,OAAO,GAAG,MAAM,IAAI,GAAG,IAAI,GAAG,EAAE;AAAA,MAC1E,EAFC,KAEM;AAAA,MACP,CAAC,KAAK,MAAM,CAAC,MAAM,UAAU;AAAA,QAC3B,CAAC,KAAK,MAAM,mBAAmB,YAAY,OAAO;AAAA,UAChD,CAAC;AAAA,IACC,MAAM,OAAO,MAAM;AAAA,IACnB,UACE,EAAE;AAAA,gBACA,CAAC,EAAE,MAAM,qBAAqB,MAAM,MAAM,EAAzC,EAA6C;AAAA,gBAC9C,CAAC,KAAK,MAAM,iBAAiB;AAAA,mBAC1B,IAAI;AAAA,mBACJ,MAAM,QAAQ,EAAE,MAAM,IAAI;AAAA,gBAC7B,EAHC,KAGM;AAAA,cACT;AAAA,GAEH;AAAA,aACE,KAAK,EAAE;AAAA,UACV,EAbC,KAaM;AAAA,QACT,EAfC,KAeM;AAAA,MACT,EAjBC,KAiBM;AAAA,IACT,EA1CC;AA4CL;AAEA,IAAO,gBAAQ;","names":[],"file":"meter.jsx"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../../src/components/dataDisplay/statusDot/index.ts"],
|
|
4
|
-
"sourcesContent": ["export { StatusDot, default } from \"./statusDot\";\nexport type { StatusDotProps, StatusDotStatus, StatusDotColor, StatusDotSize } from \"./statusDot\";\n"],
|
|
4
|
+
"sourcesContent": ["export { StatusDot, default } from \"./statusDot\";\nexport type { StatusDotProps, StatusDotStatus, StatusDotColor, StatusDotSize, StatusDotShape } from \"./statusDot\";\n"],
|
|
5
5
|
"mappings": "AAAA,SAAS,WAAW,WAAAA,gBAAe;",
|
|
6
6
|
"names": ["default"]
|
|
7
7
|
}
|
|
@@ -2,7 +2,17 @@ import { splitProps } from "solid-js";
|
|
|
2
2
|
import cn from "clsx";
|
|
3
3
|
import { mergeRefs } from "../../../primitives/mergeRefs";
|
|
4
4
|
function StatusDot(props) {
|
|
5
|
-
const [local, rest] = splitProps(props, [
|
|
5
|
+
const [local, rest] = splitProps(props, [
|
|
6
|
+
"class",
|
|
7
|
+
"status",
|
|
8
|
+
"color",
|
|
9
|
+
"size",
|
|
10
|
+
"shape",
|
|
11
|
+
"pulse",
|
|
12
|
+
"label",
|
|
13
|
+
"ref",
|
|
14
|
+
"data-testid"
|
|
15
|
+
]);
|
|
6
16
|
const shown = () => local.status ?? (local.color === void 0 ? "unknown" : void 0);
|
|
7
17
|
return <span
|
|
8
18
|
{...rest}
|
|
@@ -13,6 +23,8 @@ function StatusDot(props) {
|
|
|
13
23
|
class={cn(
|
|
14
24
|
"smwb-status-dot",
|
|
15
25
|
`smwb-status-dot_size-${local.size ?? "md"}`,
|
|
26
|
+
// Only the diamond carries a class: a dot is the shape the base rule already draws.
|
|
27
|
+
local.shape === "diamond" && "smwb-status-dot_shape-diamond",
|
|
16
28
|
shown() && `smwb-status-dot_status-${shown()}`,
|
|
17
29
|
local.color && `smwb-status-dot_color-${local.color}`,
|
|
18
30
|
{ "smwb-status-dot_pulse": local.pulse ?? local.status === "active" },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../src/components/dataDisplay/statusDot/statusDot.tsx"],"sourcesContent":["import type { JSX } from \"solid-js\";\nimport { splitProps } from \"solid-js\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\n/** What the marker says: `active` is under way, `attention` waits for someone, `idle` rests, `done` is finished. */\nexport type StatusDotStatus = \"active\" | \"attention\" | \"idle\" | \"done\" | \"error\" | \"unknown\";\n\n/** The theme colour names `Chip` takes; `default` is the neutral on-surface colour. */\nexport type StatusDotColor = \"default\" | \"primary\" | \"secondary\" | \"error\" | \"success\" | \"warning\" | \"info\";\n\nexport type StatusDotSize = \"sm\" | \"md\";\n\nexport interface StatusDotProps extends Omit<JSX.HTMLAttributes<HTMLSpanElement>, \"role\" | \"children\" | \"aria-label\"> {\n /**\n * What the dot says, and so its colour: `active` info, `attention` warning, `idle` neutral, `done` success,\n * `error` error. `unknown` is a ring in the outline colour. Without `status` (and without `color`) the dot is\n * `unknown`.\n */\n status?: StatusDotStatus | undefined;\n /**\n * A theme colour instead of the status's own, or on its own with no `status` (a plain disc). Given with a\n * `status`, the status still sets the shape.\n */\n color?: StatusDotColor | undefined;\n /** `md` (12px) unless given; `sm` is 8px. */\n size?: StatusDotSize | undefined;\n /**\n * A ring spreads from the dot. On unless given for `active`, off for every other status. Never drawn while the\n * user prefers reduced motion.\n */\n pulse?: boolean | undefined;\n /** What the dot means in words, e.g. \"Working\": the accessible name, read by assistive technology. */\n label: string;\n /** Test id of the root; `status-dot` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLSpanElement>;\n}\n\n/** A small status marker: a dot
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/components/dataDisplay/statusDot/statusDot.tsx"],"sourcesContent":["import type { JSX } from \"solid-js\";\nimport { splitProps } from \"solid-js\";\nimport cn from \"clsx\";\nimport { mergeRefs, type Ref } from \"../../../primitives/mergeRefs\";\n\n/** What the marker says: `active` is under way, `attention` waits for someone, `idle` rests, `done` is finished. */\nexport type StatusDotStatus = \"active\" | \"attention\" | \"idle\" | \"done\" | \"error\" | \"unknown\";\n\n/** The theme colour names `Chip` takes; `default` is the neutral on-surface colour. */\nexport type StatusDotColor = \"default\" | \"primary\" | \"secondary\" | \"error\" | \"success\" | \"warning\" | \"info\";\n\nexport type StatusDotSize = \"sm\" | \"md\";\n\n/** The marker's outline, chosen by the caller and not by `status`: `dot` is a disc, `diamond` a square turned corner-up. */\nexport type StatusDotShape = \"dot\" | \"diamond\";\n\nexport interface StatusDotProps extends Omit<JSX.HTMLAttributes<HTMLSpanElement>, \"role\" | \"children\" | \"aria-label\"> {\n /**\n * What the dot says, and so its colour: `active` info, `attention` warning, `idle` neutral, `done` success,\n * `error` error. `unknown` is a ring in the outline colour. Without `status` (and without `color`) the dot is\n * `unknown`.\n */\n status?: StatusDotStatus | undefined;\n /**\n * A theme colour instead of the status's own, or on its own with no `status` (a plain disc). Given with a\n * `status`, the status still sets the shape.\n */\n color?: StatusDotColor | undefined;\n /** `md` (12px) unless given; `sm` is 8px. */\n size?: StatusDotSize | undefined;\n /**\n * The marker's outline, `dot` unless given: `diamond` turns the same square corner-up. The shape is the caller's\n * choice, not the status's — a diamond takes its colour from `color` or `status`, its size from `size` and its\n * pulse from `pulse` exactly as the dot does, so `unknown` is a ring and `active` pulses in either shape. Its box\n * is the box of a dot of the same `size`, so the two swap places without moving a row.\n */\n shape?: StatusDotShape | undefined;\n /**\n * A ring spreads from the dot. On unless given for `active`, off for every other status. Never drawn while the\n * user prefers reduced motion.\n */\n pulse?: boolean | undefined;\n /** What the dot means in words, e.g. \"Working\": the accessible name, read by assistive technology. */\n label: string;\n /** Test id of the root; `status-dot` unless given. */\n \"data-testid\"?: string | undefined;\n ref?: Ref<HTMLSpanElement>;\n}\n\n/** A small status marker: a dot or a diamond, coloured by `status` or `color`, named by `label`. */\nexport function StatusDot(props: StatusDotProps): JSX.Element {\n const [local, rest] = splitProps(props, [\n \"class\",\n \"status\",\n \"color\",\n \"size\",\n \"shape\",\n \"pulse\",\n \"label\",\n \"ref\",\n \"data-testid\",\n ]);\n\n // A bare colour is a plain disc; with neither, the dot is \"unknown\".\n const shown = (): StatusDotStatus | undefined => local.status ?? (local.color === undefined ? \"unknown\" : undefined);\n\n return (\n <span\n {...rest}\n ref={mergeRefs(local.ref)}\n role=\"img\"\n aria-label={local.label}\n data-testid={local[\"data-testid\"] ?? \"status-dot\"}\n class={cn(\n \"smwb-status-dot\",\n `smwb-status-dot_size-${local.size ?? \"md\"}`,\n // Only the diamond carries a class: a dot is the shape the base rule already draws.\n local.shape === \"diamond\" && \"smwb-status-dot_shape-diamond\",\n shown() && `smwb-status-dot_status-${shown()}`,\n local.color && `smwb-status-dot_color-${local.color}`,\n { \"smwb-status-dot_pulse\": local.pulse ?? local.status === \"active\" },\n local.class\n )}\n />\n );\n}\n\nexport default StatusDot;\n"],"mappings":"AACA,SAAS,kBAAkB;AAC3B,OAAO,QAAQ;AACf,SAAS,iBAA2B;AA+C7B,SAAS,UAAU,OAAoC;AAC5D,QAAM,CAAC,OAAO,IAAI,IAAI,WAAW,OAAO;AAAA,IACtC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAGD,QAAM,QAAQ,MAAmC,MAAM,WAAW,MAAM,UAAU,SAAY,YAAY;AAE1G,SACE,CAAC;AAAA,QACK;AAAA,IACJ,KAAK,UAAU,MAAM,GAAG;AAAA,IACxB,KAAK;AAAA,IACL,YAAY,MAAM;AAAA,IAClB,aAAa,MAAM,aAAa,KAAK;AAAA,IACrC,OAAO;AAAA,MACL;AAAA,MACA,wBAAwB,MAAM,QAAQ,IAAI;AAAA;AAAA,MAE1C,MAAM,UAAU,aAAa;AAAA,MAC7B,MAAM,KAAK,0BAA0B,MAAM,CAAC;AAAA,MAC5C,MAAM,SAAS,yBAAyB,MAAM,KAAK;AAAA,MACnD,EAAE,yBAAyB,MAAM,SAAS,MAAM,WAAW,SAAS;AAAA,MACpE,MAAM;AAAA,IACR;AAAA,EACF;AAEJ;AAEA,IAAO,oBAAQ;","names":[],"file":"statusDot.jsx"}
|
|
@@ -61,6 +61,12 @@ function TreeNode(props) {
|
|
|
61
61
|
const isOpen = () => ctx.expandedIds().includes(nodeId);
|
|
62
62
|
const isSelected = () => ctx.selectedIds().includes(nodeId);
|
|
63
63
|
const isLoading = () => ctx.loadingIds().includes(nodeId);
|
|
64
|
+
const nodeIconName = () => {
|
|
65
|
+
const icons = ctx.nodeIcon;
|
|
66
|
+
if (icons === false) return void 0;
|
|
67
|
+
return isOpen() ? icons.opened ?? "folder_open" : icons.closed ?? "folder";
|
|
68
|
+
};
|
|
69
|
+
const listIconName = () => ctx.listIcon === false ? void 0 : ctx.listIcon;
|
|
64
70
|
const toggleNode = () => {
|
|
65
71
|
if (!isOpen()) ctx.ensureLoaded(item(), nodeId);
|
|
66
72
|
ctx.toggleExpanded(nodeId);
|
|
@@ -116,8 +122,11 @@ function TreeNode(props) {
|
|
|
116
122
|
</Show>
|
|
117
123
|
<span class="smwb-tree__node__content" onClick={onContentClick} onKeyDown={onKeyDown} tabindex={0} role="button">
|
|
118
124
|
<span class="smwb-tree__node__label" id={labelId}>
|
|
119
|
-
<Show
|
|
120
|
-
|
|
125
|
+
<Show
|
|
126
|
+
when={hasChildNodes()}
|
|
127
|
+
fallback={<Show when={listIconName()}>{(name) => <Icon name={name()} size={20} />}</Show>}
|
|
128
|
+
>
|
|
129
|
+
<Show when={nodeIconName()}>{(name) => <Icon name={name()} fill={1} size={20} />}</Show>
|
|
121
130
|
</Show>
|
|
122
131
|
{labelSlot()}
|
|
123
132
|
</span>
|
|
@@ -148,6 +157,8 @@ function TreeView(props) {
|
|
|
148
157
|
{
|
|
149
158
|
listIcon: "draft",
|
|
150
159
|
nodeIcon: { closed: "folder", opened: "folder_open" },
|
|
160
|
+
dense: false,
|
|
161
|
+
guides: true,
|
|
151
162
|
data: [],
|
|
152
163
|
defaultExpanded: [],
|
|
153
164
|
defaultSelected: [],
|
|
@@ -161,6 +172,8 @@ function TreeView(props) {
|
|
|
161
172
|
"class",
|
|
162
173
|
"listIcon",
|
|
163
174
|
"nodeIcon",
|
|
175
|
+
"dense",
|
|
176
|
+
"guides",
|
|
164
177
|
"data",
|
|
165
178
|
"expanded",
|
|
166
179
|
"defaultExpanded",
|
|
@@ -254,7 +267,7 @@ function TreeView(props) {
|
|
|
254
267
|
data-testid={local["data-testid"] ?? "tree-view"}
|
|
255
268
|
ref={mergeRefs(local.ref)}
|
|
256
269
|
role="tree"
|
|
257
|
-
class={cn("smwb-tree", local.class)}
|
|
270
|
+
class={cn("smwb-tree", { "smwb-tree_dense": local.dense, "smwb-tree_no-guides": !local.guides }, local.class)}
|
|
258
271
|
>
|
|
259
272
|
<TreeNodes items={local.data} path="" wrap />
|
|
260
273
|
</div>
|