@363045841yyt/klinechart 0.5.0 → 0.5.1

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.js CHANGED
@@ -8891,6 +8891,14 @@ var Ls = class {
8891
8891
  hoveredSeparatorUpperPaneId = null;
8892
8892
  hoveredRightAxisPaneId = null;
8893
8893
  isTouchSession = !1;
8894
+ activePointers = /* @__PURE__ */ new Map();
8895
+ lastPinchDistance = 0;
8896
+ pinchCenter = {
8897
+ x: 0,
8898
+ y: 0
8899
+ };
8900
+ isPinching = !1;
8901
+ onPinchZoomCallback;
8894
8902
  crosshairPos = null;
8895
8903
  crosshairIndex = null;
8896
8904
  crosshairPrice = null;
@@ -8922,6 +8930,9 @@ var Ls = class {
8922
8930
  constructor(e) {
8923
8931
  this.chart = e;
8924
8932
  }
8933
+ setOnPinchZoom(e) {
8934
+ this.onPinchZoomCallback = e;
8935
+ }
8925
8936
  getInteractionSnapshot() {
8926
8937
  return {
8927
8938
  crosshairPos: this.crosshairPos ? { ...this.crosshairPos } : null,
@@ -8947,8 +8958,19 @@ var Ls = class {
8947
8958
  this.onInteractionChangeCallback?.(this.getInteractionSnapshot());
8948
8959
  }
8949
8960
  onPointerDown(e) {
8950
- if (e.isPrimary === !1) return;
8951
- this.isTouchSession = e.pointerType === "touch";
8961
+ if (this.isTouchSession = e.pointerType === "touch", this.activePointers.set(e.pointerId, {
8962
+ x: e.clientX,
8963
+ y: e.clientY
8964
+ }), this.activePointers.size === 2 && this.isTouchSession) {
8965
+ this.isPinching = !0, this.isDragging = !1, this.dragMode = "none";
8966
+ let e = Array.from(this.activePointers.values()), t = e[0], n = e[1];
8967
+ this.lastPinchDistance = Math.hypot(n.x - t.x, n.y - t.y), this.pinchCenter = {
8968
+ x: (t.x + n.x) / 2,
8969
+ y: (t.y + n.y) / 2
8970
+ };
8971
+ return;
8972
+ }
8973
+ if (e.isPrimary === !1 || this.isPinching || this.activePointers.size > 1) return;
8952
8974
  let t = this.getPlotPointerLocation(e.clientX, e.clientY);
8953
8975
  if (!t) return;
8954
8976
  let n = this.chart.getDom().container, { mouseX: r, mouseY: i } = t, a = n.scrollLeft, o = this.chart.getMarkerManager(), s = a + r, c = o.hitTest(s, i, 3);
@@ -8971,15 +8993,26 @@ var Ls = class {
8971
8993
  this.useTooltipAnchorPositioning = e;
8972
8994
  }
8973
8995
  onPointerUp(e) {
8974
- e.isPrimary !== !1 && (this.isDragging = !1, this.dragMode = "none", this.activePaneIdOnDrag = null, this.activeSeparatorUpperPaneId = null, this.notifyInteractionChange());
8996
+ this.activePointers.delete(e.pointerId), this.isPinching && this.activePointers.size < 2 && (this.isPinching = !1, this.lastPinchDistance = 0), e.isPrimary !== !1 && (this.isDragging = !1, this.dragMode = "none", this.activePaneIdOnDrag = null, this.activeSeparatorUpperPaneId = null, this.notifyInteractionChange());
8975
8997
  }
8976
8998
  onPointerLeave(e) {
8977
- e.isPrimary !== !1 && (this.isDragging = !1, this.dragMode = "none", this.activePaneIdOnDrag = null, this.clearSeparatorState(), this.isTouchSession = !1, this.clearHover(), this.chart.scheduleDraw(), this.notifyInteractionChange());
8999
+ this.activePointers.delete(e.pointerId), this.activePointers.size < 2 && (this.isPinching = !1, this.lastPinchDistance = 0), e.isPrimary !== !1 && (this.isDragging = !1, this.dragMode = "none", this.activePaneIdOnDrag = null, this.clearSeparatorState(), this.isTouchSession = !1, this.clearHover(), this.chart.scheduleDraw(), this.notifyInteractionChange());
8978
9000
  }
8979
9001
  onScroll() {
8980
9002
  this.kLinePositions = null, this.visibleRange = null, this.clearHover(), this.chart.scheduleDraw(), this.notifyInteractionChange();
8981
9003
  }
8982
9004
  onPointerMove(e) {
9005
+ if (this.activePointers.has(e.pointerId) && this.activePointers.set(e.pointerId, {
9006
+ x: e.clientX,
9007
+ y: e.clientY
9008
+ }), this.isPinching && this.activePointers.size === 2) {
9009
+ let e = Array.from(this.activePointers.values()), t = e[0], n = e[1], r = Math.hypot(n.x - t.x, n.y - t.y), i = r - this.lastPinchDistance;
9010
+ if (Math.abs(i) > 10) {
9011
+ let e = i > 0 ? 1 : -1, a = (t.x + n.x) / 2;
9012
+ this.onPinchZoomCallback?.(e, a), this.lastPinchDistance = r;
9013
+ }
9014
+ return;
9015
+ }
8983
9016
  if (!e.isPrimary) return;
8984
9017
  e.pointerType === "touch" && (this.isTouchSession = !0);
8985
9018
  let t = this.chart.getDom().container;
@@ -9172,7 +9205,7 @@ var Ls = class {
9172
9205
  };
9173
9206
  }
9174
9207
  reset() {
9175
- this.isDragging = !1, this.dragMode = "none", this.dragStartX = 0, this.dragStartY = 0, this.scrollStartX = 0, this.activePaneIdOnDrag = null, this.clearSeparatorState(), this.isTouchSession = !1, this.crosshairPos = null, this.crosshairIndex = null, this.crosshairPrice = null, this.hoveredIndex = null, this.activePaneId = null, this.hoveredMarkerId = null, this.clickedMarkerId = null, this.hoveredMarkerData = null, this.clickedMarkerData = null, this.hoveredCustomMarker = null, this.kLinePositions = null, this.visibleRange = null, this.kWidthPx = null;
9208
+ this.isDragging = !1, this.dragMode = "none", this.dragStartX = 0, this.dragStartY = 0, this.scrollStartX = 0, this.activePaneIdOnDrag = null, this.clearSeparatorState(), this.isTouchSession = !1, this.activePointers.clear(), this.isPinching = !1, this.lastPinchDistance = 0, this.crosshairPos = null, this.crosshairIndex = null, this.crosshairPrice = null, this.hoveredIndex = null, this.activePaneId = null, this.hoveredMarkerId = null, this.clickedMarkerId = null, this.hoveredMarkerData = null, this.clickedMarkerData = null, this.hoveredCustomMarker = null, this.kLinePositions = null, this.visibleRange = null, this.kWidthPx = null;
9176
9209
  }
9177
9210
  getCrosshairIndex() {
9178
9211
  return this.crosshairIndex;
@@ -13290,20 +13323,61 @@ var Tu = d({
13290
13323
  name: "tabler-minimize",
13291
13324
  render: wu
13292
13325
  }), Eu = {
13326
+ viewBox: "0 0 24 24",
13327
+ width: "1.2em",
13328
+ height: "1.2em"
13329
+ };
13330
+ function Du(e, t) {
13331
+ return _(), o("svg", Eu, [...t[0] ||= [s("path", {
13332
+ fill: "none",
13333
+ stroke: "currentColor",
13334
+ "stroke-linecap": "round",
13335
+ "stroke-linejoin": "round",
13336
+ "stroke-width": "2",
13337
+ d: "M3 10a7 7 0 1 0 14 0a7 7 0 1 0-14 0m4 0h6m-3-3v6m11 8l-6-6"
13338
+ }, null, -1)]]);
13339
+ }
13340
+ var Ou = d({
13341
+ name: "tabler-zoom-in",
13342
+ render: Du
13343
+ }), ku = {
13344
+ viewBox: "0 0 24 24",
13345
+ width: "1.2em",
13346
+ height: "1.2em"
13347
+ };
13348
+ function Au(e, t) {
13349
+ return _(), o("svg", ku, [...t[0] ||= [s("path", {
13350
+ fill: "none",
13351
+ stroke: "currentColor",
13352
+ "stroke-linecap": "round",
13353
+ "stroke-linejoin": "round",
13354
+ "stroke-width": "2",
13355
+ d: "M3 10a7 7 0 1 0 14 0a7 7 0 1 0-14 0m4 0h6m8 11l-6-6"
13356
+ }, null, -1)]]);
13357
+ }
13358
+ var ju = d({
13359
+ name: "tabler-zoom-out",
13360
+ render: Au
13361
+ }), Mu = {
13293
13362
  class: "left-toolbar",
13294
13363
  "aria-label": "图表工具栏"
13295
- }, Du = { class: "left-toolbar__group" }, Ou = [
13364
+ }, Nu = { class: "left-toolbar__group" }, Pu = [
13296
13365
  "title",
13297
13366
  "aria-label",
13298
13367
  "onClick"
13299
- ], ku = ["onClick"], Au = [
13368
+ ], Fu = ["onClick"], Iu = [
13300
13369
  "title",
13301
13370
  "aria-label",
13302
13371
  "onClick"
13303
- ], ju = { class: "left-toolbar__group" }, Mu = ["title", "aria-label"], Nu = /* @__PURE__ */ Oo(/* @__PURE__ */ u({
13372
+ ], Lu = { class: "left-toolbar__group" }, Ru = { class: "left-toolbar__group" }, zu = ["title", "aria-label"], Bu = /* @__PURE__ */ Oo(/* @__PURE__ */ u({
13304
13373
  __name: "LeftToolbar",
13305
13374
  props: { isFullscreen: { type: Boolean } },
13306
- emits: ["selectTool", "toggleFullscreen"],
13375
+ emits: [
13376
+ "selectTool",
13377
+ "toggleFullscreen",
13378
+ "zoomIn",
13379
+ "zoomOut"
13380
+ ],
13307
13381
  setup(t, { emit: r }) {
13308
13382
  let c = r, u = [{
13309
13383
  id: "cursor",
@@ -13378,8 +13452,8 @@ var Tu = d({
13378
13452
  document.addEventListener("click", T, !0);
13379
13453
  }), g(() => {
13380
13454
  document.removeEventListener("click", T, !0);
13381
- }), (r, c) => (_(), o("nav", Eu, [
13382
- s("div", Du, [(_(), o(e, null, b(u, (t) => s("div", {
13455
+ }), (r, c) => (_(), o("nav", Mu, [
13456
+ s("div", Nu, [(_(), o(e, null, b(u, (t) => s("div", {
13383
13457
  key: t.id,
13384
13458
  class: "tool-item"
13385
13459
  }, [s("button", {
@@ -13399,7 +13473,7 @@ var Tu = d({
13399
13473
  class: p(["corner-indicator", { open: f.value === t.id }]),
13400
13474
  onClick: D((e) => C(t.id), ["stop"]),
13401
13475
  "aria-label": "展开子菜单"
13402
- }, null, 10, ku)) : a("", !0)], 42, Ou), l(n, { name: "dropdown" }, {
13476
+ }, null, 10, Fu)) : a("", !0)], 42, Pu), l(n, { name: "dropdown" }, {
13403
13477
  default: E(() => [f.value === t.id && t.children && t.children.length ? (_(), o("div", {
13404
13478
  key: 0,
13405
13479
  class: "tool-dropdown",
@@ -13416,19 +13490,45 @@ var Tu = d({
13416
13490
  }, [(_(), i(x(e.icon), {
13417
13491
  class: "tool-icon",
13418
13492
  "aria-hidden": "true"
13419
- }))], 10, Au))), 128))], 32)) : a("", !0)]),
13493
+ }))], 10, Iu))), 128))], 32)) : a("", !0)]),
13420
13494
  _: 2
13421
13495
  }, 1024)])), 64))]),
13422
- c[10] ||= s("span", { class: "left-toolbar__divider" }, null, -1),
13423
- s("div", ju, [s("button", {
13496
+ c[18] ||= s("span", { class: "left-toolbar__divider" }, null, -1),
13497
+ s("div", Lu, [s("button", {
13424
13498
  type: "button",
13425
13499
  class: "left-toolbar__button",
13426
- title: t.isFullscreen ? "退出全屏" : "全屏显示",
13427
- "aria-label": t.isFullscreen ? "退出全屏" : "全屏显示",
13428
- onClick: c[6] ||= (e) => r.$emit("toggleFullscreen"),
13500
+ title: "放大",
13501
+ "aria-label": "放大",
13502
+ onClick: c[6] ||= (e) => r.$emit("zoomIn"),
13429
13503
  onPointerdown: c[7] ||= D(() => {}, ["stop"]),
13430
13504
  onPointermove: c[8] ||= D(() => {}, ["stop"]),
13431
13505
  onPointerup: c[9] ||= D(() => {}, ["stop"])
13506
+ }, [l(w(Ou), {
13507
+ class: "tool-icon",
13508
+ "aria-hidden": "true"
13509
+ })], 32), s("button", {
13510
+ type: "button",
13511
+ class: "left-toolbar__button",
13512
+ title: "缩小",
13513
+ "aria-label": "缩小",
13514
+ onClick: c[10] ||= (e) => r.$emit("zoomOut"),
13515
+ onPointerdown: c[11] ||= D(() => {}, ["stop"]),
13516
+ onPointermove: c[12] ||= D(() => {}, ["stop"]),
13517
+ onPointerup: c[13] ||= D(() => {}, ["stop"])
13518
+ }, [l(w(ju), {
13519
+ class: "tool-icon",
13520
+ "aria-hidden": "true"
13521
+ })], 32)]),
13522
+ c[19] ||= s("span", { class: "left-toolbar__divider" }, null, -1),
13523
+ s("div", Ru, [s("button", {
13524
+ type: "button",
13525
+ class: "left-toolbar__button",
13526
+ title: t.isFullscreen ? "退出全屏" : "全屏显示",
13527
+ "aria-label": t.isFullscreen ? "退出全屏" : "全屏显示",
13528
+ onClick: c[14] ||= (e) => r.$emit("toggleFullscreen"),
13529
+ onPointerdown: c[15] ||= D(() => {}, ["stop"]),
13530
+ onPointermove: c[16] ||= D(() => {}, ["stop"]),
13531
+ onPointerup: c[17] ||= D(() => {}, ["stop"])
13432
13532
  }, [t.isFullscreen ? (_(), i(w(Tu), {
13433
13533
  key: 0,
13434
13534
  class: "tool-icon",
@@ -13437,13 +13537,13 @@ var Tu = d({
13437
13537
  key: 1,
13438
13538
  class: "tool-icon",
13439
13539
  "aria-hidden": "true"
13440
- }))], 40, Mu)])
13540
+ }))], 40, zu)])
13441
13541
  ]));
