@363045841yyt/klinechart 0.3.0 → 0.4.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/README.md +15 -0
- package/dist/index.cjs +9 -9
- package/dist/index.js +1250 -1095
- package/dist/klinechart.css +1 -1
- package/dist/src/core/chart.d.ts +14 -4
- package/dist/src/core/renderers/Indicator/macd.d.ts +12 -2
- package/dist/src/core/renderers/Indicator/scale/macd_scale.d.ts +8 -0
- package/dist/src/core/utils/tickCount.d.ts +3 -2
- package/dist/src/plugin/PluginHost.d.ts +7 -1
- package/dist/src/plugin/StateStore.d.ts +37 -0
- package/dist/src/plugin/stateKeys.d.ts +6 -0
- package/dist/src/plugin/types.d.ts +26 -0
- package/package.json +2 -1
package/dist/klinechart.css
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
.kline-tooltip[data-v-95daa55c]{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-95daa55c]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-95daa55c]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-95daa55c]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-95daa55c]:first-child{color:#0000008f}.marker-tooltip[data-v-dd43da4f]{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-dd43da4f]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-dd43da4f]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-dd43da4f]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-dd43da4f]:first-child{color:#0000008f}.params-overlay[data-v-730f2212]{-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-730f2212]{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-730f2212]{background:#f8f8f8;border-bottom:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:16px 20px;display:flex}.header-left[data-v-730f2212]{align-items:baseline;gap:8px;display:flex}.header-right[data-v-730f2212]{align-items:center;gap:8px;display:flex}.params-title[data-v-730f2212]{color:#1a1a1a;letter-spacing:.2px;font-size:14px;font-weight:600}.params-subtitle[data-v-730f2212]{color:#999;font-size:11px}.toggle-desc-btn[data-v-730f2212]{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-730f2212]:hover{color:#555;background:#f0f0f0;border-color:#ccc}.toggle-desc-btn.active[data-v-730f2212]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.toggle-desc-btn svg[data-v-730f2212]{width:14px;height:14px}.params-close[data-v-730f2212]{cursor:pointer;color:#888;background:#fff;border:1px solid #e0e0e0;border-radius:6px;justify-content:center;align-items:center;width:26px;height:26px;padding:0;transition:background .15s,color .15s,border-color .15s;display:flex}.params-close[data-v-730f2212]:hover{color:#333;background:#f0f0f0;border-color:#ccc}.params-close svg[data-v-730f2212]{width:13px;height:13px}.indicator-description[data-v-730f2212]{background:#f0f7ff;border-bottom:1px solid #d6e8f5;padding:12px 20px}.indicator-description p[data-v-730f2212]{color:#2c5282;margin:0;font-size:12px;line-height:1.6}.params-body[data-v-730f2212]{flex-direction:column;gap:10px;padding:16px 20px;display:flex}.param-item[data-v-730f2212]{background:#f8f8f8;border:1px solid #e8e8e8;border-radius:8px;padding:10px 14px;transition:border-color .2s}.param-item[data-v-730f2212]:has(.param-input:focus){border-color:#bbb}.param-item.has-desc[data-v-730f2212]{padding:10px 14px 8px}.param-header[data-v-730f2212]{justify-content:space-between;align-items:center;gap:16px;display:flex}.param-label[data-v-730f2212]{flex-direction:column;gap:3px;display:flex}.param-label-text[data-v-730f2212]{color:#333;font-size:13px;font-weight:500}.param-range[data-v-730f2212]{color:#999;font-size:11px}.param-description[data-v-730f2212]{color:#666;border-top:1px dashed #e0e0e0;margin-top:8px;padding-top:8px;font-size:11px;line-height:1.5}.input-wrapper[data-v-730f2212]{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-730f2212]:focus-within{border-color:#999}.stepper-btn[data-v-730f2212]{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-730f2212]:hover:not(:disabled){color:#333;background:#e0e0e0}.stepper-btn[data-v-730f2212]:disabled{color:#ccc;cursor:not-allowed}.param-input[data-v-730f2212]{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-730f2212]::-webkit-inner-spin-button{-webkit-appearance:none}.param-input[data-v-730f2212]::-webkit-outer-spin-button{-webkit-appearance:none}.param-input[data-v-730f2212]:focus{outline:none}.params-footer[data-v-730f2212]{background:#f8f8f8;border-top:1px solid #e8e8e8;justify-content:space-between;align-items:center;padding:12px 20px;display:flex}.footer-right[data-v-730f2212]{gap:8px;display:flex}.params-btn[data-v-730f2212]{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-730f2212]{flex-shrink:0;width:12px;height:12px}.params-btn.reset[data-v-730f2212]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.reset[data-v-730f2212]:hover{color:#e74c3c;background:#e74c3c14;border-color:#c0392b}.params-btn.cancel[data-v-730f2212]{color:#666;background:0 0;border-color:#d0d0d0}.params-btn.cancel[data-v-730f2212]:hover{color:#333;background:#f0f0f0;border-color:#bbb}.params-btn.confirm[data-v-730f2212]{color:#fff;background:#1a1a1a;border-color:#1a1a1a}.params-btn.confirm[data-v-730f2212]:hover{background:#333;border-color:#333;transform:translateY(-1px);box-shadow:0 2px 10px #00000026}.params-btn.confirm[data-v-730f2212]:active{box-shadow:none;transform:translateY(0)}.overlay-enter-active[data-v-730f2212],.overlay-leave-active[data-v-730f2212]{transition:opacity .2s}.overlay-enter-from[data-v-730f2212],.overlay-leave-to[data-v-730f2212]{opacity:0}.modal-enter-active[data-v-730f2212]{transition:all .22s cubic-bezier(.34,1.56,.64,1)}.modal-leave-active[data-v-730f2212]{transition:all .16s ease-in}.modal-enter-from[data-v-730f2212]{opacity:0;transform:scale(.88)translateY(-16px)}.modal-leave-to[data-v-730f2212]{opacity:0;transform:scale(.94)translateY(8px)}.slide-enter-active[data-v-730f2212],.slide-leave-active[data-v-730f2212]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-730f2212],.slide-leave-to[data-v-730f2212]{opacity:0;max-height:0;margin-top:0;padding-top:0;padding-bottom:0}.indicator-selector[data-v-aad3b750]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-aad3b750]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-aad3b750]::-webkit-scrollbar{display:none}.indicator-list[data-v-aad3b750]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-item[data-v-aad3b750]{align-items:center;gap:4px;display:flex}.indicator-btn-wrapper[data-v-aad3b750]{position:relative}.indicator-btn[data-v-aad3b750]{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-aad3b750]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-aad3b750]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-aad3b750]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-aad3b750]{z-index:1;position:relative}.param-hint[data-v-aad3b750]{opacity:.85;font-size:11px}.hover-overlay[data-v-aad3b750]{-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-aad3b750]{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-aad3b750]:hover{color:#333;background:#0000000f}.settings-btn[data-v-aad3b750]:hover{color:#1a1a1a}.remove-btn[data-v-aad3b750]:hover{color:#ff4d4f}.divider[data-v-aad3b750]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-aad3b750]{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-aad3b750]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-aad3b750]{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}.menu-section[data-v-aad3b750]{padding:4px 0}.menu-section[data-v-aad3b750]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-aad3b750]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-aad3b750]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-aad3b750]{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-aad3b750]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-aad3b750]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-aad3b750]{color:#999;font-size:11px}.active-tag[data-v-aad3b750]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-aad3b750],.fade-leave-active[data-v-aad3b750]{transition:opacity .2s}.fade-enter-from[data-v-aad3b750],.fade-leave-to[data-v-aad3b750]{opacity:0}.slide-enter-active[data-v-aad3b750],.slide-leave-active[data-v-aad3b750]{transition:all .2s}.slide-enter-from[data-v-aad3b750],.slide-leave-to[data-v-aad3b750]{opacity:0;transform:translate(-50%)translateY(8px)}.chart-wrapper[data-v-c5290a39]{--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-container[data-v-c5290a39]{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;border:1px solid #e0e0e0;width:95%;height:85%;min-height:255px;position:relative;overflow:auto hidden}.chart-container[data-v-c5290a39]::-webkit-scrollbar{display:none}.chart-container[data-v-c5290a39]:hover{cursor:grab}.chart-container[data-v-c5290a39]:active{cursor:grabbing}.scroll-content[data-v-c5290a39]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-c5290a39]{pointer-events:none;position:sticky;top:0;left:0}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;right:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}
|
|
1
|
+
.kline-tooltip[data-v-95daa55c]{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-95daa55c]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.kline-tooltip__grid[data-v-95daa55c]{grid-template-columns:1fr;gap:2px;display:grid}.kline-tooltip__grid .row[data-v-95daa55c]{justify-content:space-between;gap:10px;display:flex}.kline-tooltip__grid .row span[data-v-95daa55c]:first-child{color:#0000008f}.marker-tooltip[data-v-dd43da4f]{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-dd43da4f]{justify-content:space-between;gap:10px;margin-bottom:6px;font-weight:600;display:flex}.marker-tooltip__content[data-v-dd43da4f]{grid-template-columns:1fr;gap:2px;display:grid}.marker-tooltip__content .row[data-v-dd43da4f]{justify-content:space-between;gap:10px;display:flex}.marker-tooltip__content .row span[data-v-dd43da4f]:first-child{color:#0000008f}.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-aad3b750]{width:80%;margin:20px;position:relative}.indicator-scroll-container[data-v-aad3b750]{scrollbar-width:none;-webkit-overflow-scrolling:touch;text-align:center;width:100%;overflow:auto hidden}.indicator-scroll-container[data-v-aad3b750]::-webkit-scrollbar{display:none}.indicator-list[data-v-aad3b750]{gap:8px;margin:0 auto;padding:2px;display:inline-flex}.indicator-item[data-v-aad3b750]{align-items:center;gap:4px;display:flex}.indicator-btn-wrapper[data-v-aad3b750]{position:relative}.indicator-btn[data-v-aad3b750]{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-aad3b750]:hover:not(.hovering){color:#333;background:#f8f8f8;border-color:#ccc}.indicator-btn.active[data-v-aad3b750]{color:#1a1a1a;background:#f8f8f8;border-color:#1a1a1a}.indicator-btn.active[data-v-aad3b750]:hover:not(.hovering){background:#f0f0f0;border-color:#333}.btn-content[data-v-aad3b750]{z-index:1;position:relative}.param-hint[data-v-aad3b750]{opacity:.85;font-size:11px}.hover-overlay[data-v-aad3b750]{-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-aad3b750]{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-aad3b750]:hover{color:#333;background:#0000000f}.settings-btn[data-v-aad3b750]:hover{color:#1a1a1a}.remove-btn[data-v-aad3b750]:hover{color:#ff4d4f}.divider[data-v-aad3b750]{background:#e0e0e0;width:1px;height:14px}.add-btn[data-v-aad3b750]{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-aad3b750]:hover{color:#1a1a1a;background:#1a1a1a0a;border-color:#1a1a1a}.add-menu[data-v-aad3b750]{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}.menu-section[data-v-aad3b750]{padding:4px 0}.menu-section[data-v-aad3b750]:not(:last-child){border-bottom:1px solid #f0f0f0}.menu-title[data-v-aad3b750]{color:#999;padding:4px 16px;font-size:12px;font-weight:500}.menu-items[data-v-aad3b750]{flex-direction:column;gap:2px;display:flex}.menu-item[data-v-aad3b750]{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-aad3b750]:hover:not(.disabled){background:#f5f5f5}.menu-item.disabled[data-v-aad3b750]{color:#999;cursor:not-allowed}.menu-item .param-hint[data-v-aad3b750]{color:#999;font-size:11px}.active-tag[data-v-aad3b750]{color:#1a1a1a;align-items:center;margin-left:auto;display:flex}.fade-enter-active[data-v-aad3b750],.fade-leave-active[data-v-aad3b750]{transition:opacity .2s}.fade-enter-from[data-v-aad3b750],.fade-leave-to[data-v-aad3b750]{opacity:0}.slide-enter-active[data-v-aad3b750],.slide-leave-active[data-v-aad3b750]{transition:all .2s}.slide-enter-from[data-v-aad3b750],.slide-leave-to[data-v-aad3b750]{opacity:0;transform:translate(-50%)translateY(8px)}.chart-wrapper[data-v-d57ed432]{--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-container[data-v-d57ed432]{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;border:1px solid #e0e0e0;width:95%;height:85%;min-height:255px;position:relative;overflow:auto hidden}.chart-container[data-v-d57ed432]::-webkit-scrollbar{display:none}.chart-container[data-v-d57ed432]:hover{cursor:grab}.chart-container[data-v-d57ed432]:active{cursor:grabbing}.scroll-content[data-v-d57ed432]{height:100%;min-height:inherit;position:relative}.canvas-layer[data-v-d57ed432]{pointer-events:none;position:sticky;top:0;left:0}.plot-canvas{display:block;position:absolute;top:0;left:0}.right-axis{display:block;position:absolute;right:0}.x-axis-canvas{z-index:10;display:block;position:absolute;bottom:0;left:0}.main,.sub{border-bottom:1px solid #e0e0e0;border-right:1px solid #e0e0e0}.x-axis-canvas{border-right:1px solid #e0e0e0}.right-axis{border-bottom:1px solid #e0e0e0}
|
|
2
2
|
/*$vite$:1*/
|
package/dist/src/core/chart.d.ts
CHANGED
|
@@ -70,16 +70,25 @@ export declare class Chart {
|
|
|
70
70
|
private pluginHost;
|
|
71
71
|
/** 渲染器插件管理器 */
|
|
72
72
|
private rendererPluginManager;
|
|
73
|
-
/** 精确 DPR(来自 devicePixelContentBoxSize) */
|
|
73
|
+
/** 精确 DPR(来自 ResizeObserver 的 devicePixelContentBoxSize) */
|
|
74
74
|
private preciseDpr;
|
|
75
|
-
/**
|
|
76
|
-
private
|
|
75
|
+
/** 统一监听容器尺寸与 DPR 变化 */
|
|
76
|
+
private resizeObserver?;
|
|
77
|
+
/** 最近一次观测到的容器尺寸 */
|
|
78
|
+
private observedSize;
|
|
79
|
+
/** 视口变化回调(供外部同步 DPR/尺寸) */
|
|
80
|
+
private onViewportChange?;
|
|
77
81
|
/**
|
|
78
82
|
* 创建图表实例
|
|
79
83
|
* @param dom 由 Vue 组件传入的 DOM 句柄
|
|
80
84
|
* @param opt 初始配置
|
|
81
85
|
*/
|
|
82
86
|
constructor(dom: ChartDom, opt: ChartOptions);
|
|
87
|
+
private initResizeObserver;
|
|
88
|
+
private updateObservedMetrics;
|
|
89
|
+
private getEffectiveDpr;
|
|
90
|
+
getViewport(): Viewport | null;
|
|
91
|
+
getCurrentDpr(): number;
|
|
83
92
|
/** 获取插件宿主 */
|
|
84
93
|
get plugin(): PluginHostImpl;
|
|
85
94
|
/** 安装渲染器插件 */
|
|
@@ -117,6 +126,8 @@ export declare class Chart {
|
|
|
117
126
|
* @param cb 缩放回调函数
|
|
118
127
|
*/
|
|
119
128
|
setOnZoomChange(cb: (kWidth: number, kGap: number, targetScrollLeft: number) => void): void;
|
|
129
|
+
/** 注册视口变化回调 */
|
|
130
|
+
setOnViewportChange(cb: (viewport: Viewport) => void): void;
|
|
120
131
|
/** 获取所有 PaneRenderer */
|
|
121
132
|
getPaneRenderers(): PaneRenderer[];
|
|
122
133
|
/** 获取 MarkerManager(供 InteractionController 使用) */
|
|
@@ -207,6 +218,5 @@ export declare class Chart {
|
|
|
207
218
|
private initPanes;
|
|
208
219
|
/** 计算每个 pane 的布局(top 和 height) */
|
|
209
220
|
private layoutPanes;
|
|
210
|
-
/** 计算并应用 viewport */
|
|
211
221
|
private computeViewport;
|
|
212
222
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { RendererPluginWithHost, BaseIndicatorState } from '../../../../plugin';
|
|
2
2
|
import { KLineData } from '../../../../types/price';
|
|
3
3
|
export interface MACDConfig {
|
|
4
4
|
/** 快线周期(默认 12) */
|
|
@@ -14,6 +14,16 @@ export interface MACDConfig {
|
|
|
14
14
|
/** 是否显示 MACD 柱 */
|
|
15
15
|
showBAR?: boolean;
|
|
16
16
|
}
|
|
17
|
+
/** MACD 渲染器状态(共享给刻度渲染器) */
|
|
18
|
+
export interface MACDRenderState extends BaseIndicatorState {
|
|
19
|
+
valueMin: number;
|
|
20
|
+
valueMax: number;
|
|
21
|
+
latestValues?: {
|
|
22
|
+
dif: number;
|
|
23
|
+
dea: number;
|
|
24
|
+
macd: number;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
17
27
|
export interface MACDRendererOptions {
|
|
18
28
|
/** 目标 pane ID(默认 'sub') */
|
|
19
29
|
paneId?: string;
|
|
@@ -23,7 +33,7 @@ export interface MACDRendererOptions {
|
|
|
23
33
|
/**
|
|
24
34
|
* 创建 MACD 渲染器插件
|
|
25
35
|
*/
|
|
26
|
-
export declare function createMACDRendererPlugin(options?: MACDRendererOptions):
|
|
36
|
+
export declare function createMACDRendererPlugin(options?: MACDRendererOptions): RendererPluginWithHost;
|
|
27
37
|
/**
|
|
28
38
|
* 计算指定索引处的 MACD 值(供图例使用)
|
|
29
39
|
*/
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 根据面板高度计算网格线/价格标签数量
|
|
3
|
+
* 刻度间距固定约 60px
|
|
3
4
|
* @param height 面板高度(逻辑像素)
|
|
4
|
-
* @param isMain
|
|
5
|
+
* @param isMain 是否为主图面板(暂未使用,保留参数兼容)
|
|
5
6
|
* @returns tick 数量
|
|
6
7
|
*/
|
|
7
|
-
export declare function calculateTickCount(height: number, isMain
|
|
8
|
+
export declare function calculateTickCount(height: number, isMain?: boolean): number;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Plugin, PluginConfig, PluginHost, PluginState } from './types';
|
|
1
|
+
import { Plugin, PluginConfig, PluginHost, PluginState, BaseIndicatorState } from './types';
|
|
2
2
|
export declare class PluginHostImpl implements PluginHost {
|
|
3
3
|
private registry;
|
|
4
4
|
private eventBus;
|
|
5
5
|
private hookSystem;
|
|
6
6
|
private configManager;
|
|
7
|
+
private stateStore;
|
|
7
8
|
private isDestroyed;
|
|
8
9
|
constructor();
|
|
9
10
|
readonly events: {
|
|
@@ -22,6 +23,11 @@ export declare class PluginHostImpl implements PluginHost {
|
|
|
22
23
|
setConfig(pluginName: string, key: string, value: unknown): void;
|
|
23
24
|
getPlugin<T extends Plugin = Plugin>(name: string): T | undefined;
|
|
24
25
|
log(level: 'info' | 'warn' | 'error', message: string, ...args: unknown[]): void;
|
|
26
|
+
setSharedState<T extends BaseIndicatorState>(namespace: string, state: T, ownerId?: string): void;
|
|
27
|
+
getSharedState<T extends BaseIndicatorState>(namespace: string): T | undefined;
|
|
28
|
+
clearSharedState(namespace: string): void;
|
|
29
|
+
registerStateOwner(ownerId: string, namespaces: string[]): void;
|
|
30
|
+
clearByOwner(ownerId: string): void;
|
|
25
31
|
/**
|
|
26
32
|
* 安装插件
|
|
27
33
|
*/
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { BaseIndicatorState } from './types';
|
|
2
|
+
export declare class StateStore {
|
|
3
|
+
private states;
|
|
4
|
+
private ownerNamespaces;
|
|
5
|
+
/**
|
|
6
|
+
* 设置状态
|
|
7
|
+
* @param namespace 状态命名空间
|
|
8
|
+
* @param state 状态值
|
|
9
|
+
* @param ownerId 可选的拥有者 ID(用于冲突检测)
|
|
10
|
+
*/
|
|
11
|
+
setState<T extends BaseIndicatorState>(namespace: string, state: T, ownerId?: string): void;
|
|
12
|
+
/**
|
|
13
|
+
* 获取状态
|
|
14
|
+
* @param namespace 状态命名空间
|
|
15
|
+
*/
|
|
16
|
+
getState<T extends BaseIndicatorState>(namespace: string): T | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* 清除指定命名空间的状态
|
|
19
|
+
* @param namespace 状态命名空间
|
|
20
|
+
*/
|
|
21
|
+
clearState(namespace: string): void;
|
|
22
|
+
/**
|
|
23
|
+
* 注册状态拥有者
|
|
24
|
+
* @param ownerId 拥有者 ID(通常是渲染器名称)
|
|
25
|
+
* @param namespaces 声明的命名空间列表
|
|
26
|
+
*/
|
|
27
|
+
registerStateOwner(ownerId: string, namespaces: string[]): void;
|
|
28
|
+
/**
|
|
29
|
+
* 按拥有者清除所有状态
|
|
30
|
+
* @param ownerId 拥有者 ID
|
|
31
|
+
*/
|
|
32
|
+
clearByOwner(ownerId: string): void;
|
|
33
|
+
/**
|
|
34
|
+
* 清空所有状态
|
|
35
|
+
*/
|
|
36
|
+
clear(): void;
|
|
37
|
+
}
|
|
@@ -68,6 +68,16 @@ export interface PluginHost {
|
|
|
68
68
|
getPlugin<T extends Plugin = Plugin>(name: string): T | undefined;
|
|
69
69
|
/** 日志工具 */
|
|
70
70
|
log(level: 'info' | 'warn' | 'error', message: string, ...args: unknown[]): void;
|
|
71
|
+
/** 设置共享状态 */
|
|
72
|
+
setSharedState<T extends BaseIndicatorState>(namespace: string, state: T, ownerId?: string): void;
|
|
73
|
+
/** 获取共享状态 */
|
|
74
|
+
getSharedState<T extends BaseIndicatorState>(namespace: string): T | undefined;
|
|
75
|
+
/** 清除共享状态 */
|
|
76
|
+
clearSharedState(namespace: string): void;
|
|
77
|
+
/** 注册状态拥有者 */
|
|
78
|
+
registerStateOwner(ownerId: string, namespaces: string[]): void;
|
|
79
|
+
/** 按拥有者清除状态 */
|
|
80
|
+
clearByOwner(ownerId: string): void;
|
|
71
81
|
}
|
|
72
82
|
/** Pane 信息接口 */
|
|
73
83
|
export interface PaneInfo {
|
|
@@ -134,7 +144,17 @@ export declare const RENDERER_PRIORITY: {
|
|
|
134
144
|
readonly SYSTEM_XAXIS: -20;
|
|
135
145
|
readonly BACKGROUND: 0;
|
|
136
146
|
readonly GRID: 10;
|
|
147
|
+
/**
|
|
148
|
+
* 指标渲染器(MACD, RSI 等)
|
|
149
|
+
* 所有指标渲染器必须使用此优先级或 ≤30 的值
|
|
150
|
+
*/
|
|
137
151
|
readonly INDICATOR: 30;
|
|
152
|
+
/**
|
|
153
|
+
* 指标刻度渲染器(依赖于前方 INDICATOR 的状态)
|
|
154
|
+
* 所有刻度渲染器必须使用此优先级或 ≥35 的值,
|
|
155
|
+
* 确保每次绘制时指标更新先于刻度。
|
|
156
|
+
*/
|
|
157
|
+
readonly INDICATOR_SCALE: 35;
|
|
138
158
|
readonly MAIN: 50;
|
|
139
159
|
readonly OVERLAY: 80;
|
|
140
160
|
readonly FOREGROUND: 100;
|
|
@@ -183,4 +203,10 @@ export interface RendererPlugin {
|
|
|
183
203
|
export interface RendererPluginWithHost extends RendererPlugin {
|
|
184
204
|
/** 安装时获取 PluginHost 访问权限 */
|
|
185
205
|
onInstall?(host: PluginHost): void;
|
|
206
|
+
/** 声明该渲染器所拥有的状态命名空间,卸载时框架会自动清理 */
|
|
207
|
+
getDeclaredNamespaces?(): string[];
|
|
208
|
+
}
|
|
209
|
+
/** 指标渲染器状态基类 */
|
|
210
|
+
export interface BaseIndicatorState {
|
|
211
|
+
timestamp: number;
|
|
186
212
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@363045841yyt/klinechart",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"engines": {
|
|
6
6
|
"node": "^20.19.0 || >=22.12.0"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"aktools": "cd .. && cd aktoolshttp && uv run python -m aktools",
|
|
13
13
|
"build": "run-p type-check \"build-only {@}\" --",
|
|
14
14
|
"build-only": "vite build",
|
|
15
|
+
"build:demo": "vite build --config vite.demo.config.ts",
|
|
15
16
|
"preview": "vite preview",
|
|
16
17
|
"type-check": "vue-tsc --build",
|
|
17
18
|
"test:unit": "vitest",
|