@363045841yyt/klinechart 0.8.5 → 0.8.6

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.
Files changed (43) hide show
  1. package/README.md +6 -1
  2. package/dist/components/BaseModal.vue.d.ts +54 -0
  3. package/dist/components/BaseModal.vue.d.ts.map +1 -0
  4. package/dist/components/BatchStockDialog.vue.d.ts.map +1 -1
  5. package/dist/components/ChartSettingsDialog.vue.d.ts.map +1 -1
  6. package/dist/components/ColorPresetPanel.vue.d.ts +4 -1
  7. package/dist/components/ColorPresetPanel.vue.d.ts.map +1 -1
  8. package/dist/components/DrawingStyleToolbar.vue.d.ts.map +1 -1
  9. package/dist/components/ExportProgressDialog.vue.d.ts.map +1 -1
  10. package/dist/components/IndicatorParams.vue.d.ts.map +1 -1
  11. package/dist/components/IndicatorSelector.vue.d.ts.map +1 -1
  12. package/dist/components/KLineChart.vue.d.ts.map +1 -1
  13. package/dist/components/RangeSelectionExport.vue.d.ts +23 -0
  14. package/dist/components/RangeSelectionExport.vue.d.ts.map +1 -0
  15. package/dist/components/common/CanvasToolbar.vue.d.ts +14 -0
  16. package/dist/components/common/CanvasToolbar.vue.d.ts.map +1 -0
  17. package/dist/components/common/CanvasToolbarStack.vue.d.ts +14 -0
  18. package/dist/components/common/CanvasToolbarStack.vue.d.ts.map +1 -0
  19. package/dist/composables/chart/useRangeSelection.d.ts +1 -0
  20. package/dist/composables/chart/useRangeSelection.d.ts.map +1 -1
  21. package/dist/composables/useTeleportedPopup.d.ts.map +1 -1
  22. package/dist/index.cjs +6 -6
  23. package/dist/index.css +1 -1
  24. package/dist/index.js +1293 -1215
  25. package/dist/web-component.d.ts.map +1 -1
  26. package/package.json +1 -1
  27. package/src/components/BaseModal.vue +292 -0
  28. package/src/components/BatchStockDialog.vue +15 -180
  29. package/src/components/ChartSettingsDialog.vue +248 -405
  30. package/src/components/ColorPresetPanel.vue +58 -106
  31. package/src/components/CompareSymbolSelector.vue +2 -2
  32. package/src/components/DrawingStyleToolbar.vue +33 -72
  33. package/src/components/ExportProgressDialog.vue +25 -133
  34. package/src/components/IndicatorParams.vue +194 -321
  35. package/src/components/IndicatorSelector.vue +188 -405
  36. package/src/components/KLineChart.vue +34 -138
  37. package/src/components/LeftToolbar.vue +1 -1
  38. package/src/components/RangeSelectionExport.vue +117 -0
  39. package/src/components/SymbolSelector.vue +2 -2
  40. package/src/components/common/CanvasToolbar.vue +70 -0
  41. package/src/components/common/CanvasToolbarStack.vue +32 -0
  42. package/src/composables/chart/useRangeSelection.ts +7 -0
  43. package/src/composables/useTeleportedPopup.ts +15 -2