13442
13542
  }
13443
- }), [["__scopeId", "data-v-42a7d005"]]), Pu = { class: "chart-wrapper" }, Fu = { class: "chart-main" }, Iu = {
13543
+ }), [["__scopeId", "data-v-b530debe"]]), Vu = { class: "chart-wrapper" }, Hu = { class: "chart-main" }, Uu = {
13444
13544
  class: "pane-separator-layer",
13445
13545
  "aria-hidden": "true"
13446
- }, Lu = 4, Ru = /* @__PURE__ */ Oo(/* @__PURE__ */ u({
13546
+ }, Wu = 4, Gu = /* @__PURE__ */ Oo(/* @__PURE__ */ u({
13447
13547
  __name: "KLineChart",
13448
13548
  props: {
13449
13549
  semanticConfig: {},
@@ -13675,7 +13775,7 @@ var Tu = d({
13675
13775
  return { ...Ne[e].defaultParams };
13676
13776
  }
13677
13777
  function Le(e = "VOLUME", t) {
13678
- if (U.value.length >= Lu) return !1;
13778
+ if (U.value.length >= Wu) return !1;
13679
13779
  let n = `sub_${e}`;
13680
13780
  if (U.value.some((e) => e.id === n)) return !0;
13681
13781
  if (!D.value?.createSubPane(e, t ?? Ie(e))) return !1;
@@ -14001,11 +14101,13 @@ var Tu = d({
14001
14101
  }), a.setOnPaneLayoutChange((e) => {
14002
14102
  let t = {};
14003
14103
  for (let n of e) t[n.id] = n.ratio;
14004
- k.actions.setPaneRatios(t), ae.value = a.getPaneRenderers().slice(0, -1).map((e) => {
14104
+ k.actions.setPaneRatios(t);
14105
+ let n = a.getPaneRenderers(), r = E.value && parseInt(getComputedStyle(E.value).borderTopWidth) || 0;
14106
+ ae.value = n.slice(0, -1).map((e) => {
14005
14107
  let t = e.getPane();
14006
14108
  return {
14007
14109
  id: t.id,
14008
- top: t.top + t.height
14110
+ top: t.top + t.height + r
14009
14111
  };
14010
14112
  });
14011
14113
  }), a.setOnDataChange((e) => {
@@ -14020,6 +14122,21 @@ var Tu = d({
14020
14122
  }
14021
14123
  }), a.interaction.setTooltipAnchorPositioning(L.value), a.interaction.setOnInteractionChange((e) => {
14022
14124
  R.value = e;
14125
+ }), a.interaction.setOnPinchZoom((e, t) => {
14126
+ let n = E.value;
14127
+ if (!n || !a) return;
14128
+ let r = t - n.getBoundingClientRect().left, i = n.scrollLeft, o = a.getCurrentDpr(), s = gl(e, r, i, A.value, j.value, M.value, {
14129
+ minKWidth: u.minKWidth,
14130
+ maxKWidth: u.maxKWidth,
14131
+ zoomLevelCount: u.zoomLevels,
14132
+ dpr: o
14133
+ });
14134
+ s && (k.actions.setZoomState(s.targetLevel, s.newKWidth, s.newKGap), a.interaction.clearHover(), f(() => {
14135
+ let e = E.value;
14136
+ if (!e) return;
14137
+ let t = Math.max(0, e.scrollWidth - e.clientWidth), n = Math.min(Math.max(0, s.newScrollLeft), t);
14138
+ e.scrollLeft = Math.round(n * o) / o, a.applyRenderState(s.newKWidth, s.newKGap, s.targetLevel), d("zoomLevelChange", s.targetLevel, s.newKWidth);
14139
+ }));
14023
14140
  }), R.value = a.interaction.getInteractionSnapshot(), k.actions.setViewportDpr(a.getCurrentDpr()), a.resize(), O.value = new $i(a), O.value.on("config:error", (e) => {
14024
14141
  console.error("Semantic config error:", e);
14025
14142
  }), O.value.on("config:ready", () => {
@@ -14041,18 +14158,20 @@ var Tu = d({
14041
14158
  let t = await O.value?.applyConfig(e);
14042
14159
  t && !t.success && console.error("Semantic config apply failed:", t.errors);
14043
14160
  }
14044
- }, { deep: !0 }), (n, r) => (_(), o("div", Pu, [s("div", { class: p(["chart-stage", {
14161
+ }, { deep: !0 }), (n, r) => (_(), o("div", Vu, [s("div", { class: p(["chart-stage", {
14045
14162
  "is-dragging": ce.value,
14046
14163
  "is-resizing-pane": le.value,
14047
14164
  "is-hovering-pane-separator": ue.value,
14048
14165
  "is-hovering-right-axis": fe.value,
14049
14166
  "is-hovering-kline": pe.value !== null
14050
- }]) }, [l(Nu, {
14167
+ }]) }, [l(Bu, {
14051
14168
  "is-fullscreen": t.isFullscreen,
14052
14169
  onSelectTool: be,
14053
- onToggleFullscreen: r[0] ||= (e) => n.$emit("toggleFullscreen")
14054
- }, null, 8, ["is-fullscreen"]), s("div", Fu, [
14055
- s("div", Iu, [(_(!0), o(e, null, b(ae.value, (e) => (_(), o("div", {
14170
+ onToggleFullscreen: r[0] ||= (e) => n.$emit("toggleFullscreen"),
14171
+ onZoomIn: r[1] ||= (e) => Ze(A.value + 1),
14172
+ onZoomOut: r[2] ||= (e) => Ze(A.value - 1)
14173
+ }, null, 8, ["is-fullscreen"]), s("div", Hu, [
14174
+ s("div", Uu, [(_(!0), o(e, null, b(ae.value, (e) => (_(), o("div", {
14056
14175
  key: e.id,
14057
14176
  class: p(["pane-separator-line", { "is-active": de.value === e.id }]),
14058
14177
  style: m({ top: `${e.top}px` })
@@ -14150,8 +14269,8 @@ var Tu = d({
14150
14269
  onReorderSubIndicators: qe
14151
14270
  }, null, 8, ["active-indicators", "indicator-params"])]));
14152
14271
  }
14153
- }), [["__scopeId", "data-v-eede0b8f"]]), zu = { install(e) {
14154
- e.component("KLineChart", Ru);
14272
+ }), [["__scopeId", "data-v-3f35943c"]]), Ku = { install(e) {
14273
+ e.component("KLineChart", Gu);
14155
14274
  } };
14156
14275
  //#endregion
14157
- export { ya as ConfigManager, I as EventBus, ga as GLOBAL_PANE_ID, va as HookSystem, Ru as KLineChart, zu as KMapPlugin, xa as PluginHostImpl, _a as PluginRegistry, ma as PluginState, X as RENDERER_PRIORITY, wa as RendererPluginManager, Sa as createPluginHost, ha as wrapPaneInfo };
14276
+ export { ya as ConfigManager, I as EventBus, ga as GLOBAL_PANE_ID, va as HookSystem, Gu as KLineChart, Ku as KMapPlugin, xa as PluginHostImpl, _a as PluginRegistry, ma as PluginState, X as RENDERER_PRIORITY, wa as RendererPluginManager, Sa as createPluginHost, ha as wrapPaneInfo };
@@ -1,2 +1,2 @@
1
- .kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-c14eedcc]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-c14eedcc]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-c14eedcc]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-c14eedcc]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-c14eedcc]{align-items:center;gap:8px;display:flex}.params-title[data-v-c14eedcc]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-c14eedcc]{color:#999;font-size:11px}.toggle-desc-btn[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-c14eedcc]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-c14eedcc]{width:14px;height:14px}.params-close[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-c14eedcc]{width:14px;height:14px}.indicator-description[data-v-c14eedcc]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-c14eedcc]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-c14eedcc]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-c14eedcc]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-c14eedcc]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-c14eedcc]{padding:10px 14px 8px}.param-header[data-v-c14eedcc]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-c14eedcc]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-c14eedcc]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-c14eedcc]{color:#999;font-size:11px}.param-description[data-v-c14eedcc]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-c14eedcc]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-c14eedcc]:focus-within{border-color:#999}.stepper-btn[data-v-c14eedcc]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-c14eedcc]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-c14eedcc]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-c14eedcc]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-c14eedcc]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]:focus{outline:none}.params-footer[data-v-c14eedcc]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-c14eedcc]{gap:8px;display:flex}.params-btn[data-v-c14eedcc]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-c14eedcc]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-c14eedcc]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-c14eedcc]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-c14eedcc]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-c14eedcc],.overlay-leave-active[data-v-c14eedcc]{transition:opacity .2s}.overlay-enter-from[data-v-c14eedcc],.overlay-leave-to[data-v-c14eedcc]{opacity:0}.modal-enter-active[data-v-c14eedcc]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-c14eedcc]{transition:all .16s ease-in}.modal-enter-from[data-v-c14eedcc]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-c14eedcc]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-c14eedcc],.slide-leave-active[data-v-c14eedcc]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-c14eedcc],.slide-leave-to[data-v-c14eedcc]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-4b90c954]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-4b90c954]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-4b90c954]::-webkit-scrollbar{display:none}.indicator-list[data-v-4b90c954]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-4b90c954]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-4b90c954]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-4b90c954],.indicator-item.draggable .indicator-btn[data-v-4b90c954],.indicator-item.draggable[data-v-4b90c954]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-4b90c954]{cursor:move}.indicator-item.is-dragging[data-v-4b90c954]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-4b90c954]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-4b90c954]{position:relative}.indicator-btn[data-v-4b90c954]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-4b90c954]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-4b90c954]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-4b90c954]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-4b90c954]{z-index:1;position:relative}.param-hint[data-v-4b90c954]{opacity:.85;font-size:11px}.hover-overlay[data-v-4b90c954]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-4b90c954]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-4b90c954]:hover{color:#333;background:#0000000f}.settings-btn[data-v-4b90c954]:hover{color:#1a1a1a}.remove-btn[data-v-4b90c954]:hover{color:#ff4d4f}.divider[data-v-4b90c954]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-4b90c954]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-4b90c954]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-4b90c954]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-4b90c954]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-4b90c954]{padding:4px 0}.menu-section[data-v-4b90c954]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-4b90c954]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-4b90c954]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-4b90c954]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-4b90c954]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-4b90c954]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-4b90c954]{color:#999;font-size:11px}.active-tag[data-v-4b90c954]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-4b90c954],.fade-leave-active[data-v-4b90c954]{transition:opacity .2s}.fade-enter-from[data-v-4b90c954],.fade-leave-to[data-v-4b90c954]{opacity:0}.slide-enter-active[data-v-4b90c954],.slide-leave-active[data-v-4b90c954]{transition:all .2s}.slide-enter-from[data-v-4b90c954],.slide-leave-to[data-v-4b90c954]{opacity:0;transform:translate(-50%)translateY(8px)}.drawing-style-toolbar[data-v-088ccef5]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-088ccef5]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-088ccef5]{width:24px;height:24px;position:relative}.color-swatch[data-v-088ccef5]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-088ccef5]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-088ccef5]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-088ccef5]:hover{border-color:#9ca3af}.toolbar-btn[data-v-088ccef5]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-088ccef5]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-088ccef5]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-088ccef5]{width:14px;height:14px}.left-toolbar[data-v-42a7d005]{box-sizing:border-box;-webkit-user-select:none;user-select:none;background:#fafbfc;border:1px solid #e5e7eb;border-radius:6px;flex-direction:column;flex:0 0 40px;align-items:center;gap:6px;padding:8px 5px;display:flex;box-shadow:0 1px 3px #0000000f}.left-toolbar__group[data-v-42a7d005]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-42a7d005]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-42a7d005]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex;position:relative}.left-toolbar__button[data-v-42a7d005]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-42a7d005]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-42a7d005]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-42a7d005]{width:16px;height:16px}.corner-indicator[data-v-42a7d005]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-42a7d005]:after{content:"";opacity:.45;border-bottom:5px solid;border-left:5px solid #0000;width:0;height:0;transition:opacity .15s;position:absolute;bottom:0;right:0}.left-toolbar__button:hover .corner-indicator[data-v-42a7d005]:after,.left-toolbar__button.active .corner-indicator[data-v-42a7d005]:after{opacity:.7}.corner-indicator.open[data-v-42a7d005]:after{opacity:.8}.tool-dropdown[data-v-42a7d005]{-webkit-backdrop-filter:blur(8px);box-sizing:border-box;z-index:100;background:#fafbfcd1;border:1px solid #e5e7eb;border-radius:6px;flex-direction:row;align-items:center;gap:4px;height:40px;padding:0 5px;display:flex;position:absolute;top:50%;left:calc(100% + 13px);transform:translateY(-50%);box-shadow:0 1px 3px #0000000f}.tool-item[data-v-42a7d005]{position:relative}.dropdown-enter-active[data-v-42a7d005],.dropdown-leave-active[data-v-42a7d005]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-42a7d005],.dropdown-leave-to[data-v-42a7d005]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-42a7d005]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-42a7d005]{gap:3px}.left-toolbar__button[data-v-42a7d005]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-42a7d005]{width:16px}.corner-indicator[data-v-42a7d005]{width:7px;height:7px}.corner-indicator[data-v-42a7d005]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-42a7d005]{height:36px}}.chart-wrapper[data-v-eede0b8f]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-stage[data-v-eede0b8f]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-eede0b8f]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-eede0b8f]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-eede0b8f]{opacity:1;background:#e5e7eb;height:1px;transition:background-color .12s,box-shadow .12s,opacity .12s;position:absolute;left:1px;right:1px;transform:translateY(-.5px)}.pane-separator-line.is-active[data-v-eede0b8f]{background:#3b82f6;box-shadow:0 0 0 .5px #3b82f6e6,0 0 6px #3b82f673,0 0 12px #3b82f640}.chart-stage.is-resizing-pane[data-v-eede0b8f],.chart-stage.is-hovering-pane-separator[data-v-eede0b8f]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-eede0b8f]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-eede0b8f]{cursor:ns-resize}.chart-stage.is-dragging[data-v-eede0b8f]{cursor:grabbing}.chart-container[data-v-eede0b8f]{height:100%;min-height:inherit;scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-eede0b8f]::-webkit-scrollbar{display:none}.chart-container[data-v-eede0b8f]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-eede0b8f],.chart-stage.is-hovering-pane-separator .chart-container[data-v-eede0b8f]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-eede0b8f]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-eede0b8f]{cursor:grabbing}.right-axis-host[data-v-eede0b8f]{height:100%;min-height:inherit;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.right-axis-host[data-v-eede0b8f]:after{content:"";pointer-events:none;box-sizing:border-box;border:1px solid #e5e7eb;border-top-right-radius:6px;border-bottom-right-radius:6px;position:absolute;inset:0}.scroll-content[data-v-eede0b8f]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-eede0b8f]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-anchor[data-v-eede0b8f]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-eede0b8f]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-eede0b8f]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-eede0b8f]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:999}
1
+ .kline-tooltip[data-v-d0fe85e6]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:200px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.kline-tooltip__title[data-v-d0fe85e6]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-d0fe85e6]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-d0fe85e6]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-d0fe85e6]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.kline-tooltip.use-anchor[data-v-d0fe85e6]{position-anchor:--kline-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.kline-tooltip.use-anchor.anchor-right-bottom[data-v-d0fe85e6]{transform:translate(14px,14px)}.kline-tooltip.use-anchor.anchor-left-bottom[data-v-d0fe85e6]{transform:translate(calc(-100% - 14px),14px)}}.marker-tooltip[data-v-5574cc25]{z-index:10;color:#000000c7;pointer-events:none;-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);background:#ffffffeb;border:1px solid #0000001f;border-radius:8px;min-width:180px;max-width:260px;padding:10px 12px;font-size:12px;line-height:1.4;position:absolute;box-shadow:0 6px 18px #0000001f}.marker-tooltip__title[data-v-5574cc25]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-5574cc25]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-5574cc25]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-5574cc25]:first-child{color:#0000008f}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.marker-tooltip.use-anchor[data-v-5574cc25]{position-anchor:--marker-tooltip-anchor;left:anchor(left);top:anchor(top);position:absolute}.marker-tooltip.use-anchor.anchor-right-bottom[data-v-5574cc25]{transform:translate(12px,12px)}.marker-tooltip.use-anchor.anchor-left-bottom[data-v-5574cc25]{transform:translate(calc(-100% - 12px),12px)}}.params-overlay[data-v-c14eedcc]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:1000;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.indicator-params[data-v-c14eedcc]{background:#fff;border:1px solid #e0e0e0;border-radius:12px;width:90vw;min-width:340px;max-width:420px;overflow:hidden;box-shadow:0 8px 40px #00000026}.params-header[data-v-c14eedcc]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-c14eedcc]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-c14eedcc]{align-items:center;gap:8px;display:flex}.params-title[data-v-c14eedcc]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-c14eedcc]{color:#999;font-size:11px}.toggle-desc-btn[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:all .2s;display:flex}.toggle-desc-btn[data-v-c14eedcc]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-c14eedcc]{width:14px;height:14px}.params-close[data-v-c14eedcc]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-c14eedcc]{width:14px;height:14px}.indicator-description[data-v-c14eedcc]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-c14eedcc]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-c14eedcc]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-c14eedcc]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-c14eedcc]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-c14eedcc]{padding:10px 14px 8px}.param-header[data-v-c14eedcc]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-c14eedcc]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-c14eedcc]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-c14eedcc]{color:#999;font-size:11px}.param-description[data-v-c14eedcc]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-c14eedcc]{background:#fff;border:1px solid #d0d0d0;border-radius:7px;align-items:stretch;height:32px;transition:border-color .2s;display:flex;overflow:hidden}.input-wrapper[data-v-c14eedcc]:focus-within{border-color:#999}.stepper-btn[data-v-c14eedcc]{cursor:pointer;color:#666;background:#f0f0f0;border:none;flex-shrink:0;justify-content:center;align-items:center;width:28px;font-size:15px;font-weight:400;line-height:1;transition:background .15s,color .15s;display:flex}.stepper-btn[data-v-c14eedcc]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-c14eedcc]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-c14eedcc]{text-align:center;color:#1a1a1a;appearance:textfield;background:0 0;border:none;border-left:1px solid #e8e8e8;border-right:1px solid #e8e8e8;width:60px;font-size:13px;font-weight:600}.param-input[data-v-c14eedcc]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-c14eedcc]:focus{outline:none}.params-footer[data-v-c14eedcc]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-c14eedcc]{gap:8px;display:flex}.params-btn[data-v-c14eedcc]{cursor:pointer;border:1px solid #0000;border-radius:7px;align-items:center;gap:5px;padding:6px 14px;font-size:13px;font-weight:500;line-height:1.4;transition:all .15s;display:flex}.params-btn svg[data-v-c14eedcc]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-c14eedcc]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-c14eedcc]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-c14eedcc]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-c14eedcc]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-c14eedcc]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-c14eedcc]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-c14eedcc],.overlay-leave-active[data-v-c14eedcc]{transition:opacity .2s}.overlay-enter-from[data-v-c14eedcc],.overlay-leave-to[data-v-c14eedcc]{opacity:0}.modal-enter-active[data-v-c14eedcc]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-c14eedcc]{transition:all .16s ease-in}.modal-enter-from[data-v-c14eedcc]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-c14eedcc]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-c14eedcc],.slide-leave-active[data-v-c14eedcc]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-c14eedcc],.slide-leave-to[data-v-c14eedcc]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-4b90c954]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-4b90c954]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-4b90c954]::-webkit-scrollbar{display:none}.indicator-list[data-v-4b90c954]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-divider[data-v-4b90c954]{background:#d9d9d9;align-self:center;width:1px;height:20px}.indicator-item[data-v-4b90c954]{align-items:center;gap:4px;display:flex}.indicator-item.draggable[data-v-4b90c954],.indicator-item.draggable .indicator-btn[data-v-4b90c954],.indicator-item.draggable[data-v-4b90c954]:hover,.indicator-item.draggable:hover .indicator-btn[data-v-4b90c954]{cursor:move}.indicator-item.is-dragging[data-v-4b90c954]{opacity:.6}.indicator-item.drag-over .indicator-btn[data-v-4b90c954]{border-color:#1a1a1a;box-shadow:0 0 0 2px #1a1a1a1f}.indicator-btn-wrapper[data-v-4b90c954]{position:relative}.indicator-btn[data-v-4b90c954]{color:#666;cursor:pointer;white-space:nowrap;background:#fff;border:1px solid #e0e0e0;border-radius:16px;flex-shrink:0;justify-content:center;align-items:center;gap:4px;padding:6px 16px;font-size:13px;font-weight:500;transition:all .3s;display:flex;position:relative;overflow:hidden}.indicator-btn[data-v-4b90c954]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-4b90c954]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-4b90c954]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-4b90c954]{z-index:1;position:relative}.param-hint[data-v-4b90c954]{opacity:.85;font-size:11px}.hover-overlay[data-v-4b90c954]{-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:2;background:#ffffffd9;border-radius:16px;justify-content:center;align-items:center;gap:4px;display:flex;position:absolute;inset:0}.action-btn[data-v-4b90c954]{color:#666;cursor:pointer;background:0 0;border:none;border-radius:50%;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:all .2s;display:flex}.action-btn[data-v-4b90c954]:hover{color:#333;background:#0000000f}.settings-btn[data-v-4b90c954]:hover{color:#1a1a1a}.remove-btn[data-v-4b90c954]:hover{color:#ff4d4f}.divider[data-v-4b90c954]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-4b90c954]{anchor-name:--indicator-add-btn;color:#999;cursor:pointer;background:0 0;border:1px dashed #d9d9d9;border-radius:50%;flex-shrink:0;justify-content:center;align-items:center;width:32px;height:32px;padding:0;transition:all .3s;display:flex}.add-btn[data-v-4b90c954]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-4b90c954]{white-space:nowrap;z-index:9999;background:#fff;border-radius:8px;padding:8px 0;position:fixed;transform:translate(-50%);box-shadow:0 6px 16px #00000014,0 3px 6px -4px #0000001f,0 9px 28px 8px #0000000d}@supports (anchor-name:--kmap-anchor) and (position-anchor:--kmap-anchor){.add-menu.use-anchor[data-v-4b90c954]{position-anchor:--indicator-add-btn;left:anchor(center);top:anchor(top);max-width:calc(100vw - 16px);position:fixed;transform:translate(-50%,calc(-100% - 8px))}}.menu-section[data-v-4b90c954]{padding:4px 0}.menu-section[data-v-4b90c954]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-4b90c954]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-4b90c954]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-4b90c954]{text-align:left;color:#333;cursor:pointer;background:0 0;border:none;align-items:center;gap:8px;width:100%;padding:8px 16px;font-size:13px;transition:background .2s;display:flex}.menu-item[data-v-4b90c954]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-4b90c954]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-4b90c954]{color:#999;font-size:11px}.active-tag[data-v-4b90c954]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-4b90c954],.fade-leave-active[data-v-4b90c954]{transition:opacity .2s}.fade-enter-from[data-v-4b90c954],.fade-leave-to[data-v-4b90c954]{opacity:0}.slide-enter-active[data-v-4b90c954],.slide-leave-active[data-v-4b90c954]{transition:all .2s}.slide-enter-from[data-v-4b90c954],.slide-leave-to[data-v-4b90c954]{opacity:0;transform:translate(-50%)translateY(8px)}.drawing-style-toolbar[data-v-088ccef5]{-webkit-backdrop-filter:blur(8px);z-index:100;-webkit-user-select:none;user-select:none;pointer-events:auto;background:#fafbfce0;border:1px solid #e5e7eb;border-radius:6px;align-items:center;gap:6px;height:32px;padding:4px 8px;display:flex;position:absolute;top:8px;left:50%;transform:translate(-50%);box-shadow:0 1px 3px #0000000f}.toolbar-item[data-v-088ccef5]{justify-content:center;align-items:center;display:inline-flex}.color-item[data-v-088ccef5]{width:24px;height:24px;position:relative}.color-swatch[data-v-088ccef5]{cursor:pointer;border:1px solid #d1d5db;border-radius:4px;width:100%;height:100%;display:block}.color-input[data-v-088ccef5]{opacity:0;cursor:pointer;width:100%;height:100%;position:absolute;inset:0}.toolbar-select[data-v-088ccef5]{color:#374151;cursor:pointer;background:#fff;border:1px solid #d1d5db;border-radius:4px;outline:none;height:24px;padding:0 4px;font-size:12px}.toolbar-select[data-v-088ccef5]:hover{border-color:#9ca3af}.toolbar-btn[data-v-088ccef5]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:24px;height:24px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex}.toolbar-btn[data-v-088ccef5]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.delete-btn[data-v-088ccef5]:hover{color:#dc2626;background:#fef2f2;border-color:#fca5a5}.delete-icon[data-v-088ccef5]{width:14px;height:14px}.left-toolbar[data-v-b530debe]{box-sizing:border-box;-webkit-user-select:none;user-select:none;background:#fafbfc;border:1px solid #e5e7eb;border-radius:6px;flex-direction:column;flex:0 0 40px;align-items:center;gap:6px;padding:8px 5px;display:flex;box-shadow:0 1px 3px #0000000f}.left-toolbar__group[data-v-b530debe]{flex-direction:column;gap:4px;display:flex}.left-toolbar__divider[data-v-b530debe]{background:#e5e7eb;width:18px;height:1px}.left-toolbar__button[data-v-b530debe]{color:#6b7280;cursor:pointer;background:0 0;border:1px solid #0000;border-radius:4px;justify-content:center;align-items:center;width:28px;height:28px;padding:0;transition:border-color .15s,background .15s,color .15s;display:inline-flex;position:relative}.left-toolbar__button[data-v-b530debe]:hover{color:#374151;background:#f3f4f6;border-color:#d1d5db}.left-toolbar__button.active[data-v-b530debe]{color:#1f2937;background:#e5e7eb;border-color:#9ca3af}.left-toolbar__button[data-v-b530debe]:focus-visible{border-color:#6b7280;outline:none}.tool-icon[data-v-b530debe]{width:16px;height:16px}.corner-indicator[data-v-b530debe]{cursor:pointer;width:8px;height:8px;position:absolute;bottom:0;right:0;overflow:hidden}.corner-indicator[data-v-b530debe]:after{content:"";opacity:.45;border-bottom:5px solid;border-left:5px solid #0000;width:0;height:0;transition:opacity .15s;position:absolute;bottom:0;right:0}.left-toolbar__button:hover .corner-indicator[data-v-b530debe]:after,.left-toolbar__button.active .corner-indicator[data-v-b530debe]:after{opacity:.7}.corner-indicator.open[data-v-b530debe]:after{opacity:.8}.tool-dropdown[data-v-b530debe]{-webkit-backdrop-filter:blur(8px);box-sizing:border-box;z-index:100;background:#fafbfcd1;border:1px solid #e5e7eb;border-radius:6px;flex-direction:row;align-items:center;gap:4px;height:40px;padding:0 5px;display:flex;position:absolute;top:50%;left:calc(100% + 13px);transform:translateY(-50%);box-shadow:0 1px 3px #0000000f}.tool-item[data-v-b530debe]{position:relative}.dropdown-enter-active[data-v-b530debe],.dropdown-leave-active[data-v-b530debe]{transition:opacity .15s,transform .15s}.dropdown-enter-from[data-v-b530debe],.dropdown-leave-to[data-v-b530debe]{opacity:0;transform:translateY(-50%)translate(-6px)}@media (width<=768px),(height<=640px){.left-toolbar[data-v-b530debe]{border-radius:5px;flex-basis:36px;gap:5px;padding:6px 4px}.left-toolbar__group[data-v-b530debe]{gap:3px}.left-toolbar__button[data-v-b530debe]{border-radius:3px;width:26px;height:26px}.left-toolbar__divider[data-v-b530debe]{width:16px}.corner-indicator[data-v-b530debe]{width:7px;height:7px}.corner-indicator[data-v-b530debe]:after{border-bottom-width:4px;border-left-width:4px}.tool-dropdown[data-v-b530debe]{height:36px}}.chart-wrapper[data-v-3f35943c]{--kmap-height:var(--kmap-chart-height,100%);--kmap-width:var(--kmap-chart-width,100%);width:var(--kmap-width);height:var(--kmap-height);flex-direction:column;justify-content:center;align-items:center;min-height:300px;display:flex}.chart-stage[data-v-3f35943c]{align-items:stretch;gap:8px;width:95%;height:85%;min-height:255px;display:flex}.chart-main[data-v-3f35943c]{flex:auto;align-items:stretch;gap:0;min-width:0;height:100%;display:flex;position:relative}.pane-separator-layer[data-v-3f35943c]{pointer-events:none;z-index:20;position:absolute;inset:0}.pane-separator-line[data-v-3f35943c]{opacity:1;background:#fff;height:3px;transition:background-color .12s,box-shadow .12s,opacity .12s;position:absolute;left:1px;right:1px;transform:translateY(-50%);box-shadow:inset 0 1px #e5e7eb}.pane-separator-line.is-active[data-v-3f35943c]{height:2px;box-shadow:none;background:#3b82f6;transform:translateY(-50%)}.chart-stage.is-resizing-pane[data-v-3f35943c],.chart-stage.is-hovering-pane-separator[data-v-3f35943c]{cursor:ns-resize}.chart-stage.is-hovering-kline[data-v-3f35943c]{cursor:pointer}.chart-stage.is-hovering-right-axis[data-v-3f35943c]{cursor:ns-resize}.chart-stage.is-dragging[data-v-3f35943c]{cursor:grabbing}.chart-container[data-v-3f35943c]{height:100%;min-height:inherit;scrollbar-width:none;-ms-overflow-style:none;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border:1px solid #e5e7eb;border-right:0;border-radius:6px 0 0 6px;flex:auto;position:relative;overflow:auto hidden}.chart-container[data-v-3f35943c]::-webkit-scrollbar{display:none}.chart-container[data-v-3f35943c]:hover{cursor:crosshair}.chart-stage.is-resizing-pane .chart-container[data-v-3f35943c],.chart-stage.is-hovering-pane-separator .chart-container[data-v-3f35943c]{cursor:ns-resize}.chart-stage.is-hovering-kline .chart-container[data-v-3f35943c]{cursor:pointer}.chart-stage.is-dragging .chart-container[data-v-3f35943c]{cursor:grabbing}.right-axis-host[data-v-3f35943c]{height:100%;min-height:inherit;box-sizing:border-box;-webkit-touch-callout:none;-webkit-user-select:none;user-select:none;touch-action:none;background:#fff;border-top-right-radius:6px;border-bottom-right-radius:6px;flex:none;position:relative;overflow:visible}.right-axis-host[data-v-3f35943c]:after{content:"";pointer-events:none;box-sizing:border-box;border:1px solid #e5e7eb;border-top-right-radius:6px;border-bottom-right-radius:6px;position:absolute;inset:0}.scroll-content[data-v-3f35943c]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-3f35943c]{pointer-events:none;position:sticky;top:0;left:0}.tooltip-anchor[data-v-3f35943c]{pointer-events:none;width:1px;height:1px;position:absolute}.tooltip-anchor.kline-tooltip-anchor.use-anchor[data-v-3f35943c]{anchor-name:--kline-tooltip-anchor}.tooltip-anchor.marker-tooltip-anchor.use-anchor[data-v-3f35943c]{anchor-name:--marker-tooltip-anchor}@media (width<=768px),(height<=640px){.chart-stage[data-v-3f35943c]{gap:6px}}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;left:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.right-axis{z-index:999}
2
2
  /*$vite$:1*/
@@ -10,8 +10,12 @@ type __VLS_Props = {
10
10
  declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {} & {
11
11
  selectTool: (toolId: string) => any;
12
12
  toggleFullscreen: () => any;
13
+ zoomIn: () => any;
14
+ zoomOut: () => any;
13
15
  }, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{
14
16
  onSelectTool?: ((toolId: string) => any) | undefined;
15
17
  onToggleFullscreen?: (() => any) | undefined;
18
+ onZoomIn?: (() => any) | undefined;
19
+ onZoomOut?: (() => any) | undefined;
16
20
  }>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLElement>;
17
21
  export default _default;
@@ -42,6 +42,13 @@ export declare class InteractionController {
42
42
  private hoveredRightAxisPaneId;
43
43
  /** [触屏]:触摸会话标记,避免触摸触发的模拟 mouse 事件干扰 */
44
44
  private isTouchSession;
45
+ /** [触屏]:多点触摸跟踪,用于双指捏合缩放 */
46
+ private activePointers;
47
+ private lastPinchDistance;
48
+ private pinchCenter;
49
+ private isPinching;
50
+ /** 捏合缩放回调 */
51
+ private onPinchZoomCallback?;
45
52
  /** 十字线位置 */
46
53
  crosshairPos: {
47
54
  x: number;
@@ -96,6 +103,8 @@ export declare class InteractionController {
96
103
  /** K 线宽度(物理像素),用于计算 K 线中心偏移 */
97
104
  private kWidthPx;
98
105
  constructor(chart: Chart);
106
+ /** 设置捏合缩放回调 */
107
+ setOnPinchZoom(callback: (delta: number, centerX: number) => void): void;
99
108
  getInteractionSnapshot(): InteractionSnapshot;
100
109
  setOnInteractionChange(callback: (snapshot: InteractionSnapshot) => void): void;
101
110
  private notifyInteractionChange;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@363045841yyt/klinechart",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "engines": {