@coderyo/ui-shell 1.0.3 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -4,7 +4,9 @@ import { Locale, I18nDictionary } from '@coderyo/i18n';
4
4
  import { IndicatorConfig } from '@coderyo/indicators';
5
5
  import * as _coderyo_drawings from '@coderyo/drawings';
6
6
  import { DrawingRecord } from '@coderyo/drawings';
7
+ import { BridgeLayerPane } from '@coderyo/bridge';
7
8
  import { StreamLanguage } from '@codemirror/language';
9
+ export { isValidLayerBridgePane as isValidBridgeLayerPane } from '@coderyo/core';
8
10
 
9
11
  interface I18nProvider {
10
12
  t(key: string, fallback?: string, params?: Record<string, string | number>): string;
@@ -108,6 +110,117 @@ declare function mountSymbolSearchDialogTrigger(parent: HTMLElement, dialog: Sym
108
110
  i18n?: I18nProvider;
109
111
  }): HTMLElement;
110
112
 
113
+ /** LayoutPreset v2 — free-floating layer compositor (replaces layout-schema v1). */
114
+ declare const LAYER_PRESET_VERSION: 2;
115
+ type LayerPresetAuthor = 'integrator' | 'user';
116
+ type LayerType = 'shell.topBar' | 'shell.leftToolbar' | 'shell.bottomToolbar' | 'shell.statusBar' | 'shell.propertiesPanel' | 'chart.host' | 'chart.main' | 'chart.volume' | 'chart.indicator' | 'chart.indicatorHost' | 'overlay.crosshairLegend' | 'overlay.drawing' | 'group';
117
+ /** Normalized frame relative to page root (0..1). */
118
+ interface LayerFrame {
119
+ x: number;
120
+ y: number;
121
+ w: number;
122
+ h: number;
123
+ }
124
+ interface LayoutPage {
125
+ id: string;
126
+ title: string;
127
+ }
128
+ interface LayerNode {
129
+ id: string;
130
+ pageId: string;
131
+ type: LayerType;
132
+ /** Maps to legacy widget id or chart role for mount. */
133
+ widgetKey: string;
134
+ frame: LayerFrame;
135
+ zIndex: number;
136
+ visible: boolean;
137
+ locked: boolean;
138
+ groupId?: string;
139
+ /**
140
+ * @public Time-scale sync group for chart panes. Same non-empty id → pan/zoom together;
141
+ * omit or empty → pane is independent (own TimeScaleBus).
142
+ */
143
+ syncTimeScaleGroupId?: string;
144
+ }
145
+ interface BindGroup {
146
+ id: string;
147
+ name?: string;
148
+ layerIds: string[];
149
+ }
150
+ interface LayoutPreset {
151
+ version: typeof LAYER_PRESET_VERSION;
152
+ /**
153
+ * Monotonic revision for remote `host.layer.setPreset` merge/replace (integer ≥ 1).
154
+ * @public Bridge schema 2 — stale host revision is rejected with `STALE_PRESET_REVISION`.
155
+ */
156
+ revision?: number;
157
+ id: string;
158
+ name: string;
159
+ author: LayerPresetAuthor;
160
+ readonly?: boolean;
161
+ forkedFrom?: string;
162
+ pages: LayoutPage[];
163
+ layers: LayerNode[];
164
+ groups: BindGroup[];
165
+ }
166
+ type LayerWidgetKey = 'topBar' | 'leftToolbar' | 'bottomToolbar' | 'chartHost' | 'chartMain' | 'chartVolume' | 'chartIndicator' | 'indicatorHost' | 'statusBar' | 'propertiesPanel' | 'crosshairLegend' | 'drawingOverlay';
167
+
168
+ /** @public Mutable controller for LayoutPreset v2 (layers, groups, pane focus). */
169
+ declare class LayerController {
170
+ private preset;
171
+ private readonly listeners;
172
+ private readonly focusListeners;
173
+ private interactionDepth;
174
+ private pageIdSeq;
175
+ activePageId: string;
176
+ /** P2: active chart pane layer (click-to-focus). */
177
+ focusedPaneLayerId: string | null;
178
+ /** Monotonic preset revision (Bridge `host.layer.setPreset`). */
179
+ presetRevision: number;
180
+ constructor(initial: LayoutPreset);
181
+ getPreset(): LayoutPreset;
182
+ /** True while pointer drag/resize/marquee is active — blocks setPreset. */
183
+ isInteracting(): boolean;
184
+ beginInteraction(): void;
185
+ endInteraction(): void;
186
+ setPreset(next: LayoutPreset): boolean;
187
+ getLayersForActivePage(): LayoutPreset['layers'];
188
+ getFocusedPaneLayerId(): string | null;
189
+ getFocusedPaneId(): 'main' | 'volume' | 'indicator' | null;
190
+ /** Raise z-index among chart panes only; does not rebuild compositor DOM. */
191
+ focusChartPane(layerId: string): void;
192
+ subscribeFocus(listener: () => void): () => void;
193
+ private notifyFocus;
194
+ private afterChartMainFrameChange;
195
+ setActivePage(pageId: string): boolean;
196
+ addPage(title?: string): string;
197
+ renamePage(pageId: string, title: string): boolean;
198
+ removePage(pageId: string): boolean;
199
+ getLayer(layerId: string): LayerNode | undefined;
200
+ /**
201
+ * @public Set time-scale sync group for a chart pane layer (`''` clears → independent).
202
+ */
203
+ setLayerSyncGroup(layerId: string, groupId: string | null | undefined): boolean;
204
+ getGroup(groupId: string): BindGroup | undefined;
205
+ /** Layer ids that move/resize together (group members or singleton). */
206
+ getTransformLayerIds(layerId: string): string[];
207
+ getGroupMemberLayers(groupId: string): LayoutPreset['layers'];
208
+ setLayerFrame(layerId: string, frame: LayerFrame): void;
209
+ private expandTransformIds;
210
+ moveLayers(layerIds: string[], dx: number, dy: number): void;
211
+ resizeLayersFromBbox(layerIds: string[], newBbox: LayerFrame): void;
212
+ setLayerVisible(layerId: string, visible: boolean): void;
213
+ setLayerLocked(layerId: string, locked: boolean): void;
214
+ private syncGroupLayerIds;
215
+ bumpZIndex(layerId: string, delta: 1 | -1): void;
216
+ reorderLayers(orderedIds: string[]): void;
217
+ createBindGroup(layerIds: string[], name?: string): string | null;
218
+ dissolveGroup(groupId: string): void;
219
+ removeLayerFromGroup(layerId: string): void;
220
+ subscribe(listener: () => void): () => void;
221
+ private emit;
222
+ }
223
+
111
224
  interface ContextMenuAction {
112
225
  id: string;
113
226
  label: string;
@@ -142,7 +255,7 @@ interface CrosshairLegendOptions {
142
255
  symbol?: string;
143
256
  interval?: string;
144
257
  }
145
- declare function mountCrosshairLegend(chartHost: HTMLElement, opts?: CrosshairLegendOptions): {
258
+ declare function mountCrosshairLegend(chartHost?: HTMLElement, opts?: CrosshairLegendOptions): {
146
259
  el: HTMLElement;
147
260
  update: (payload: {
148
261
  time?: number;
@@ -195,10 +308,52 @@ declare function mergeLayoutFeatures(current: ResolvedLayoutFeatures, patch: Lay
195
308
  /** Playground: enable full TV shell. */
196
309
  declare function createDemoLayoutOptions(partial?: ChartLayoutOptions): ChartLayoutOptions;
197
310
 
311
+ /** Visual layout schema (grid-based composable shell). */
312
+ type LayoutWidgetId = 'topBar' | 'leftToolbar' | 'bottomToolbar' | 'chartHost' | 'indicatorHost' | 'statusBar' | 'propertiesPanel';
313
+ interface LayoutWidgetPlacement {
314
+ id: LayoutWidgetId;
315
+ col: number;
316
+ row: number;
317
+ colSpan: number;
318
+ rowSpan: number;
319
+ }
320
+ interface LayoutSchema {
321
+ version: 1;
322
+ columns: number;
323
+ rows: number;
324
+ widgets: LayoutWidgetPlacement[];
325
+ }
326
+ declare const LAYOUT_SCHEMA_VERSION: 1;
327
+ /** TV-style default when integrator omits `layout` (matches legacy mountChartLayout proportions). */
328
+ declare const DEFAULT_LAYOUT_SCHEMA: LayoutSchema;
329
+ declare function layoutStorageKey(layoutId: string): string;
330
+ declare function resolveLayoutSchema(partial?: LayoutSchema | null): LayoutSchema;
331
+ declare function cloneLayoutSchema(schema: LayoutSchema): LayoutSchema;
332
+ declare function normalizeLayoutSchema(input: LayoutSchema): LayoutSchema;
333
+ declare function loadLayoutSchema(layoutId: string): LayoutSchema | null;
334
+ declare function saveLayoutSchema(layoutId: string, schema: LayoutSchema): void;
335
+ declare function getWidgetPlacement(schema: LayoutSchema, id: LayoutWidgetId): LayoutWidgetPlacement | undefined;
336
+
198
337
  type DrawingToolId = 'cursor' | 'trendline' | 'hline' | 'vline' | 'rectangle' | 'fibonacci' | 'text';
199
338
  interface ChartLayoutOptions extends TopBarOptions {
200
339
  themeProvider?: ThemeProvider;
201
340
  i18n?: I18nProvider;
341
+ /** When false, do not auto-create theme provider / localStorage (default true). */
342
+ autoThemeProvider?: boolean;
343
+ /** When false, do not auto-create i18n provider (default true). */
344
+ autoI18n?: boolean;
345
+ /** Grid layout schema; omit to use {@link DEFAULT_LAYOUT_SCHEMA}. */
346
+ layout?: LayoutSchema | null;
347
+ /** Key for layout persistence (`layoutPersist`). Default `default`. */
348
+ layoutId?: string;
349
+ /** Persist layout schema to localStorage on change / saveLayout(). */
350
+ layoutPersist?: boolean;
351
+ /**
352
+ * Enable drag/resize layout editor on mount.
353
+ * @deprecated Ignored when `layerCompositorManaged` — use `mountLayerCompositor` + `enableLayerEditor`.
354
+ */
355
+ layoutEditor?: boolean;
356
+ onLayoutChange?: (schema: LayoutSchema) => void;
202
357
  showTopBar?: boolean;
203
358
  showLeftToolbar?: boolean;
204
359
  showBottomToolbar?: boolean;
@@ -220,9 +375,21 @@ interface ChartLayoutOptions extends TopBarOptions {
220
375
  text?: string;
221
376
  }) => void;
222
377
  onDrawingSelectionBind?: (bind: (drawing: _coderyo_drawings.DrawingRecord | null) => void) => void;
378
+ /**
379
+ * When true, crosshair legend is not mounted under chartMain and visibility is driven by
380
+ * LayerCompositor (not grid CSS / el.style.display here).
381
+ */
382
+ layerCompositorManaged?: boolean;
223
383
  }
224
384
  declare function mountChartLayout(root: HTMLElement, opts?: ChartLayoutOptions): {
385
+ layoutRoot: HTMLElement;
386
+ layoutGrid: HTMLElement;
387
+ /** @deprecated Alias of chartMain — use chartMain for LWC mount. */
225
388
  chartHost: HTMLElement;
389
+ chartMain: HTMLElement;
390
+ chartVolume: HTMLElement;
391
+ /** Drawing canvas host (same element as chartMain when compositor-managed). */
392
+ drawingOverlay: HTMLElement;
226
393
  indicatorHost: HTMLElement;
227
394
  topBar: HTMLElement;
228
395
  setActiveInterval: (interval: _coderyo_data.Interval) => void;
@@ -231,10 +398,236 @@ declare function mountChartLayout(root: HTMLElement, opts?: ChartLayoutOptions):
231
398
  detachContextMenu: () => void;
232
399
  setActiveDrawingTool: (tool: DrawingToolId) => void;
233
400
  propertiesPanel: ReturnType<typeof mountDrawingPropertiesPanel>;
401
+ /** Bind drawing + apply properties panel visibility (compositor-safe). */
402
+ handleDrawingSelection: (drawing: _coderyo_drawings.DrawingRecord | null) => void;
403
+ /** Sync showCrosshairLegend (etc.) to compositor layer.visible when layerCompositorManaged. */
404
+ syncCompositorShellVisibility?: (controller: LayerController) => void;
405
+ /**
406
+ * Bind compositor controller so `setLayoutFeatures` keeps shell/legend layer.visible in sync.
407
+ * Call once after `mountLayerCompositor` (Playground pattern).
408
+ */
409
+ bindLayerCompositorController?: (controller: LayerController) => void;
234
410
  setLayoutFeatures: (patch: LayoutFeatures) => void;
235
411
  getLayoutFeatures: () => ResolvedLayoutFeatures;
412
+ getLayoutSchema: () => LayoutSchema;
413
+ setLayoutSchema: (schema: LayoutSchema) => void;
414
+ enableLayoutEditor: (enabled: boolean) => void;
415
+ saveLayout: () => void;
236
416
  };
237
417
 
418
+ type LayoutWidgetElements = Partial<Record<LayoutWidgetId, HTMLElement>>;
419
+ interface LayoutGridHandle {
420
+ root: HTMLElement;
421
+ grid: HTMLElement;
422
+ cells: Map<LayoutWidgetId, HTMLElement>;
423
+ applySchema: (schema: LayoutSchema, features: ResolvedLayoutFeatures) => void;
424
+ enableEditor: (enabled: boolean) => void;
425
+ getSchema: () => LayoutSchema;
426
+ setSchema: (schema: LayoutSchema) => void;
427
+ destroyEditor: () => void;
428
+ }
429
+ interface CreateLayoutGridOptions {
430
+ schema: LayoutSchema;
431
+ widgets: LayoutWidgetElements;
432
+ features: ResolvedLayoutFeatures;
433
+ editor?: boolean;
434
+ onSchemaChange?: (schema: LayoutSchema) => void;
435
+ }
436
+ declare function createLayoutGrid(opts: CreateLayoutGridOptions): LayoutGridHandle;
437
+
438
+ declare function clampFrame(frame: LayerFrame): LayerFrame;
439
+ declare function normalizeLayoutPreset(input: LayoutPreset): LayoutPreset;
440
+ declare function cloneLayoutPreset(preset: LayoutPreset): LayoutPreset;
441
+
442
+ /** Convert legacy 12×12 grid schema to normalized layer preset (single page). */
443
+ declare function layoutSchemaToPreset(schema?: LayoutSchema, opts?: {
444
+ id?: string;
445
+ name?: string;
446
+ }): LayoutPreset;
447
+
448
+ /** Built-in integrator preset — matches legacy DEFAULT_LAYOUT_SCHEMA proportions. */
449
+ declare const VENDOR_DEFAULT_PRESET: LayoutPreset;
450
+ /** Compact: chart-focused, smaller chrome. */
451
+ declare const VENDOR_COMPACT_PRESET: LayoutPreset;
452
+ /** Demo: main+volume share `prices`; indicator pane uses separate `osc` group. */
453
+ declare const VENDOR_DUAL_SYNC_PRESET: LayoutPreset;
454
+ declare const BUILTIN_PRESETS: LayoutPreset[];
455
+ declare function getBuiltinPreset(id: string): LayoutPreset | undefined;
456
+
457
+ declare function presetStorageKey(id: string): string;
458
+ interface PresetListEntry {
459
+ id: string;
460
+ name: string;
461
+ author: LayoutPreset['author'];
462
+ readonly?: boolean;
463
+ builtin?: boolean;
464
+ }
465
+ declare function listPresets(): PresetListEntry[];
466
+ declare function loadPreset(id: string): LayoutPreset | null;
467
+ declare function savePreset(preset: LayoutPreset): void;
468
+ declare function deleteUserPreset(id: string): boolean;
469
+ declare function forkPreset(sourceId: string, newId: string, newName: string): LayoutPreset | null;
470
+ declare function resolvePreset(id: string | LayoutPreset | null | undefined): LayoutPreset;
471
+
472
+ /** Union bounding box of layer frames (normalized 0..1). */
473
+ declare function getLayersBoundingBox(layers: Pick<LayerNode, 'frame'>[]): LayerFrame | null;
474
+ /** Move all frames by normalized delta; each frame is clamped independently. */
475
+ declare function moveLayerFrames(frames: LayerFrame[], dx: number, dy: number): LayerFrame[];
476
+ /**
477
+ * Resize a group by mapping each member's relative position inside oldBbox into newBbox.
478
+ */
479
+ declare function resizeGroupFrames(members: Pick<LayerNode, 'frame'>[], oldBbox: LayerFrame, newBbox: LayerFrame): LayerFrame[];
480
+ declare function clampBBox(frame: LayerFrame): LayerFrame;
481
+
482
+ type LayerWidgetElements = Partial<Record<LayerWidgetKey, HTMLElement>>;
483
+ interface LayerCompositorOptions {
484
+ preset: LayoutPreset;
485
+ widgets: LayerWidgetElements;
486
+ /** Hide legacy grid container when compositor positions widgets. */
487
+ hideLegacyGrid?: HTMLElement;
488
+ /** Fired after user drag/resize commits a preset change. */
489
+ onPresetChange?: (preset: LayoutPreset) => void;
490
+ /** Shift+drag marquee on compositor root (edit mode). */
491
+ onMarqueeSelect?: (layerIds: string[]) => void;
492
+ /** P2: chart pane focus changed (main / volume / indicator). */
493
+ onChartPaneFocus?: (pane: 'main' | 'volume' | 'indicator' | null) => void;
494
+ }
495
+ interface LayerCompositorHandle {
496
+ root: HTMLElement;
497
+ controller: LayerController;
498
+ apply(): void;
499
+ enableLayerEditor(enabled: boolean): void;
500
+ isLayerEditorEnabled(): boolean;
501
+ destroy(): void;
502
+ }
503
+ /** @public Mount floating layer compositor (LayoutPreset v2) over shell widgets. */
504
+ declare function mountLayerCompositor(parent: HTMLElement, opts: LayerCompositorOptions): LayerCompositorHandle;
505
+
506
+ interface LayerEditorOptions {
507
+ controller: LayerController;
508
+ /** Called after drag/resize commits preset changes. */
509
+ onPresetChange?: () => void;
510
+ /** Shift+drag marquee selection on compositor root. */
511
+ onMarqueeSelect?: (layerIds: string[]) => void;
512
+ }
513
+ interface LayerEditorHandle {
514
+ setEnabled(enabled: boolean): void;
515
+ isEnabled(): boolean;
516
+ rebind(): void;
517
+ destroy(): void;
518
+ }
519
+ declare function attachLayerEditor(compositorRoot: HTMLElement, opts: LayerEditorOptions): LayerEditorHandle;
520
+
521
+ interface LayerPanelOptions {
522
+ onSaveAsPreset?: (preset: ReturnType<LayerController['getPreset']>) => void;
523
+ }
524
+ interface LayerPanelHandle {
525
+ el: HTMLElement;
526
+ destroy: () => void;
527
+ toggle: () => boolean;
528
+ /** Replace panel checkbox selection (e.g. compositor shift+marquee). */
529
+ selectLayers(layerIds: string[]): void;
530
+ }
531
+ /** @public Layer list UI bound to a LayerController. */
532
+ declare function mountLayerPanel(parent: HTMLElement, controller: LayerController, opts?: LayerPanelOptions): LayerPanelHandle;
533
+
534
+ declare const CHART_PANE_LAYER_TYPES: readonly LayerType[];
535
+ declare const DEFAULT_SYNC_TIME_SCALE_GROUP = "chart-timescale";
536
+ declare function isChartPaneLayerType(type: string): type is LayerType;
537
+ declare function widgetKeyForChartPaneType(type: LayerType): string | null;
538
+ declare function paneIdFromWidgetKey(widgetKey: string): 'main' | 'volume' | 'indicator' | null;
539
+ interface HostSplitResult {
540
+ layers: LayerNode[];
541
+ /** Maps removed `chart.host` layer id → [mainId, volumeId]. */
542
+ idRemap: Map<string, string[]>;
543
+ }
544
+ /** Split legacy `chart.host` into main + volume layers (vertical tile inside host frame). */
545
+ declare function expandLegacyChartHostLayers(layers: LayerNode[]): LayerNode[];
546
+ declare function splitLegacyChartHost(layers: LayerNode[]): HostSplitResult;
547
+ /** @deprecated Use syncOverlayLayersToMain / syncAllOverlayLayersToMain */
548
+ declare function syncCrosshairLegendToMain(layers: LayerNode[]): void;
549
+ declare function upgradeIndicatorHostType(layers: LayerNode[]): LayerNode[];
550
+
551
+ declare const OVERLAY_LAYER_TYPES: readonly LayerType[];
552
+ declare function isOverlayLayerType(type: string): type is LayerType;
553
+ /** Anchor crosshair legend + drawing overlay frames to chart.main on one page (P3). */
554
+ declare function syncOverlayLayersToMain(layers: LayerNode[], pageId: string): void;
555
+ /** Sync overlays for every page (normalize / bulk migrate). */
556
+ declare function syncAllOverlayLayersToMain(layers: LayerNode[]): void;
557
+ /** Active-page drawing overlay visibility (wire to `IChart.setFeatures({ drawings: { layer } })`). */
558
+ declare function getDrawingOverlayVisible(controller: {
559
+ getLayersForActivePage(): LayerNode[];
560
+ }): boolean;
561
+ /** Insert default overlay layers when chart.main exists (normalize). */
562
+ declare function ensureOverlayLayers(layers: LayerNode[], pageId: string): LayerNode[];
563
+
564
+ type CompositorShellWidgetId = LayoutWidgetId;
565
+ interface CompositorShellHandle {
566
+ root: HTMLElement;
567
+ /** Hidden anchor grid (v2 compositor positions widgets; no 12×12 layout). */
568
+ grid: HTMLElement;
569
+ cells: Map<CompositorShellWidgetId, HTMLElement>;
570
+ }
571
+ interface CreateCompositorShellOptions {
572
+ widgets: Partial<Record<CompositorShellWidgetId, HTMLElement>>;
573
+ }
574
+ /** Minimal DOM shell for LayoutPreset v2 — replaces legacy createLayoutGrid when compositor-managed. */
575
+ declare function createCompositorShell(opts: CreateCompositorShellOptions): CompositorShellHandle;
576
+ /** No-op schema apply for compositor shell (features still drive widget mount in chart-layout). */
577
+ declare function applyCompositorShellFeatures(_cells: Map<CompositorShellWidgetId, HTMLElement>, _features: ResolvedLayoutFeatures): void;
578
+
579
+ /** Map `LayoutFeatures` toggles to compositor layer.visible on the active page. */
580
+ declare function syncCompositorShellVisibilityFromFeatures(controller: LayerController, features: ResolvedLayoutFeatures): void;
581
+
582
+ interface PageNavigatorOptions {
583
+ /** Show tab bar even on wide viewports (default: narrow only). */
584
+ alwaysVisible?: boolean;
585
+ narrowMq?: string;
586
+ onPageChange?: (pageId: string) => void;
587
+ }
588
+ interface PageNavigatorHandle {
589
+ el: HTMLElement;
590
+ destroy: () => void;
591
+ refresh: () => void;
592
+ }
593
+ /** @public Mobile-style page tabs for LayoutPreset v2 (P4). */
594
+ declare function mountPageNavigator(parent: HTMLElement, controller: LayerController, opts?: PageNavigatorOptions): PageNavigatorHandle;
595
+
596
+ /** Minimal chart surface for layer time-scale sync (matches `IChart.applyTimeScaleSyncFromLayers`). */
597
+ interface LayerTimeScaleSyncChart {
598
+ applyTimeScaleSyncFromLayers(layers: Array<{
599
+ type: string;
600
+ pageId?: string;
601
+ syncTimeScaleGroupId?: string;
602
+ }>, pageId?: string): unknown;
603
+ }
604
+ interface BindLayerTimeScaleSyncOptions {
605
+ /** Called after each sync apply (e.g. `requestAnimationFrame(chart.resize)`). */
606
+ onSync?: () => void;
607
+ }
608
+ /**
609
+ * @public Wire `IChart.applyTimeScaleSyncFromLayers` to `LayerController` preset mutations.
610
+ * Applies immediately and on `controller.subscribe` (page switch, sync group, layer edits).
611
+ * Returns unsubscribe — call after `mountLayerCompositor` + `createChart`.
612
+ */
613
+ declare function bindLayerTimeScaleSync(chart: LayerTimeScaleSyncChart, controller: LayerController, options?: BindLayerTimeScaleSyncOptions): () => void;
614
+
615
+ /**
616
+ * @public Merge partial LayoutPreset v2 into `current` (pages/layers/groups upsert by id).
617
+ * Unmentioned entries are preserved. Result is normalized.
618
+ */
619
+ declare function mergeLayoutPreset(current: LayoutPreset, partial: LayoutPreset): LayoutPreset;
620
+
621
+ declare function layerTypeForBridgePane(pane: BridgeLayerPane): LayerType;
622
+
623
+ /**
624
+ * @public Resolve chart pane → layer ids for preset scope (supports `allPages`).
625
+ */
626
+ declare function resolvePaneLayerIds(preset: Pick<LayoutPreset, 'layers' | 'pages'>, pane: BridgeLayerPane, opts?: {
627
+ allPages?: boolean;
628
+ activePageId?: string;
629
+ }): string[];
630
+
238
631
  interface SymbolSearchOptions {
239
632
  onSearch: (query: string) => Promise<SymbolSearchHit[]>;
240
633
  onSelect: (symbol: string) => void;
@@ -275,4 +668,4 @@ declare function mountPineEditorPanel(parent: HTMLElement, opts?: PineEditorPane
275
668
 
276
669
  declare const pineLanguage: StreamLanguage<{}>;
277
670
 
278
- export { type ChartLayoutOptions, type ContextMenuAction, type ContextMenuOptions, type CrosshairLegendOptions, DEFAULT_LAYOUT_FEATURES, type DrawingContextMenuHandlers, type DrawingPropertiesPanelOptions, type DrawingToolId, GRID_SETTING_KEY, type I18nProvider, type LayoutFeatures, type LogoSlotOptions, type OhlcvSnapshot, PINE_SCRIPT_STORAGE_KEY, type PineEditorPanelOptions, RETURN_CURSOR_KEY, type ResolvedLayoutFeatures, type SettingsPanelOptions as SettingsMenuOptions, type SettingsPanelOptions, type StatusBarOptions, type SymbolInputMode, type SymbolSearchDialogHandle, type SymbolSearchDialogOptions, type SymbolSearchOptions, THEME_STORAGE_KEY, type ThemeId, type ThemeProvider, type ThemeToggleOptions, type TopBarOptions, applyThemeToDocument, attachChartContextMenu, bindShortcutsModal, createDemoLayoutOptions, createI18nProvider, createSymbolSearchDialog, createThemeProvider, loadIndicatorConfig, loadPineScriptPreference, loadReturnToCursorPreference, loadShowGridPreference, loadTheme, mergeLayoutFeatures, mountChartLayout, mountCodeSnippetPanel, mountCrosshairLegend, mountDrawingPropertiesPanel, mountLogoSlot, mountPineEditorPanel, mountSettingsPanel as mountSettingsMenu, mountSettingsPanel, mountStatusBar, mountSymbolSearch, mountSymbolSearchDialogTrigger, mountThemeToggle, mountTopBar, openDrawingContextMenu, openShortcutsModal, pineLanguage, resolveLayoutFeatures, saveIndicatorConfig, savePineScriptPreference, saveReturnToCursorPreference, saveShowGridPreference, saveTheme };
671
+ export { BUILTIN_PRESETS, type BindGroup, type BindLayerTimeScaleSyncOptions, CHART_PANE_LAYER_TYPES, type ChartLayoutOptions, type CompositorShellHandle, type CompositorShellWidgetId, type ContextMenuAction, type ContextMenuOptions, type CreateCompositorShellOptions, type CreateLayoutGridOptions, type CrosshairLegendOptions, DEFAULT_LAYOUT_FEATURES, DEFAULT_LAYOUT_SCHEMA, DEFAULT_SYNC_TIME_SCALE_GROUP, type DrawingContextMenuHandlers, type DrawingPropertiesPanelOptions, type DrawingToolId, GRID_SETTING_KEY, type HostSplitResult, type I18nProvider, LAYER_PRESET_VERSION, LAYOUT_SCHEMA_VERSION, type LayerCompositorHandle, type LayerCompositorOptions, LayerController, type LayerEditorHandle, type LayerEditorOptions, type LayerFrame, type LayerNode, type LayerPanelHandle, type LayerPanelOptions, type LayerPresetAuthor, type LayerTimeScaleSyncChart, type LayerType, type LayerWidgetElements, type LayerWidgetKey, type LayoutFeatures, type LayoutGridHandle, type LayoutPage, type LayoutPreset, type LayoutSchema, type LayoutWidgetElements, type LayoutWidgetId, type LayoutWidgetPlacement, type LogoSlotOptions, OVERLAY_LAYER_TYPES, type OhlcvSnapshot, PINE_SCRIPT_STORAGE_KEY, type PageNavigatorHandle, type PageNavigatorOptions, type PineEditorPanelOptions, type PresetListEntry, RETURN_CURSOR_KEY, type ResolvedLayoutFeatures, type SettingsPanelOptions as SettingsMenuOptions, type SettingsPanelOptions, type StatusBarOptions, type SymbolInputMode, type SymbolSearchDialogHandle, type SymbolSearchDialogOptions, type SymbolSearchOptions, THEME_STORAGE_KEY, type ThemeId, type ThemeProvider, type ThemeToggleOptions, type TopBarOptions, VENDOR_COMPACT_PRESET, VENDOR_DEFAULT_PRESET, VENDOR_DUAL_SYNC_PRESET, applyCompositorShellFeatures, applyThemeToDocument, attachChartContextMenu, attachLayerEditor, bindLayerTimeScaleSync, bindShortcutsModal, clampBBox, clampFrame, cloneLayoutPreset, cloneLayoutSchema, createCompositorShell, createDemoLayoutOptions, createI18nProvider, createLayoutGrid, createSymbolSearchDialog, createThemeProvider, deleteUserPreset, ensureOverlayLayers, expandLegacyChartHostLayers, forkPreset, getBuiltinPreset, getDrawingOverlayVisible, getLayersBoundingBox, getWidgetPlacement, isChartPaneLayerType, isOverlayLayerType, layerTypeForBridgePane, layoutSchemaToPreset, layoutStorageKey, listPresets, loadIndicatorConfig, loadLayoutSchema, loadPineScriptPreference, loadPreset, loadReturnToCursorPreference, loadShowGridPreference, loadTheme, mergeLayoutFeatures, mergeLayoutPreset, mountChartLayout, mountCodeSnippetPanel, mountCrosshairLegend, mountDrawingPropertiesPanel, mountLayerCompositor, mountLayerPanel, mountLogoSlot, mountPageNavigator, mountPineEditorPanel, mountSettingsPanel as mountSettingsMenu, mountSettingsPanel, mountStatusBar, mountSymbolSearch, mountSymbolSearchDialogTrigger, mountThemeToggle, mountTopBar, moveLayerFrames, normalizeLayoutPreset, normalizeLayoutSchema, openDrawingContextMenu, openShortcutsModal, paneIdFromWidgetKey, pineLanguage, presetStorageKey, resizeGroupFrames, resolveLayoutFeatures, resolveLayoutSchema, resolvePaneLayerIds, resolvePreset, saveIndicatorConfig, saveLayoutSchema, savePineScriptPreference, savePreset, saveReturnToCursorPreference, saveShowGridPreference, saveTheme, splitLegacyChartHost, syncAllOverlayLayersToMain, syncCompositorShellVisibilityFromFeatures, syncCrosshairLegendToMain, syncOverlayLayersToMain, upgradeIndicatorHostType, widgetKeyForChartPaneType };