@k2b/ui 0.28.0 → 0.29.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/dist/browser/actions/ContextMenu.js +5 -0
- package/dist/browser/actions/ContextMenu.js.map +1 -1
- package/dist/browser/actions/DragAndDrop.js +89 -0
- package/dist/browser/actions/DragAndDrop.js.map +1 -0
- package/dist/browser/actions/GestureMenu.js +26 -3
- package/dist/browser/actions/GestureMenu.js.map +1 -1
- package/dist/browser/actions/drag-and-drop-messages.js +75 -0
- package/dist/browser/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/browser/actions/drag-and-drop.js +692 -0
- package/dist/browser/actions/drag-and-drop.js.map +1 -0
- package/dist/browser/actions/index.js +1 -0
- package/dist/browser/actions/index.js.map +1 -1
- package/dist/browser/chat/ChatComposer.js +385 -265
- package/dist/browser/chat/ChatComposer.js.map +1 -1
- package/dist/browser/chat/ChatDecision.js +778 -0
- package/dist/browser/chat/ChatDecision.js.map +1 -0
- package/dist/browser/chat/ChatPrimitives.js +34 -28
- package/dist/browser/chat/ChatPrimitives.js.map +1 -1
- package/dist/browser/chat/ChatTimeline.js.map +1 -1
- package/dist/browser/chat/chat-messages.js +6 -0
- package/dist/browser/chat/chat-messages.js.map +1 -1
- package/dist/browser/chat/command-search.js +10 -3
- package/dist/browser/chat/command-search.js.map +1 -1
- package/dist/browser/chat/index.js +6 -1
- package/dist/browser/chat/index.js.map +1 -1
- package/dist/browser/chat/types.js.map +1 -1
- package/dist/browser/content/Calendar.js +3 -3
- package/dist/browser/content/Calendar.js.map +1 -1
- package/dist/browser/content/Chart.js +54 -71
- package/dist/browser/content/Chart.js.map +1 -1
- package/dist/browser/content/FileBrowser.js +2 -2
- package/dist/browser/content/FileBrowser.js.map +1 -1
- package/dist/browser/content/FileTree.js +42 -36
- package/dist/browser/content/FileTree.js.map +1 -1
- package/dist/browser/content/FileTypeIcon.js +72 -0
- package/dist/browser/content/FileTypeIcon.js.map +1 -0
- package/dist/browser/content/FileView.js +2 -2
- package/dist/browser/content/FileView.js.map +1 -1
- package/dist/browser/content/ReferenceChip.js +162 -0
- package/dist/browser/content/ReferenceChip.js.map +1 -0
- package/dist/browser/content/calendar-pointer.js +9 -0
- package/dist/browser/content/calendar-pointer.js.map +1 -1
- package/dist/browser/content/calendar-time-view.js +6 -3
- package/dist/browser/content/calendar-time-view.js.map +1 -1
- package/dist/browser/content/index.js +2 -0
- package/dist/browser/content/index.js.map +1 -1
- package/dist/browser/layout/AppOverview.js +1 -1
- package/dist/browser/layout/AppOverview.js.map +1 -1
- package/dist/browser/layout/AppWorkspace.js +644 -445
- package/dist/browser/layout/AppWorkspace.js.map +1 -1
- package/dist/browser/layout/PanelDialog.js +88 -86
- package/dist/browser/layout/PanelDialog.js.map +1 -1
- package/dist/browser/layout/ResizeSeparator.js +81 -0
- package/dist/browser/layout/ResizeSeparator.js.map +1 -0
- package/dist/browser/layout/SidebarSwitcher.js +9 -2
- package/dist/browser/layout/SidebarSwitcher.js.map +1 -1
- package/dist/browser/layout/TabBar.js +15 -12
- package/dist/browser/layout/TabBar.js.map +1 -1
- package/dist/browser/layout/app-workspace-controller.js +130 -17
- package/dist/browser/layout/app-workspace-controller.js.map +1 -1
- package/dist/browser/layout/index.js +3 -1
- package/dist/browser/layout/index.js.map +1 -1
- package/dist/browser/layout/resize-separator.js +90 -0
- package/dist/browser/layout/resize-separator.js.map +1 -0
- package/dist/browser/layout/workspace-messages.js +12 -2
- package/dist/browser/layout/workspace-messages.js.map +1 -1
- package/dist/browser/surfaces/LinkCard.js +1 -1
- package/dist/browser/surfaces/LinkCard.js.map +1 -1
- package/dist/browser/surfaces/Placeholder.js +14 -3
- package/dist/browser/surfaces/Placeholder.js.map +1 -1
- package/dist/browser/surfaces/StatCell.js +23 -0
- package/dist/browser/surfaces/StatCell.js.map +1 -1
- package/dist/browser/widgets/Widget.js +1 -1
- package/dist/browser/widgets/Widget.js.map +1 -1
- package/dist/ssr/actions/ContextMenu.js +5 -0
- package/dist/ssr/actions/ContextMenu.js.map +1 -1
- package/dist/ssr/actions/DragAndDrop.js +63 -0
- package/dist/ssr/actions/DragAndDrop.js.map +1 -0
- package/dist/ssr/actions/GestureMenu.js +26 -3
- package/dist/ssr/actions/GestureMenu.js.map +1 -1
- package/dist/ssr/actions/drag-and-drop-messages.js +75 -0
- package/dist/ssr/actions/drag-and-drop-messages.js.map +1 -0
- package/dist/ssr/actions/drag-and-drop.js +692 -0
- package/dist/ssr/actions/drag-and-drop.js.map +1 -0
- package/dist/ssr/actions/index.js +1 -0
- package/dist/ssr/actions/index.js.map +1 -1
- package/dist/ssr/chat/ChatComposer.js +131 -14
- package/dist/ssr/chat/ChatComposer.js.map +1 -1
- package/dist/ssr/chat/ChatDecision.js +465 -0
- package/dist/ssr/chat/ChatDecision.js.map +1 -0
- package/dist/ssr/chat/ChatPrimitives.js +2 -2
- package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
- package/dist/ssr/chat/ChatTimeline.js.map +1 -1
- package/dist/ssr/chat/chat-messages.js +6 -0
- package/dist/ssr/chat/chat-messages.js.map +1 -1
- package/dist/ssr/chat/command-search.js +10 -3
- package/dist/ssr/chat/command-search.js.map +1 -1
- package/dist/ssr/chat/index.js +6 -1
- package/dist/ssr/chat/index.js.map +1 -1
- package/dist/ssr/chat/types.js.map +1 -1
- package/dist/ssr/content/Calendar.js +3 -3
- package/dist/ssr/content/Calendar.js.map +1 -1
- package/dist/ssr/content/Chart.js +19 -23
- package/dist/ssr/content/Chart.js.map +1 -1
- package/dist/ssr/content/FileBrowser.js +2 -2
- package/dist/ssr/content/FileBrowser.js.map +1 -1
- package/dist/ssr/content/FileTree.js +21 -14
- package/dist/ssr/content/FileTree.js.map +1 -1
- package/dist/ssr/content/FileTypeIcon.js +50 -0
- package/dist/ssr/content/FileTypeIcon.js.map +1 -0
- package/dist/ssr/content/FileView.js +2 -2
- package/dist/ssr/content/FileView.js.map +1 -1
- package/dist/ssr/content/ReferenceChip.js +121 -0
- package/dist/ssr/content/ReferenceChip.js.map +1 -0
- package/dist/ssr/content/calendar-pointer.js +9 -0
- package/dist/ssr/content/calendar-pointer.js.map +1 -1
- package/dist/ssr/content/calendar-time-view.js +6 -3
- package/dist/ssr/content/calendar-time-view.js.map +1 -1
- package/dist/ssr/content/index.js +2 -0
- package/dist/ssr/content/index.js.map +1 -1
- package/dist/ssr/layout/AppOverview.js +1 -1
- package/dist/ssr/layout/AppOverview.js.map +1 -1
- package/dist/ssr/layout/AppWorkspace.js +272 -95
- package/dist/ssr/layout/AppWorkspace.js.map +1 -1
- package/dist/ssr/layout/PanelDialog.js +7 -6
- package/dist/ssr/layout/PanelDialog.js.map +1 -1
- package/dist/ssr/layout/ResizeSeparator.js +45 -0
- package/dist/ssr/layout/ResizeSeparator.js.map +1 -0
- package/dist/ssr/layout/SidebarSwitcher.js +9 -2
- package/dist/ssr/layout/SidebarSwitcher.js.map +1 -1
- package/dist/ssr/layout/TabBar.js +1 -1
- package/dist/ssr/layout/TabBar.js.map +1 -1
- package/dist/ssr/layout/app-workspace-controller.js +130 -17
- package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
- package/dist/ssr/layout/index.js +3 -1
- package/dist/ssr/layout/index.js.map +1 -1
- package/dist/ssr/layout/resize-separator.js +90 -0
- package/dist/ssr/layout/resize-separator.js.map +1 -0
- package/dist/ssr/layout/workspace-messages.js +12 -2
- package/dist/ssr/layout/workspace-messages.js.map +1 -1
- package/dist/ssr/surfaces/LinkCard.js +1 -1
- package/dist/ssr/surfaces/LinkCard.js.map +1 -1
- package/dist/ssr/surfaces/Placeholder.js +4 -2
- package/dist/ssr/surfaces/Placeholder.js.map +1 -1
- package/dist/ssr/surfaces/StatCell.js +23 -0
- package/dist/ssr/surfaces/StatCell.js.map +1 -1
- package/dist/ssr/widgets/Widget.js +1 -1
- package/dist/ssr/widgets/Widget.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/actions/ContextMenu.d.ts +1 -0
- package/dist/types/actions/DragAndDrop.d.ts +29 -0
- package/dist/types/actions/drag-and-drop-messages.d.ts +35 -0
- package/dist/types/actions/drag-and-drop.d.ts +36 -0
- package/dist/types/actions/index.d.ts +2 -0
- package/dist/types/chat/ChatComposer.d.ts +19 -1
- package/dist/types/chat/ChatDecision.d.ts +133 -0
- package/dist/types/chat/ChatPrimitives.d.ts +4 -1
- package/dist/types/chat/ChatTimeline.d.ts +2 -1
- package/dist/types/chat/chat-messages.d.ts +3 -0
- package/dist/types/chat/command-search.d.ts +3 -0
- package/dist/types/chat/index.d.ts +23 -1
- package/dist/types/chat/types.d.ts +54 -1
- package/dist/types/content/Chart.d.ts +9 -3
- package/dist/types/content/FileTypeIcon.d.ts +27 -0
- package/dist/types/content/ReferenceChip.d.ts +49 -0
- package/dist/types/content/calendar-pointer.d.ts +6 -0
- package/dist/types/content/index.d.ts +3 -0
- package/dist/types/layout/AppWorkspace.d.ts +5 -3
- package/dist/types/layout/ResizeSeparator.d.ts +9 -0
- package/dist/types/layout/TabBar.d.ts +7 -0
- package/dist/types/layout/app-workspace-controller.d.ts +2 -0
- package/dist/types/layout/index.d.ts +3 -1
- package/dist/types/layout/resize-separator.d.ts +18 -0
- package/dist/types/layout/workspace-messages.d.ts +5 -0
- package/dist/types/surfaces/StatCell.d.ts +6 -0
- package/package.json +2 -2
|
@@ -5,11 +5,9 @@ import { createComponent as _$createComponent } from "solid-js/web";
|
|
|
5
5
|
import { ssr as _$ssr } from "solid-js/web";
|
|
6
6
|
import { escape as _$escape } from "solid-js/web";
|
|
7
7
|
var _tmpl$ = ["<i class=\"", "\" aria-hidden=\"true\"></i>"],
|
|
8
|
-
_tmpl$2 = "<
|
|
9
|
-
_tmpl$3 = ["<span", " role=\"tooltip\" popover=\"manual\" data-instant=\"true\" class=\"k2b-tooltip k2b-chart__tooltip\"></span>"],
|
|
10
|
-
_tmpl$4 = ["<div class=\"
|
|
11
|
-
_tmpl$5 = ["<div class=\"", "\"", " style=\"", "\" role=\"group\"", "><div class=\"k2b-chart__svg\"", " style=\"", "\">", "</div>", "", "</div>"],
|
|
12
|
-
_tmpl$6 = ["<div class=\"", "\" style=\"", "\">", "</div>"];
|
|
8
|
+
_tmpl$2 = ["<div class=\"k2b-chart__controls\">", "", "", "</div>"],
|
|
9
|
+
_tmpl$3 = ["<div class=\"", "\"", " data-interactive=\"true\" style=\"", "\" role=\"group\"", " tabindex=\"0\"><div class=\"k2b-chart__svg\"", " style=\"", "\">", "</div><span class=\"k2b-chart__anchor\" aria-hidden=\"true\"></span><span", " role=\"tooltip\" popover=\"manual\" data-instant=\"true\" class=\"k2b-tooltip k2b-chart__tooltip\"></span>", "</div>"],
|
|
10
|
+
_tmpl$4 = ["<div class=\"", "\" style=\"", "\">", "</div>"];
|
|
13
11
|
import { charts } from "@k2b/stdlib";
|
|
14
12
|
import { createEffect, createMemo, createSignal, createUniqueId, onCleanup, onMount, Show, splitProps, untrack } from "solid-js";
|
|
15
13
|
import { isServer } from "solid-js/web";
|
|
@@ -47,9 +45,9 @@ import { useViewportMessages } from "./viewport-messages";
|
|
|
47
45
|
* **Why so thin.** The props are a discriminated union over each
|
|
48
46
|
* stdlib chart function — `kind: "line"` brings in exactly the params
|
|
49
47
|
* `charts.line` expects, `kind: "bar"` brings in `charts.bar`'s, etc.
|
|
50
|
-
* Options stay aligned with stdlib without renaming.
|
|
51
|
-
*
|
|
52
|
-
*
|
|
48
|
+
* Options stay aligned with stdlib without renaming. Every chart provides
|
|
49
|
+
* renderer-owned inspection, tooltips and optional selection by default.
|
|
50
|
+
* `interactive` adds bounded pan / zoom and reset controls to maps and state timelines.
|
|
53
51
|
* If stdlib gains a new option, it's automatically available at every
|
|
54
52
|
* callsite.
|
|
55
53
|
*
|
|
@@ -117,7 +115,7 @@ export const renderChartSvg = (props, width, height, mapViewport, timelineViewpo
|
|
|
117
115
|
width,
|
|
118
116
|
height,
|
|
119
117
|
viewport: timelineViewport,
|
|
120
|
-
interactive:
|
|
118
|
+
interactive: true
|
|
121
119
|
}));
|
|
122
120
|
}
|
|
123
121
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -128,7 +126,7 @@ export const renderChartSvg = (props, width, height, mapViewport, timelineViewpo
|
|
|
128
126
|
} : {}),
|
|
129
127
|
width,
|
|
130
128
|
height,
|
|
131
|
-
inspect:
|
|
129
|
+
inspect: true
|
|
132
130
|
});
|
|
133
131
|
if (props.kind === "line" && props.maxGap !== undefined) {
|
|
134
132
|
if (props.area || props.errorBand) throw new Error("Chart maxGap does not support area or errorBand fills");
|
|
@@ -190,10 +188,15 @@ const Chart = props => {
|
|
|
190
188
|
let pendingPointer;
|
|
191
189
|
const interactiveMap = () => props.kind === "map" && props.interactive === true;
|
|
192
190
|
const interactiveTimeline = () => props.kind === "stateTimeline" && props.interactive === true;
|
|
193
|
-
const interactiveLine = () => props.kind === "line" && props.interactive === true;
|
|
194
|
-
const interactive = () => props.interactive === true;
|
|
195
191
|
const draggable = () => interactiveMap() || interactiveTimeline();
|
|
196
192
|
const labels = () => props.labels ?? {};
|
|
193
|
+
const accessibleName = () => {
|
|
194
|
+
const override = props.kind === "map" ? labels().interactiveMap : props.kind === "stateTimeline" ? labels().interactiveTimeline : props.kind === "line" ? labels().interactiveLine : labels().interactiveChart;
|
|
195
|
+
const title = "title" in props && typeof props.title === "string" && props.title.trim() ? props.title : undefined;
|
|
196
|
+
const valueLabel = (props.kind === "stat" || props.kind === "gauge") && props.label?.trim() ? props.label : undefined;
|
|
197
|
+
const fallback = props.kind === "map" ? chartMessages().interactiveMap : props.kind === "stateTimeline" ? chartMessages().interactiveTimeline : props.kind === "line" ? chartMessages().interactiveLineChart : chartMessages().interactiveChart;
|
|
198
|
+
return override ?? title ?? valueLabel ?? fallback;
|
|
199
|
+
};
|
|
197
200
|
const timelineFullDomain = () => props.kind === "stateTimeline" ? stateTimelineDomain(props.rows, props.domain) : [0, 1];
|
|
198
201
|
createEffect(() => {
|
|
199
202
|
if (props.kind === "map") {
|
|
@@ -380,7 +383,7 @@ const Chart = props => {
|
|
|
380
383
|
tooltip: () => chartTooltipRef,
|
|
381
384
|
anchor: () => lineAnchorRef,
|
|
382
385
|
kind: () => props.kind,
|
|
383
|
-
enabled:
|
|
386
|
+
enabled: () => !isEmpty(props),
|
|
384
387
|
select: selection => props.onSelect?.(selection),
|
|
385
388
|
format: selection => {
|
|
386
389
|
if (props.tooltip) return props.tooltip(selection);
|
|
@@ -438,22 +441,15 @@ const Chart = props => {
|
|
|
438
441
|
return !isEmpty(props);
|
|
439
442
|
},
|
|
440
443
|
get fallback() {
|
|
441
|
-
return _$ssr(_tmpl$
|
|
444
|
+
return _$ssr(_tmpl$4, `k2b-chart k2b-chart__empty ${_$escape(props.class ?? "", true)}`, _$ssrStyle(chartStyle()), _$escape(labels().empty ?? messages().noData));
|
|
442
445
|
},
|
|
443
446
|
get children() {
|
|
444
|
-
return _$ssr(_tmpl$
|
|
445
|
-
get when() {
|
|
446
|
-
return interactive();
|
|
447
|
-
},
|
|
448
|
-
get children() {
|
|
449
|
-
return [_$ssr(_tmpl$2), _$ssr(_tmpl$3, _$ssrAttribute("id", _$escape(chartTooltipId, true), false))];
|
|
450
|
-
}
|
|
451
|
-
})), _$escape(_$createComponent(Show, {
|
|
447
|
+
return _$ssr(_tmpl$3, `k2b-chart ${_$escape(props.class ?? "", true)}`, _$ssrAttribute("data-chart-kind", _$escape(props.kind, true), false) + _$ssrAttribute("data-drag", draggable() ? dragging() ? "active" : "idle" : _$escape(undefined, true), false) + _$ssrAttribute("data-crosshair", !draggable() && props.kind === "line" ? "true" : _$escape(undefined, true), false), _$ssrStyle(chartStyle()), _$ssrAttribute("aria-label", _$escape(accessibleName(), true), false) + _$ssrAttribute("aria-description", accessibleName() !== chartMessages().interactiveChart ? _$escape(chartMessages().interactiveChart, true) : _$escape(undefined, true), false), _$ssrAttribute("data-stretch", !preservesAspectRatio(props.kind) ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("--k2b-chart-width:", `${_$escape(size().width, true)}px`) + _$ssrStyleProperty(";--k2b-chart-height:", `${_$escape(size().height, true)}px`) + _$ssrStyleProperty(";aspect-ratio:", `${_$escape(size().width, true)} / ${_$escape(size().height, true)}`), isServer ? selectedChartSvg(svgMarkup(), props.selected) : svgMarkup(), _$ssrAttribute("id", _$escape(chartTooltipId, true), false), _$escape(_$createComponent(Show, {
|
|
452
448
|
get when() {
|
|
453
449
|
return draggable();
|
|
454
450
|
},
|
|
455
451
|
get children() {
|
|
456
|
-
return _$ssr(_tmpl$
|
|
452
|
+
return _$ssr(_tmpl$2, _$escape(control(labels().zoomIn ?? viewportMessages().zoomIn, "+", "ti-plus", () => zoom(1))), _$escape(control(labels().zoomOut ?? viewportMessages().zoomOut, "-", "ti-minus", () => zoom(-1))), _$escape(control(interactiveMap() ? labels().resetMap ?? chartMessages().resetMapView : labels().resetTimeline ?? chartMessages().resetTimelineView, "0", "ti-focus-centered", reset)));
|
|
457
453
|
}
|
|
458
454
|
})));
|
|
459
455
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/Chart.tsx"],"sourcesContent":["import type { MapViewport } from \"@k2b/stdlib\";\nimport { charts } from \"@k2b/stdlib\";\nimport type { JSX } from \"solid-js\";\nimport { createEffect, createMemo, createSignal, createUniqueId, onCleanup, onMount, Show, splitProps, untrack } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { IconButton } from \"../actions/Button\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ChartCursor } from \"./chart-cursor\";\nimport { createChartInspection } from \"./chart-inspection\";\nimport {\n type ChartDatumRef,\n type ChartKind,\n type ChartSelection,\n type ChartTooltipFormatter,\n closeChartInspectionOnOutside,\n} from \"./chart-inspection-core\";\nimport { lineGapsSvg } from \"./chart-line-gaps\";\nimport { DEFAULT_MAP_VIEWPORT, normalizeMapViewport, panMapViewport, zoomMapViewport } from \"./chart-map-viewport\";\nimport { useChartMessages } from \"./chart-messages\";\nimport {\n panStateTimelineViewport,\n renderStateTimelineSvg,\n type StateTimelineChartOptions,\n type StateTimelineDomain,\n stateTimelineDomain,\n stateTimelineHeight,\n zoomStateTimelineViewport,\n} from \"./chart-state-timeline\";\nimport { responsiveChartSvg, responsiveMapSvg, selectedChartSvg } from \"./chart-svg\";\nimport { useViewportMessages } from \"./viewport-messages\";\n\n/**\n * Chart — minimal Solid wrapper around `stdlib.charts`.\n *\n * **Live-update story.** `charts.<kind>(opts)` returns an SVG string;\n * Solid's `innerHTML` is reactive, so any time a prop (signal, store\n * slice, derived value) changes, the SVG re-renders. No manual\n * subscription, no imperative DOM patching. Trade-off: every change\n * is a full SVG re-build, not a diff — fine for dashboard cadences\n * (poll, websocket, store updates). Don't use this for 60fps streaming.\n *\n * **Sizing.** The server and browser render the same logical viewBox. CSS\n * fits Cartesian plots to the container and preserves text/marker sizes;\n * maps fit the whole world and zoom uniformly across the full plot; pies, donuts and gauges retain\n * their aspect ratio. No measurement\n * or hydration redraw is needed. The caller sizes the wrapper, for example\n * `style={{ height: \"14rem\" }}`. State timelines derive their default height\n * from the row count and legend via `stateTimelineHeight()`.\n *\n * **Why so thin.** The props are a discriminated union over each\n * stdlib chart function — `kind: \"line\"` brings in exactly the params\n * `charts.line` expects, `kind: \"bar\"` brings in `charts.bar`'s, etc.\n * Options stay aligned with stdlib without renaming. Shared interactive\n * layers add bounded pan / zoom controls to maps and state timelines, plus\n * renderer-owned inspection, tooltips and optional selection for all chart kinds.\n * If stdlib gains a new option, it's automatically available at every\n * callsite.\n *\n * **Theming.** stdlib charts use `currentColor` for axes / ticks /\n * tick labels — set the wrapping element's `color` and everything\n * inherits. Series colors come from `--stdlib-chart-c1..c8` CSS\n * custom properties; override on the parent for per-chart palettes.\n *\n * ```tsx\n * <Chart kind=\"line\" style={{ height: \"12rem\" }}\n * series={[{ data: points() }]}\n * yAxis={{ format: v => `€${v}k` }} />\n *\n * <Chart kind=\"donut\" style={{ height: \"12rem\" }} data={slices()} />\n *\n * <Chart kind=\"sparkline\" style={{ width: \"6rem\", height: \"1.5rem\" }} data={trend()} />\n *\n * <Chart kind=\"map\" style={{ height: \"16rem\" }} series={locations()} interactive />\n * ```\n */\n\n/** All chart kinds shipped by `stdlib.charts`. */\nexport type { ChartKind } from \"./chart-inspection-core\";\n\nexport type ChartLabels = Partial<{\n empty: string;\n series: string;\n interactiveMap: string;\n interactiveTimeline: string;\n interactiveLine: string;\n interactiveChart: string;\n zoomIn: string;\n zoomOut: string;\n resetMap: string;\n resetTimeline: string;\n}>;\n\n/**\n * Per-kind props: `kind` discriminator + the exact options that\n * `charts.<kind>` accepts, **minus** `width` / `height` (the wrapper\n * owns those — CSS fits a stable coordinate space to the box). Solid's\n * component model handles discriminated unions natively, so callsites\n * get full type safety.\n */\nexport type ChartProps = {\n [K in ChartKind]: {\n kind: K;\n class?: string;\n style?: JSX.CSSProperties | string;\n labels?: ChartLabels;\n interactive?: boolean;\n onSelect?: (selection: ChartSelection) => void;\n /** Controlled highlight; indices belong to this exact input snapshot. */\n selected?: ChartDatumRef | null;\n tooltip?: ChartTooltipFormatter;\n /** Optional shared X cursor for line charts. */\n cursor?: ChartCursor;\n } & (K extends \"map\"\n ? {\n /** Target when zooming in from the world view. Defaults to Europe (50, 10). */\n zoomFocus?: Pick<MapViewport, \"latitude\" | \"longitude\">;\n }\n : {}) &\n (K extends \"line\" ? { /** Largest connected X distance; positive, finite, without area/errorBand fills. */ maxGap?: number } : {}) &\n (K extends \"stateTimeline\" ? StateTimelineChartOptions : Omit<Parameters<(typeof charts)[K]>[0], \"width\" | \"height\" | \"inspect\">);\n}[ChartKind];\n\n/** Pure renderer options: component layout, events and inspection are configured elsewhere. */\nexport type ChartRenderOptions = {\n [K in ChartKind]: Omit<\n Extract<ChartProps, { kind: K }>,\n \"class\" | \"style\" | \"labels\" | \"interactive\" | \"onSelect\" | \"selected\" | \"tooltip\" | \"cursor\"\n >;\n}[ChartKind];\n\n/** Keep the fixed 28-unit bar-gauge rows inside the shared SSR/browser coordinate space. */\nexport const chartRenderHeight = (props: ChartRenderOptions): number => {\n if (props.kind === \"stateTimeline\") return stateTimelineHeight(props.rows.length, props.legend !== false);\n if (props.kind === \"barGauge\") return Math.max(280, (props.title || props.subtitle ? 42 : 16) + props.data.length * 28 + 14);\n return 280;\n};\n\n/**\n * Internal — strips wrapper-only keys from props and forwards the\n * rest (plus logical size) to `charts[kind]`. The `any` is the\n * price for dispatching one function call across 14 different option\n * types; an explicit per-kind switch would type it but balloon the\n * component for no runtime benefit.\n */\nexport const renderChartSvg = (\n props: ChartProps,\n width: number,\n height: number,\n mapViewport?: MapViewport,\n timelineViewport?: StateTimelineDomain,\n): string => {\n const {\n kind,\n class: _class,\n style: _style,\n labels: _labels,\n interactive: _interactive,\n onSelect: _onSelect,\n selected: _selected,\n tooltip: _tooltip,\n cursor: _cursor,\n zoomFocus: _zoomFocus,\n ...opts\n } = props as ChartProps & { interactive?: boolean; zoomFocus?: Pick<MapViewport, \"latitude\" | \"longitude\"> };\n if (kind === \"stateTimeline\") {\n return responsiveChartSvg(\n renderStateTimelineSvg({\n ...(opts as StateTimelineChartOptions),\n width,\n height,\n viewport: timelineViewport,\n interactive: props.interactive,\n }),\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let svg = (charts[kind] as (o: unknown) => string)({\n ...(opts as any),\n ...(kind === \"map\" ? { viewport: DEFAULT_MAP_VIEWPORT } : {}),\n width,\n height,\n inspect: props.interactive === true || (props.kind === \"line\" && props.maxGap !== undefined),\n });\n if (props.kind === \"line\" && props.maxGap !== undefined) {\n if (props.area || props.errorBand) throw new Error(\"Chart maxGap does not support area or errorBand fills\");\n svg = lineGapsSvg(svg, props.maxGap, props);\n }\n if (props.kind === \"map\") return responsiveMapSvg(svg, width, height, normalizeMapViewport(mapViewport ?? props.viewport));\n return preservesAspectRatio(kind) ? svg : responsiveChartSvg(svg);\n};\n\nconst preservesAspectRatio = (kind: ChartKind) => kind === \"map\" || kind === \"pie\" || kind === \"donut\" || kind === \"gauge\";\n\n/** Empty-data short-circuit. Kept per-kind because stdlib's payload\n * key differs (series vs data vs groups). We're conservative: only\n * block on truly empty inputs; partially-filled series get rendered\n * as-is and stdlib handles the gaps. */\nconst isEmpty = (props: ChartProps): boolean => {\n if (props.kind === \"line\" || props.kind === \"scatter\") {\n return !props.series?.length || props.series.every((s) => !s.data.length);\n }\n if (props.kind === \"bar\" || props.kind === \"donut\" || props.kind === \"pie\") {\n return !props.data?.length;\n }\n if (props.kind === \"histogram\" || props.kind === \"sparkline\") {\n return !props.data?.length;\n }\n if (props.kind === \"boxplot\") {\n return !props.groups?.length;\n }\n if (props.kind === \"stateTimeline\") {\n return !props.rows?.length || props.rows.every((row) => !row.intervals.length);\n }\n return false;\n};\n\nconst Chart = (props: ChartProps): JSX.Element => {\n const [, drawingProps] = splitProps(props, [\"selected\", \"onSelect\", \"tooltip\", \"cursor\"]);\n const messages = useUiMessages();\n const chartMessages = useChartMessages();\n const viewportMessages = useViewportMessages();\n const locale = useLocale();\n let containerRef: HTMLDivElement | undefined;\n let chartTooltipRef: HTMLSpanElement | undefined;\n let lineAnchorRef: HTMLSpanElement | undefined;\n // One deterministic coordinate space on the server and client. CSS fits the\n // SVG to its box; hydration must never replace it with measured geometry.\n const size = () => ({\n width: 480,\n height: chartRenderHeight(props),\n });\n const dimensions = () => containerRef?.getBoundingClientRect() ?? size();\n const initialMapViewport = props.kind === \"map\" ? normalizeMapViewport(props.viewport) : DEFAULT_MAP_VIEWPORT;\n const [mapViewport, setMapViewport] = createSignal<MapViewport>(initialMapViewport);\n const initialTimelineViewport =\n props.kind === \"stateTimeline\" ? stateTimelineDomain(props.rows, props.domain) : ([0, 1] as StateTimelineDomain);\n const [timelineViewport, setTimelineViewport] = createSignal<StateTimelineDomain>(initialTimelineViewport);\n const [dragging, setDragging] = createSignal(false);\n const chartTooltipId = `k2b-chart-tooltip-${createUniqueId()}`;\n let timelineViewportLocallyChanged = false;\n let drag:\n | {\n pointerId: number;\n x: number;\n y: number;\n width: number;\n height: number;\n viewport: MapViewport;\n }\n | undefined;\n let timelineDrag:\n | {\n pointerId: number;\n x: number;\n width: number;\n viewport: StateTimelineDomain;\n }\n | undefined;\n let pointerFrame: number | undefined;\n let pendingPointer: { pointerId: number; clientX: number; clientY: number } | undefined;\n\n const interactiveMap = () => props.kind === \"map\" && props.interactive === true;\n const interactiveTimeline = () => props.kind === \"stateTimeline\" && props.interactive === true;\n const interactiveLine = () => props.kind === \"line\" && props.interactive === true;\n const interactive = () => props.interactive === true;\n const draggable = () => interactiveMap() || interactiveTimeline();\n const labels = () => props.labels ?? {};\n const timelineFullDomain = (): StateTimelineDomain =>\n props.kind === \"stateTimeline\" ? stateTimelineDomain(props.rows, props.domain) : [0, 1];\n\n createEffect(() => {\n if (props.kind === \"map\") {\n setMapViewport(normalizeMapViewport(props.viewport));\n }\n });\n\n createEffect(() => {\n if (props.kind === \"stateTimeline\" && !timelineViewportLocallyChanged) {\n setTimelineViewport(timelineFullDomain());\n }\n });\n\n const updateTimelineViewport = (update: (current: StateTimelineDomain) => StateTimelineDomain) => {\n timelineViewportLocallyChanged = true;\n setTimelineViewport(update);\n };\n\n const mapDimensions = () => {\n const viewportElement = containerRef?.querySelector<SVGSVGElement>(\".stdlib-chart-map-viewport\");\n const matrix = viewportElement?.getScreenCTM?.();\n const box = viewportElement?.viewBox?.baseVal;\n if (matrix && box?.width && box.height) {\n return { width: box.width * Math.hypot(matrix.a, matrix.b), height: box.height * Math.hypot(matrix.c, matrix.d) };\n }\n const rect = viewportElement?.getBoundingClientRect();\n if (rect && rect.width > 0 && rect.height > 0) {\n return { width: rect.width, height: rect.height };\n }\n return dimensions();\n };\n\n const zoom = (delta: number) => {\n closeChartTooltip();\n if (interactiveMap()) {\n setMapViewport((current) => zoomMapViewport(current, delta, props.kind === \"map\" ? props.zoomFocus : undefined));\n } else if (interactiveTimeline()) {\n updateTimelineViewport((current) => zoomStateTimelineViewport(current, timelineFullDomain(), delta));\n }\n };\n\n const reset = () => {\n closeChartTooltip();\n if (interactiveMap() && props.kind === \"map\") {\n setMapViewport(normalizeMapViewport(props.viewport));\n }\n if (interactiveTimeline()) {\n timelineViewportLocallyChanged = false;\n setTimelineViewport(timelineFullDomain());\n }\n };\n\n const handlePointerDown: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n inspection.down(event);\n if (!draggable() || event.button !== 0 || (event.target as Element).closest(\"button, a\")) {\n return;\n }\n closeChartTooltip();\n // The pointer's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n if (interactiveTimeline()) {\n timelineDrag = {\n pointerId: event.pointerId,\n x: event.clientX,\n width: Math.max(1, event.currentTarget.getBoundingClientRect().width),\n viewport: timelineViewport(),\n };\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(true);\n return;\n }\n const dimensions = mapDimensions();\n drag = {\n pointerId: event.pointerId,\n x: event.clientX,\n y: event.clientY,\n width: dimensions.width,\n height: dimensions.height,\n viewport: mapViewport(),\n };\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(true);\n };\n\n const flushPointerMove = () => {\n if (pointerFrame !== undefined) {\n cancelAnimationFrame(pointerFrame);\n pointerFrame = undefined;\n }\n const sample = pendingPointer;\n pendingPointer = undefined;\n if (!sample) return;\n const start = timelineDrag ?? drag;\n if (start && Math.hypot(sample.clientX - start.x, sample.clientY - (\"y\" in start ? start.y : sample.clientY)) <= 6) return;\n const activeTimelineDrag = timelineDrag;\n if (activeTimelineDrag?.pointerId === sample.pointerId) {\n updateTimelineViewport(() =>\n panStateTimelineViewport(\n activeTimelineDrag.viewport,\n timelineFullDomain(),\n sample.clientX - activeTimelineDrag.x,\n activeTimelineDrag.width,\n ),\n );\n return;\n }\n if (!drag || drag.pointerId !== sample.pointerId) return;\n setMapViewport(panMapViewport(drag.viewport, sample.clientX - drag.x, sample.clientY - drag.y, drag.width, drag.height));\n };\n\n const handlePointerMove: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n inspection.move(event);\n if (timelineDrag?.pointerId !== event.pointerId && drag?.pointerId !== event.pointerId) return;\n pendingPointer = { pointerId: event.pointerId, clientX: event.clientX, clientY: event.clientY };\n if (pointerFrame !== undefined) return;\n pointerFrame = requestAnimationFrame(flushPointerMove);\n };\n\n const stopDragging: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n if (pendingPointer?.pointerId === event.pointerId) flushPointerMove();\n if (timelineDrag?.pointerId === event.pointerId) {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n timelineDrag = undefined;\n setDragging(false);\n return;\n }\n if (!drag || drag.pointerId !== event.pointerId) return;\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n drag = undefined;\n setDragging(false);\n };\n\n const handleWheel: JSX.EventHandlerUnion<HTMLDivElement, WheelEvent> = (event) => {\n if (interactiveMap() && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n zoom(event.deltaY < 0 ? 1 : -1);\n return;\n }\n if (!interactiveTimeline()) return;\n if (event.ctrlKey || event.metaKey) {\n event.preventDefault();\n const rect = event.currentTarget.getBoundingClientRect();\n const anchor = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0.5;\n updateTimelineViewport((current) => zoomStateTimelineViewport(current, timelineFullDomain(), event.deltaY < 0 ? 1 : -1, anchor));\n } else if (event.shiftKey) {\n event.preventDefault();\n updateTimelineViewport((current) =>\n panStateTimelineViewport(current, timelineFullDomain(), -event.deltaY, event.currentTarget.getBoundingClientRect().width),\n );\n }\n };\n\n const handleKeyDown: JSX.EventHandlerUnion<HTMLDivElement, KeyboardEvent> = (event) => {\n if (inspection.key(event)) return;\n if (!draggable() || event.target !== containerRef) return;\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n zoom(1);\n return;\n }\n if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n zoom(-1);\n return;\n }\n if (event.key === \"0\" || event.key === \"Home\") {\n event.preventDefault();\n reset();\n return;\n }\n if (interactiveTimeline() && (event.key === \"ArrowLeft\" || event.key === \"ArrowRight\")) {\n event.preventDefault();\n updateTimelineViewport((current) =>\n panStateTimelineViewport(\n current,\n timelineFullDomain(),\n event.key === \"ArrowLeft\" ? 80 : -80,\n event.currentTarget.getBoundingClientRect().width,\n ),\n );\n return;\n }\n const delta: readonly [number, number] | undefined = {\n ArrowLeft: [40, 0],\n ArrowRight: [-40, 0],\n ArrowUp: [0, 40],\n ArrowDown: [0, -40],\n }[event.key] as readonly [number, number] | undefined;\n if (!delta) return;\n event.preventDefault();\n const dimensions = mapDimensions();\n setMapViewport((current) => panMapViewport(current, delta[0], delta[1], dimensions.width, dimensions.height));\n };\n\n const inspection = createChartInspection({\n container: () => containerRef,\n cursor: () => props.cursor,\n tooltip: () => chartTooltipRef,\n anchor: () => lineAnchorRef,\n kind: () => props.kind,\n enabled: interactive,\n select: (selection) => props.onSelect?.(selection),\n format: (selection) => {\n if (props.tooltip) return props.tooltip(selection);\n const fields = chartMessages().chartFields;\n const format = new Intl.NumberFormat(locale(), { maximumFractionDigits: 6 });\n return {\n title:\n selection.datum.label ??\n (selection.datum.seriesIndex !== undefined\n ? `${labels().series ?? chartMessages().series} ${selection.datum.seriesIndex + 1}`\n : undefined),\n rows: selection.datum.values.map((field) => ({\n label:\n selection.kind === \"line\" && field.key === \"y\"\n ? (selection.datum.label ?? labels().series ?? chartMessages().series)\n : fields({ key: field.key }),\n value:\n field.formatted ??\n (field.key === \"upperInclusive\"\n ? field.value === \"true\"\n ? messages().yes\n : messages().no\n : typeof field.value === \"number\"\n ? `${format.format(field.value)}${field.key === \"percent\" ? \"%\" : \"\"}`\n : field.value),\n })),\n };\n },\n });\n const closeChartTooltip = () => inspection.close();\n const svgMarkup = createMemo(() =>\n renderChartSvg(\n drawingProps,\n size().width,\n size().height,\n interactiveMap() ? mapViewport() : undefined,\n interactiveTimeline() ? timelineViewport() : undefined,\n ),\n );\n createEffect(() => {\n svgMarkup();\n inspection.invalidate();\n untrack(() => inspection.selectDatum(props.selected));\n });\n\n createEffect(() => inspection.selectDatum(props.selected));\n\n onCleanup(() => {\n inspection.close();\n if (pointerFrame !== undefined) cancelAnimationFrame(pointerFrame);\n pointerFrame = undefined;\n pendingPointer = undefined;\n });\n\n onMount(() => {\n if (!containerRef) return;\n onCleanup(\n closeChartInspectionOnOutside({\n container: () => containerRef,\n tooltip: () => chartTooltipRef,\n close: closeChartTooltip,\n }),\n );\n });\n\n const chartStyle = () =>\n props.style ??\n (props.kind === \"stateTimeline\"\n ? {\n height: `${stateTimelineHeight(props.rows.length, props.legend !== false)}px`,\n }\n : undefined);\n\n const control = (label: string, shortcut: string, icon: string, action: () => void) => (\n <IconButton variant=\"secondary\" label={label} tooltip={`${label} (${shortcut})`} onClick={action}>\n <i class={`ti ${icon}`} aria-hidden=\"true\" />\n </IconButton>\n );\n\n return (\n <Show\n when={!isEmpty(props)}\n fallback={\n <div ref={containerRef} class={`k2b-chart k2b-chart__empty ${props.class ?? \"\"}`} style={chartStyle()}>\n {labels().empty ?? messages().noData}\n </div>\n }\n >\n {/* CSS fits the server-rendered SVG to the caller's box. Only changes\n to chart data/options rebuild the SVG; resizing does not. */}\n <div\n ref={containerRef}\n class={`k2b-chart ${props.class ?? \"\"}`}\n data-chart-kind={props.kind}\n data-drag={draggable() ? (dragging() ? \"active\" : \"idle\") : undefined}\n data-crosshair={!draggable() && interactiveLine() ? \"true\" : undefined}\n data-interactive={interactive() ? \"true\" : undefined}\n style={chartStyle()}\n role=\"group\"\n aria-label={\n interactiveMap()\n ? (labels().interactiveMap ?? chartMessages().interactiveMap)\n : interactiveTimeline()\n ? (labels().interactiveTimeline ?? chartMessages().interactiveTimeline)\n : interactiveLine()\n ? (labels().interactiveLine ?? chartMessages().interactiveLineChart)\n : interactive()\n ? (labels().interactiveChart ?? chartMessages().interactiveChart)\n : undefined\n }\n aria-description={interactive() ? chartMessages().interactiveChart : undefined}\n tabIndex={interactive() ? 0 : undefined}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={stopDragging}\n onPointerCancel={stopDragging}\n onClick={inspection.click}\n onPointerLeave={inspection.leave}\n onFocusIn={inspection.focus}\n onFocusOut={closeChartTooltip}\n onWheel={handleWheel}\n onKeyDown={handleKeyDown}\n >\n <div\n class=\"k2b-chart__svg\"\n data-stretch={!preservesAspectRatio(props.kind) ? \"true\" : undefined}\n style={{\n \"--k2b-chart-width\": `${size().width}px`,\n \"--k2b-chart-height\": `${size().height}px`,\n \"aspect-ratio\": `${size().width} / ${size().height}`,\n }}\n innerHTML={isServer ? selectedChartSvg(svgMarkup(), props.selected) : svgMarkup()}\n />\n <Show when={interactive()}>\n <span ref={lineAnchorRef} class=\"k2b-chart__anchor\" aria-hidden=\"true\" />\n <span\n id={chartTooltipId}\n ref={chartTooltipRef}\n role=\"tooltip\"\n popover=\"manual\"\n data-instant=\"true\"\n class=\"k2b-tooltip k2b-chart__tooltip\"\n />\n </Show>\n <Show when={draggable()}>\n <div class=\"k2b-chart__controls\">\n {control(labels().zoomIn ?? viewportMessages().zoomIn, \"+\", \"ti-plus\", () => zoom(1))}\n {control(labels().zoomOut ?? viewportMessages().zoomOut, \"-\", \"ti-minus\", () => zoom(-1))}\n {control(\n interactiveMap()\n ? (labels().resetMap ?? chartMessages().resetMapView)\n : (labels().resetTimeline ?? chartMessages().resetTimelineView),\n \"0\",\n \"ti-focus-centered\",\n reset,\n )}\n </div>\n </Show>\n </div>\n </Show>\n );\n};\n\nexport default Chart;\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/Chart.tsx"],"sourcesContent":["import type { MapViewport } from \"@k2b/stdlib\";\nimport { charts } from \"@k2b/stdlib\";\nimport type { JSX } from \"solid-js\";\nimport { createEffect, createMemo, createSignal, createUniqueId, onCleanup, onMount, Show, splitProps, untrack } from \"solid-js\";\nimport { isServer } from \"solid-js/web\";\nimport { IconButton } from \"../actions/Button\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\nimport { useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport type { ChartCursor } from \"./chart-cursor\";\nimport { createChartInspection } from \"./chart-inspection\";\nimport {\n type ChartDatumRef,\n type ChartKind,\n type ChartSelection,\n type ChartTooltipFormatter,\n closeChartInspectionOnOutside,\n} from \"./chart-inspection-core\";\nimport { lineGapsSvg } from \"./chart-line-gaps\";\nimport { DEFAULT_MAP_VIEWPORT, normalizeMapViewport, panMapViewport, zoomMapViewport } from \"./chart-map-viewport\";\nimport { useChartMessages } from \"./chart-messages\";\nimport {\n panStateTimelineViewport,\n renderStateTimelineSvg,\n type StateTimelineChartOptions,\n type StateTimelineDomain,\n stateTimelineDomain,\n stateTimelineHeight,\n zoomStateTimelineViewport,\n} from \"./chart-state-timeline\";\nimport { responsiveChartSvg, responsiveMapSvg, selectedChartSvg } from \"./chart-svg\";\nimport { useViewportMessages } from \"./viewport-messages\";\n\n/**\n * Chart — minimal Solid wrapper around `stdlib.charts`.\n *\n * **Live-update story.** `charts.<kind>(opts)` returns an SVG string;\n * Solid's `innerHTML` is reactive, so any time a prop (signal, store\n * slice, derived value) changes, the SVG re-renders. No manual\n * subscription, no imperative DOM patching. Trade-off: every change\n * is a full SVG re-build, not a diff — fine for dashboard cadences\n * (poll, websocket, store updates). Don't use this for 60fps streaming.\n *\n * **Sizing.** The server and browser render the same logical viewBox. CSS\n * fits Cartesian plots to the container and preserves text/marker sizes;\n * maps fit the whole world and zoom uniformly across the full plot; pies, donuts and gauges retain\n * their aspect ratio. No measurement\n * or hydration redraw is needed. The caller sizes the wrapper, for example\n * `style={{ height: \"14rem\" }}`. State timelines derive their default height\n * from the row count and legend via `stateTimelineHeight()`.\n *\n * **Why so thin.** The props are a discriminated union over each\n * stdlib chart function — `kind: \"line\"` brings in exactly the params\n * `charts.line` expects, `kind: \"bar\"` brings in `charts.bar`'s, etc.\n * Options stay aligned with stdlib without renaming. Every chart provides\n * renderer-owned inspection, tooltips and optional selection by default.\n * `interactive` adds bounded pan / zoom and reset controls to maps and state timelines.\n * If stdlib gains a new option, it's automatically available at every\n * callsite.\n *\n * **Theming.** stdlib charts use `currentColor` for axes / ticks /\n * tick labels — set the wrapping element's `color` and everything\n * inherits. Series colors come from `--stdlib-chart-c1..c8` CSS\n * custom properties; override on the parent for per-chart palettes.\n *\n * ```tsx\n * <Chart kind=\"line\" style={{ height: \"12rem\" }}\n * series={[{ data: points() }]}\n * yAxis={{ format: v => `€${v}k` }} />\n *\n * <Chart kind=\"donut\" style={{ height: \"12rem\" }} data={slices()} />\n *\n * <Chart kind=\"sparkline\" style={{ width: \"6rem\", height: \"1.5rem\" }} data={trend()} />\n *\n * <Chart kind=\"map\" style={{ height: \"16rem\" }} series={locations()} interactive />\n * ```\n */\n\n/** All chart kinds shipped by `stdlib.charts`. */\nexport type { ChartKind } from \"./chart-inspection-core\";\n\nexport type ChartLabels = Partial<{\n empty: string;\n series: string;\n interactiveMap: string;\n interactiveTimeline: string;\n interactiveLine: string;\n interactiveChart: string;\n zoomIn: string;\n zoomOut: string;\n resetMap: string;\n resetTimeline: string;\n}>;\n\n/**\n * Per-kind props: `kind` discriminator + the exact options that\n * `charts.<kind>` accepts, **minus** `width` / `height` (the wrapper\n * owns those — CSS fits a stable coordinate space to the box). Solid's\n * component model handles discriminated unions natively, so callsites\n * get full type safety.\n */\nexport type ChartProps = {\n [K in ChartKind]: {\n kind: K;\n class?: string;\n style?: JSX.CSSProperties | string;\n labels?: ChartLabels;\n /**\n * Navigation for maps and state timelines: pan, zoom and reset controls.\n * Arrows pan; Alt+arrows inspect. Every chart shows tooltips and keyboard\n * inspection without this prop.\n */\n interactive?: boolean;\n onSelect?: (selection: ChartSelection) => void;\n /** Controlled highlight; indices belong to this exact input snapshot. */\n selected?: ChartDatumRef | null;\n /** Customize the always-on tooltip with a title and labeled text rows. */\n tooltip?: ChartTooltipFormatter;\n /** Optional shared X cursor for line charts. */\n cursor?: ChartCursor;\n } & (K extends \"map\"\n ? {\n /** Target when zooming in from the world view. Defaults to Europe (50, 10). */\n zoomFocus?: Pick<MapViewport, \"latitude\" | \"longitude\">;\n }\n : {}) &\n (K extends \"line\" ? { /** Largest connected X distance; positive, finite, without area/errorBand fills. */ maxGap?: number } : {}) &\n (K extends \"stateTimeline\" ? StateTimelineChartOptions : Omit<Parameters<(typeof charts)[K]>[0], \"width\" | \"height\" | \"inspect\">);\n}[ChartKind];\n\n/** Pure renderer options: component layout, events and inspection are configured elsewhere. */\nexport type ChartRenderOptions = {\n [K in ChartKind]: Omit<\n Extract<ChartProps, { kind: K }>,\n \"class\" | \"style\" | \"labels\" | \"interactive\" | \"onSelect\" | \"selected\" | \"tooltip\" | \"cursor\"\n >;\n}[ChartKind];\n\n/** Keep the fixed 28-unit bar-gauge rows inside the shared SSR/browser coordinate space. */\nexport const chartRenderHeight = (props: ChartRenderOptions): number => {\n if (props.kind === \"stateTimeline\") return stateTimelineHeight(props.rows.length, props.legend !== false);\n if (props.kind === \"barGauge\") return Math.max(280, (props.title || props.subtitle ? 42 : 16) + props.data.length * 28 + 14);\n return 280;\n};\n\n/**\n * Internal — strips wrapper-only keys from props and forwards the\n * rest (plus logical size) to `charts[kind]`. The `any` is the\n * price for dispatching one function call across 14 different option\n * types; an explicit per-kind switch would type it but balloon the\n * component for no runtime benefit.\n */\nexport const renderChartSvg = (\n props: ChartProps,\n width: number,\n height: number,\n mapViewport?: MapViewport,\n timelineViewport?: StateTimelineDomain,\n): string => {\n const {\n kind,\n class: _class,\n style: _style,\n labels: _labels,\n interactive: _interactive,\n onSelect: _onSelect,\n selected: _selected,\n tooltip: _tooltip,\n cursor: _cursor,\n zoomFocus: _zoomFocus,\n ...opts\n } = props as ChartProps & { interactive?: boolean; zoomFocus?: Pick<MapViewport, \"latitude\" | \"longitude\"> };\n if (kind === \"stateTimeline\") {\n return responsiveChartSvg(\n renderStateTimelineSvg({\n ...(opts as StateTimelineChartOptions),\n width,\n height,\n viewport: timelineViewport,\n interactive: true,\n }),\n );\n }\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let svg = (charts[kind] as (o: unknown) => string)({\n ...(opts as any),\n ...(kind === \"map\" ? { viewport: DEFAULT_MAP_VIEWPORT } : {}),\n width,\n height,\n inspect: true,\n });\n if (props.kind === \"line\" && props.maxGap !== undefined) {\n if (props.area || props.errorBand) throw new Error(\"Chart maxGap does not support area or errorBand fills\");\n svg = lineGapsSvg(svg, props.maxGap, props);\n }\n if (props.kind === \"map\") return responsiveMapSvg(svg, width, height, normalizeMapViewport(mapViewport ?? props.viewport));\n return preservesAspectRatio(kind) ? svg : responsiveChartSvg(svg);\n};\n\nconst preservesAspectRatio = (kind: ChartKind) => kind === \"map\" || kind === \"pie\" || kind === \"donut\" || kind === \"gauge\";\n\n/** Empty-data short-circuit. Kept per-kind because stdlib's payload\n * key differs (series vs data vs groups). We're conservative: only\n * block on truly empty inputs; partially-filled series get rendered\n * as-is and stdlib handles the gaps. */\nconst isEmpty = (props: ChartProps): boolean => {\n if (props.kind === \"line\" || props.kind === \"scatter\") {\n return !props.series?.length || props.series.every((s) => !s.data.length);\n }\n if (props.kind === \"bar\" || props.kind === \"donut\" || props.kind === \"pie\") {\n return !props.data?.length;\n }\n if (props.kind === \"histogram\" || props.kind === \"sparkline\") {\n return !props.data?.length;\n }\n if (props.kind === \"boxplot\") {\n return !props.groups?.length;\n }\n if (props.kind === \"stateTimeline\") {\n return !props.rows?.length || props.rows.every((row) => !row.intervals.length);\n }\n return false;\n};\n\nconst Chart = (props: ChartProps): JSX.Element => {\n const [, drawingProps] = splitProps(props, [\"selected\", \"onSelect\", \"tooltip\", \"cursor\"]);\n const messages = useUiMessages();\n const chartMessages = useChartMessages();\n const viewportMessages = useViewportMessages();\n const locale = useLocale();\n let containerRef: HTMLDivElement | undefined;\n let chartTooltipRef: HTMLSpanElement | undefined;\n let lineAnchorRef: HTMLSpanElement | undefined;\n // One deterministic coordinate space on the server and client. CSS fits the\n // SVG to its box; hydration must never replace it with measured geometry.\n const size = () => ({\n width: 480,\n height: chartRenderHeight(props),\n });\n const dimensions = () => containerRef?.getBoundingClientRect() ?? size();\n const initialMapViewport = props.kind === \"map\" ? normalizeMapViewport(props.viewport) : DEFAULT_MAP_VIEWPORT;\n const [mapViewport, setMapViewport] = createSignal<MapViewport>(initialMapViewport);\n const initialTimelineViewport =\n props.kind === \"stateTimeline\" ? stateTimelineDomain(props.rows, props.domain) : ([0, 1] as StateTimelineDomain);\n const [timelineViewport, setTimelineViewport] = createSignal<StateTimelineDomain>(initialTimelineViewport);\n const [dragging, setDragging] = createSignal(false);\n const chartTooltipId = `k2b-chart-tooltip-${createUniqueId()}`;\n let timelineViewportLocallyChanged = false;\n let drag:\n | {\n pointerId: number;\n x: number;\n y: number;\n width: number;\n height: number;\n viewport: MapViewport;\n }\n | undefined;\n let timelineDrag:\n | {\n pointerId: number;\n x: number;\n width: number;\n viewport: StateTimelineDomain;\n }\n | undefined;\n let pointerFrame: number | undefined;\n let pendingPointer: { pointerId: number; clientX: number; clientY: number } | undefined;\n\n const interactiveMap = () => props.kind === \"map\" && props.interactive === true;\n const interactiveTimeline = () => props.kind === \"stateTimeline\" && props.interactive === true;\n const draggable = () => interactiveMap() || interactiveTimeline();\n const labels = () => props.labels ?? {};\n const accessibleName = () => {\n const override =\n props.kind === \"map\"\n ? labels().interactiveMap\n : props.kind === \"stateTimeline\"\n ? labels().interactiveTimeline\n : props.kind === \"line\"\n ? labels().interactiveLine\n : labels().interactiveChart;\n const title = \"title\" in props && typeof props.title === \"string\" && props.title.trim() ? props.title : undefined;\n const valueLabel = (props.kind === \"stat\" || props.kind === \"gauge\") && props.label?.trim() ? props.label : undefined;\n const fallback =\n props.kind === \"map\"\n ? chartMessages().interactiveMap\n : props.kind === \"stateTimeline\"\n ? chartMessages().interactiveTimeline\n : props.kind === \"line\"\n ? chartMessages().interactiveLineChart\n : chartMessages().interactiveChart;\n return override ?? title ?? valueLabel ?? fallback;\n };\n const timelineFullDomain = (): StateTimelineDomain =>\n props.kind === \"stateTimeline\" ? stateTimelineDomain(props.rows, props.domain) : [0, 1];\n\n createEffect(() => {\n if (props.kind === \"map\") {\n setMapViewport(normalizeMapViewport(props.viewport));\n }\n });\n\n createEffect(() => {\n if (props.kind === \"stateTimeline\" && !timelineViewportLocallyChanged) {\n setTimelineViewport(timelineFullDomain());\n }\n });\n\n const updateTimelineViewport = (update: (current: StateTimelineDomain) => StateTimelineDomain) => {\n timelineViewportLocallyChanged = true;\n setTimelineViewport(update);\n };\n\n const mapDimensions = () => {\n const viewportElement = containerRef?.querySelector<SVGSVGElement>(\".stdlib-chart-map-viewport\");\n const matrix = viewportElement?.getScreenCTM?.();\n const box = viewportElement?.viewBox?.baseVal;\n if (matrix && box?.width && box.height) {\n return { width: box.width * Math.hypot(matrix.a, matrix.b), height: box.height * Math.hypot(matrix.c, matrix.d) };\n }\n const rect = viewportElement?.getBoundingClientRect();\n if (rect && rect.width > 0 && rect.height > 0) {\n return { width: rect.width, height: rect.height };\n }\n return dimensions();\n };\n\n const zoom = (delta: number) => {\n closeChartTooltip();\n if (interactiveMap()) {\n setMapViewport((current) => zoomMapViewport(current, delta, props.kind === \"map\" ? props.zoomFocus : undefined));\n } else if (interactiveTimeline()) {\n updateTimelineViewport((current) => zoomStateTimelineViewport(current, timelineFullDomain(), delta));\n }\n };\n\n const reset = () => {\n closeChartTooltip();\n if (interactiveMap() && props.kind === \"map\") {\n setMapViewport(normalizeMapViewport(props.viewport));\n }\n if (interactiveTimeline()) {\n timelineViewportLocallyChanged = false;\n setTimelineViewport(timelineFullDomain());\n }\n };\n\n const handlePointerDown: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n inspection.down(event);\n if (!draggable() || event.button !== 0 || (event.target as Element).closest(\"button, a\")) {\n return;\n }\n closeChartTooltip();\n // The pointer's own pointerup or pointercancel ends the hold.\n suppressTextSelection(event.pointerId);\n if (interactiveTimeline()) {\n timelineDrag = {\n pointerId: event.pointerId,\n x: event.clientX,\n width: Math.max(1, event.currentTarget.getBoundingClientRect().width),\n viewport: timelineViewport(),\n };\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(true);\n return;\n }\n const dimensions = mapDimensions();\n drag = {\n pointerId: event.pointerId,\n x: event.clientX,\n y: event.clientY,\n width: dimensions.width,\n height: dimensions.height,\n viewport: mapViewport(),\n };\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(true);\n };\n\n const flushPointerMove = () => {\n if (pointerFrame !== undefined) {\n cancelAnimationFrame(pointerFrame);\n pointerFrame = undefined;\n }\n const sample = pendingPointer;\n pendingPointer = undefined;\n if (!sample) return;\n const start = timelineDrag ?? drag;\n if (start && Math.hypot(sample.clientX - start.x, sample.clientY - (\"y\" in start ? start.y : sample.clientY)) <= 6) return;\n const activeTimelineDrag = timelineDrag;\n if (activeTimelineDrag?.pointerId === sample.pointerId) {\n updateTimelineViewport(() =>\n panStateTimelineViewport(\n activeTimelineDrag.viewport,\n timelineFullDomain(),\n sample.clientX - activeTimelineDrag.x,\n activeTimelineDrag.width,\n ),\n );\n return;\n }\n if (!drag || drag.pointerId !== sample.pointerId) return;\n setMapViewport(panMapViewport(drag.viewport, sample.clientX - drag.x, sample.clientY - drag.y, drag.width, drag.height));\n };\n\n const handlePointerMove: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n inspection.move(event);\n if (timelineDrag?.pointerId !== event.pointerId && drag?.pointerId !== event.pointerId) return;\n pendingPointer = { pointerId: event.pointerId, clientX: event.clientX, clientY: event.clientY };\n if (pointerFrame !== undefined) return;\n pointerFrame = requestAnimationFrame(flushPointerMove);\n };\n\n const stopDragging: JSX.EventHandlerUnion<HTMLDivElement, PointerEvent> = (event) => {\n if (pendingPointer?.pointerId === event.pointerId) flushPointerMove();\n if (timelineDrag?.pointerId === event.pointerId) {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n timelineDrag = undefined;\n setDragging(false);\n return;\n }\n if (!drag || drag.pointerId !== event.pointerId) return;\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n drag = undefined;\n setDragging(false);\n };\n\n const handleWheel: JSX.EventHandlerUnion<HTMLDivElement, WheelEvent> = (event) => {\n if (interactiveMap() && (event.ctrlKey || event.metaKey)) {\n event.preventDefault();\n zoom(event.deltaY < 0 ? 1 : -1);\n return;\n }\n if (!interactiveTimeline()) return;\n if (event.ctrlKey || event.metaKey) {\n event.preventDefault();\n const rect = event.currentTarget.getBoundingClientRect();\n const anchor = rect.width > 0 ? (event.clientX - rect.left) / rect.width : 0.5;\n updateTimelineViewport((current) => zoomStateTimelineViewport(current, timelineFullDomain(), event.deltaY < 0 ? 1 : -1, anchor));\n } else if (event.shiftKey) {\n event.preventDefault();\n updateTimelineViewport((current) =>\n panStateTimelineViewport(current, timelineFullDomain(), -event.deltaY, event.currentTarget.getBoundingClientRect().width),\n );\n }\n };\n\n const handleKeyDown: JSX.EventHandlerUnion<HTMLDivElement, KeyboardEvent> = (event) => {\n if (inspection.key(event)) return;\n if (!draggable() || event.target !== containerRef) return;\n if (event.key === \"+\" || event.key === \"=\") {\n event.preventDefault();\n zoom(1);\n return;\n }\n if (event.key === \"-\" || event.key === \"_\") {\n event.preventDefault();\n zoom(-1);\n return;\n }\n if (event.key === \"0\" || event.key === \"Home\") {\n event.preventDefault();\n reset();\n return;\n }\n if (interactiveTimeline() && (event.key === \"ArrowLeft\" || event.key === \"ArrowRight\")) {\n event.preventDefault();\n updateTimelineViewport((current) =>\n panStateTimelineViewport(\n current,\n timelineFullDomain(),\n event.key === \"ArrowLeft\" ? 80 : -80,\n event.currentTarget.getBoundingClientRect().width,\n ),\n );\n return;\n }\n const delta: readonly [number, number] | undefined = {\n ArrowLeft: [40, 0],\n ArrowRight: [-40, 0],\n ArrowUp: [0, 40],\n ArrowDown: [0, -40],\n }[event.key] as readonly [number, number] | undefined;\n if (!delta) return;\n event.preventDefault();\n const dimensions = mapDimensions();\n setMapViewport((current) => panMapViewport(current, delta[0], delta[1], dimensions.width, dimensions.height));\n };\n\n const inspection = createChartInspection({\n container: () => containerRef,\n cursor: () => props.cursor,\n tooltip: () => chartTooltipRef,\n anchor: () => lineAnchorRef,\n kind: () => props.kind,\n enabled: () => !isEmpty(props),\n select: (selection) => props.onSelect?.(selection),\n format: (selection) => {\n if (props.tooltip) return props.tooltip(selection);\n const fields = chartMessages().chartFields;\n const format = new Intl.NumberFormat(locale(), { maximumFractionDigits: 6 });\n return {\n title:\n selection.datum.label ??\n (selection.datum.seriesIndex !== undefined\n ? `${labels().series ?? chartMessages().series} ${selection.datum.seriesIndex + 1}`\n : undefined),\n rows: selection.datum.values.map((field) => ({\n label:\n selection.kind === \"line\" && field.key === \"y\"\n ? (selection.datum.label ?? labels().series ?? chartMessages().series)\n : fields({ key: field.key }),\n value:\n field.formatted ??\n (field.key === \"upperInclusive\"\n ? field.value === \"true\"\n ? messages().yes\n : messages().no\n : typeof field.value === \"number\"\n ? `${format.format(field.value)}${field.key === \"percent\" ? \"%\" : \"\"}`\n : field.value),\n })),\n };\n },\n });\n const closeChartTooltip = () => inspection.close();\n const svgMarkup = createMemo(() =>\n renderChartSvg(\n drawingProps,\n size().width,\n size().height,\n interactiveMap() ? mapViewport() : undefined,\n interactiveTimeline() ? timelineViewport() : undefined,\n ),\n );\n createEffect(() => {\n svgMarkup();\n inspection.invalidate();\n untrack(() => inspection.selectDatum(props.selected));\n });\n\n createEffect(() => inspection.selectDatum(props.selected));\n\n onCleanup(() => {\n inspection.close();\n if (pointerFrame !== undefined) cancelAnimationFrame(pointerFrame);\n pointerFrame = undefined;\n pendingPointer = undefined;\n });\n\n onMount(() => {\n if (!containerRef) return;\n onCleanup(\n closeChartInspectionOnOutside({\n container: () => containerRef,\n tooltip: () => chartTooltipRef,\n close: closeChartTooltip,\n }),\n );\n });\n\n const chartStyle = () =>\n props.style ??\n (props.kind === \"stateTimeline\"\n ? {\n height: `${stateTimelineHeight(props.rows.length, props.legend !== false)}px`,\n }\n : undefined);\n\n const control = (label: string, shortcut: string, icon: string, action: () => void) => (\n <IconButton variant=\"secondary\" label={label} tooltip={`${label} (${shortcut})`} onClick={action}>\n <i class={`ti ${icon}`} aria-hidden=\"true\" />\n </IconButton>\n );\n\n return (\n <Show\n when={!isEmpty(props)}\n fallback={\n <div ref={containerRef} class={`k2b-chart k2b-chart__empty ${props.class ?? \"\"}`} style={chartStyle()}>\n {labels().empty ?? messages().noData}\n </div>\n }\n >\n {/* CSS fits the server-rendered SVG to the caller's box. Only changes\n to chart data/options rebuild the SVG; resizing does not. */}\n <div\n ref={containerRef}\n class={`k2b-chart ${props.class ?? \"\"}`}\n data-chart-kind={props.kind}\n data-drag={draggable() ? (dragging() ? \"active\" : \"idle\") : undefined}\n data-crosshair={!draggable() && props.kind === \"line\" ? \"true\" : undefined}\n data-interactive=\"true\"\n style={chartStyle()}\n role=\"group\"\n aria-label={accessibleName()}\n aria-description={accessibleName() !== chartMessages().interactiveChart ? chartMessages().interactiveChart : undefined}\n tabIndex={0}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={stopDragging}\n onPointerCancel={stopDragging}\n onClick={inspection.click}\n onPointerLeave={inspection.leave}\n onFocusIn={inspection.focus}\n onFocusOut={closeChartTooltip}\n onWheel={handleWheel}\n onKeyDown={handleKeyDown}\n >\n <div\n class=\"k2b-chart__svg\"\n data-stretch={!preservesAspectRatio(props.kind) ? \"true\" : undefined}\n style={{\n \"--k2b-chart-width\": `${size().width}px`,\n \"--k2b-chart-height\": `${size().height}px`,\n \"aspect-ratio\": `${size().width} / ${size().height}`,\n }}\n innerHTML={isServer ? selectedChartSvg(svgMarkup(), props.selected) : svgMarkup()}\n />\n <span ref={lineAnchorRef} class=\"k2b-chart__anchor\" aria-hidden=\"true\" />\n <span\n id={chartTooltipId}\n ref={chartTooltipRef}\n role=\"tooltip\"\n popover=\"manual\"\n data-instant=\"true\"\n class=\"k2b-tooltip k2b-chart__tooltip\"\n />\n <Show when={draggable()}>\n <div class=\"k2b-chart__controls\">\n {control(labels().zoomIn ?? viewportMessages().zoomIn, \"+\", \"ti-plus\", () => zoom(1))}\n {control(labels().zoomOut ?? viewportMessages().zoomOut, \"-\", \"ti-minus\", () => zoom(-1))}\n {control(\n interactiveMap()\n ? (labels().resetMap ?? chartMessages().resetMapView)\n : (labels().resetTimeline ?? chartMessages().resetTimelineView),\n \"0\",\n \"ti-focus-centered\",\n reset,\n )}\n </div>\n </Show>\n </div>\n </Show>\n );\n};\n\nexport default Chart;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -272,7 +272,7 @@ export function FileBrowserPanel(props) {
|
|
|
272
272
|
},
|
|
273
273
|
get children() {
|
|
274
274
|
return _$createComponent(Placeholder, {
|
|
275
|
-
|
|
275
|
+
state: "loading",
|
|
276
276
|
get title() {
|
|
277
277
|
return fileBrowserMessages().loadingFiles;
|
|
278
278
|
}
|
|
@@ -284,7 +284,7 @@ export function FileBrowserPanel(props) {
|
|
|
284
284
|
},
|
|
285
285
|
get children() {
|
|
286
286
|
return _$createComponent(Placeholder, {
|
|
287
|
-
|
|
287
|
+
state: "error",
|
|
288
288
|
get title() {
|
|
289
289
|
return fileInputMessages().failedLoadFiles;
|
|
290
290
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["content/FileBrowser.tsx"],"sourcesContent":["/**\n * FileBrowser — FileTree + FileView over a FileSource adapter. One dialog\n * serves every file surface (conversation VFS, skills, later the Files app):\n * the source decides the capabilities, optional methods enable the matching\n * UI (write → edit/save, remove → delete, rename → rename, upload → upload).\n * Fixed-height IDE-style layout: both panes scroll, the shell never jumps.\n */\nimport { createZip, downloadFileFromContent } from \"@k2b/stdlib/browser\";\nimport { mutation } from \"@k2b/stdlib/solid\";\nimport { createEffect, createMemo, createResource, createSignal, Match, onCleanup, Show, Switch, untrack } from \"solid-js\";\nimport Dropdown from \"../actions/Dropdown\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { prompts } from \"../feedback/prompts\";\nimport { useFileInputMessages } from \"../inputs/file-input-messages\";\nimport { useUiMessages } from \"../intl/messages\";\nimport PanelDialog, { panelDialogOptions } from \"../layout/PanelDialog\";\nimport Placeholder from \"../surfaces/Placeholder\";\nimport FileTree, { type FileTreeEntry } from \"./FileTree\";\nimport FileView, { type FileViewContent, type FileViewRenderer } from \"./FileView\";\nimport { resolveFileBrowserMessages, useFileBrowserMessages } from \"./file-browser-messages\";\n\nexport type FileSource = {\n previewPreferencesKey?: string;\n list(): Promise<FileTreeEntry[]>;\n read(path: string): Promise<FileViewContent>;\n write?(path: string, content: string, encoding?: \"utf8\" | \"base64\"): Promise<void>;\n remove?(path: string): Promise<void>;\n rename?(from: string, to: string): Promise<void>;\n upload?(dirPath: string, files: File[]): Promise<void>;\n downloadHref?(path: string): string | null;\n /** Paths matching this predicate stay read-only even when the source can write (e.g. /input). */\n isReadOnly?(path: string): boolean;\n};\n\nexport type FileBrowserPanelProps = {\n source: FileSource;\n /** Hide every mutating affordance while retaining file selection and downloads. */\n readOnly?: boolean;\n /** Refetch entries when this host-controlled value changes. */\n refreshKey?: unknown;\n /** Preselect a file once entries are loaded. */\n initialPath?: string;\n /** Mirrors file selection into route state when the host needs durable navigation. */\n onSelectedPathChange?: (path: string | null) => void;\n /** Per-instance preview extensions forwarded to FileView. */\n renderers?: readonly FileViewRenderer[];\n /** Optional host copy/policy for leaving an unsaved file. */\n confirmDiscard?: (path: string, nextPath: string | null) => boolean | Promise<boolean>;\n /** Fixed shell height — the panes scroll inside it. */\n class?: string;\n /** Optional imperative refresh used by realtime owners that must await the visible update. */\n registerRefresh?: (refresh: () => Promise<void>) => void | (() => void);\n};\n\nconst parentOf = (path: string): string => {\n const index = path.lastIndexOf(\"/\");\n return index <= 0 ? \"/\" : path.slice(0, index);\n};\n\nexport function FileBrowserPanel(props: FileBrowserPanelProps) {\n const messages = useUiMessages();\n const fileBrowserMessages = useFileBrowserMessages();\n const fileInputMessages = useFileInputMessages();\n // FileSource is an imperative adapter. Its methods may read host signals,\n // but refreshes stay owned by this component (`refetch` / `refreshKey`);\n // tracking those implementation details can otherwise feed a write back\n // into its own list request indefinitely.\n const [entries, { refetch }] = createResource(async () => untrack(() => props.source.list()));\n const [selectedPath, setSelectedPath] = createSignal<string | null>(props.initialPath ?? null);\n const [selectedDirty, setSelectedDirty] = createSignal(false);\n // Folders exist implicitly through file paths — freshly created (still empty)\n // ones live here until their first file makes them real.\n const [pendingFolders, setPendingFolders] = createSignal<string[]>([]);\n let uploadInputRef: HTMLInputElement | undefined;\n let uploadDir = \"/\";\n let previousRefreshKey = props.refreshKey;\n let refreshPreview = async (): Promise<void> => undefined;\n\n createEffect(() => {\n if (!props.registerRefresh) return;\n const unregister = props.registerRefresh(async () => {\n await Promise.all([refetch(), refreshPreview()]);\n });\n if (unregister) onCleanup(unregister);\n });\n\n createEffect(() => {\n const next = props.initialPath ?? null;\n if (!selectedDirty() && next !== selectedPath()) setSelectedPath(next);\n });\n createEffect(() => props.onSelectedPathChange?.(selectedPath()));\n createEffect(() => {\n const refreshKey = props.refreshKey;\n if (Object.is(refreshKey, previousRefreshKey)) return;\n previousRefreshKey = refreshKey;\n void refetch();\n });\n\n const allEntries = createMemo<FileTreeEntry[]>(() => {\n const loaded = entries() ?? [];\n const real = new Set(loaded.map((entry) => entry.path));\n return [\n ...loaded,\n ...pendingFolders()\n .filter((path) => !real.has(path))\n .map((path) => ({ path, kind: \"folder\" as const })),\n ];\n });\n const selectedEntry = createMemo(() => allEntries().find((entry) => entry.path === selectedPath()) ?? null);\n const fileMutation = mutation.create<void, () => Promise<void>>({\n mutation: (work) => work(),\n onSuccess: () => void refetch(),\n onError: (error) => void prompts.error(error.message),\n });\n const pathMutable = (path: string) => !fileMutation.loading() && !props.readOnly && !props.source.isReadOnly?.(path);\n const pathWritable = (path: string) => pathMutable(path) && Boolean(props.source.write);\n const run = (work: () => Promise<void>) => void fileMutation.mutate(work);\n const canLeaveCurrent = async (nextPath: string | null): Promise<boolean> => {\n const current = selectedPath();\n if (nextPath === current || !selectedDirty() || !current) return true;\n if (selectedDirty() && current) {\n const confirmed = props.confirmDiscard\n ? await props.confirmDiscard(current, nextPath)\n : await prompts.confirm(fileBrowserMessages().discardUnsavedFile, {\n title: fileBrowserMessages().discardChanges,\n variant: \"danger\",\n });\n if (!confirmed) return false;\n }\n return true;\n };\n const selectPath = async (nextPath: string | null) => {\n if (!(await canLeaveCurrent(nextPath))) return;\n setSelectedDirty(false);\n setSelectedPath(nextPath);\n };\n\n const removeFile = (path: string) =>\n run(async () => {\n const confirmed = await prompts.confirm(`Delete ${path}?`, { title: \"Delete file\", variant: \"danger\" });\n if (!confirmed) return;\n await props.source.remove!(path);\n setPendingFolders((folders) => folders.filter((candidate) => candidate !== path && !candidate.startsWith(`${path}/`)));\n const selected = selectedPath();\n if (selected === path || selected?.startsWith(`${path}/`)) setSelectedPath(null);\n });\n\n const renameFile = (path: string, nextName: string) =>\n run(async () => {\n const target = `${parentOf(path) === \"/\" ? \"\" : parentOf(path)}/${nextName}`;\n await props.source.rename!(path, target);\n if (selectedPath() === path) setSelectedPath(target);\n });\n\n const createFile = (dirPath: string) =>\n run(async () => {\n const name = await prompts.prompt(fileBrowserMessages().newFileName, \"\", { title: fileBrowserMessages().newFile });\n if (!name || typeof name !== \"string\" || !name.trim() || name.includes(\"/\")) return;\n const path = `${dirPath === \"/\" ? \"\" : dirPath}/${name.trim()}`;\n if (!(await canLeaveCurrent(path))) return;\n await props.source.write!(path, \"\");\n setSelectedDirty(false);\n setSelectedPath(path);\n });\n\n const createFolder = (dirPath: string) =>\n void (async () => {\n const name = await prompts.prompt(fileBrowserMessages().newFolderName, \"\", { title: fileBrowserMessages().newFolder });\n if (!name || typeof name !== \"string\" || !name.trim() || name.includes(\"/\")) return;\n const path = `${dirPath === \"/\" ? \"\" : dirPath}/${name.trim()}`;\n setPendingFolders((folders) => [...folders, path]);\n })();\n\n const pickUpload = (dirPath: string) => {\n uploadDir = dirPath;\n uploadInputRef?.click();\n };\n\n const onUploadPicked = (input: HTMLInputElement) => {\n const files = Array.from(input.files ?? []);\n input.value = \"\";\n if (files.length > 0) run(() => props.source.upload!(uploadDir, files));\n };\n\n const baseName = (path: string) => path.slice(path.lastIndexOf(\"/\") + 1);\n\n /** Concrete file paths behind an entry: the file itself, or everything under a folder. */\n const filesBehind = (path: string): string[] => {\n const list = entries() ?? [];\n if (list.some((entry) => entry.path === path && entry.kind !== \"folder\")) return [path];\n const prefix = `${path}/`;\n return list.filter((entry) => entry.path.startsWith(prefix) && entry.kind !== \"folder\").map((entry) => entry.path);\n };\n\n /** Move a file OR a whole folder subtree (per-file renames preserve the structure). */\n const moveEntry = (path: string, targetDir: string) =>\n run(async () => {\n const destBase = `${targetDir === \"/\" ? \"\" : targetDir}/${baseName(path)}`;\n const files = filesBehind(path);\n if (files.length === 0) {\n // Still-empty pending folder — relocating it is a purely local affair.\n setPendingFolders((folders) => folders.map((candidate) => (candidate === path ? destBase : candidate)));\n return;\n }\n for (const file of files) {\n await props.source.rename!(file, `${destBase}${file.slice(path.length)}`);\n }\n const selected = selectedPath();\n if (selected && (selected === path || selected.startsWith(`${path}/`))) {\n setSelectedPath(`${destBase}${selected.slice(path.length)}`);\n }\n });\n\n const contentBytes = async (path: string): Promise<Uint8Array> => {\n const content = await props.source.read(path);\n return content.encoding === \"utf8\"\n ? new TextEncoder().encode(content.content)\n : Uint8Array.from(atob(content.content), (char) => char.charCodeAt(0));\n };\n\n const downloadEntry = (path: string, isFolder: boolean) =>\n void (async () => {\n try {\n if (!isFolder) {\n const href = props.source.downloadHref?.(path);\n if (href) {\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.download = baseName(path);\n anchor.click();\n return;\n }\n const content = await props.source.read(path);\n downloadFileFromContent(await contentBytes(path), baseName(path), content.mediaType || \"application/octet-stream\");\n return;\n }\n const files = filesBehind(path);\n if (files.length === 0) throw new Error(fileBrowserMessages().folderEmpty);\n const zipEntries = await Promise.all(\n files.map(async (file) => ({ filename: file.slice(path.length + 1), source: await contentBytes(file) })),\n );\n downloadFileFromContent(await createZip(zipEntries), `${baseName(path) || \"files\"}.zip`, \"application/zip\");\n } catch (error) {\n void prompts.error(error instanceof Error ? error.message : fileBrowserMessages().downloadFailed);\n }\n })();\n\n const treeActions = () => ({\n ...(!props.readOnly && props.source.rename\n ? { rename: (path: string, next: string) => (pathMutable(path) ? renameFile(path, next) : undefined) }\n : {}),\n ...(!props.readOnly && props.source.remove ? { remove: (path: string) => (pathMutable(path) ? removeFile(path) : undefined) } : {}),\n ...(!props.readOnly && props.source.write ? { createFile: (dir: string) => (pathWritable(dir) ? createFile(dir) : undefined) } : {}),\n ...(!props.readOnly && props.source.write\n ? { createFolder: (dir: string) => (pathWritable(dir) ? createFolder(dir) : undefined) }\n : {}),\n ...(!props.readOnly && props.source.rename\n ? { move: (path: string, dir: string) => (pathMutable(path) && pathMutable(dir) ? moveEntry(path, dir) : undefined) }\n : {}),\n download: (path: string, isFolder: boolean) => downloadEntry(path, isFolder),\n });\n\n const addMenuItems = () => [\n ...(pathWritable(\"/\") ? [{ icon: \"ti ti-file-plus\", label: fileBrowserMessages().newFile, action: () => createFile(\"/\") }] : []),\n ...(pathWritable(\"/\") ? [{ icon: \"ti ti-folder-plus\", label: fileBrowserMessages().newFolder, action: () => createFolder(\"/\") }] : []),\n ...(pathMutable(\"/\") && props.source.upload\n ? [{ icon: \"ti ti-upload\", label: fileBrowserMessages().uploadFiles, action: () => pickUpload(\"/\") }]\n : []),\n ];\n\n return (\n <div class={`k2b-content-file-browser ${props.class ?? \"\"}`} data-default-height={props.class ? undefined : \"true\"}>\n <div class=\"k2b-content-file-browser__sidebar\">\n <div class=\"k2b-content-file-browser__header\">\n <p class=\"k2b-content-file-browser__title\">{fileBrowserMessages().files}</p>\n <Show when={addMenuItems().length > 0}>\n <Dropdown.Root position=\"bottom-left\" items={addMenuItems()} label={fileBrowserMessages().addFileFolderUpload}>\n <Dropdown.Trigger\n appearance=\"plain\"\n class=\"k2b-content-file-browser__add\"\n label={fileBrowserMessages().addFileFolderUpload}\n tooltip={messages().add}\n >\n <i class=\"ti ti-plus\" aria-hidden=\"true\" />\n <span class=\"k2b-sr-only\">{fileBrowserMessages().addFileFolderUpload}</span>\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n <Switch>\n <Match when={entries.loading && entries() === undefined}>\n <Placeholder icon=\"ti ti-loader-2\" title={fileBrowserMessages().loadingFiles} />\n </Match>\n <Match when={entries.error}>\n <Placeholder\n icon=\"ti ti-alert-circle\"\n title={fileInputMessages().failedLoadFiles}\n description={String(entries.error?.message ?? entries.error ?? \"\")}\n />\n </Match>\n <Match when={allEntries().length > 0}>\n <FileTree\n class=\"k2b-content-file-browser__tree\"\n entries={allEntries()}\n selectedPath={selectedPath()}\n onSelect={(entry) => void selectPath(entry.path)}\n actions={treeActions()}\n />\n </Match>\n <Match when={true}>\n <Placeholder icon=\"ti ti-folder-open\" title={fileBrowserMessages().noFiles} description={fileBrowserMessages().spaceEmpty} />\n </Match>\n </Switch>\n <input\n ref={uploadInputRef}\n type=\"file\"\n multiple\n class=\"k2b-content-file-browser__upload\"\n onChange={(event) => onUploadPicked(event.currentTarget)}\n />\n </div>\n\n <Switch\n fallback={\n <Placeholder icon=\"ti ti-file\" title={fileBrowserMessages().selectFile} description={fileBrowserMessages().pickFileFromTree} />\n }\n >\n <Match when={selectedEntry()?.kind === \"folder\"}>\n <Placeholder\n icon=\"ti ti-folder\"\n title={fileBrowserMessages().folderSelected}\n description={fileBrowserMessages().chooseFileToPreview}\n />\n </Match>\n <Match when={selectedEntry()}>\n {(entry) => (\n <FileView\n previewPreferencesKey={props.source.previewPreferencesKey}\n file={{ path: entry().path, mediaType: entry().mediaType, size: entry().size }}\n load={() => props.source.read(entry().path)}\n revision={props.refreshKey}\n registerRefresh={(refresh) => {\n refreshPreview = refresh;\n return () => {\n refreshPreview = async () => undefined;\n };\n }}\n renderers={props.renderers}\n onDirtyChange={setSelectedDirty}\n save={\n pathWritable(entry().path)\n ? async (content) => {\n await props.source.write!(entry().path, content);\n await refetch();\n }\n : undefined\n }\n downloadHref={props.source.downloadHref?.(entry().path) ?? null}\n />\n )}\n </Match>\n </Switch>\n </div>\n );\n}\n\n/** Open the file browser as a dialog. Returns when the dialog closes. */\nexport const openFileBrowser = (options: { source: FileSource; title?: string; subtitle?: string; icon?: string }): Promise<void> => {\n const fileBrowserMessages = resolveFileBrowserMessages();\n return dialogCore.open<void>(\n (close) => (\n <PanelDialog>\n <PanelDialog.Header\n title={options.title ?? fileBrowserMessages.files}\n subtitle={options.subtitle}\n icon={options.icon ?? \"ti ti-folder\"}\n close={() => close()}\n />\n <PanelDialog.Body>\n <FileBrowserPanel source={options.source} />\n </PanelDialog.Body>\n </PanelDialog>\n ),\n panelDialogOptions,\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":[],"sources":["content/FileBrowser.tsx"],"sourcesContent":["/**\n * FileBrowser — FileTree + FileView over a FileSource adapter. One dialog\n * serves every file surface (conversation VFS, skills, later the Files app):\n * the source decides the capabilities, optional methods enable the matching\n * UI (write → edit/save, remove → delete, rename → rename, upload → upload).\n * Fixed-height IDE-style layout: both panes scroll, the shell never jumps.\n */\nimport { createZip, downloadFileFromContent } from \"@k2b/stdlib/browser\";\nimport { mutation } from \"@k2b/stdlib/solid\";\nimport { createEffect, createMemo, createResource, createSignal, Match, onCleanup, Show, Switch, untrack } from \"solid-js\";\nimport Dropdown from \"../actions/Dropdown\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { prompts } from \"../feedback/prompts\";\nimport { useFileInputMessages } from \"../inputs/file-input-messages\";\nimport { useUiMessages } from \"../intl/messages\";\nimport PanelDialog, { panelDialogOptions } from \"../layout/PanelDialog\";\nimport Placeholder from \"../surfaces/Placeholder\";\nimport FileTree, { type FileTreeEntry } from \"./FileTree\";\nimport FileView, { type FileViewContent, type FileViewRenderer } from \"./FileView\";\nimport { resolveFileBrowserMessages, useFileBrowserMessages } from \"./file-browser-messages\";\n\nexport type FileSource = {\n previewPreferencesKey?: string;\n list(): Promise<FileTreeEntry[]>;\n read(path: string): Promise<FileViewContent>;\n write?(path: string, content: string, encoding?: \"utf8\" | \"base64\"): Promise<void>;\n remove?(path: string): Promise<void>;\n rename?(from: string, to: string): Promise<void>;\n upload?(dirPath: string, files: File[]): Promise<void>;\n downloadHref?(path: string): string | null;\n /** Paths matching this predicate stay read-only even when the source can write (e.g. /input). */\n isReadOnly?(path: string): boolean;\n};\n\nexport type FileBrowserPanelProps = {\n source: FileSource;\n /** Hide every mutating affordance while retaining file selection and downloads. */\n readOnly?: boolean;\n /** Refetch entries when this host-controlled value changes. */\n refreshKey?: unknown;\n /** Preselect a file once entries are loaded. */\n initialPath?: string;\n /** Mirrors file selection into route state when the host needs durable navigation. */\n onSelectedPathChange?: (path: string | null) => void;\n /** Per-instance preview extensions forwarded to FileView. */\n renderers?: readonly FileViewRenderer[];\n /** Optional host copy/policy for leaving an unsaved file. */\n confirmDiscard?: (path: string, nextPath: string | null) => boolean | Promise<boolean>;\n /** Fixed shell height — the panes scroll inside it. */\n class?: string;\n /** Optional imperative refresh used by realtime owners that must await the visible update. */\n registerRefresh?: (refresh: () => Promise<void>) => void | (() => void);\n};\n\nconst parentOf = (path: string): string => {\n const index = path.lastIndexOf(\"/\");\n return index <= 0 ? \"/\" : path.slice(0, index);\n};\n\nexport function FileBrowserPanel(props: FileBrowserPanelProps) {\n const messages = useUiMessages();\n const fileBrowserMessages = useFileBrowserMessages();\n const fileInputMessages = useFileInputMessages();\n // FileSource is an imperative adapter. Its methods may read host signals,\n // but refreshes stay owned by this component (`refetch` / `refreshKey`);\n // tracking those implementation details can otherwise feed a write back\n // into its own list request indefinitely.\n const [entries, { refetch }] = createResource(async () => untrack(() => props.source.list()));\n const [selectedPath, setSelectedPath] = createSignal<string | null>(props.initialPath ?? null);\n const [selectedDirty, setSelectedDirty] = createSignal(false);\n // Folders exist implicitly through file paths — freshly created (still empty)\n // ones live here until their first file makes them real.\n const [pendingFolders, setPendingFolders] = createSignal<string[]>([]);\n let uploadInputRef: HTMLInputElement | undefined;\n let uploadDir = \"/\";\n let previousRefreshKey = props.refreshKey;\n let refreshPreview = async (): Promise<void> => undefined;\n\n createEffect(() => {\n if (!props.registerRefresh) return;\n const unregister = props.registerRefresh(async () => {\n await Promise.all([refetch(), refreshPreview()]);\n });\n if (unregister) onCleanup(unregister);\n });\n\n createEffect(() => {\n const next = props.initialPath ?? null;\n if (!selectedDirty() && next !== selectedPath()) setSelectedPath(next);\n });\n createEffect(() => props.onSelectedPathChange?.(selectedPath()));\n createEffect(() => {\n const refreshKey = props.refreshKey;\n if (Object.is(refreshKey, previousRefreshKey)) return;\n previousRefreshKey = refreshKey;\n void refetch();\n });\n\n const allEntries = createMemo<FileTreeEntry[]>(() => {\n const loaded = entries() ?? [];\n const real = new Set(loaded.map((entry) => entry.path));\n return [\n ...loaded,\n ...pendingFolders()\n .filter((path) => !real.has(path))\n .map((path) => ({ path, kind: \"folder\" as const })),\n ];\n });\n const selectedEntry = createMemo(() => allEntries().find((entry) => entry.path === selectedPath()) ?? null);\n const fileMutation = mutation.create<void, () => Promise<void>>({\n mutation: (work) => work(),\n onSuccess: () => void refetch(),\n onError: (error) => void prompts.error(error.message),\n });\n const pathMutable = (path: string) => !fileMutation.loading() && !props.readOnly && !props.source.isReadOnly?.(path);\n const pathWritable = (path: string) => pathMutable(path) && Boolean(props.source.write);\n const run = (work: () => Promise<void>) => void fileMutation.mutate(work);\n const canLeaveCurrent = async (nextPath: string | null): Promise<boolean> => {\n const current = selectedPath();\n if (nextPath === current || !selectedDirty() || !current) return true;\n if (selectedDirty() && current) {\n const confirmed = props.confirmDiscard\n ? await props.confirmDiscard(current, nextPath)\n : await prompts.confirm(fileBrowserMessages().discardUnsavedFile, {\n title: fileBrowserMessages().discardChanges,\n variant: \"danger\",\n });\n if (!confirmed) return false;\n }\n return true;\n };\n const selectPath = async (nextPath: string | null) => {\n if (!(await canLeaveCurrent(nextPath))) return;\n setSelectedDirty(false);\n setSelectedPath(nextPath);\n };\n\n const removeFile = (path: string) =>\n run(async () => {\n const confirmed = await prompts.confirm(`Delete ${path}?`, { title: \"Delete file\", variant: \"danger\" });\n if (!confirmed) return;\n await props.source.remove!(path);\n setPendingFolders((folders) => folders.filter((candidate) => candidate !== path && !candidate.startsWith(`${path}/`)));\n const selected = selectedPath();\n if (selected === path || selected?.startsWith(`${path}/`)) setSelectedPath(null);\n });\n\n const renameFile = (path: string, nextName: string) =>\n run(async () => {\n const target = `${parentOf(path) === \"/\" ? \"\" : parentOf(path)}/${nextName}`;\n await props.source.rename!(path, target);\n if (selectedPath() === path) setSelectedPath(target);\n });\n\n const createFile = (dirPath: string) =>\n run(async () => {\n const name = await prompts.prompt(fileBrowserMessages().newFileName, \"\", { title: fileBrowserMessages().newFile });\n if (!name || typeof name !== \"string\" || !name.trim() || name.includes(\"/\")) return;\n const path = `${dirPath === \"/\" ? \"\" : dirPath}/${name.trim()}`;\n if (!(await canLeaveCurrent(path))) return;\n await props.source.write!(path, \"\");\n setSelectedDirty(false);\n setSelectedPath(path);\n });\n\n const createFolder = (dirPath: string) =>\n void (async () => {\n const name = await prompts.prompt(fileBrowserMessages().newFolderName, \"\", { title: fileBrowserMessages().newFolder });\n if (!name || typeof name !== \"string\" || !name.trim() || name.includes(\"/\")) return;\n const path = `${dirPath === \"/\" ? \"\" : dirPath}/${name.trim()}`;\n setPendingFolders((folders) => [...folders, path]);\n })();\n\n const pickUpload = (dirPath: string) => {\n uploadDir = dirPath;\n uploadInputRef?.click();\n };\n\n const onUploadPicked = (input: HTMLInputElement) => {\n const files = Array.from(input.files ?? []);\n input.value = \"\";\n if (files.length > 0) run(() => props.source.upload!(uploadDir, files));\n };\n\n const baseName = (path: string) => path.slice(path.lastIndexOf(\"/\") + 1);\n\n /** Concrete file paths behind an entry: the file itself, or everything under a folder. */\n const filesBehind = (path: string): string[] => {\n const list = entries() ?? [];\n if (list.some((entry) => entry.path === path && entry.kind !== \"folder\")) return [path];\n const prefix = `${path}/`;\n return list.filter((entry) => entry.path.startsWith(prefix) && entry.kind !== \"folder\").map((entry) => entry.path);\n };\n\n /** Move a file OR a whole folder subtree (per-file renames preserve the structure). */\n const moveEntry = (path: string, targetDir: string) =>\n run(async () => {\n const destBase = `${targetDir === \"/\" ? \"\" : targetDir}/${baseName(path)}`;\n const files = filesBehind(path);\n if (files.length === 0) {\n // Still-empty pending folder — relocating it is a purely local affair.\n setPendingFolders((folders) => folders.map((candidate) => (candidate === path ? destBase : candidate)));\n return;\n }\n for (const file of files) {\n await props.source.rename!(file, `${destBase}${file.slice(path.length)}`);\n }\n const selected = selectedPath();\n if (selected && (selected === path || selected.startsWith(`${path}/`))) {\n setSelectedPath(`${destBase}${selected.slice(path.length)}`);\n }\n });\n\n const contentBytes = async (path: string): Promise<Uint8Array> => {\n const content = await props.source.read(path);\n return content.encoding === \"utf8\"\n ? new TextEncoder().encode(content.content)\n : Uint8Array.from(atob(content.content), (char) => char.charCodeAt(0));\n };\n\n const downloadEntry = (path: string, isFolder: boolean) =>\n void (async () => {\n try {\n if (!isFolder) {\n const href = props.source.downloadHref?.(path);\n if (href) {\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.download = baseName(path);\n anchor.click();\n return;\n }\n const content = await props.source.read(path);\n downloadFileFromContent(await contentBytes(path), baseName(path), content.mediaType || \"application/octet-stream\");\n return;\n }\n const files = filesBehind(path);\n if (files.length === 0) throw new Error(fileBrowserMessages().folderEmpty);\n const zipEntries = await Promise.all(\n files.map(async (file) => ({ filename: file.slice(path.length + 1), source: await contentBytes(file) })),\n );\n downloadFileFromContent(await createZip(zipEntries), `${baseName(path) || \"files\"}.zip`, \"application/zip\");\n } catch (error) {\n void prompts.error(error instanceof Error ? error.message : fileBrowserMessages().downloadFailed);\n }\n })();\n\n const treeActions = () => ({\n ...(!props.readOnly && props.source.rename\n ? { rename: (path: string, next: string) => (pathMutable(path) ? renameFile(path, next) : undefined) }\n : {}),\n ...(!props.readOnly && props.source.remove ? { remove: (path: string) => (pathMutable(path) ? removeFile(path) : undefined) } : {}),\n ...(!props.readOnly && props.source.write ? { createFile: (dir: string) => (pathWritable(dir) ? createFile(dir) : undefined) } : {}),\n ...(!props.readOnly && props.source.write\n ? { createFolder: (dir: string) => (pathWritable(dir) ? createFolder(dir) : undefined) }\n : {}),\n ...(!props.readOnly && props.source.rename\n ? { move: (path: string, dir: string) => (pathMutable(path) && pathMutable(dir) ? moveEntry(path, dir) : undefined) }\n : {}),\n download: (path: string, isFolder: boolean) => downloadEntry(path, isFolder),\n });\n\n const addMenuItems = () => [\n ...(pathWritable(\"/\") ? [{ icon: \"ti ti-file-plus\", label: fileBrowserMessages().newFile, action: () => createFile(\"/\") }] : []),\n ...(pathWritable(\"/\") ? [{ icon: \"ti ti-folder-plus\", label: fileBrowserMessages().newFolder, action: () => createFolder(\"/\") }] : []),\n ...(pathMutable(\"/\") && props.source.upload\n ? [{ icon: \"ti ti-upload\", label: fileBrowserMessages().uploadFiles, action: () => pickUpload(\"/\") }]\n : []),\n ];\n\n return (\n <div class={`k2b-content-file-browser ${props.class ?? \"\"}`} data-default-height={props.class ? undefined : \"true\"}>\n <div class=\"k2b-content-file-browser__sidebar\">\n <div class=\"k2b-content-file-browser__header\">\n <p class=\"k2b-content-file-browser__title\">{fileBrowserMessages().files}</p>\n <Show when={addMenuItems().length > 0}>\n <Dropdown.Root position=\"bottom-left\" items={addMenuItems()} label={fileBrowserMessages().addFileFolderUpload}>\n <Dropdown.Trigger\n appearance=\"plain\"\n class=\"k2b-content-file-browser__add\"\n label={fileBrowserMessages().addFileFolderUpload}\n tooltip={messages().add}\n >\n <i class=\"ti ti-plus\" aria-hidden=\"true\" />\n <span class=\"k2b-sr-only\">{fileBrowserMessages().addFileFolderUpload}</span>\n </Dropdown.Trigger>\n </Dropdown.Root>\n </Show>\n </div>\n <Switch>\n <Match when={entries.loading && entries() === undefined}>\n <Placeholder state=\"loading\" title={fileBrowserMessages().loadingFiles} />\n </Match>\n <Match when={entries.error}>\n <Placeholder\n state=\"error\"\n title={fileInputMessages().failedLoadFiles}\n description={String(entries.error?.message ?? entries.error ?? \"\")}\n />\n </Match>\n <Match when={allEntries().length > 0}>\n <FileTree\n class=\"k2b-content-file-browser__tree\"\n entries={allEntries()}\n selectedPath={selectedPath()}\n onSelect={(entry) => void selectPath(entry.path)}\n actions={treeActions()}\n />\n </Match>\n <Match when={true}>\n <Placeholder icon=\"ti ti-folder-open\" title={fileBrowserMessages().noFiles} description={fileBrowserMessages().spaceEmpty} />\n </Match>\n </Switch>\n <input\n ref={uploadInputRef}\n type=\"file\"\n multiple\n class=\"k2b-content-file-browser__upload\"\n onChange={(event) => onUploadPicked(event.currentTarget)}\n />\n </div>\n\n <Switch\n fallback={\n <Placeholder icon=\"ti ti-file\" title={fileBrowserMessages().selectFile} description={fileBrowserMessages().pickFileFromTree} />\n }\n >\n <Match when={selectedEntry()?.kind === \"folder\"}>\n <Placeholder\n icon=\"ti ti-folder\"\n title={fileBrowserMessages().folderSelected}\n description={fileBrowserMessages().chooseFileToPreview}\n />\n </Match>\n <Match when={selectedEntry()}>\n {(entry) => (\n <FileView\n previewPreferencesKey={props.source.previewPreferencesKey}\n file={{ path: entry().path, mediaType: entry().mediaType, size: entry().size }}\n load={() => props.source.read(entry().path)}\n revision={props.refreshKey}\n registerRefresh={(refresh) => {\n refreshPreview = refresh;\n return () => {\n refreshPreview = async () => undefined;\n };\n }}\n renderers={props.renderers}\n onDirtyChange={setSelectedDirty}\n save={\n pathWritable(entry().path)\n ? async (content) => {\n await props.source.write!(entry().path, content);\n await refetch();\n }\n : undefined\n }\n downloadHref={props.source.downloadHref?.(entry().path) ?? null}\n />\n )}\n </Match>\n </Switch>\n </div>\n );\n}\n\n/** Open the file browser as a dialog. Returns when the dialog closes. */\nexport const openFileBrowser = (options: { source: FileSource; title?: string; subtitle?: string; icon?: string }): Promise<void> => {\n const fileBrowserMessages = resolveFileBrowserMessages();\n return dialogCore.open<void>(\n (close) => (\n <PanelDialog>\n <PanelDialog.Header\n title={options.title ?? fileBrowserMessages.files}\n subtitle={options.subtitle}\n icon={options.icon ?? \"ti ti-folder\"}\n close={() => close()}\n />\n <PanelDialog.Body>\n <FileBrowserPanel source={options.source} />\n </PanelDialog.Body>\n </PanelDialog>\n ),\n panelDialogOptions,\n );\n};\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -10,7 +10,7 @@ var _tmpl$ = ["<ul class=\"", "\"", " role=\"tree\"", ">", "</ul>"],
|
|
|
10
10
|
_tmpl$4 = ["<span class=\"k2b-content-file-tree__badge\">", "</span>"],
|
|
11
11
|
_tmpl$5 = "<i class=\"ti ti-dots\" aria-hidden=\"true\"></i>",
|
|
12
12
|
_tmpl$6 = ["<span class=\"k2b-sr-only\">Actions for ", "</span>"],
|
|
13
|
-
_tmpl$7 = ["<div", " class=\"k2b-content-file-tree__row\"><button type=\"button\" tabindex=\"-1\" class=\"k2b-content-file-tree__select\" style=\"", "\"", "
|
|
13
|
+
_tmpl$7 = ["<div", " class=\"k2b-content-file-tree__row\"><button type=\"button\" tabindex=\"-1\" class=\"k2b-content-file-tree__select\" style=\"", "\"", ">", "<span class=\"k2b-content-file-tree__name\">", "</span>", "</button>", "</div>"];
|
|
14
14
|
/**
|
|
15
15
|
* FileTree — path-first tree over a flat entry list (folders derived from
|
|
16
16
|
* paths, explicit folder entries allowed for empty dirs). Capabilities are
|
|
@@ -18,19 +18,13 @@ var _tmpl$ = ["<ul class=\"", "\"", " role=\"tree\"", ">", "</ul>"],
|
|
|
18
18
|
* pure read-only browser. Context menus render through the platform
|
|
19
19
|
* ContextMenu. Minimal look: text rows, bevel on selection, no hover motion.
|
|
20
20
|
*/
|
|
21
|
-
import { fileIcons } from "@k2b/stdlib";
|
|
22
21
|
import { createEffect, createMemo, createSignal, For, Show } from "solid-js";
|
|
23
22
|
import ContextMenu from "../actions/ContextMenu";
|
|
24
23
|
import Dropdown from "../actions/Dropdown";
|
|
25
24
|
import { useUiMessages } from "../intl/messages";
|
|
25
|
+
import { FileTypeIcon } from "./FileTypeIcon";
|
|
26
26
|
import { useFileBrowserMessages } from "./file-browser-messages";
|
|
27
27
|
import { allFolderPaths, buildTree, flattenVisible, parentOf } from "./file-tree";
|
|
28
|
-
/**
|
|
29
|
-
* `fileIcons` (and app-supplied entry icons) may carry Tailwind colour classes.
|
|
30
|
-
* @k2b/ui ships no Tailwind utilities, so only the `ti-*` glyph is kept — the
|
|
31
|
-
* row owns the icon colour.
|
|
32
|
-
*/
|
|
33
|
-
const glyphOnly = icon => icon.split(/\s+/).filter(token => token.startsWith("ti-")).join(" ");
|
|
34
28
|
|
|
35
29
|
/** Presence of a callback enables the matching UI affordance. */
|
|
36
30
|
|
|
@@ -239,18 +233,31 @@ export default function FileTree(props) {
|
|
|
239
233
|
};
|
|
240
234
|
const isSelected = () => props.selectedPath === currentNode().entry.path;
|
|
241
235
|
const isDropTarget = () => currentNode().isFolder && dropTarget() === currentNode().entry.path;
|
|
242
|
-
const icon = () => currentNode().isFolder ? expanded().has(currentNode().entry.path) ? "ti-folder-open" : "ti-folder" : glyphOnly(currentNode().entry.icon ?? fileIcons.getFileIcon({
|
|
243
|
-
name: currentNode().name,
|
|
244
|
-
type: "file",
|
|
245
|
-
mimeType: currentNode().entry.mediaType ?? "text/plain"
|
|
246
|
-
}));
|
|
247
236
|
const hasItems = () => menuItems(node).length > 0;
|
|
248
237
|
return _$ssr(_tmpl$3, _$ssrAttribute("tabindex", renamingPath() === node.entry.path ? -1 : focusedPath() === node.entry.path ? 0 : -1, false) + _$ssrAttribute("aria-label", _$escape(currentNode().entry.displayName ?? currentNode().name, true), false) + _$ssrAttribute("aria-level", _$escape(currentNode().depth, true) + 1, false) + _$ssrAttribute("aria-selected", _$escape(isSelected(), true), false) + _$ssrAttribute("aria-expanded", currentNode().isFolder ? _$escape(expanded().has(currentNode().entry.path), true) : _$escape(undefined, true), false) + _$ssrAttribute("aria-haspopup", hasItems() ? "menu" : _$escape(undefined, true), false) + _$ssrAttribute("data-context-open", contextMenuOpen() && contextPath() === node.entry.path ? "true" : _$escape(undefined, true), false), _$escape(_$createComponent(Show, {
|
|
249
238
|
get when() {
|
|
250
239
|
return renamingPath() === node.entry.path;
|
|
251
240
|
},
|
|
252
241
|
get fallback() {
|
|
253
|
-
return _$ssr(_tmpl$7, _$ssrAttribute("data-state", isSelected() ? "selected" : isDropTarget() ? "drop-target" : "idle", false), _$ssrStyleProperty("padding-left:", `${6 + _$escape(currentNode().depth, true) * 14}px`), _$ssrAttribute("title", _$escape(currentNode().entry.path, true), false) + _$ssrAttribute("draggable", _$escape(Boolean(props.actions?.move), true), false),
|
|
242
|
+
return _$ssr(_tmpl$7, _$ssrAttribute("data-state", isSelected() ? "selected" : isDropTarget() ? "drop-target" : "idle", false), _$ssrStyleProperty("padding-left:", `${6 + _$escape(currentNode().depth, true) * 14}px`), _$ssrAttribute("title", _$escape(currentNode().entry.path, true), false) + _$ssrAttribute("draggable", _$escape(Boolean(props.actions?.move), true), false), _$escape(_$createComponent(FileTypeIcon, {
|
|
243
|
+
size: "sm",
|
|
244
|
+
"class": "k2b-content-file-tree__icon",
|
|
245
|
+
get name() {
|
|
246
|
+
return currentNode().name;
|
|
247
|
+
},
|
|
248
|
+
get folder() {
|
|
249
|
+
return currentNode().isFolder;
|
|
250
|
+
},
|
|
251
|
+
get open() {
|
|
252
|
+
return _$memo(() => !!currentNode().isFolder)() && expanded().has(currentNode().entry.path);
|
|
253
|
+
},
|
|
254
|
+
get icon() {
|
|
255
|
+
return _$memo(() => !!currentNode().isFolder)() ? undefined : currentNode().entry.icon;
|
|
256
|
+
},
|
|
257
|
+
get mediaType() {
|
|
258
|
+
return currentNode().entry.mediaType ?? "text/plain";
|
|
259
|
+
}
|
|
260
|
+
})), _$escape(currentNode().entry.displayName ?? currentNode().name), _$escape(_$createComponent(Show, {
|
|
254
261
|
get when() {
|
|
255
262
|
return currentNode().entry.badge;
|
|
256
263
|
},
|