react-klinecharts-ui 1.0.0 → 1.2.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.cjs CHANGED
@@ -1,32 +1,12 @@
1
1
  'use strict';
2
2
 
3
- var chunkLGYYJ2GP_cjs = require('./chunk-LGYYJ2GP.cjs');
3
+ var chunkSZDU2D3D_cjs = require('./chunk-SZDU2D3D.cjs');
4
+ var chunkF24D6PWY_cjs = require('./chunk-F24D6PWY.cjs');
5
+ require('./chunk-Q7SFCCGT.cjs');
4
6
  var react = require('react');
5
7
  var klinecharts = require('klinecharts');
6
8
  var jsxRuntime = require('react/jsx-runtime');
7
9
 
8
- var KlinechartsUIStateContext = react.createContext(null);
9
- var KlinechartsUIDispatchContext = react.createContext(null);
10
- function useKlinechartsUIDispatch() {
11
- const ctx = react.useContext(KlinechartsUIDispatchContext);
12
- if (!ctx) {
13
- throw new Error(
14
- "useKlinechartsUI must be used within a <KlinechartsUIProvider>"
15
- );
16
- }
17
- return ctx;
18
- }
19
- function useKlinechartsUI() {
20
- const state = react.useContext(KlinechartsUIStateContext);
21
- const dispatch = react.useContext(KlinechartsUIDispatchContext);
22
- if (!state || !dispatch) {
23
- throw new Error(
24
- "useKlinechartsUI must be used within a <KlinechartsUIProvider>"
25
- );
26
- }
27
- return { state, ...dispatch };
28
- }
29
-
30
10
  // src/data/periods.ts
