@wicklib/layouts 0.0.0-stage → 0.12.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"names":["WickError","createChart","entry"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Free multi-chart layout primitives for Wicklib.\n */\n\nimport {\n WickError,\n createChart,\n type ChartApi,\n type ChartOptions,\n type ChartOverlayApi,\n type CrosshairEvent,\n type Unsubscribe,\n type VisibleRangeEvent,\n} from \"@wicklib/core\";\n\n/**\n * Options for a layout chart cell.\n */\nexport interface ChartLayoutSlotOptions {\n /** Stable slot id. Generated when omitted. */\n id?: string;\n /** Chart options for this slot. Merged over the layout defaults. */\n chartOptions?: ChartOptions;\n /** Number of grid rows covered by the cell. Defaults to 1. */\n rowSpan?: number;\n /** Number of grid columns covered by the cell. Defaults to 1. */\n columnSpan?: number;\n}\n\n/**\n * One chart cell in a layout.\n */\nexport interface ChartLayoutSlot {\n readonly id: string;\n readonly chart: ChartApi;\n readonly element: HTMLElement;\n readonly rowSpan: number;\n readonly columnSpan: number;\n}\n\n/**\n * Serializable structural layout state. Chart state is owned by the host.\n */\nexport interface ChartLayoutSnapshot {\n version: 1;\n columns: number;\n gap: number;\n slots: ReadonlyArray<{\n id: string;\n rowSpan: number;\n columnSpan: number;\n }>;\n}\n\n/**\n * Options for a multi-chart layout.\n */\nexport interface ChartLayoutOptions {\n /** Number of grid columns. Defaults to 2. */\n columns?: number;\n /** Gap between cells in CSS pixels. Defaults to 1. */\n gap?: number;\n /** Default chart options applied to every slot. */\n chartOptions?: ChartOptions;\n /** Synchronize visible time ranges. Defaults to true. */\n syncTimeRange?: boolean;\n /** Synchronize the vertical crosshair time line. Defaults to true. */\n syncCrosshair?: boolean;\n /** Crosshair line colour. */\n crosshairColor?: string;\n /** Extra class name on the layout root. */\n className?: string;\n /** Called when the active chart changes. */\n onActiveChange?: (chartId: string | null) => void;\n}\n\n/**\n * A live multi-chart layout.\n */\nexport interface ChartLayoutApi {\n /** Layout root inserted into the host container. */\n readonly element: HTMLElement;\n /** Adds a chart cell and returns its live slot. */\n addChart(options?: ChartLayoutSlotOptions): ChartLayoutSlot;\n /** Destroys and removes one chart cell. */\n removeChart(id: string): void;\n /** Returns a live chart, or null when the id is unknown. */\n getChart(id: string): ChartApi | null;\n /** Returns the current slots in DOM order. */\n getSlots(): readonly ChartLayoutSlot[];\n /** Returns slot ids in DOM order. */\n chartIds(): readonly string[];\n /** Changes the grid column count. */\n setColumns(columns: number): void;\n /** Changes the cell gap in CSS pixels. */\n setGap(gap: number): void;\n /** Marks one chart as active. Pass null to clear. */\n setActiveChart(id: string | null): void;\n /** Returns the active chart id, or null. */\n activeChartId(): string | null;\n /** Subscribes to active chart changes. */\n onActiveChange(handler: (chartId: string | null) => void): Unsubscribe;\n /** Applies the active chart's visible range to every other chart. */\n syncNow(): void;\n /** Returns structural layout state for host persistence. */\n serialize(): ChartLayoutSnapshot;\n /** Destroys every chart and removes the layout root. */\n destroy(): void;\n}\n\ninterface InternalSlot {\n readonly slot: ChartLayoutSlot;\n readonly unsubscribe: readonly Unsubscribe[];\n readonly overlay: ChartOverlayApi | null;\n readonly onPointerDown: () => void;\n readonly onFocusIn: () => void;\n}\n\nconst DEFAULT_COLUMNS = 2;\nconst DEFAULT_GAP = 1;\nconst MAX_COLUMNS = 12;\nconst DEFAULT_CROSSHAIR_COLOR = \"rgba(139, 149, 167, 0.6)\";\n\n/**\n * Creates a framework-agnostic grid of Wicklib charts.\n *\n * The layout owns chart creation, grid placement, time-range synchronization, and a\n * mirrored crosshair line. It does not own data, symbol state, accounts, or persistence.\n */\nexport function createChartLayout(\n container: HTMLElement,\n options: ChartLayoutOptions = {},\n): ChartLayoutApi {\n return new ChartLayout(container, options);\n}\n\nclass ChartLayout implements ChartLayoutApi {\n readonly element: HTMLElement;\n\n private readonly slots: InternalSlot[] = [];\n private readonly activeHandlers = new Set<(chartId: string | null) => void>();\n private readonly crosshairOverlays = new Map<string, ChartOverlayApi>();\n private readonly chartOptions: ChartOptions | undefined;\n private readonly syncTimeRange: boolean;\n private readonly syncCrosshair: boolean;\n private readonly crosshairColor: string;\n private columns: number;\n private gap: number;\n private activeId: string | null = null;\n private counter = 0;\n private applyingRange = false;\n private crosshair: { sourceId: string; time: number } | null = null;\n private destroyed = false;\n\n constructor(container: HTMLElement, options: ChartLayoutOptions) {\n if (!container || typeof container.appendChild !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"createChartLayout requires a DOM container\");\n }\n\n this.columns = validateColumns(options.columns ?? DEFAULT_COLUMNS);\n this.gap = validateGap(options.gap ?? DEFAULT_GAP);\n this.chartOptions = options.chartOptions;\n this.syncTimeRange = options.syncTimeRange ?? true;\n this.syncCrosshair = options.syncCrosshair ?? true;\n this.crosshairColor = options.crosshairColor ?? DEFAULT_CROSSHAIR_COLOR;\n if (options.onActiveChange) {\n this.activeHandlers.add(options.onActiveChange);\n }\n\n this.element = document.createElement(\"div\");\n this.element.className = [\"wicklib-chart-layout\", options.className].filter(Boolean).join(\" \");\n Object.assign(this.element.style, {\n display: \"grid\",\n width: \"100%\",\n height: \"100%\",\n minWidth: \"0\",\n minHeight: \"0\",\n gridAutoRows: \"minmax(0, 1fr)\",\n gap: `${this.gap}px`,\n });\n this.applyGrid();\n container.appendChild(this.element);\n }\n\n addChart(options: ChartLayoutSlotOptions = {}): ChartLayoutSlot {\n this.assertAlive();\n const id = options.id ?? `chart-${++this.counter}`;\n if (this.findSlot(id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Duplicate chart layout id: ${id}`);\n }\n const rowSpan = validateSpan(options.rowSpan ?? 1, \"rowSpan\");\n const columnSpan = validateSpan(options.columnSpan ?? 1, \"columnSpan\");\n\n const element = document.createElement(\"div\");\n element.className = \"wicklib-chart-layout__cell\";\n element.dataset.chartId = id;\n Object.assign(element.style, {\n position: \"relative\",\n minWidth: \"0\",\n minHeight: \"0\",\n overflow: \"hidden\",\n gridRow: `span ${rowSpan}`,\n gridColumn: `span ${columnSpan}`,\n });\n this.element.appendChild(element);\n\n let chart: ChartApi;\n try {\n chart = createChart(element, mergeChartOptions(this.chartOptions, options.chartOptions));\n } catch (error) {\n element.remove();\n throw error;\n }\n\n const onPointerDown = (): void => this.setActiveChart(id);\n const onFocusIn = (): void => this.setActiveChart(id);\n element.addEventListener(\"pointerdown\", onPointerDown, true);\n element.addEventListener(\"focusin\", onFocusIn);\n\n const unsubscribes: Unsubscribe[] = [\n chart.on(\"visible-range\", (event) => this.handleVisibleRange(id, event)),\n chart.on(\"crosshair\", (event) => this.handleCrosshair(id, event)),\n ];\n\n let overlay: ChartOverlayApi | null = null;\n if (this.syncCrosshair) {\n overlay = chart.addOverlay({\n id: \"wicklib-layout-crosshair\",\n draw: (context, frame) => {\n const current = this.crosshair;\n if (!current || current.sourceId === id) {\n return;\n }\n const x = frame.timeToX(current.time);\n if (x === null || x < frame.plot.left || x > frame.plot.right) {\n return;\n }\n const crispX = Math.round(x) + 0.5;\n context.save();\n context.beginPath();\n context.rect(frame.plot.left, frame.plot.top, frame.plot.width, frame.plot.height);\n context.clip();\n context.strokeStyle = this.crosshairColor;\n context.lineWidth = 1;\n context.setLineDash([3, 4]);\n context.beginPath();\n context.moveTo(crispX, frame.plot.top);\n context.lineTo(crispX, frame.plot.bottom);\n context.stroke();\n context.restore();\n },\n });\n this.crosshairOverlays.set(id, overlay);\n }\n\n const slot: ChartLayoutSlot = {\n id,\n chart,\n element,\n rowSpan,\n columnSpan,\n };\n this.slots.push({\n slot,\n unsubscribe: unsubscribes,\n overlay,\n onPointerDown,\n onFocusIn,\n });\n\n if (this.activeId === null) {\n this.setActiveChart(id);\n }\n\n return slot;\n }\n\n removeChart(id: string): void {\n this.assertAlive();\n const index = this.slots.findIndex((entry) => entry.slot.id === id);\n if (index < 0) {\n return;\n }\n const entry = this.slots[index]!;\n this.disposeSlot(entry);\n this.slots.splice(index, 1);\n if (this.activeId === id) {\n this.setActiveChart(null);\n }\n if (this.crosshair?.sourceId === id) {\n this.crosshair = null;\n this.requestCrosshairRender();\n }\n }\n\n getChart(id: string): ChartApi | null {\n this.assertAlive();\n return this.findSlot(id)?.slot.chart ?? null;\n }\n\n getSlots(): readonly ChartLayoutSlot[] {\n this.assertAlive();\n return this.slots.map((entry) => entry.slot);\n }\n\n chartIds(): readonly string[] {\n this.assertAlive();\n return this.slots.map((entry) => entry.slot.id);\n }\n\n setColumns(columns: number): void {\n this.assertAlive();\n this.columns = validateColumns(columns);\n this.applyGrid();\n }\n\n setGap(gap: number): void {\n this.assertAlive();\n this.gap = validateGap(gap);\n this.element.style.gap = `${this.gap}px`;\n }\n\n setActiveChart(id: string | null): void {\n this.assertAlive();\n if (id !== null && !this.findSlot(id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Unknown chart layout id: ${id}`);\n }\n if (this.activeId === id) {\n return;\n }\n const previous = this.activeId;\n this.activeId = id;\n for (const entry of this.slots) {\n if (entry.slot.id === previous) {\n delete entry.slot.element.dataset.active;\n }\n if (entry.slot.id === id) {\n entry.slot.element.dataset.active = \"true\";\n }\n }\n for (const handler of this.activeHandlers) {\n handler(id);\n }\n }\n\n activeChartId(): string | null {\n this.assertAlive();\n return this.activeId;\n }\n\n onActiveChange(handler: (chartId: string | null) => void): Unsubscribe {\n this.assertAlive();\n this.activeHandlers.add(handler);\n return () => {\n this.activeHandlers.delete(handler);\n };\n }\n\n syncNow(): void {\n this.assertAlive();\n const source = this.findSlot(this.activeId ?? this.slots[0]?.slot.id ?? \"\");\n if (!source) {\n return;\n }\n this.applyRange(source.slot.id, source.slot.chart.timeScale().getVisibleRange());\n }\n\n serialize(): ChartLayoutSnapshot {\n this.assertAlive();\n return {\n version: 1,\n columns: this.columns,\n gap: this.gap,\n slots: this.slots.map((entry) => ({\n id: entry.slot.id,\n rowSpan: entry.slot.rowSpan,\n columnSpan: entry.slot.columnSpan,\n })),\n };\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n this.destroyed = true;\n for (const entry of this.slots) {\n this.disposeSlot(entry);\n }\n this.slots.length = 0;\n this.activeHandlers.clear();\n this.crosshairOverlays.clear();\n this.element.remove();\n }\n\n private applyGrid(): void {\n this.element.style.gridTemplateColumns = `repeat(${this.columns}, minmax(0, 1fr))`;\n }\n\n private findSlot(id: string | null): InternalSlot | undefined {\n if (id === null) {\n return undefined;\n }\n return this.slots.find((entry) => entry.slot.id === id);\n }\n\n private handleVisibleRange(sourceId: string, event: VisibleRangeEvent): void {\n if (!this.syncTimeRange || this.applyingRange) {\n return;\n }\n this.applyRange(sourceId, { from: event.from, to: event.to });\n }\n\n private applyRange(sourceId: string, range: { from: number; to: number }): void {\n if (!Number.isFinite(range.from) || !Number.isFinite(range.to) || range.to <= range.from) {\n return;\n }\n this.applyingRange = true;\n try {\n for (const entry of this.slots) {\n if (entry.slot.id === sourceId) {\n continue;\n }\n try {\n entry.slot.chart.timeScale().setVisibleRange(range);\n } catch {\n // A chart with incompatible data can reject the range; leave it unchanged.\n }\n }\n } finally {\n this.applyingRange = false;\n }\n }\n\n private handleCrosshair(sourceId: string, event: CrosshairEvent): void {\n if (!this.syncCrosshair) {\n return;\n }\n if (event.time === null || event.point === null) {\n if (this.crosshair !== null) {\n this.crosshair = null;\n this.requestCrosshairRender();\n }\n return;\n }\n this.crosshair = { sourceId, time: event.time };\n this.requestCrosshairRender();\n }\n\n private requestCrosshairRender(): void {\n for (const overlay of this.crosshairOverlays.values()) {\n overlay.requestRender();\n }\n }\n\n private disposeSlot(entry: InternalSlot): void {\n entry.slot.element.removeEventListener(\"pointerdown\", entry.onPointerDown, true);\n entry.slot.element.removeEventListener(\"focusin\", entry.onFocusIn);\n for (const unsubscribe of entry.unsubscribe) {\n unsubscribe();\n }\n entry.overlay?.remove();\n this.crosshairOverlays.delete(entry.slot.id);\n entry.slot.chart.destroy();\n entry.slot.element.remove();\n }\n\n private assertAlive(): void {\n if (this.destroyed) {\n throw new WickError(\"DISPOSED\", \"Chart layout is disposed\");\n }\n }\n}\n\nfunction mergeChartOptions(\n base: ChartOptions | undefined,\n override: ChartOptions | undefined,\n): ChartOptions | undefined {\n if (!base) {\n return override;\n }\n if (!override) {\n return base;\n }\n return { ...base, ...override };\n}\n\nfunction validateColumns(columns: number): number {\n if (!Number.isInteger(columns) || columns < 1 || columns > MAX_COLUMNS) {\n throw new WickError(\"INVALID_ARGUMENT\", `columns must be an integer from 1 to ${MAX_COLUMNS}`);\n }\n return columns;\n}\n\nfunction validateGap(gap: number): number {\n if (!Number.isFinite(gap) || gap < 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"gap must be a non-negative finite number\");\n }\n return gap;\n}\n\nfunction validateSpan(value: number, name: string): number {\n if (!Number.isInteger(value) || value < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", `${name} must be a positive integer`);\n }\n return value;\n}\n"]}
@@ -0,0 +1,106 @@
1
+ import { ChartOptions, ChartApi, Unsubscribe } from '@wicklib/core';
2
+
3
+ /**
4
+ * Free multi-chart layout primitives for Wicklib.
5
+ */
6
+
7
+ /**
8
+ * Options for a layout chart cell.
9
+ */
10
+ interface ChartLayoutSlotOptions {
11
+ /** Stable slot id. Generated when omitted. */
12
+ id?: string;
13
+ /** Chart options for this slot. Merged over the layout defaults. */
14
+ chartOptions?: ChartOptions;
15
+ /** Number of grid rows covered by the cell. Defaults to 1. */
16
+ rowSpan?: number;
17
+ /** Number of grid columns covered by the cell. Defaults to 1. */
18
+ columnSpan?: number;
19
+ }
20
+ /**
21
+ * One chart cell in a layout.
22
+ */
23
+ interface ChartLayoutSlot {
24
+ readonly id: string;
25
+ readonly chart: ChartApi;
26
+ readonly element: HTMLElement;
27
+ readonly rowSpan: number;
28
+ readonly columnSpan: number;
29
+ }
30
+ /**
31
+ * Serializable structural layout state. Chart state is owned by the host.
32
+ */
33
+ interface ChartLayoutSnapshot {
34
+ version: 1;
35
+ columns: number;
36
+ gap: number;
37
+ slots: ReadonlyArray<{
38
+ id: string;
39
+ rowSpan: number;
40
+ columnSpan: number;
41
+ }>;
42
+ }
43
+ /**
44
+ * Options for a multi-chart layout.
45
+ */
46
+ interface ChartLayoutOptions {
47
+ /** Number of grid columns. Defaults to 2. */
48
+ columns?: number;
49
+ /** Gap between cells in CSS pixels. Defaults to 1. */
50
+ gap?: number;
51
+ /** Default chart options applied to every slot. */
52
+ chartOptions?: ChartOptions;
53
+ /** Synchronize visible time ranges. Defaults to true. */
54
+ syncTimeRange?: boolean;
55
+ /** Synchronize the vertical crosshair time line. Defaults to true. */
56
+ syncCrosshair?: boolean;
57
+ /** Crosshair line colour. */
58
+ crosshairColor?: string;
59
+ /** Extra class name on the layout root. */
60
+ className?: string;
61
+ /** Called when the active chart changes. */
62
+ onActiveChange?: (chartId: string | null) => void;
63
+ }
64
+ /**
65
+ * A live multi-chart layout.
66
+ */
67
+ interface ChartLayoutApi {
68
+ /** Layout root inserted into the host container. */
69
+ readonly element: HTMLElement;
70
+ /** Adds a chart cell and returns its live slot. */
71
+ addChart(options?: ChartLayoutSlotOptions): ChartLayoutSlot;
72
+ /** Destroys and removes one chart cell. */
73
+ removeChart(id: string): void;
74
+ /** Returns a live chart, or null when the id is unknown. */
75
+ getChart(id: string): ChartApi | null;
76
+ /** Returns the current slots in DOM order. */
77
+ getSlots(): readonly ChartLayoutSlot[];
78
+ /** Returns slot ids in DOM order. */
79
+ chartIds(): readonly string[];
80
+ /** Changes the grid column count. */
81
+ setColumns(columns: number): void;
82
+ /** Changes the cell gap in CSS pixels. */
83
+ setGap(gap: number): void;
84
+ /** Marks one chart as active. Pass null to clear. */
85
+ setActiveChart(id: string | null): void;
86
+ /** Returns the active chart id, or null. */
87
+ activeChartId(): string | null;
88
+ /** Subscribes to active chart changes. */
89
+ onActiveChange(handler: (chartId: string | null) => void): Unsubscribe;
90
+ /** Applies the active chart's visible range to every other chart. */
91
+ syncNow(): void;
92
+ /** Returns structural layout state for host persistence. */
93
+ serialize(): ChartLayoutSnapshot;
94
+ /** Destroys every chart and removes the layout root. */
95
+ destroy(): void;
96
+ }
97
+ /**
98
+ * Creates a framework-agnostic grid of Wicklib charts.
99
+ *
100
+ * The layout owns chart creation, grid placement, time-range synchronization, and a
101
+ * mirrored crosshair line. It does not own data, symbol state, accounts, or persistence.
102
+ */
103
+ declare function createChartLayout(container: HTMLElement, options?: ChartLayoutOptions): ChartLayoutApi;
104
+
105
+ export { createChartLayout };
106
+ export type { ChartLayoutApi, ChartLayoutOptions, ChartLayoutSlot, ChartLayoutSlotOptions, ChartLayoutSnapshot };
@@ -0,0 +1,106 @@
1
+ import { ChartOptions, ChartApi, Unsubscribe } from '@wicklib/core';
2
+
3
+ /**
4
+ * Free multi-chart layout primitives for Wicklib.
5
+ */
6
+
7
+ /**
8
+ * Options for a layout chart cell.
9
+ */
10
+ interface ChartLayoutSlotOptions {
11
+ /** Stable slot id. Generated when omitted. */
12
+ id?: string;
13
+ /** Chart options for this slot. Merged over the layout defaults. */
14
+ chartOptions?: ChartOptions;
15
+ /** Number of grid rows covered by the cell. Defaults to 1. */
16
+ rowSpan?: number;
17
+ /** Number of grid columns covered by the cell. Defaults to 1. */
18
+ columnSpan?: number;
19
+ }
20
+ /**
21
+ * One chart cell in a layout.
22
+ */
23
+ interface ChartLayoutSlot {
24
+ readonly id: string;
25
+ readonly chart: ChartApi;
26
+ readonly element: HTMLElement;
27
+ readonly rowSpan: number;
28
+ readonly columnSpan: number;
29
+ }
30
+ /**
31
+ * Serializable structural layout state. Chart state is owned by the host.
32
+ */
33
+ interface ChartLayoutSnapshot {
34
+ version: 1;
35
+ columns: number;
36
+ gap: number;
37
+ slots: ReadonlyArray<{
38
+ id: string;
39
+ rowSpan: number;
40
+ columnSpan: number;
41
+ }>;
42
+ }
43
+ /**
44
+ * Options for a multi-chart layout.
45
+ */
46
+ interface ChartLayoutOptions {
47
+ /** Number of grid columns. Defaults to 2. */
48
+ columns?: number;
49
+ /** Gap between cells in CSS pixels. Defaults to 1. */
50
+ gap?: number;
51
+ /** Default chart options applied to every slot. */
52
+ chartOptions?: ChartOptions;
53
+ /** Synchronize visible time ranges. Defaults to true. */
54
+ syncTimeRange?: boolean;
55
+ /** Synchronize the vertical crosshair time line. Defaults to true. */
56
+ syncCrosshair?: boolean;
57
+ /** Crosshair line colour. */
58
+ crosshairColor?: string;
59
+ /** Extra class name on the layout root. */
60
+ className?: string;
61
+ /** Called when the active chart changes. */
62
+ onActiveChange?: (chartId: string | null) => void;
63
+ }
64
+ /**
65
+ * A live multi-chart layout.
66
+ */
67
+ interface ChartLayoutApi {
68
+ /** Layout root inserted into the host container. */
69
+ readonly element: HTMLElement;
70
+ /** Adds a chart cell and returns its live slot. */
71
+ addChart(options?: ChartLayoutSlotOptions): ChartLayoutSlot;
72
+ /** Destroys and removes one chart cell. */
73
+ removeChart(id: string): void;
74
+ /** Returns a live chart, or null when the id is unknown. */
75
+ getChart(id: string): ChartApi | null;
76
+ /** Returns the current slots in DOM order. */
77
+ getSlots(): readonly ChartLayoutSlot[];
78
+ /** Returns slot ids in DOM order. */
79
+ chartIds(): readonly string[];
80
+ /** Changes the grid column count. */
81
+ setColumns(columns: number): void;
82
+ /** Changes the cell gap in CSS pixels. */
83
+ setGap(gap: number): void;
84
+ /** Marks one chart as active. Pass null to clear. */
85
+ setActiveChart(id: string | null): void;
86
+ /** Returns the active chart id, or null. */
87
+ activeChartId(): string | null;
88
+ /** Subscribes to active chart changes. */
89
+ onActiveChange(handler: (chartId: string | null) => void): Unsubscribe;
90
+ /** Applies the active chart's visible range to every other chart. */
91
+ syncNow(): void;
92
+ /** Returns structural layout state for host persistence. */
93
+ serialize(): ChartLayoutSnapshot;
94
+ /** Destroys every chart and removes the layout root. */
95
+ destroy(): void;
96
+ }
97
+ /**
98
+ * Creates a framework-agnostic grid of Wicklib charts.
99
+ *
100
+ * The layout owns chart creation, grid placement, time-range synchronization, and a
101
+ * mirrored crosshair line. It does not own data, symbol state, accounts, or persistence.
102
+ */
103
+ declare function createChartLayout(container: HTMLElement, options?: ChartLayoutOptions): ChartLayoutApi;
104
+
105
+ export { createChartLayout };
106
+ export type { ChartLayoutApi, ChartLayoutOptions, ChartLayoutSlot, ChartLayoutSlotOptions, ChartLayoutSnapshot };
package/dist/index.js ADDED
@@ -0,0 +1,344 @@
1
+ import { WickError, createChart } from '@wicklib/core';
2
+
3
+ // src/index.ts
4
+ var DEFAULT_COLUMNS = 2;
5
+ var DEFAULT_GAP = 1;
6
+ var MAX_COLUMNS = 12;
7
+ var DEFAULT_CROSSHAIR_COLOR = "rgba(139, 149, 167, 0.6)";
8
+ function createChartLayout(container, options = {}) {
9
+ return new ChartLayout(container, options);
10
+ }
11
+ var ChartLayout = class {
12
+ element;
13
+ slots = [];
14
+ activeHandlers = /* @__PURE__ */ new Set();
15
+ crosshairOverlays = /* @__PURE__ */ new Map();
16
+ chartOptions;
17
+ syncTimeRange;
18
+ syncCrosshair;
19
+ crosshairColor;
20
+ columns;
21
+ gap;
22
+ activeId = null;
23
+ counter = 0;
24
+ applyingRange = false;
25
+ crosshair = null;
26
+ destroyed = false;
27
+ constructor(container, options) {
28
+ if (!container || typeof container.appendChild !== "function") {
29
+ throw new WickError("INVALID_ARGUMENT", "createChartLayout requires a DOM container");
30
+ }
31
+ this.columns = validateColumns(options.columns ?? DEFAULT_COLUMNS);
32
+ this.gap = validateGap(options.gap ?? DEFAULT_GAP);
33
+ this.chartOptions = options.chartOptions;
34
+ this.syncTimeRange = options.syncTimeRange ?? true;
35
+ this.syncCrosshair = options.syncCrosshair ?? true;
36
+ this.crosshairColor = options.crosshairColor ?? DEFAULT_CROSSHAIR_COLOR;
37
+ if (options.onActiveChange) {
38
+ this.activeHandlers.add(options.onActiveChange);
39
+ }
40
+ this.element = document.createElement("div");
41
+ this.element.className = ["wicklib-chart-layout", options.className].filter(Boolean).join(" ");
42
+ Object.assign(this.element.style, {
43
+ display: "grid",
44
+ width: "100%",
45
+ height: "100%",
46
+ minWidth: "0",
47
+ minHeight: "0",
48
+ gridAutoRows: "minmax(0, 1fr)",
49
+ gap: `${this.gap}px`
50
+ });
51
+ this.applyGrid();
52
+ container.appendChild(this.element);
53
+ }
54
+ addChart(options = {}) {
55
+ this.assertAlive();
56
+ const id = options.id ?? `chart-${++this.counter}`;
57
+ if (this.findSlot(id)) {
58
+ throw new WickError("INVALID_ARGUMENT", `Duplicate chart layout id: ${id}`);
59
+ }
60
+ const rowSpan = validateSpan(options.rowSpan ?? 1, "rowSpan");
61
+ const columnSpan = validateSpan(options.columnSpan ?? 1, "columnSpan");
62
+ const element = document.createElement("div");
63
+ element.className = "wicklib-chart-layout__cell";
64
+ element.dataset.chartId = id;
65
+ Object.assign(element.style, {
66
+ position: "relative",
67
+ minWidth: "0",
68
+ minHeight: "0",
69
+ overflow: "hidden",
70
+ gridRow: `span ${rowSpan}`,
71
+ gridColumn: `span ${columnSpan}`
72
+ });
73
+ this.element.appendChild(element);
74
+ let chart;
75
+ try {
76
+ chart = createChart(element, mergeChartOptions(this.chartOptions, options.chartOptions));
77
+ } catch (error) {
78
+ element.remove();
79
+ throw error;
80
+ }
81
+ const onPointerDown = () => this.setActiveChart(id);
82
+ const onFocusIn = () => this.setActiveChart(id);
83
+ element.addEventListener("pointerdown", onPointerDown, true);
84
+ element.addEventListener("focusin", onFocusIn);
85
+ const unsubscribes = [
86
+ chart.on("visible-range", (event) => this.handleVisibleRange(id, event)),
87
+ chart.on("crosshair", (event) => this.handleCrosshair(id, event))
88
+ ];
89
+ let overlay = null;
90
+ if (this.syncCrosshair) {
91
+ overlay = chart.addOverlay({
92
+ id: "wicklib-layout-crosshair",
93
+ draw: (context, frame) => {
94
+ const current = this.crosshair;
95
+ if (!current || current.sourceId === id) {
96
+ return;
97
+ }
98
+ const x = frame.timeToX(current.time);
99
+ if (x === null || x < frame.plot.left || x > frame.plot.right) {
100
+ return;
101
+ }
102
+ const crispX = Math.round(x) + 0.5;
103
+ context.save();
104
+ context.beginPath();
105
+ context.rect(frame.plot.left, frame.plot.top, frame.plot.width, frame.plot.height);
106
+ context.clip();
107
+ context.strokeStyle = this.crosshairColor;
108
+ context.lineWidth = 1;
109
+ context.setLineDash([3, 4]);
110
+ context.beginPath();
111
+ context.moveTo(crispX, frame.plot.top);
112
+ context.lineTo(crispX, frame.plot.bottom);
113
+ context.stroke();
114
+ context.restore();
115
+ }
116
+ });
117
+ this.crosshairOverlays.set(id, overlay);
118
+ }
119
+ const slot = {
120
+ id,
121
+ chart,
122
+ element,
123
+ rowSpan,
124
+ columnSpan
125
+ };
126
+ this.slots.push({
127
+ slot,
128
+ unsubscribe: unsubscribes,
129
+ overlay,
130
+ onPointerDown,
131
+ onFocusIn
132
+ });
133
+ if (this.activeId === null) {
134
+ this.setActiveChart(id);
135
+ }
136
+ return slot;
137
+ }
138
+ removeChart(id) {
139
+ this.assertAlive();
140
+ const index = this.slots.findIndex((entry2) => entry2.slot.id === id);
141
+ if (index < 0) {
142
+ return;
143
+ }
144
+ const entry = this.slots[index];
145
+ this.disposeSlot(entry);
146
+ this.slots.splice(index, 1);
147
+ if (this.activeId === id) {
148
+ this.setActiveChart(null);
149
+ }
150
+ if (this.crosshair?.sourceId === id) {
151
+ this.crosshair = null;
152
+ this.requestCrosshairRender();
153
+ }
154
+ }
155
+ getChart(id) {
156
+ this.assertAlive();
157
+ return this.findSlot(id)?.slot.chart ?? null;
158
+ }
159
+ getSlots() {
160
+ this.assertAlive();
161
+ return this.slots.map((entry) => entry.slot);
162
+ }
163
+ chartIds() {
164
+ this.assertAlive();
165
+ return this.slots.map((entry) => entry.slot.id);
166
+ }
167
+ setColumns(columns) {
168
+ this.assertAlive();
169
+ this.columns = validateColumns(columns);
170
+ this.applyGrid();
171
+ }
172
+ setGap(gap) {
173
+ this.assertAlive();
174
+ this.gap = validateGap(gap);
175
+ this.element.style.gap = `${this.gap}px`;
176
+ }
177
+ setActiveChart(id) {
178
+ this.assertAlive();
179
+ if (id !== null && !this.findSlot(id)) {
180
+ throw new WickError("INVALID_ARGUMENT", `Unknown chart layout id: ${id}`);
181
+ }
182
+ if (this.activeId === id) {
183
+ return;
184
+ }
185
+ const previous = this.activeId;
186
+ this.activeId = id;
187
+ for (const entry of this.slots) {
188
+ if (entry.slot.id === previous) {
189
+ delete entry.slot.element.dataset.active;
190
+ }
191
+ if (entry.slot.id === id) {
192
+ entry.slot.element.dataset.active = "true";
193
+ }
194
+ }
195
+ for (const handler of this.activeHandlers) {
196
+ handler(id);
197
+ }
198
+ }
199
+ activeChartId() {
200
+ this.assertAlive();
201
+ return this.activeId;
202
+ }
203
+ onActiveChange(handler) {
204
+ this.assertAlive();
205
+ this.activeHandlers.add(handler);
206
+ return () => {
207
+ this.activeHandlers.delete(handler);
208
+ };
209
+ }
210
+ syncNow() {
211
+ this.assertAlive();
212
+ const source = this.findSlot(this.activeId ?? this.slots[0]?.slot.id ?? "");
213
+ if (!source) {
214
+ return;
215
+ }
216
+ this.applyRange(source.slot.id, source.slot.chart.timeScale().getVisibleRange());
217
+ }
218
+ serialize() {
219
+ this.assertAlive();
220
+ return {
221
+ version: 1,
222
+ columns: this.columns,
223
+ gap: this.gap,
224
+ slots: this.slots.map((entry) => ({
225
+ id: entry.slot.id,
226
+ rowSpan: entry.slot.rowSpan,
227
+ columnSpan: entry.slot.columnSpan
228
+ }))
229
+ };
230
+ }
231
+ destroy() {
232
+ if (this.destroyed) {
233
+ return;
234
+ }
235
+ this.destroyed = true;
236
+ for (const entry of this.slots) {
237
+ this.disposeSlot(entry);
238
+ }
239
+ this.slots.length = 0;
240
+ this.activeHandlers.clear();
241
+ this.crosshairOverlays.clear();
242
+ this.element.remove();
243
+ }
244
+ applyGrid() {
245
+ this.element.style.gridTemplateColumns = `repeat(${this.columns}, minmax(0, 1fr))`;
246
+ }
247
+ findSlot(id) {
248
+ if (id === null) {
249
+ return void 0;
250
+ }
251
+ return this.slots.find((entry) => entry.slot.id === id);
252
+ }
253
+ handleVisibleRange(sourceId, event) {
254
+ if (!this.syncTimeRange || this.applyingRange) {
255
+ return;
256
+ }
257
+ this.applyRange(sourceId, { from: event.from, to: event.to });
258
+ }
259
+ applyRange(sourceId, range) {
260
+ if (!Number.isFinite(range.from) || !Number.isFinite(range.to) || range.to <= range.from) {
261
+ return;
262
+ }
263
+ this.applyingRange = true;
264
+ try {
265
+ for (const entry of this.slots) {
266
+ if (entry.slot.id === sourceId) {
267
+ continue;
268
+ }
269
+ try {
270
+ entry.slot.chart.timeScale().setVisibleRange(range);
271
+ } catch {
272
+ }
273
+ }
274
+ } finally {
275
+ this.applyingRange = false;
276
+ }
277
+ }
278
+ handleCrosshair(sourceId, event) {
279
+ if (!this.syncCrosshair) {
280
+ return;
281
+ }
282
+ if (event.time === null || event.point === null) {
283
+ if (this.crosshair !== null) {
284
+ this.crosshair = null;
285
+ this.requestCrosshairRender();
286
+ }
287
+ return;
288
+ }
289
+ this.crosshair = { sourceId, time: event.time };
290
+ this.requestCrosshairRender();
291
+ }
292
+ requestCrosshairRender() {
293
+ for (const overlay of this.crosshairOverlays.values()) {
294
+ overlay.requestRender();
295
+ }
296
+ }
297
+ disposeSlot(entry) {
298
+ entry.slot.element.removeEventListener("pointerdown", entry.onPointerDown, true);
299
+ entry.slot.element.removeEventListener("focusin", entry.onFocusIn);
300
+ for (const unsubscribe of entry.unsubscribe) {
301
+ unsubscribe();
302
+ }
303
+ entry.overlay?.remove();
304
+ this.crosshairOverlays.delete(entry.slot.id);
305
+ entry.slot.chart.destroy();
306
+ entry.slot.element.remove();
307
+ }
308
+ assertAlive() {
309
+ if (this.destroyed) {
310
+ throw new WickError("DISPOSED", "Chart layout is disposed");
311
+ }
312
+ }
313
+ };
314
+ function mergeChartOptions(base, override) {
315
+ if (!base) {
316
+ return override;
317
+ }
318
+ if (!override) {
319
+ return base;
320
+ }
321
+ return { ...base, ...override };
322
+ }
323
+ function validateColumns(columns) {
324
+ if (!Number.isInteger(columns) || columns < 1 || columns > MAX_COLUMNS) {
325
+ throw new WickError("INVALID_ARGUMENT", `columns must be an integer from 1 to ${MAX_COLUMNS}`);
326
+ }
327
+ return columns;
328
+ }
329
+ function validateGap(gap) {
330
+ if (!Number.isFinite(gap) || gap < 0) {
331
+ throw new WickError("INVALID_ARGUMENT", "gap must be a non-negative finite number");
332
+ }
333
+ return gap;
334
+ }
335
+ function validateSpan(value, name) {
336
+ if (!Number.isInteger(value) || value < 1) {
337
+ throw new WickError("INVALID_ARGUMENT", `${name} must be a positive integer`);
338
+ }
339
+ return value;
340
+ }
341
+
342
+ export { createChartLayout };
343
+ //# sourceMappingURL=index.js.map
344
+ //# sourceMappingURL=index.js.map