@@ -1 +1 @@
1
- {"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;aAU2qsC,CAAC;kBAAyB,CAAC;;;;;iBAAsH,CAAC;gBAAc,CAAC;;;iBAAuD,CAAC;gBAAc,CAAC;;qBAAgC,CAAC;;EARz8sC,CAAA;AAIF,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAC5B,eAAe,iBAAiB,CAAA;AAEhC,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAA"}
1
+ {"version":3,"file":"web-component.d.ts","sourceRoot":"","sources":["../src/web-component.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wCAAwC,CAAA;AAE9F,QAAA,MAAM,iBAAiB;;;;;;;;;;;;;;aAUojnC,CAAC;kBAAyB,CAAC;;;;;iBAAsH,CAAC;gBAAc,CAAC;;;iBAAuD,CAAC;gBAAc,CAAC;;qBAAgC,CAAC;;EARl1nC,CAAA;AAIF,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAC5B,eAAe,iBAAiB,CAAA;AAEhC,YAAY,EAAE,mBAAmB,EAAE,WAAW,EAAE,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@363045841yyt/klinechart",
3
- "version": "0.8.5",
3
+ "version": "0.8.6",
4
4
  "description": "Vue 3 bindings for @363045841yyt/klinechart-core. Idiomatic composables, SFC components.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -0,0 +1,292 @@
1
+ <template>
2
+ <Teleport :to="teleportTarget">
3
+ <Transition name="overlay">
4
+ <div
5
+ v-if="show"
6
+ class="base-overlay"
7
+ :style="{ zIndex, padding: overlayPadding }"
8
+ @click="closeOnOverlay ? emit('close') : undefined"
9
+ >
10
+ <Transition :name="modalTransitionName">
11
+ <div
12
+ class="base-modal"
13
+ :style="modalStyle"
14
+ @click.stop
15
+ >
16
+ <div v-if="$slots.header || title" class="base-header">
17
+ <slot name="header">
18
+ <div class="base-header-left">
19
+ <span class="base-title">{{ title }}</span>
20
+ <span v-if="subtitle" class="base-subtitle">{{ subtitle }}</span>
21
+ </div>
22
+ </slot>
23
+ <div v-if="showClose" class="base-header-right">
24
+ <slot name="header-extra" />
25
+ <button class="base-close-btn" @click="emit('close')">
26
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
27
+ <path d="M18 6L6 18M6 6l12 12" />
28
+ </svg>
29
+ </button>
30
+ </div>
31
+ </div>
32
+
33
+ <div v-if="$slots.subheader" class="base-subheader">
34
+ <slot name="subheader" />
35
+ </div>
36
+
37
+ <div class="base-body" :style="{ padding: bodyPadding }">
38
+ <slot />
39
+ </div>
40
+
41
+ <div v-if="$slots.footer" class="base-footer" :style="{ justifyContent: footerAlign }">
42
+ <slot name="footer" />
43
+ </div>
44
+ </div>
45
+ </Transition>
46
+ </div>
47
+ </Transition>
48
+ </Teleport>
49
+ </template>
50
+
51
+ <script setup lang="ts">
52
+ import { computed } from 'vue'
53
+ import { useFullscreenTeleportTarget } from '../composables/useFullscreenTeleportTarget'
54
+
55
+ const props = withDefaults(
56
+ defineProps<{
57
+ show: boolean
58
+ title?: string
59
+ subtitle?: string
60
+ zIndex?: number
61
+ width?: string
62
+ maxWidth?: string
63
+ maxHeight?: string
64
+ overlayPadding?: string
65
+ bodyPadding?: string
66
+ footerAlign?: 'flex-end' | 'center' | 'flex-start' | 'space-between'
67
+ closeOnOverlay?: boolean
68
+ showClose?: boolean
69
+ transitionVariant?: 'default' | 'compact'
70
+ }>(),
71
+ {
72
+ title: '',
73
+ subtitle: '',
74
+ zIndex: 1000,
75
+ width: 'min(92vw, 400px)',
76
+ maxWidth: '',
77
+ maxHeight: 'min(600px, calc(100vh - 48px))',
78
+ overlayPadding: '24px',
79
+ bodyPadding: '16px 20px',
80
+ footerAlign: 'flex-end',
81
+ closeOnOverlay: true,
82
+ showClose: true,
83
+ transitionVariant: 'default',
84
+ },
85
+ )
86
+
87
+ const emit = defineEmits<{
88
+ close: []
89
+ }>()
90
+
91
+ const teleportTarget = useFullscreenTeleportTarget()
92
+
93
+ const modalTransitionName = computed(() =>
94
+ props.transitionVariant === 'compact' ? 'modal-compact' : 'modal',
95
+ )
96
+
97
+ const modalStyle = computed(() => ({
98
+ width: props.width,
99
+ maxWidth: props.maxWidth || undefined,
100
+ maxHeight: props.maxHeight,
101
+ }))
102
+ </script>
103
+
104
+ <style scoped>
105
+ .base-overlay {
106
+ position: fixed;
107
+ inset: 0;
108
+ background: rgba(0, 0, 0, 0.3);
109
+ backdrop-filter: blur(4px);
110
+ display: flex;
111
+ align-items: center;
112
+ justify-content: center;
113
+ }
114
+
115
+ .base-modal {
116
+ background: var(--klc-color-background);
117
+ border: 1px solid var(--klc-color-border-button);
118
+ border-radius: 10px;
119
+ box-shadow: 0 18px 48px rgba(0, 0, 0, 0.15);
120
+ overflow: hidden;
121
+ display: flex;
122
+ flex-direction: column;
123
+ }
124
+
125
+ .base-header {
126
+ display: flex;
127
+ justify-content: space-between;
128
+ align-items: center;
129
+ padding: 14px 18px 14px 20px;
130
+ background: var(--klc-color-background);
131
+ border-bottom: 1px solid var(--klc-color-grid-major);
132
+ flex-shrink: 0;
133
+ gap: 12px;
134
+ }
135
+
136
+ .base-header-left {
137
+ display: flex;
138
+ align-items: baseline;
139
+ gap: 8px;
140
+ min-width: 0;
141
+ }
142
+
143
+ .base-title {
144
+ font-size: 15px;
145
+ font-weight: 600;
146
+ color: var(--klc-color-foreground);
147
+ line-height: 1.35;
148
+ }
149
+
150
+ .base-subtitle {
151
+ font-size: 11px;
152
+ color: var(--klc-color-axis-text);
153
+ line-height: 1.3;
154
+ white-space: nowrap;
155
+ }
156
+
157
+ .base-header-right {
158
+ display: flex;
159
+ align-items: center;
160
+ gap: 8px;
161
+ flex-shrink: 0;
162
+ }
163
+
164
+ .base-close-btn {
165
+ background: var(--klc-color-background);
166
+ border: 1px solid var(--klc-color-border-button);
167
+ border-radius: 8px;
168
+ width: 32px;
169
+ height: 32px;
170
+ display: flex;
171
+ align-items: center;
172
+ justify-content: center;
173
+ cursor: pointer;
174
+ color: var(--klc-color-axis-text);
175
+ transition: background 0.15s, color 0.15s, border-color 0.15s;
176
+ padding: 0;
177
+ }
178
+
179
+ .base-close-btn:hover {
180
+ background: var(--klc-color-tag-bg-hover);
181
+ color: var(--klc-color-foreground);
182
+ border-color: var(--klc-color-axis-line);
183
+ }
184
+
185
+ .base-close-btn svg {
186
+ width: 14px;
187
+ height: 14px;
188
+ }
189
+
190
+ .base-subheader {
191
+ flex-shrink: 0;
192
+ padding: 16px 20px;
193
+ background: var(--klc-color-background);
194
+ border-bottom: 1px solid var(--klc-color-grid-major);
195
+ }
196
+
197
+ .base-body {
198
+ flex: 1;
199
+ min-height: 0;
200
+ overflow-y: auto;
201
+ background: var(--klc-color-background);
202
+ }
203
+
204
+ .base-body::-webkit-scrollbar {
205
+ width: 8px;
206
+ }
207
+
208
+ .base-body::-webkit-scrollbar-track {
209
+ background: var(--klc-color-background);
210
+ }
211
+
212
+ .base-body::-webkit-scrollbar-thumb {
213
+ background: var(--klc-color-axis-line);
214
+ border: 2px solid var(--klc-color-background);
215
+ border-radius: 999px;
216
+ }
217
+
218
+ .base-footer {
219
+ display: flex;
220
+ align-items: center;
221
+ justify-content: flex-end;
222
+ gap: 8px;
223
+ padding: 12px 20px;
224
+ background: var(--klc-color-background);
225
+ border-top: 1px solid var(--klc-color-grid-major);
226
+ flex-shrink: 0;
227
+ }
228
+
229
+ /* ── Overlay transition ── */
230
+ .overlay-enter-active,
231
+ .overlay-leave-active {
232
+ transition: opacity 0.2s ease;
233
+ }
234
+
235
+ .overlay-enter-from,
236
+ .overlay-leave-to {
237
+ opacity: 0;
238
+ }
239
+
240
+ /* ── Modal transition (default variant) ── */
241
+ .modal-enter-active {
242
+ transition: all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
243
+ }
244
+
245
+ .modal-leave-active {
246
+ transition: all 0.16s ease-in;
247
+ }
248
+
249
+ .modal-enter-from {
250
+ opacity: 0;
251
+ transform: scale(0.96) translateY(-10px);
252
+ }
253
+
254
+ .modal-leave-to {
255
+ opacity: 0;
256
+ transform: scale(0.98) translateY(8px);
257
+ }
258
+
259
+ /* ── Modal transition (compact variant) ── */
260
+ .modal-compact-enter-active {
261
+ transition: all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
262
+ }
263
+
264
+ .modal-compact-leave-active {
265
+ transition: all 0.16s ease-in;
266
+ }
267
+
268
+ .modal-compact-enter-from {
269
+ opacity: 0;
270
+ transform: scale(0.88) translateY(-16px);
271
+ }
272
+
273
+ .modal-compact-leave-to {
274
+ opacity: 0;
275
+ transform: scale(0.94) translateY(8px);
276
+ }
277
+
278
+ /* ── Responsive ── */
279
+ @media (max-width: 480px) {
280
+ .base-overlay {
281
+ padding: 12px;
282
+ align-items: flex-end;
283
+ }
284
+
285
+ .base-modal {
286
+ min-width: 0;
287
+ width: 100% !important;
288
+ max-height: calc(100vh - 24px);
289
+ border-radius: 10px;
290
+ }
291
+ }
292
+ </style>
@@ -1,42 +1,22 @@
1
1
  <template>
2
- <Teleport :to="teleportTarget">
3
- <Transition name="overlay">
4
- <div v-if="show" class="batch-overlay" @click="emit('close')">
5
- <Transition name="modal">
6
- <div class="batch-modal" @click.stop>
7
- <div class="batch-header">
8
- <span class="batch-title">批量设置股票代码</span>
9
- <button class="batch-close-btn" @click="emit('close')">
10
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
11
- <path d="M18 6L6 18M6 6l12 12" />
12
- </svg>
13
- </button>
14
- </div>
15
-
16
- <div class="batch-body">
17
- <textarea
18
- v-model="codesText"
19
- class="batch-textarea"
20
- placeholder="每行一个股票代码&#10;例如:&#10;000001&#10;600036&#10;002415"
21
- rows="8"
22
- spellcheck="false"
23
- />
24
- </div>
25
-
26
- <div class="batch-footer">
27
- <button class="batch-btn batch-btn--cancel" @click="emit('close')">取消</button>
28
- <button class="batch-btn batch-btn--confirm" @click="onApply">应用</button>
29
- </div>
30
- </div>
31
- </Transition>
32
- </div>
33
- </Transition>
34
- </Teleport>
2
+ <BaseModal title="批量设置股票代码" :show="show" @close="emit('close')">
3
+ <textarea
4
+ v-model="codesText"
5
+ class="batch-textarea"
6
+ placeholder="每行一个股票代码,导出时会将所选区间内这些品种的数据一并导出&#10;例如:&#10;000001&#10;600036&#10;002415"
7
+ rows="8"
8
+ spellcheck="false"
9
+ />
10
+ <template #footer>
11
+ <button class="batch-btn batch-btn--cancel" @click="emit('close')">取消</button>
12
+ <button class="batch-btn batch-btn--confirm" @click="onApply">应用</button>
13
+ </template>
14
+ </BaseModal>
35
15
  </template>
36
16
 
37
17
  <script setup lang="ts">
38
18
  import { ref, computed } from 'vue'
39
- import { useFullscreenTeleportTarget } from '../composables/useFullscreenTeleportTarget'
19
+ import BaseModal from './BaseModal.vue'
40
20
 
41
21
  const props = defineProps<{
42
22
  show: boolean
@@ -47,8 +27,6 @@ const emit = defineEmits<{
47
27
  apply: [codes: string[]]
48
28
  }>()
49
29
 
50
- const teleportTarget = useFullscreenTeleportTarget()
51
-
52
30
  const codes = ref<string[]>([])
53
31
 
54
32
  const codesText = computed({
@@ -69,88 +47,10 @@ function onApply() {
69
47
  </script>
70
48
 
71
49
  <style scoped>
72
- .batch-overlay {
73
- position: fixed;
74
- inset: 0;
75
- background: rgba(0, 0, 0, 0.3);
76
- backdrop-filter: blur(4px);
77
- padding: 24px;
78
- display: flex;
79
- align-items: center;
80
- justify-content: center;
81
- z-index: 1000;
82
- }
83
-
84
- .batch-modal {
85
- background: var(--klc-color-tag-bg-white);
86
- border: 1px solid var(--klc-color-border-button);
87
- border-radius: 10px;
88
- box-shadow: 0 18px 48px rgba(0, 0, 0, 0.15);
89
- min-width: 360px;
90
- max-width: 400px;
91
- width: min(92vw, 400px);
92
- max-height: min(600px, calc(100vh - 48px));
93
- overflow: hidden;
94
- display: flex;
95
- flex-direction: column;
96
- }
97
-
98
- .batch-header {
99
- display: flex;
100
- justify-content: space-between;
101
- align-items: center;
102
- padding: 14px 18px 14px 20px;
103
- background: var(--klc-color-background);
104
- border-bottom: 1px solid var(--klc-color-grid-major);
105
- flex-shrink: 0;
106
- }
107
-
108
- .batch-title {
109
- font-size: 15px;
110
- font-weight: 600;
111
- color: var(--klc-color-foreground);
112
- line-height: 1.35;
113
- }
114
-
115
- .batch-close-btn {
116
- background: var(--klc-color-tag-bg-white);
117
- border: 1px solid var(--klc-color-border-button);
118
- border-radius: 7px;
119
- width: 30px;
120
- height: 30px;
121
- display: flex;
122
- align-items: center;
123
- justify-content: center;
124
- cursor: pointer;
125
- color: var(--klc-color-axis-text);
126
- transition:
127
- background 0.15s,
128
- color 0.15s,
129
- border-color 0.15s;
130
- padding: 0;
131
- }
132
-
133
- .batch-close-btn:hover {
134
- background: var(--klc-color-tag-bg-hover);
135
- color: var(--klc-color-foreground);
136
- border-color: var(--klc-color-axis-line);
137
- }
138
-
139
- .batch-close-btn svg {
140
- width: 14px;
141
- height: 14px;
142
- }
143
-
144
- .batch-body {
145
- padding: 16px 20px;
146
- display: flex;
147
- flex-direction: column;
148
- gap: 12px;
149
- }
150
-
151
50
  .batch-textarea {
152
51
  width: 100%;
153
52
  min-height: 160px;
53
+ max-height: 100%;
154
54
  padding: 10px 12px;
155
55
  border: 1px solid var(--klc-color-border-button);
156
56
  border-radius: 6px;
@@ -174,17 +74,6 @@ function onApply() {
174
74
  opacity: 0.5;
175
75
  }
176
76
 
177
- .batch-footer {
178
- display: flex;
179
- align-items: center;
180
- justify-content: flex-end;
181
- gap: 8px;
182
- padding: 12px 20px;
183
- background: var(--klc-color-background);
184
- border-top: 1px solid var(--klc-color-grid-major);
185
- flex-shrink: 0;
186
- }
187
-
188
77
  .batch-btn {
189
78
  display: flex;
190
79
  align-items: center;
@@ -236,58 +125,4 @@ function onApply() {
236
125
  transform: translateY(0);
237
126
  box-shadow: none;
238
127
  }
239
-
240
- .overlay-enter-active,
241
- .overlay-leave-active {
242
- transition: opacity 0.2s ease;
243
- }
244
-
245
- .overlay-enter-from,
246
- .overlay-leave-to {
247
- opacity: 0;
248
- }
249
-
250
- .modal-enter-active {
251
- transition: all 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
252
- }
253
-
254
- .modal-leave-active {
255
- transition: all 0.16s ease-in;
256
- }
257
-
258
- .modal-enter-from {
259
- opacity: 0;
260
- transform: scale(0.96) translateY(-10px);
261
- }
262
-
263
- .modal-leave-to {
264
- opacity: 0;
265
- transform: scale(0.98) translateY(8px);
266
- }
267
-
268
- @media (max-width: 480px) {
269
- .batch-overlay {
270
- padding: 12px;
271
- align-items: flex-end;
272
- }
273
-
274
- .batch-modal {
275
- min-width: 0;
276
- width: 100%;
277
- max-height: calc(100vh - 24px);
278
- border-radius: 10px;
279
- }
280
-
281
- .batch-header,
282
- .batch-body,
283
- .batch-footer {
284
- padding-left: 16px;
285
- padding-right: 16px;
286
- }
287
-
288
- .batch-footer {
289
- flex-direction: column-reverse;
290
- align-items: stretch;
291
- }
292
- }
293
128
  </style>