31
11
  var DEFAULT_PERIODS = [
32
12
  { span: 1, type: "minute", label: "1m" },
@@ -40,6 +20,50 @@ var DEFAULT_PERIODS = [
40
20
  { span: 1, type: "month", label: "M" },
41
21
  { span: 1, type: "year", label: "Y" }
42
22
  ];
23
+
24
+ // src/storage/types.ts
25
+ var DEFAULT_STORAGE_NAMESPACES = [
26
+ "alerts",
27
+ "settings",
28
+ "indicators"
29
+ ];
30
+ var DEFAULT_STORAGE_KEY_PREFIX = "rkui:";
31
+
32
+ // src/storage/createDefaultStorage.ts
33
+ var NOOP_ADAPTER = {
34
+ getItem: () => null,
35
+ setItem: () => {
36
+ },
37
+ removeItem: () => {
38
+ }
39
+ };
40
+ function createDefaultStorage() {
41
+ if (typeof localStorage === "undefined") return NOOP_ADAPTER;
42
+ try {
43
+ const probe = localStorage.getItem("__rkui_probe__");
44
+ return probe === null ? localStorage : localStorage;
45
+ } catch {
46
+ return NOOP_ADAPTER;
47
+ }
48
+ }
49
+ function resolveStorage(options) {
50
+ const adapter = options?.adapter ?? createDefaultStorage();
51
+ const keyPrefix = options?.keyPrefix ?? DEFAULT_STORAGE_KEY_PREFIX;
52
+ const namespaces = new Set(
53
+ options?.namespaces ?? DEFAULT_STORAGE_NAMESPACES
54
+ );
55
+ return {
56
+ adapter,
57
+ namespaces,
58
+ keyPrefix,
59
+ key(namespace) {
60
+ return `${keyPrefix}${namespace}`;
61
+ },
62
+ persists(namespace) {
63
+ return namespaces.has(namespace);
64
+ }
65
+ };
66
+ }
43
67
  function reducer(state, action) {
44
68
  switch (action.type) {
45
69
  case "SET_CHART":
@@ -103,13 +127,16 @@ function KlinechartsUIProvider({
103
127
  defaultPeriod,
104
128
  defaultTheme = "light",
105
129
  defaultTimezone = "Asia/Shanghai",
106
- defaultMainIndicators = ["MA"],
107
- defaultSubIndicators = ["VOL"],
130
+ // NOTE: no destructuring default here — the init function must distinguish
131
+ // "consumer passed default*" (wins) from "use stored value" (hydrate).
132
+ defaultMainIndicators,
133
+ defaultSubIndicators,
108
134
  defaultLocale = "en-US",
109
135
  periods,
110
136
  styles,
111
137
  registerExtensions: shouldRegister = true,
112
138
  overlays: extraOverlays,
139
+ storage: storageOptions,
113
140
  children,
114
141
  onStateChange,
115
142
  onSymbolChange,
@@ -120,6 +147,11 @@ function KlinechartsUIProvider({
120
147
  onSubIndicatorsChange,
121
148
  onSettingsChange
122
149
  }) {
150
+ const resolvedStorage = react.useMemo(
151
+ () => storageOptions ? resolveStorage(storageOptions) : null,
152
+ // eslint-disable-next-line react-hooks/exhaustive-deps
153
+ []
154
+ );
123
155
  const [state, dispatch] = react.useReducer(
124
156
  reducer,
125
157
  {
@@ -132,41 +164,61 @@ function KlinechartsUIProvider({
132
164
  defaultSubIndicators,
133
165
  defaultLocale,
134
166
  periods,
135
- styles
136
- },
137
- (opts) => ({
138
- chart: null,
139
- datafeed: opts.datafeed,
140
- symbol: opts.defaultSymbol ?? null,
141
- period: opts.defaultPeriod ?? (opts.periods ?? DEFAULT_PERIODS)[0],
142
- theme: opts.defaultTheme ?? "light",
143
- timezone: opts.defaultTimezone ?? "Asia/Shanghai",
144
- isLoading: false,
145
- locale: opts.defaultLocale ?? "en-US",
146
- periods: opts.periods ?? DEFAULT_PERIODS,
147
- mainIndicators: opts.defaultMainIndicators ?? ["MA"],
148
- subIndicators: (opts.defaultSubIndicators ?? ["VOL"]).reduce(
149
- (acc, name) => ({ ...acc, [name]: "" }),
150
- {}
151
- ),
152
- indicatorAxes: {},
153
- indicatorVisibility: {},
154
- alerts: [],
155
- measure: { isActive: false, fromPoint: null, result: null },
156
- replay: {
157
- isReplaying: false,
158
- isPaused: false,
159
- speed: 1,
160
- barIndex: 0,
161
- totalBars: 0
162
- },
163
- styles: opts.styles,
164
- screenshotUrl: null
165
- })
167
+ styles,
168
+ storage: resolvedStorage
169
+ },
170
+ (opts) => {
171
+ const s = opts.storage;
172
+ const read = (ns, fallback) => {
173
+ if (!s || !s.persists(ns)) return fallback;
174
+ try {
175
+ const raw = s.adapter.getItem(s.key(ns));
176
+ return raw ? JSON.parse(raw) : fallback;
177
+ } catch {
178
+ return fallback;
179
+ }
180
+ };
181
+ const storedIndicators = read("indicators", {});
182
+ return {
183
+ chart: null,
184
+ datafeed: opts.datafeed,
185
+ symbol: opts.defaultSymbol ?? null,
186
+ period: opts.defaultPeriod ?? (opts.periods ?? DEFAULT_PERIODS)[0],
187
+ theme: opts.defaultTheme ?? "light",
188
+ timezone: opts.defaultTimezone ?? "Asia/Shanghai",
189
+ isLoading: false,
190
+ locale: opts.defaultLocale ?? "en-US",
191
+ periods: opts.periods ?? DEFAULT_PERIODS,
192
+ // Persistence semantics: STORED values win over `default*` props —
193
+ // the user's saved configuration should survive reload even when the
194
+ // app passes defaults. Only when storage is empty/unconfigured do the
195
+ // `default*` props apply, falling back to the built-ins last.
196
+ // (Settings live in useKlinechartsUISettings useState and hydrate
197
+ // separately via the dispatch-context `storage`.)
198
+ mainIndicators: storedIndicators.main ?? opts.defaultMainIndicators ?? ["MA"],
199
+ subIndicators: storedIndicators.sub ?? (opts.defaultSubIndicators ? opts.defaultSubIndicators.reduce(
200
+ (acc, name) => ({ ...acc, [name]: "" }),
201
+ {}
202
+ ) : { VOL: "" }),
203
+ indicatorAxes: storedIndicators.axes ?? {},
204
+ indicatorVisibility: storedIndicators.visibility ?? {},
205
+ alerts: read("alerts", []),
206
+ measure: { isActive: false, fromPoint: null, result: null },
207
+ replay: {
208
+ isReplaying: false,
209
+ isPaused: false,
210
+ speed: 1,
211
+ barIndex: 0,
212
+ totalBars: 0
213
+ },
214
+ styles: opts.styles,
215
+ screenshotUrl: null
216
+ };
217
+ }
166
218
  );
167
219
  const fullscreenContainerRef = react.useRef(null);
168
220
  const undoRedoListenerRef = react.useRef(null);
169
- const alertTriggeredListenerRef = react.useRef(null);
221
+ const alertTriggeredListenersRef = react.useRef(/* @__PURE__ */ new Set());
170
222
  const replayIntervalRef = react.useRef(null);
171
223
  const replaySavedDataRef = react.useRef([]);
172
224
  const replayIndexRef = react.useRef(0);
@@ -230,7 +282,7 @@ function KlinechartsUIProvider({
230
282
  });
231
283
  react.useEffect(() => {
232
284
  if (shouldRegister) {
233
- chunkLGYYJ2GP_cjs.registerExtensions();
285
+ chunkSZDU2D3D_cjs.registerExtensions();
234
286
  }
235
287
  extraOverlaysRef.current?.forEach((overlay) => klinecharts.registerOverlay(overlay));
236
288
  }, [shouldRegister]);
@@ -244,23 +296,53 @@ function KlinechartsUIProvider({
244
296
  const chart = state.chart;
245
297
  if (!chart || !hasAlerts) return;
246
298
  alertPrevCloseRef.current = null;
299
+ const prevValueByAlert = /* @__PURE__ */ new Map();
247
300
  const interval = setInterval(() => {
248
301
  const dataList = chart.getDataList();
249
302
  if (!dataList || dataList.length === 0) return;
250
- const currentClose = dataList[dataList.length - 1].close;
251
- const prevClose = alertPrevCloseRef.current;
252
- alertPrevCloseRef.current = currentClose;
253
- if (prevClose === null) return;
303
+ const lastIdx = dataList.length - 1;
304
+ const indicatorCache = /* @__PURE__ */ new Map();
305
+ const readIndicatorValue = (indicatorId, figureKey) => {
306
+ const cacheKey = `${indicatorId}:${figureKey}`;
307
+ if (indicatorCache.has(cacheKey)) return indicatorCache.get(cacheKey);
308
+ let value = null;
309
+ try {
310
+ const indicators2 = chart.getIndicators({ id: indicatorId });
311
+ const ind = indicators2?.[0];
312
+ const result = ind?.result;
313
+ const last = Array.isArray(result) ? result[lastIdx] : null;
314
+ if (last && typeof last === "object") {
315
+ const v = last[figureKey];
316
+ value = typeof v === "number" ? v : null;
317
+ }
318
+ } catch {
319
+ value = null;
320
+ }
321
+ indicatorCache.set(cacheKey, value);
322
+ return value;
323
+ };
254
324
  const alerts = stateRef.current.alerts;
255
325
  const triggeredIds = [];
256
326
  for (const alert of alerts) {
257
327
  if (alert.triggered) continue;
258
- const crossedUp = prevClose < alert.price && currentClose >= alert.price;
259
- const crossedDown = prevClose > alert.price && currentClose <= alert.price;
328
+ const target = alert.target ?? { type: "price" };
329
+ let currentValue;
330
+ if (target.type === "indicator") {
331
+ currentValue = readIndicatorValue(target.indicatorId, target.figureKey);
332
+ } else {
333
+ currentValue = dataList[lastIdx].close;
334
+ }
335
+ if (currentValue === null || !Number.isFinite(currentValue)) continue;
336
+ const prevValue = prevValueByAlert.get(alert.id) ?? null;
337
+ prevValueByAlert.set(alert.id, currentValue);
338
+ if (prevValue === null) continue;
339
+ const crossedUp = prevValue < alert.price && currentValue >= alert.price;
340
+ const crossedDown = prevValue > alert.price && currentValue <= alert.price;
260
341
  const shouldTrigger = alert.condition === "crossing_up" ? crossedUp : alert.condition === "crossing_down" ? crossedDown : crossedUp || crossedDown;
261
342
  if (shouldTrigger) {
262
343
  triggeredIds.push(alert.id);
263
- alertTriggeredListenerRef.current?.({ ...alert, triggered: true });
344
+ const fired = { ...alert, triggered: true };
345
+ alertTriggeredListenersRef.current.forEach((cb) => cb(fired));
264
346
  }
265
347
  }
266
348
  if (triggeredIds.length > 0) {
@@ -275,6 +357,36 @@ function KlinechartsUIProvider({
275
357
  react.useEffect(() => {
276
358
  alertPrevCloseRef.current = null;
277
359
  }, [state.symbol, state.period]);
360
+ const writeNs = react.useCallback(
361
+ (ns, value) => {
362
+ if (!resolvedStorage || !resolvedStorage.persists(ns)) return;
363
+ try {
364
+ resolvedStorage.adapter.setItem(
365
+ resolvedStorage.key(ns),
366
+ JSON.stringify(value)
367
+ );
368
+ } catch {
369
+ }
370
+ },
371
+ [resolvedStorage]
372
+ );
373
+ react.useEffect(() => {
374
+ writeNs("alerts", state.alerts);
375
+ }, [state.alerts, writeNs]);
376
+ react.useEffect(() => {
377
+ writeNs("indicators", {
378
+ main: state.mainIndicators,
379
+ sub: state.subIndicators,
380
+ axes: state.indicatorAxes,
381
+ visibility: state.indicatorVisibility
382
+ });
383
+ }, [
384
+ state.mainIndicators,
385
+ state.subIndicators,
386
+ state.indicatorAxes,
387
+ state.indicatorVisibility,
388
+ writeNs
389
+ ]);
278
390
  react.useEffect(() => {
279
391
  return () => {
280
392
  if (replayIntervalRef.current !== null) {
@@ -290,18 +402,19 @@ function KlinechartsUIProvider({
290
402
  onSettingsChange: onSettingsChangeRef.current,
291
403
  fullscreenContainerRef,
292
404
  undoRedoListenerRef,
293
- alertTriggeredListenerRef,
405
+ alertTriggeredListenersRef,
294
406
  replayIntervalRef,
295
407
  replaySavedDataRef,
296
- replayIndexRef
408
+ replayIndexRef,
409
+ storage: resolvedStorage
297
410
  }),
298
411
  // eslint-disable-next-line react-hooks/exhaustive-deps
299
- [enhancedDispatch]
412
+ [enhancedDispatch, resolvedStorage]
300
413
  );
301
- return /* @__PURE__ */ jsxRuntime.jsx(KlinechartsUIStateContext.Provider, { value: state, children: /* @__PURE__ */ jsxRuntime.jsx(KlinechartsUIDispatchContext.Provider, { value: dispatchValue, children }) });
414
+ return /* @__PURE__ */ jsxRuntime.jsx(chunkF24D6PWY_cjs.KlinechartsUIStateContext.Provider, { value: state, children: /* @__PURE__ */ jsxRuntime.jsx(chunkF24D6PWY_cjs.KlinechartsUIDispatchContext.Provider, { value: dispatchValue, children }) });
302
415
  }
303
416
  function useKlinechartsUITheme() {
304
- const { state, dispatch } = useKlinechartsUI();
417
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
305
418
  const setTheme = react.useCallback(
306
419
  (theme) => {
307
420
  state.chart?.setStyles(theme);
@@ -322,11 +435,11 @@ function useKlinechartsUITheme() {
322
435
 
323
436
  // src/hooks/useKlinechartsUILoading.ts
324
437
  function useKlinechartsUILoading() {
325
- const { state } = useKlinechartsUI();
438
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
326
439
  return { isLoading: state.isLoading };
327
440
  }
328
441
  function usePeriods() {
329
- const { state, dispatch } = useKlinechartsUI();
442
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
330
443
  const setPeriod = react.useCallback(
331
444
  (period) => {
332
445
  dispatch({ type: "SET_PERIOD", period });
@@ -364,7 +477,7 @@ var TIMEZONES = [
364
477
 
365
478
  // src/hooks/useTimezone.ts
366
479
  function useTimezone() {
367
- const { state, dispatch } = useKlinechartsUI();
480
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
368
481
  const timezones = react.useMemo(
369
482
  () => TIMEZONES.map((tz) => ({
370
483
  key: tz.key,
@@ -386,7 +499,7 @@ function useTimezone() {
386
499
  };
387
500
  }
388
501
  function useSymbolSearch(debounceMs = 300) {
389
- const { state, dispatch, datafeed } = useKlinechartsUI();
502
+ const { state, dispatch, datafeed } = chunkF24D6PWY_cjs.useKlinechartsUI();
390
503
  const [query, setQueryState] = react.useState("");
391
504
  const [results, setResults] = react.useState([]);
392
505
  const [isSearching, setIsSearching] = react.useState(false);
@@ -748,8 +861,8 @@ var INDICATOR_PARAMS = {
748
861
  // src/hooks/useIndicators.ts
749
862
  var COLLAPSED_HEIGHT = 30;
750
863
  function useIndicators() {
751
- const { state, dispatch } = useKlinechartsUI();
752
- const { undoRedoListenerRef } = useKlinechartsUIDispatch();
864
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
865
+ const { undoRedoListenerRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
753
866
  const paneHeightsRef = react.useRef({});
754
867
  const collapsedPanesRef = react.useRef(/* @__PURE__ */ new Set());
755
868
  const mainIndicators = react.useMemo(() => {
@@ -1245,9 +1358,28 @@ var DRAWING_CATEGORIES = [
1245
1358
 
1246
1359
  // src/hooks/useDrawingTools.ts
1247
1360
  var DRAWING_GROUP_ID = "drawing_tools";
1361
+ var DRAWING_NAME_TO_LOCALE_KEY = new Map(
1362
+ DRAWING_CATEGORIES.flatMap(
1363
+ (cat) => cat.tools.map((tool) => [tool.name, tool.localeKey])
1364
+ )
1365
+ );
1366
+ function drawingLabel(name) {
1367
+ return DRAWING_NAME_TO_LOCALE_KEY.get(name) ?? name;
1368
+ }
1369
+ function overlaysEqual(a, b) {
1370
+ if (a.length !== b.length) return false;
1371
+ for (let i = 0; i < a.length; i++) {
1372
+ const x = a[i];
1373
+ const y = b[i];
1374
+ if (x.id !== y.id || x.name !== y.name || x.paneId !== y.paneId || x.locked !== y.locked || x.visible !== y.visible) {
1375
+ return false;
1376
+ }
1377
+ }
1378
+ return true;
1379
+ }
1248
1380
  function useDrawingTools() {
1249
- const { state } = useKlinechartsUI();
1250
- const { undoRedoListenerRef } = useKlinechartsUIDispatch();
1381
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
1382
+ const { undoRedoListenerRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
1251
1383
  const [activeTool, setActiveTool] = react.useState(null);
1252
1384
  const [magnetMode, setMagnetModeState] = react.useState("normal");
1253
1385
  const [isLocked, setIsLocked] = react.useState(false);
@@ -1265,6 +1397,34 @@ function useDrawingTools() {
1265
1397
  isVisibleRef.current = isVisible;
1266
1398
  magnetModeRef.current = magnetMode;
1267
1399
  });
1400
+ const [overlays2, setOverlays] = react.useState([]);
1401
+ const refreshOverlays = react.useCallback(() => {
1402
+ if (!state.chart) {
1403
+ setOverlays((prev) => prev.length === 0 ? prev : []);
1404
+ return;
1405
+ }
1406
+ const list = state.chart.getOverlays({ groupId: DRAWING_GROUP_ID });
1407
+ const next = list.map((o) => ({
1408
+ id: o.id,
1409
+ name: o.name,
1410
+ paneId: o.paneId,
1411
+ locked: !!o.lock,
1412
+ visible: o.visible !== false
1413
+ // klinecharts default = true
1414
+ }));
1415
+ setOverlays((prev) => overlaysEqual(prev, next) ? prev : next);
1416
+ }, [state.chart]);
1417
+ const refreshOverlaysRef = react.useRef(() => {
1418
+ });
1419
+ react.useEffect(() => {
1420
+ refreshOverlaysRef.current = refreshOverlays;
1421
+ });
1422
+ react.useEffect(() => {
1423
+ if (!state.chart) return;
1424
+ queueMicrotask(() => refreshOverlaysRef.current());
1425
+ const interval = setInterval(() => refreshOverlaysRef.current(), 1e3);
1426
+ return () => clearInterval(interval);
1427
+ }, [state.chart, refreshOverlays]);
1268
1428
  const categories = react.useMemo(
1269
1429
  () => DRAWING_CATEGORIES.map((cat) => ({
1270
1430
  key: cat.key,
@@ -1300,6 +1460,7 @@ function useDrawingTools() {
1300
1460
  }
1301
1461
  }
1302
1462
  });
1463
+ refreshOverlaysRef.current();
1303
1464
  if (autoRetriggerRef.current && activeToolRef.current === name) {
1304
1465
  requestAnimationFrame(() => {
1305
1466
  createOverlayForToolRef.current(name);
@@ -1326,49 +1487,52 @@ function useDrawingTools() {
1326
1487
  const setMagnetMode = react.useCallback(
1327
1488
  (mode) => {
1328
1489
  setMagnetModeState(mode);
1329
- const overlays2 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1330
- if (overlays2) {
1490
+ const overlays3 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1491
+ if (overlays3) {
1331
1492
  const overlayMode = mode === "strong" ? "strong_magnet" : mode === "weak" ? "weak_magnet" : "normal";
1332
- overlays2.forEach((overlay) => {
1493
+ overlays3.forEach((overlay) => {
1333
1494
  state.chart?.overrideOverlay({
1334
1495
  id: overlay.id,
1335
1496
  mode: overlayMode
1336
1497
  });
1337
1498
  });
1338
1499
  }
1500
+ refreshOverlaysRef.current();
1339
1501
  },
1340
1502
  [state.chart]
1341
1503
  );
1342
1504
  const toggleLock = react.useCallback(() => {
1343
1505
  const newLocked = !isLocked;
1344
1506
  setIsLocked(newLocked);
1345
- const overlays2 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1346
- if (overlays2) {
1347
- overlays2.forEach((overlay) => {
1507
+ const overlays3 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1508
+ if (overlays3) {
1509
+ overlays3.forEach((overlay) => {
1348
1510
  state.chart?.overrideOverlay({
1349
1511
  id: overlay.id,
1350
1512
  lock: newLocked
1351
1513
  });
1352
1514
  });
1353
1515
  }
1516
+ refreshOverlaysRef.current();
1354
1517
  }, [state.chart, isLocked]);
1355
1518
  const toggleVisibility = react.useCallback(() => {
1356
1519
  const newVisible = !isVisible;
1357
1520
  setIsVisible(newVisible);
1358
- const overlays2 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1359
- if (overlays2) {
1360
- overlays2.forEach((overlay) => {
1521
+ const overlays3 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1522
+ if (overlays3) {
1523
+ overlays3.forEach((overlay) => {
1361
1524
  state.chart?.overrideOverlay({
1362
1525
  id: overlay.id,
1363
1526
  visible: newVisible
1364
1527
  });
1365
1528
  });
1366
1529
  }
1530
+ refreshOverlaysRef.current();
1367
1531
  }, [state.chart, isVisible]);
1368
1532
  const removeAllDrawings = react.useCallback(() => {
1369
- const overlays2 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1370
- if (overlays2 && overlays2.length > 0) {
1371
- const snapshot = overlays2.map((o) => ({
1533
+ const overlays3 = state.chart?.getOverlays({ groupId: DRAWING_GROUP_ID });
1534
+ if (overlays3 && overlays3.length > 0) {
1535
+ const snapshot = overlays3.map((o) => ({
1372
1536
  name: o.name,
1373
1537
  id: o.id,
1374
1538
  points: o.points,
@@ -1382,7 +1546,29 @@ function useDrawingTools() {
1382
1546
  }
1383
1547
  state.chart?.removeOverlay({ groupId: DRAWING_GROUP_ID });
1384
1548
  setActiveTool(null);
1549
+ refreshOverlaysRef.current();
1385
1550
  }, [state.chart, undoRedoListenerRef]);
1551
+ const removeDrawing = react.useCallback(
1552
+ (id) => {
1553
+ state.chart?.removeOverlay({ id, groupId: DRAWING_GROUP_ID });
1554
+ refreshOverlaysRef.current();
1555
+ },
1556
+ [state.chart]
1557
+ );
1558
+ const setDrawingVisible = react.useCallback(
1559
+ (id, visible) => {
1560
+ state.chart?.overrideOverlay({ id, visible });
1561
+ refreshOverlaysRef.current();
1562
+ },
1563
+ [state.chart]
1564
+ );
1565
+ const setDrawingLocked = react.useCallback(
1566
+ (id, locked) => {
1567
+ state.chart?.overrideOverlay({ id, lock: locked });
1568
+ refreshOverlaysRef.current();
1569
+ },
1570
+ [state.chart]
1571
+ );
1386
1572
  return {
1387
1573
  categories,
1388
1574
  activeTool,
@@ -1390,13 +1576,17 @@ function useDrawingTools() {
1390
1576
  isLocked,
1391
1577
  isVisible,
1392
1578
  autoRetrigger,
1579
+ overlays: overlays2,
1393
1580
  selectTool,
1394
1581
  clearActiveTool,
1395
1582
  setMagnetMode,
1396
1583
  toggleLock,
1397
1584
  toggleVisibility,
1398
1585
  removeAllDrawings,
1399
- setAutoRetrigger
1586
+ setAutoRetrigger,
1587
+ removeDrawing,
1588
+ setDrawingVisible,
1589
+ setDrawingLocked
1400
1590
  };
1401
1591
  }
1402
1592
 
@@ -1437,8 +1627,18 @@ var defaultSettings = {
1437
1627
  tooltipShowRule: "always"
1438
1628
  };
1439
1629
  function useKlinechartsUISettings() {
1440
- const { state, onSettingsChange } = useKlinechartsUI();
1441
- const [settings, setSettings] = react.useState(defaultSettings);
1630
+ const { state, onSettingsChange } = chunkF24D6PWY_cjs.useKlinechartsUI();
1631
+ const { storage } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
1632
+ const [settings, setSettings] = react.useState(() => {
1633
+ if (storage && storage.persists("settings")) {
1634
+ try {
1635
+ const raw = storage.adapter.getItem(storage.key("settings"));
1636
+ if (raw) return { ...defaultSettings, ...JSON.parse(raw) };
1637
+ } catch {
1638
+ }
1639
+ }
1640
+ return defaultSettings;
1641
+ });
1442
1642
  const isInitialMount = react.useRef(true);
1443
1643
  react.useEffect(() => {
1444
1644
  if (isInitialMount.current) {
@@ -1447,6 +1647,14 @@ function useKlinechartsUISettings() {
1447
1647
  }
1448
1648
  onSettingsChange?.({ ...settings });
1449
1649
  }, [settings, onSettingsChange]);
1650
+ react.useEffect(() => {
1651
+ if (!storage || !storage.persists("settings")) return;
1652
+ if (isInitialMount.current) return;
1653
+ try {
1654
+ storage.adapter.setItem(storage.key("settings"), JSON.stringify(settings));
1655
+ } catch {
1656
+ }
1657
+ }, [settings, storage]);
1450
1658
  const candleTypes = react.useMemo(
1451
1659
  () => CANDLE_TYPES.map((ct) => ({
1452
1660
  key: ct.key,
@@ -1688,7 +1896,7 @@ function useKlinechartsUISettings() {
1688
1896
  };
1689
1897
  }
1690
1898
  function useScreenshot() {
1691
- const { state, dispatch } = useKlinechartsUI();
1899
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
1692
1900
  const capture = react.useCallback(() => {
1693
1901
  if (!state.chart) return;
1694
1902
  const url = state.chart.getConvertPictureUrl(true, "jpeg", state.theme === "dark" ? "#151517" : "#ffffff");
@@ -1717,7 +1925,7 @@ function useScreenshot() {
1717
1925
  };
1718
1926
  }
1719
1927
  function useHotkeys() {
1720
- const { state } = useKlinechartsUI();
1928
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
1721
1929
  const registerHotkey = react.useCallback((template) => {
1722
1930
  klinecharts.registerHotkey(template);
1723
1931
  }, []);
@@ -1746,7 +1954,7 @@ function useHotkeys() {
1746
1954
  };
1747
1955
  }
1748
1956
  function useChartAxes() {
1749
- const { state } = useKlinechartsUI();
1957
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
1750
1958
  const overrideXAxis = react.useCallback(
1751
1959
  (override) => {
1752
1960
  if (!state.chart) return;
@@ -1764,7 +1972,7 @@ function useChartAxes() {
1764
1972
  return { overrideXAxis, overrideYAxis };
1765
1973
  }
1766
1974
  function useFullscreen() {
1767
- const { fullscreenContainerRef } = useKlinechartsUIDispatch();
1975
+ const { fullscreenContainerRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
1768
1976
  const [isFullscreen, setIsFullscreen] = react.useState(false);
1769
1977
  const enter = react.useCallback(() => {
1770
1978
  const el = fullscreenContainerRef.current;
@@ -1819,7 +2027,7 @@ function useFullscreen() {
1819
2027
  };
1820
2028
  }
1821
2029
  function useOrderLines() {
1822
- const { state } = useKlinechartsUI();
2030
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
1823
2031
  const callbacksRef = react.useRef(/* @__PURE__ */ new Map());
1824
2032
  const ownedIdsRef = react.useRef(/* @__PURE__ */ new Set());
1825
2033
  const createOrderLine = react.useCallback(
@@ -1916,8 +2124,8 @@ function useOrderLines() {
1916
2124
  }
1917
2125
  var DRAWING_GROUP_ID2 = "drawing_tools";
1918
2126
  function useUndoRedo() {
1919
- const { state, dispatch } = useKlinechartsUI();
1920
- const { undoRedoListenerRef } = useKlinechartsUIDispatch();
2127
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
2128
+ const { undoRedoListenerRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
1921
2129
  const [undoStack, setUndoStack] = react.useState([]);
1922
2130
  const [redoStack, setRedoStack] = react.useState([]);
1923
2131
  const isProcessingRef = react.useRef(false);
@@ -2259,7 +2467,7 @@ function getEntry(id) {
2259
2467
  }
2260
2468
  }
2261
2469
  function useLayoutManager() {
2262
- const { state, dispatch } = useKlinechartsUI();
2470
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
2263
2471
  const [layouts, setLayouts] = react.useState(
2264
2472
  () => getLayoutIds().map((id) => getEntry(id)).filter((e) => e !== null)
2265
2473
  );
@@ -2563,7 +2771,7 @@ var SHADOW_KEYS = [
2563
2771
  ];
2564
2772
  var scriptCounter = 0;
2565
2773
  function useScriptEditor() {
2566
- const { state } = useKlinechartsUI();
2774
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
2567
2775
  const [code, setCode] = react.useState(DEFAULT_SCRIPT);
2568
2776
  const [scriptName, setScriptName] = react.useState("");
2569
2777
  const [params, setParams] = react.useState("14");
@@ -2600,7 +2808,7 @@ ${code}`
2600
2808
  const shadowValues = SHADOW_KEYS.map(() => void 0);
2601
2809
  const sampleResult = compiledFn(
2602
2810
  ...shadowValues,
2603
- chunkLGYYJ2GP_cjs.TA_default,
2811
+ chunkSZDU2D3D_cjs.TA_default,
2604
2812
  dataList,
2605
2813
  parsedParams
2606
2814
  );
@@ -2627,7 +2835,7 @@ ${code}`
2627
2835
  shortName: (scriptName.trim() || `Script #${scriptCounter}`) + (placement === "main" ? " (Main)" : " (Sub)"),
2628
2836
  calcParams: parsedParams,
2629
2837
  figures,
2630
- calc: (liveDataList) => compiledFn(...shadowValues, chunkLGYYJ2GP_cjs.TA_default, liveDataList, parsedParams),
2838
+ calc: (liveDataList) => compiledFn(...shadowValues, chunkSZDU2D3D_cjs.TA_default, liveDataList, parsedParams),
2631
2839
  extendData: {
2632
2840
  isCustomScript: true,
2633
2841
  code,
@@ -2738,7 +2946,7 @@ ${code}`
2738
2946
  };
2739
2947
  }
2740
2948
  function useCrosshair() {
2741
- const { state } = useKlinechartsUI();
2949
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
2742
2950
  const [barData, setBarData] = react.useState(null);
2743
2951
  const rafRef = react.useRef(0);
2744
2952
  const handler = react.useCallback(
@@ -2788,11 +2996,11 @@ function useCrosshair() {
2788
2996
  }
2789
2997
  var alertCounter = 0;
2790
2998
  function useAlerts() {
2791
- const { state, dispatch } = useKlinechartsUI();
2792
- const { alertTriggeredListenerRef } = useKlinechartsUIDispatch();
2999
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
3000
+ const { alertTriggeredListenersRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
2793
3001
  const alerts = state.alerts;
2794
3002
  const addAlert = react.useCallback(
2795
- (price, condition, message, extendData) => {
3003
+ (price, condition, message, extendData, target) => {
2796
3004
  const id = `alert_${++alertCounter}`;
2797
3005
  const precision = state.chart?.getSymbol()?.pricePrecision ?? 2;
2798
3006
  const resolvedExtendData = {
@@ -2805,11 +3013,14 @@ function useAlerts() {
2805
3013
  condition,
2806
3014
  message,
2807
3015
  triggered: false,
2808
- extendData: resolvedExtendData
3016
+ extendData: resolvedExtendData,
3017
+ // Persist the target only when it's an indicator alert; omit for the
3018
+ // default price target so existing serialized alerts stay compatible.
3019
+ ...target && target.type === "indicator" ? { target } : {}
2809
3020
  };
2810
3021
  dispatch({ type: "ADD_ALERT", alert });
2811
3022
  if (state.chart) {
2812
- chunkLGYYJ2GP_cjs.ensureAlertLineRegistered();
3023
+ chunkSZDU2D3D_cjs.ensureAlertLineRegistered();
2813
3024
  state.chart.createOverlay({
2814
3025
  name: "alertLine",
2815
3026
  id,
@@ -2836,9 +3047,13 @@ function useAlerts() {
2836
3047
  }, [state.chart, dispatch]);
2837
3048
  const onAlertTriggered = react.useCallback(
2838
3049
  (callback) => {
2839
- alertTriggeredListenerRef.current = callback;
3050
+ const set = alertTriggeredListenersRef.current;
3051
+ set.add(callback);
3052
+ return () => {
3053
+ set.delete(callback);
3054
+ };
2840
3055
  },
2841
- [alertTriggeredListenerRef]
3056
+ [alertTriggeredListenersRef]
2842
3057
  );
2843
3058
  return {
2844
3059
  alerts,
@@ -2849,7 +3064,7 @@ function useAlerts() {
2849
3064
  };
2850
3065
  }
2851
3066
  function useDataExport() {
2852
- const { state } = useKlinechartsUI();
3067
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
2853
3068
  const exportAll = react.useCallback(
2854
3069
  (format) => {
2855
3070
  if (!state.chart) return;
@@ -2915,8 +3130,8 @@ function downloadData(dataList, format, ticker) {
2915
3130
  URL.revokeObjectURL(url);
2916
3131
  }
2917
3132
  function useWatchlist() {
2918
- const { state } = useKlinechartsUI();
2919
- const { dispatch, datafeed } = useKlinechartsUIDispatch();
3133
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
3134
+ const { dispatch, datafeed } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
2920
3135
  const [items, setItems] = react.useState([]);
2921
3136
  const subscriptionsRef = react.useRef(/* @__PURE__ */ new Map());
2922
3137
  const activeSymbol = state.symbol?.ticker ?? null;
@@ -2985,8 +3200,8 @@ function useWatchlist() {
2985
3200
  };
2986
3201
  }
2987
3202
  function useReplay() {
2988
- const { state, dispatch } = useKlinechartsUI();
2989
- const { replayIntervalRef, replaySavedDataRef, replayIndexRef } = useKlinechartsUIDispatch();
3203
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
3204
+ const { replayIntervalRef, replaySavedDataRef, replayIndexRef } = chunkF24D6PWY_cjs.useKlinechartsUIDispatch();
2990
3205
  const { isReplaying, isPaused, speed, barIndex, totalBars } = state.replay;
2991
3206
  const clearInterval_ = react.useCallback(() => {
2992
3207
  if (replayIntervalRef.current !== null) {
@@ -3135,7 +3350,7 @@ var DEFAULT_COLORS = [
3135
3350
  "#8bc34a"
3136
3351
  ];
3137
3352
  function useCompare() {
3138
- const { state, datafeed } = useKlinechartsUI();
3353
+ const { state, datafeed } = chunkF24D6PWY_cjs.useKlinechartsUI();
3139
3354
  const [symbols, setSymbols] = react.useState([]);
3140
3355
  const indicatorsRef = react.useRef(/* @__PURE__ */ new Map());
3141
3356
  const instanceSalt = react.useId().replace(/[^a-zA-Z0-9]/g, "");
@@ -3281,7 +3496,7 @@ function computeResult(from, to) {
3281
3496
  return { from, to, priceDiff, pricePercent, bars, timeDiff };
3282
3497
  }
3283
3498
  function useMeasure() {
3284
- const { state, dispatch } = useKlinechartsUI();
3499
+ const { state, dispatch } = chunkF24D6PWY_cjs.useKlinechartsUI();
3285
3500
  const { isActive, fromPoint, result } = state.measure;
3286
3501
  const cleanup = react.useCallback(() => {
3287
3502
  state.chart?.removeOverlay({ id: MEASURE_OVERLAY_ID });
@@ -3362,7 +3577,7 @@ function useMeasure() {
3362
3577
  }
3363
3578
  var annotationCounter = 0;
3364
3579
  function useAnnotations() {
3365
- const { state } = useKlinechartsUI();
3580
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
3366
3581
  const [annotations, setAnnotations] = react.useState([]);
3367
3582
  const addAnnotation = react.useCallback(
3368
3583
  (text, price, timestamp, color) => {
@@ -3442,265 +3657,376 @@ function useAnnotations() {
3442
3657
  clearAnnotations
3443
3658
  };
3444
3659
  }
3660
+ var WorkspaceContext = react.createContext(null);
3661
+ function useWorkspace() {
3662
+ const ctx = react.useContext(WorkspaceContext);
3663
+ if (!ctx) {
3664
+ throw new Error("useWorkspace must be used within a <WorkspaceProvider>");
3665
+ }
3666
+ return ctx;
3667
+ }
3445
3668
 
3446
- // src/utils/createDataLoader.ts
3447
- function createDataLoader(datafeed, dispatch) {
3448
- let oldestTimestamp = null;
3449
- let currentGen = 0;
3450
- return {
3451
- getBars: async (params) => {
3669
+ // src/workspace/types.ts
3670
+ var DEFAULT_SYNC_CONFIG = {
3671
+ crosshair: true,
3672
+ scroll: true,
3673
+ zoom: true,
3674
+ symbol: true,
3675
+ period: true
3676
+ };
3677
+ function reducer2(state, action) {
3678
+ switch (action.type) {
3679
+ case "SET_CELLS":
3680
+ return { ...state, cells: action.cells };
3681
+ case "ADD_CELL":
3682
+ return { ...state, cells: [...state.cells, action.cell] };
3683
+ case "REMOVE_CELL": {
3684
+ const cells = state.cells.filter((c) => c.id !== action.id);
3685
+ return {
3686
+ cells,
3687
+ activeCellId: state.activeCellId === action.id ? cells[0]?.id ?? null : state.activeCellId
3688
+ };
3689
+ }
3690
+ case "SET_CELL_SYMBOL":
3691
+ return {
3692
+ ...state,
3693
+ cells: state.cells.map(
3694
+ (c) => c.id === action.id ? { ...c, symbol: action.symbol } : c
3695
+ )
3696
+ };
3697
+ case "SET_CELL_PERIOD":
3698
+ return {
3699
+ ...state,
3700
+ cells: state.cells.map(
3701
+ (c) => c.id === action.id ? { ...c, period: action.period } : c
3702
+ )
3703
+ };
3704
+ case "SET_ACTIVE_CELL":
3705
+ return { ...state, activeCellId: action.id };
3706
+ default:
3707
+ return state;
3708
+ }
3709
+ }
3710
+ function WorkspaceProvider({
3711
+ defaultCells,
3712
+ sync,
3713
+ children
3714
+ }) {
3715
+ const [state, dispatch] = react.useReducer(reducer2, defaultCells, (cells) => ({
3716
+ cells,
3717
+ activeCellId: cells[0]?.id ?? null
3718
+ }));
3719
+ const chartsRef = react.useRef(/* @__PURE__ */ new Map());
3720
+ const broadcastingRef = react.useRef(false);
3721
+ const resolvedSync = react.useMemo(
3722
+ () => ({ ...DEFAULT_SYNC_CONFIG, ...sync }),
3723
+ // eslint-disable-next-line react-hooks/exhaustive-deps
3724
+ []
3725
+ );
3726
+ const value = react.useMemo(
3727
+ () => ({
3728
+ state,
3729
+ dispatch,
3730
+ chartsRef,
3731
+ broadcastingRef,
3732
+ sync: resolvedSync
3733
+ }),
3734
+ [state, resolvedSync]
3735
+ );
3736
+ return /* @__PURE__ */ jsxRuntime.jsx(WorkspaceContext.Provider, { value, children });
3737
+ }
3738
+ function useChartSync({ cellId }) {
3739
+ const { chartsRef, broadcastingRef, sync, dispatch: workspaceDispatch } = useWorkspace();
3740
+ const { state } = chunkF24D6PWY_cjs.useKlinechartsUI();
3741
+ const chart = state.chart;
3742
+ react.useEffect(() => {
3743
+ if (!chart) return;
3744
+ chartsRef.current.set(cellId, chart);
3745
+ return () => {
3746
+ chartsRef.current.delete(cellId);
3747
+ };
3748
+ }, [chart, cellId, chartsRef]);
3749
+ react.useEffect(() => {
3750
+ if (!chart) return;
3751
+ const broadcast = (fn) => {
3752
+ if (broadcastingRef.current) return;
3753
+ broadcastingRef.current = true;
3452
3754
  try {
3453
- dispatch({ type: "SET_LOADING", isLoading: true });
3454
- if (params.type === "init") {
3455
- oldestTimestamp = null;
3456
- const gen = ++currentGen;
3457
- const data = await datafeed.getHistoryKLineData(
3458
- params.symbol,
3459
- { ...params.period, label: "" },
3460
- 0,
3461
- Date.now()
3462
- );
3463
- if (gen !== currentGen) return;
3464
- if (data.length > 0) {
3465
- oldestTimestamp = data[0].timestamp;
3466
- }
3467
- params.callback(data, {
3468
- forward: data.length > 0,
3469
- backward: false
3470
- });
3471
- } else if (params.type === "forward" && oldestTimestamp !== null) {
3472
- const gen = currentGen;
3473
- const data = await datafeed.getHistoryKLineData(
3474
- params.symbol,
3475
- { ...params.period, label: "" },
3476
- 0,
3477
- oldestTimestamp - 1
3478
- );
3479
- if (gen !== currentGen) return;
3480
- if (data.length > 0) {
3481
- oldestTimestamp = data[0].timestamp;
3755
+ chartsRef.current.forEach((target, id) => {
3756
+ if (id !== cellId) {
3757
+ try {
3758
+ fn(target);
3759
+ } catch {
3760
+ }
3482
3761
  }
3483
- params.callback(data, {
3484
- forward: data.length > 0,
3485
- backward: false
3486
- });
3487
- } else if (params.type === "backward") {
3488
- params.callback([], { forward: false, backward: false });
3489
- }
3490
- } catch (error) {
3491
- console.error("Failed to load chart data:", error);
3492
- params.callback([], { forward: false, backward: false });
3762
+ });
3493
3763
  } finally {
3494
- dispatch({ type: "SET_LOADING", isLoading: false });
3764
+ broadcastingRef.current = false;
3495
3765
  }
3496
- },
3497
- subscribeBar: (params) => {
3498
- datafeed.subscribe(
3499
- params.symbol,
3500
- { ...params.period, label: "" },
3501
- (klineData) => params.callback(klineData)
3766
+ };
3767
+ const onCrosshairChange = (data) => {
3768
+ if (!sync.crosshair) return;
3769
+ const crosshair = data;
3770
+ if (!crosshair) return;
3771
+ broadcast((target) => target.executeAction("onCrosshairChange", crosshair));
3772
+ };
3773
+ const onScroll = () => {
3774
+ if (!sync.scroll) return;
3775
+ let range = null;
3776
+ try {
3777
+ range = chart.getVisibleRange();
3778
+ } catch {
3779
+ return;
3780
+ }
3781
+ if (!range || range.realTo == null) return;
3782
+ broadcast(
3783
+ (target) => target.scrollToTimestamp(range.realTo, 0)
3502
3784
  );
3503
- },
3504
- unsubscribeBar: (params) => {
3505
- datafeed.unsubscribe(params.symbol, { ...params.period, label: "" });
3785
+ };
3786
+ const onZoom = () => {
3787
+ if (!sync.zoom) return;
3788
+ let bar = 0;
3789
+ try {
3790
+ bar = chart.getBarSpace().bar;
3791
+ } catch {
3792
+ return;
3793
+ }
3794
+ broadcast((target) => target.setBarSpace(bar));
3795
+ };
3796
+ chart.subscribeAction("onCrosshairChange", onCrosshairChange);
3797
+ chart.subscribeAction("onScroll", onScroll);
3798
+ chart.subscribeAction("onZoom", onZoom);
3799
+ return () => {
3800
+ chart.unsubscribeAction("onCrosshairChange", onCrosshairChange);
3801
+ chart.unsubscribeAction("onScroll", onScroll);
3802
+ chart.unsubscribeAction("onZoom", onZoom);
3803
+ };
3804
+ }, [chart, cellId, chartsRef, broadcastingRef, sync.crosshair, sync.scroll, sync.zoom]);
3805
+ react.useEffect(() => {
3806
+ if (state.symbol) {
3807
+ workspaceDispatch({ type: "SET_CELL_SYMBOL", id: cellId, symbol: state.symbol });
3506
3808
  }
3507
- };
3809
+ }, [state.symbol]);
3810
+ react.useEffect(() => {
3811
+ workspaceDispatch({ type: "SET_CELL_PERIOD", id: cellId, period: state.period });
3812
+ }, [state.period]);
3508
3813
  }
3509
3814
 
3510
3815
  Object.defineProperty(exports, "TA", {
3511
3816
  enumerable: true,
3512
- get: function () { return chunkLGYYJ2GP_cjs.TA_default; }
3817
+ get: function () { return chunkSZDU2D3D_cjs.TA_default; }
3513
3818
  });
3514
3819
  Object.defineProperty(exports, "abcd", {
3515
3820
  enumerable: true,
3516
- get: function () { return chunkLGYYJ2GP_cjs.abcd_default; }
3821
+ get: function () { return chunkSZDU2D3D_cjs.abcd_default; }
3517
3822
  });
3518
3823
  Object.defineProperty(exports, "alertLine", {
3519
3824
  enumerable: true,
3520
- get: function () { return chunkLGYYJ2GP_cjs.alertLine_default; }
3825
+ get: function () { return chunkSZDU2D3D_cjs.alertLine_default; }
3521
3826
  });
3522
3827
  Object.defineProperty(exports, "anyWaves", {
3523
3828
  enumerable: true,
3524
- get: function () { return chunkLGYYJ2GP_cjs.anyWaves_default; }
3829
+ get: function () { return chunkSZDU2D3D_cjs.anyWaves_default; }
3525
3830
  });
3526
3831
  Object.defineProperty(exports, "arrow", {
3527
3832
  enumerable: true,
3528
- get: function () { return chunkLGYYJ2GP_cjs.arrow_default; }
3833
+ get: function () { return chunkSZDU2D3D_cjs.arrow_default; }
3529
3834
  });
3530
3835
  Object.defineProperty(exports, "bollTv", {
3531
3836
  enumerable: true,
3532
- get: function () { return chunkLGYYJ2GP_cjs.bollTv_default; }
3837
+ get: function () { return chunkSZDU2D3D_cjs.bollTv_default; }
3533
3838
  });
3534
3839
  Object.defineProperty(exports, "brush", {
3535
3840
  enumerable: true,
3536
- get: function () { return chunkLGYYJ2GP_cjs.brush_default; }
3841
+ get: function () { return chunkSZDU2D3D_cjs.brush_default; }
3537
3842
  });
3538
3843
  Object.defineProperty(exports, "cci", {
3539
3844
  enumerable: true,
3540
- get: function () { return chunkLGYYJ2GP_cjs.cci_default; }
3845
+ get: function () { return chunkSZDU2D3D_cjs.cci_default; }
3541
3846
  });
3542
3847
  Object.defineProperty(exports, "circle", {
3543
3848
  enumerable: true,
3544
- get: function () { return chunkLGYYJ2GP_cjs.circle_default; }
3849
+ get: function () { return chunkSZDU2D3D_cjs.circle_default; }
3545
3850
  });
3546
3851
  Object.defineProperty(exports, "depthOverlay", {
3547
3852
  enumerable: true,
3548
- get: function () { return chunkLGYYJ2GP_cjs.depthOverlay_default; }
3853
+ get: function () { return chunkSZDU2D3D_cjs.depthOverlay_default; }
3549
3854
  });
3550
3855
  Object.defineProperty(exports, "eightWaves", {
3551
3856
  enumerable: true,
3552
- get: function () { return chunkLGYYJ2GP_cjs.eightWaves_default; }
3857
+ get: function () { return chunkSZDU2D3D_cjs.eightWaves_default; }
3553
3858
  });
3554
3859
  Object.defineProperty(exports, "elliottWave", {
3555
3860
  enumerable: true,
3556
- get: function () { return chunkLGYYJ2GP_cjs.elliottWave_default; }
3861
+ get: function () { return chunkSZDU2D3D_cjs.elliottWave_default; }
3557
3862
  });
3558
3863
  Object.defineProperty(exports, "fibRetracement", {
3559
3864
  enumerable: true,
3560
- get: function () { return chunkLGYYJ2GP_cjs.fibRetracement_default; }
3865
+ get: function () { return chunkSZDU2D3D_cjs.fibRetracement_default; }
3561
3866
  });
3562
3867
  Object.defineProperty(exports, "fibonacciCircle", {
3563
3868
  enumerable: true,
3564
- get: function () { return chunkLGYYJ2GP_cjs.fibonacciCircle_default; }
3869
+ get: function () { return chunkSZDU2D3D_cjs.fibonacciCircle_default; }
3565
3870
  });
3566
3871
  Object.defineProperty(exports, "fibonacciExtension", {
3567
3872
  enumerable: true,
3568
- get: function () { return chunkLGYYJ2GP_cjs.fibonacciExtension_default; }
3873
+ get: function () { return chunkSZDU2D3D_cjs.fibonacciExtension_default; }
3569
3874
  });
3570
3875
  Object.defineProperty(exports, "fibonacciSegment", {
3571
3876
  enumerable: true,
3572
- get: function () { return chunkLGYYJ2GP_cjs.fibonacciSegment_default; }
3877
+ get: function () { return chunkSZDU2D3D_cjs.fibonacciSegment_default; }
3573
3878
  });
3574
3879
  Object.defineProperty(exports, "fibonacciSpeedResistanceFan", {
3575
3880
  enumerable: true,
3576
- get: function () { return chunkLGYYJ2GP_cjs.fibonacciSpeedResistanceFan_default; }
3881
+ get: function () { return chunkSZDU2D3D_cjs.fibonacciSpeedResistanceFan_default; }
3577
3882
  });
3578
3883
  Object.defineProperty(exports, "fibonacciSpiral", {
3579
3884
  enumerable: true,
3580
- get: function () { return chunkLGYYJ2GP_cjs.fibonacciSpiral_default; }
3885
+ get: function () { return chunkSZDU2D3D_cjs.fibonacciSpiral_default; }
3581
3886
  });
3582
3887
  Object.defineProperty(exports, "fiveWaves", {
3583
3888
  enumerable: true,
3584
- get: function () { return chunkLGYYJ2GP_cjs.fiveWaves_default; }
3889
+ get: function () { return chunkSZDU2D3D_cjs.fiveWaves_default; }
3585
3890
  });
3586
3891
  Object.defineProperty(exports, "gannBox", {
3587
3892
  enumerable: true,
3588
- get: function () { return chunkLGYYJ2GP_cjs.gannBox_default; }
3893
+ get: function () { return chunkSZDU2D3D_cjs.gannBox_default; }
3589
3894
  });
3590
3895
  Object.defineProperty(exports, "gannFan", {
3591
3896
  enumerable: true,
3592
- get: function () { return chunkLGYYJ2GP_cjs.gannFan_default; }
3897
+ get: function () { return chunkSZDU2D3D_cjs.gannFan_default; }
3593
3898
  });
3594
3899
  Object.defineProperty(exports, "hma", {
3595
3900
  enumerable: true,
3596
- get: function () { return chunkLGYYJ2GP_cjs.hma_default; }
3901
+ get: function () { return chunkSZDU2D3D_cjs.hma_default; }
3597
3902
  });
3598
3903
  Object.defineProperty(exports, "ichimoku", {
3599
3904
  enumerable: true,
3600
- get: function () { return chunkLGYYJ2GP_cjs.ichimoku_default; }
3905
+ get: function () { return chunkSZDU2D3D_cjs.ichimoku_default; }
3601
3906
  });
3602
3907
  Object.defineProperty(exports, "indicators", {
3603
3908
  enumerable: true,
3604
- get: function () { return chunkLGYYJ2GP_cjs.indicators; }
3909
+ get: function () { return chunkSZDU2D3D_cjs.indicators; }
3605
3910
  });
3606
3911
  Object.defineProperty(exports, "longPosition", {
3607
3912
  enumerable: true,
3608
- get: function () { return chunkLGYYJ2GP_cjs.longPosition_default; }
3913
+ get: function () { return chunkSZDU2D3D_cjs.longPosition_default; }
3609
3914
  });
3610
3915
  Object.defineProperty(exports, "maRibbon", {
3611
3916
  enumerable: true,
3612
- get: function () { return chunkLGYYJ2GP_cjs.maRibbon_default; }
3917
+ get: function () { return chunkSZDU2D3D_cjs.maRibbon_default; }
3613
3918
  });
3614
3919
  Object.defineProperty(exports, "macdTv", {
3615
3920
  enumerable: true,
3616
- get: function () { return chunkLGYYJ2GP_cjs.macdTv_default; }
3921
+ get: function () { return chunkSZDU2D3D_cjs.macdTv_default; }
3617
3922
  });
3618
3923
  Object.defineProperty(exports, "measure", {
3619
3924
  enumerable: true,
3620
- get: function () { return chunkLGYYJ2GP_cjs.measure_default; }
3925
+ get: function () { return chunkSZDU2D3D_cjs.measure_default; }
3621
3926
  });
3622
3927
  Object.defineProperty(exports, "orderLine", {
3623
3928
  enumerable: true,
3624
- get: function () { return chunkLGYYJ2GP_cjs.orderLine_default; }
3929
+ get: function () { return chunkSZDU2D3D_cjs.orderLine_default; }
3625
3930
  });
3626
3931
  Object.defineProperty(exports, "overlays", {
3627
3932
  enumerable: true,
3628
- get: function () { return chunkLGYYJ2GP_cjs.overlays; }
3933
+ get: function () { return chunkSZDU2D3D_cjs.overlays; }
3629
3934
  });
3630
3935
  Object.defineProperty(exports, "parallelChannel", {
3631
3936
  enumerable: true,
3632
- get: function () { return chunkLGYYJ2GP_cjs.parallelChannel_default; }
3937
+ get: function () { return chunkSZDU2D3D_cjs.parallelChannel_default; }
3633
3938
  });
3634
3939
  Object.defineProperty(exports, "parallelogram", {
3635
3940
  enumerable: true,
3636
- get: function () { return chunkLGYYJ2GP_cjs.parallelogram_default; }
3941
+ get: function () { return chunkSZDU2D3D_cjs.parallelogram_default; }
3637
3942
  });
3638
3943
  Object.defineProperty(exports, "pivotPoints", {
3639
3944
  enumerable: true,
3640
- get: function () { return chunkLGYYJ2GP_cjs.pivotPoints_default; }
3945
+ get: function () { return chunkSZDU2D3D_cjs.pivotPoints_default; }
3641
3946
  });
3642
3947
  Object.defineProperty(exports, "ray", {
3643
3948
  enumerable: true,
3644
- get: function () { return chunkLGYYJ2GP_cjs.ray_default; }
3949
+ get: function () { return chunkSZDU2D3D_cjs.ray_default; }
3645
3950
  });
3646
3951
  Object.defineProperty(exports, "rect", {
3647
3952
  enumerable: true,
3648
- get: function () { return chunkLGYYJ2GP_cjs.rect_default; }
3953
+ get: function () { return chunkSZDU2D3D_cjs.rect_default; }
3649
3954
  });
3650
3955
  Object.defineProperty(exports, "registerExtensions", {
3651
3956
  enumerable: true,
3652
- get: function () { return chunkLGYYJ2GP_cjs.registerExtensions; }
3957
+ get: function () { return chunkSZDU2D3D_cjs.registerExtensions; }
3653
3958
  });
3654
3959
  Object.defineProperty(exports, "rsiTv", {
3655
3960
  enumerable: true,
3656
- get: function () { return chunkLGYYJ2GP_cjs.rsiTv_default; }
3961
+ get: function () { return chunkSZDU2D3D_cjs.rsiTv_default; }
3657
3962
  });
3658
3963
  Object.defineProperty(exports, "shortPosition", {
3659
3964
  enumerable: true,
3660
- get: function () { return chunkLGYYJ2GP_cjs.shortPosition_default; }
3965
+ get: function () { return chunkSZDU2D3D_cjs.shortPosition_default; }
3661
3966
  });
3662
3967
  Object.defineProperty(exports, "stochastic", {
3663
3968
  enumerable: true,
3664
- get: function () { return chunkLGYYJ2GP_cjs.stochastic_default; }
3969
+ get: function () { return chunkSZDU2D3D_cjs.stochastic_default; }
3665
3970
  });
3666
3971
  Object.defineProperty(exports, "superTrend", {
3667
3972
  enumerable: true,
3668
- get: function () { return chunkLGYYJ2GP_cjs.superTrend_default; }
3973
+ get: function () { return chunkSZDU2D3D_cjs.superTrend_default; }
3669
3974
  });
3670
3975
  Object.defineProperty(exports, "threeWaves", {
3671
3976
  enumerable: true,
3672
- get: function () { return chunkLGYYJ2GP_cjs.threeWaves_default; }
3977
+ get: function () { return chunkSZDU2D3D_cjs.threeWaves_default; }
3673
3978
  });
3674
3979
  Object.defineProperty(exports, "triangle", {
3675
3980
  enumerable: true,
3676
- get: function () { return chunkLGYYJ2GP_cjs.triangle_default; }
3981
+ get: function () { return chunkSZDU2D3D_cjs.triangle_default; }
3677
3982
  });
3678
3983
  Object.defineProperty(exports, "vwap", {
3679
3984
  enumerable: true,
3680
- get: function () { return chunkLGYYJ2GP_cjs.vwap_default; }
3985
+ get: function () { return chunkSZDU2D3D_cjs.vwap_default; }
3681
3986
  });
3682
3987
  Object.defineProperty(exports, "xabcd", {
3683
3988
  enumerable: true,
3684
- get: function () { return chunkLGYYJ2GP_cjs.xabcd_default; }
3989
+ get: function () { return chunkSZDU2D3D_cjs.xabcd_default; }
3990
+ });
3991
+ Object.defineProperty(exports, "KlinechartsUIDispatchContext", {
3992
+ enumerable: true,
3993
+ get: function () { return chunkF24D6PWY_cjs.KlinechartsUIDispatchContext; }
3994
+ });
3995
+ Object.defineProperty(exports, "KlinechartsUIStateContext", {
3996
+ enumerable: true,
3997
+ get: function () { return chunkF24D6PWY_cjs.KlinechartsUIStateContext; }
3998
+ });
3999
+ Object.defineProperty(exports, "createDataLoader", {
4000
+ enumerable: true,
4001
+ get: function () { return chunkF24D6PWY_cjs.createDataLoader; }
4002
+ });
4003
+ Object.defineProperty(exports, "useKlinechartsUI", {
4004
+ enumerable: true,
4005
+ get: function () { return chunkF24D6PWY_cjs.useKlinechartsUI; }
3685
4006
  });
3686
4007
  exports.CANDLE_TYPES = CANDLE_TYPES;
3687
4008
  exports.COMPARE_RULES = COMPARE_RULES;
3688
4009
  exports.DEFAULT_PERIODS = DEFAULT_PERIODS;
4010
+ exports.DEFAULT_STORAGE_KEY_PREFIX = DEFAULT_STORAGE_KEY_PREFIX;
4011
+ exports.DEFAULT_STORAGE_NAMESPACES = DEFAULT_STORAGE_NAMESPACES;
4012
+ exports.DEFAULT_SYNC_CONFIG = DEFAULT_SYNC_CONFIG;
3689
4013
  exports.DRAWING_CATEGORIES = DRAWING_CATEGORIES;
3690
4014
  exports.INDICATOR_PARAMS = INDICATOR_PARAMS;
3691
- exports.KlinechartsUIDispatchContext = KlinechartsUIDispatchContext;
3692
4015
  exports.KlinechartsUIProvider = KlinechartsUIProvider;
3693
- exports.KlinechartsUIStateContext = KlinechartsUIStateContext;
3694
4016
  exports.MAIN_INDICATORS = MAIN_INDICATORS;
3695
4017
  exports.PRICE_AXIS_TYPES = PRICE_AXIS_TYPES;
3696
4018
  exports.SUB_INDICATORS = SUB_INDICATORS;
3697
4019
  exports.TIMEZONES = TIMEZONES;
3698
4020
  exports.TOOLTIP_SHOW_RULES = TOOLTIP_SHOW_RULES;
4021
+ exports.WorkspaceProvider = WorkspaceProvider;
3699
4022
  exports.YAXIS_POSITIONS = YAXIS_POSITIONS;
3700
- exports.createDataLoader = createDataLoader;
4023
+ exports.createDefaultStorage = createDefaultStorage;
4024
+ exports.drawingLabel = drawingLabel;
4025
+ exports.resolveStorage = resolveStorage;
3701
4026
  exports.useAlerts = useAlerts;
3702
4027
  exports.useAnnotations = useAnnotations;
3703
4028
  exports.useChartAxes = useChartAxes;
4029
+ exports.useChartSync = useChartSync;
3704
4030
  exports.useCompare = useCompare;
3705
4031
  exports.useCrosshair = useCrosshair;
3706
4032
  exports.useDataExport = useDataExport;
@@ -3708,7 +4034,6 @@ exports.useDrawingTools = useDrawingTools;
3708
4034
  exports.useFullscreen = useFullscreen;
3709
4035
  exports.useHotkeys = useHotkeys;
3710
4036
  exports.useIndicators = useIndicators;
3711
- exports.useKlinechartsUI = useKlinechartsUI;
3712
4037
  exports.useKlinechartsUILoading = useKlinechartsUILoading;
3713
4038
  exports.useKlinechartsUISettings = useKlinechartsUISettings;
3714
4039
  exports.useKlinechartsUITheme = useKlinechartsUITheme;
@@ -3723,5 +4048,6 @@ exports.useSymbolSearch = useSymbolSearch;
3723
4048
  exports.useTimezone = useTimezone;
3724
4049
  exports.useUndoRedo = useUndoRedo;
3725
4050
  exports.useWatchlist = useWatchlist;
4051
+ exports.useWorkspace = useWorkspace;
3726
4052
  //# sourceMappingURL=index.cjs.map
3727
4053
  //# sourceMappingURL=index.cjs.map