Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
110ddff
Merge pull request #1 from coinrayio/flexible-zoom-behaviour
Basttyy Nov 5, 2025
ad820b8
Merge pull request #2 from coinrayio/flexible-zoom-behaviour
Basttyy Nov 6, 2025
3f65c8f
feat: 支持修改单根蜡烛柱所占的空间的最大值和最小值
Jul 21, 2025
a8a2bf9
feat: 增加setBarSpaceLimit和getBarSpaceLimit文档说明
Jul 21, 2025
444b4d9
Merge pull request #3 from coinrayio/feat-support-setBarspaceLimit
Basttyy Nov 7, 2025
e76df35
feat(hiekin_ashi): re-write getDataList and getVisibleRangeDataList t…
Basttyy Nov 20, 2025
814da33
feat(heikin_ashi): add 'heikin_ashi' to CandleType
Basttyy Nov 20, 2025
ad7a59c
feat(heikin_ashi): ensure getDataList and getVisibleRangeDataList ret…
Basttyy Nov 20, 2025
8ba588a
feat(heikin_ashi): add 'heikin_ashi' to the candle type options in st…
Basttyy Nov 20, 2025
cdf596f
feat(implement-heikin-ashi-bars): mutate data to candleType for heiki…
Basttyy Jan 23, 2026
a03059a
feat(implement-heikin-ashi-bars): mutate data to candleType for heiki…
Basttyy Jan 23, 2026
6675700
Merge pull request #4 from coinrayio/feat-heikin-ashi-bars
Basttyy Jan 23, 2026
317b97e
docs: update
liihuu Sep 3, 2025
f9e0e2a
docs: update and rebase main into here
liihuu Sep 5, 2025
e4df173
docs: update
liihuu Sep 6, 2025
424782c
docs: update
liihuu Sep 6, 2025
41aa805
docs: update
liihuu Sep 7, 2025
6e1bfb0
docs: update
liihuu Sep 9, 2025
50955fc
docs: update
liihuu Sep 10, 2025
3feb624
docs: update
liihuu Sep 10, 2025
0a14195
docs: update
liihuu Sep 10, 2025
51fc068
docs: update
liihuu Sep 16, 2025
0fbd30e
opt: opt merge
liihuu Nov 12, 2025
5147305
revert: fix the problem that asynchronous calculation of indicators m…
liihuu Nov 12, 2025
3c2496b
opt: indicator calc
liihuu Nov 14, 2025
fb945e8
opt: opt mobile event
liihuu Nov 17, 2025
f4809bf
opt: opt `feature` click event trigger
liihuu Nov 17, 2025
25bc2ed
opt: opt indicator last value display
liihuu Nov 17, 2025
1427112
opt: opt indicator tooltip display
liihuu Nov 17, 2025
01ed2c7
fix: preveOvlay too large to strigify
Jun 9, 2025
291924d
feat: rebase zoom anchor
liihuu Nov 20, 2025
17cc018
docs: update
liihuu Nov 20, 2025
24e8876
docs: update
liihuu Nov 20, 2025
9c4540e
docs: update
liihuu Nov 20, 2025
25123fc
ci: npm publish
liihuu Nov 21, 2025
d1fa19f
docs: update
liihuu Nov 22, 2025
300d1a7
ci: upgrade vitepress
liihuu Nov 24, 2025
20a77b5
docs: update
liihuu Nov 30, 2025
f505054
opt: opt `executeAction`
liihuu Nov 30, 2025
b2ba3a5
rebase: add smooth freehand drawing with continuous drawing mode
benoist Jan 19, 2026
c6242d9
docs: add freeHand to list of default indicators and sample
Basttyy Jan 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ jobs:
cache: pnpm
registry-url: https://registry.npmjs.org/
- run: pnpm install && pnpm run build
- run: npm publish
- run: npm publish --tag latest
env:
NODE_AUTH_TOKEN: ${{secrets.NPM_TOKEN}}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
/docs/node_modules

.npmrc

.DS_Store
13 changes: 12 additions & 1 deletion docs/.vitepress/config/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { fileURLToPath, URL } from 'node:url'
import fs from 'fs'
import path from 'path'
import { defineConfig } from 'vitepress'
Expand All @@ -18,6 +19,16 @@ function config () {
},
define: {
'process.env': JSON.stringify(process.env)
},
resolve: {
alias: [
{
find: /^.*\/VPNavBarTitle\.vue$/,
replacement: fileURLToPath(
new URL('../../@components/NavbarTitle.vue', import.meta.url)
)
}
]
}
},
cleanUrls: true,
Expand All @@ -37,7 +48,7 @@ function config () {
languages: ['js', 'jsx', 'ts', 'tsx']
},
head: [
['link', { rel: 'icon', type: 'image/svg+xml', href: '/images/logo.svg' }],
['link', { rel: 'icon', type: 'image/x-icon', href: '/images/fav.png' }],
['script', {}, `${klinecharts}`],
[
'script',
Expand Down
6 changes: 4 additions & 2 deletions docs/.vitepress/config/share.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export function getInstanceApiMenus (lang = '') {
{ text: 'setRightMinVisibleBarCount', link: `${prefix}/setRightMinVisibleBarCount` },
{ text: 'setBarSpace', link: `${prefix}/setBarSpace` },
{ text: 'getBarSpace', link: `${prefix}/getBarSpace` },
{ text: 'setBarSpaceLimit', link: `${prefix}/setBarSpaceLimit` },
{ text: 'getBarSpaceLimit', link: `${prefix}/getBarSpaceLimit` },
{ text: 'setSymbol', link: `${prefix}/setSymbol` },
{ text: 'getSymbol', link: `${prefix}/getSymbol` },
{ text: 'setPeriod', link: `${prefix}/setPeriod` },
Expand All @@ -67,10 +69,10 @@ export function getInstanceApiMenus (lang = '') {
{ text: 'removeOverlay', link: `${prefix}/removeOverlay` },
{ text: 'setPaneOptions', link: `${prefix}/setPaneOptions` },
{ text: 'getPaneOptions', link: `${prefix}/getPaneOptions` },
{ text: 'setZoomEnabled', link: `${prefix}/setZoomEnabled` },
{ text: 'setZoomAnchor', link: `${prefix}/setZoomAnchor` },
{ text: 'isZoomEnabled', link: `${prefix}/isZoomEnabled` },
{ text: 'getZoomAnchor', link: `${prefix}/getZoomAnchor` },
{ text: 'setZoomEnabled', link: `${prefix}/setZoomEnabled` },
{ text: 'isZoomEnabled', link: `${prefix}/isZoomEnabled` },
{ text: 'setScrollEnabled', link: `${prefix}/setScrollEnabled` },
{ text: 'isScrollEnabled', link: `${prefix}/isScrollEnabled` },
{ text: 'scrollByDistance', link: `${prefix}/scrollByDistance` },
Expand Down
25 changes: 8 additions & 17 deletions docs/.vitepress/theme/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,17 @@
:root {
--light-c-text-1: #09090B;
--light-c-text-2: #71717A;
--light-c-text-3: #71717A;
--light-c-text-3: #A1A1AA;
--light-c-bg: #FFFFFF;

--dark-c-text-1: #FAFAFA;
--dark-c-text-2: #A1A1AA;
--dark-c-text-3: #A1A1AA;
--dark-c-text-3: #828282;
--dark-c-bg: #09090B;

--vp-c-indigo-1: #E6AC00;
--vp-c-indigo-2: #d6ac2e;
--vp-c-indigo-3: #c9aa4e;
--vp-c-indigo-2: #ebbc33;
--vp-c-indigo-3: #f0cd66;

--vp-c-text-1: var(--light-c-text-1);
--vp-c-text-2: var(--light-c-text-2);
Expand All @@ -41,22 +41,12 @@

--vp-c-indigo-soft: rgb(22, 119, 255, 0.14);

--custom-red: #F92855;
--custom-green: #2DC08E;

--vp-c-bg-soft: #F5F5F5;
--vp-code-bg: var(--vp-c-bg-soft);
--vp-code-color: var(--vp-c-text-1);

--vp-nav-height: 60px;

--vp-button-brand-border: var(--vp-c-indigo-2);
--vp-button-brand-bg: var(--vp-c-indigo-1);
--vp-button-brand-hover-border: var(--vp-c-indigo-2);
--vp-button-brand-hover-bg: var(--vp-c-indigo-2);
--vp-button-brand-active-border: var(--vp-c-indigo-2);
--vp-button-brand-active-bg: var(--vp-button-brand-bg);

--vp-sidebar-bg-color: var(--vp-c-bg);
--vp-c-divider: #EFEFEF;
--vp-c-border: var(--vp-c-divider);
Expand All @@ -66,7 +56,8 @@
--vp-font-family-mono: SourceCode, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--vp-font-family-base: "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Arial", "sans-serif";

--vp-home-hero-bg: linear-gradient(180deg, rgba(238, 238, 238, 0) 0%, rgba(234, 204, 117, 0.2) 52%, rgba(230, 172, 0, 0) 100%);
--custom-c-warn: #E6AC00;
--vp-custom-block-warning-bg: #f5dd99;
}

.dark {
Expand All @@ -79,18 +70,18 @@
--vp-c-divider: #27272A;

--vp-c-bg-alt: #161616;
--vp-c-bg-elv: #161616;

--vp-c-bg-soft: #262626;

--vp-local-search-bg: var(--vp-c-bg-alt);

--vp-home-hero-bg: linear-gradient(180deg, rgba(238, 238, 238, 0) 0%, rgba(234, 204, 117, 0.15) 52%, rgba(230, 172, 0, 0) 100%);
}

body {
font-feature-settings: normal;
font-variation-settings: normal;
line-height: 1.6;
overflow: hidden;
}

.VPFeatures .VPFeature {
Expand Down
98 changes: 56 additions & 42 deletions docs/@components/ChartPreview.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import SmoothExpand from './SmoothExpand.vue'

const { isDark, lang } = useData()


const href = ref()

const props = defineProps(['title', 'chartId', 'chartHeight', 'code'])
Expand All @@ -33,6 +32,7 @@ const loading = ref(true)
const showCode = ref(!props.chartId)

const chartContainer = ref(null)
const chartInitializedFlag = ref(false)

const observer = ref(null)
const codeHtml = ref(null)
Expand Down Expand Up @@ -166,50 +166,58 @@ onMounted(() => {
defaultColor: 'light'
})
}

if (props.code) {
highlightCode()
if (!!props.chartId) {
const transformJs = props.code + '\n' + `window['chart_${props.chartId}'] = chart`
const ast = parse(transformJs, { sourceType: 'module' })

traverse(ast, {
CallExpression(path) {
if (
t.isCallExpression(path.node) &&
t.isIdentifier(path.node.callee, { name: 'callback' })
) {
const postMessageFun = t.expressionStatement(
t.callExpression(
t.memberExpression(t.identifier('window'), t.identifier('postMessage')),
[t.stringLiteral(props.chartId)]
)
)
path.insertBefore(postMessageFun)
}
}
})

window.addEventListener('message', handlerMessage, false);

const { code } = transform(generator(ast, {}, transformJs).code, {
presets: [
'es2015',
['stage-3', { decoratorsBeforeExport: true }],
],
plugins: ['transform-modules-umd'],
})
const chartDom = document.createElement('div')
const height = `${props.chartHeight || 350}px`
chartDom.style.height = height
chartDom.id = props.chartId
chartContainer.value.appendChild(chartDom)
const script = document.createElement('script')
script.innerHTML = code
chartContainer.value.appendChild(script)
window[`chart_${props.chartId}`].setStyles(isDark.value ? 'dark' : 'light')

observer.value = new ResizeObserver(_ => {
window[`chart_${props.chartId}`].resize()
if (!chartInitializedFlag.value) {
const bounding = chartContainer.value.getBoundingClientRect()
if (bounding.width === 0 || bounding.height === 0) {
return
}
chartInitializedFlag.value = true
const transformJs = props.code + '\n' + `window['chart_${props.chartId}'] = chart`
const ast = parse(transformJs, { sourceType: 'module' })

traverse(ast, {
CallExpression(path) {
if (
t.isCallExpression(path.node) &&
t.isIdentifier(path.node.callee, { name: 'callback' })
) {
const postMessageFun = t.expressionStatement(
t.callExpression(
t.memberExpression(t.identifier('window'), t.identifier('postMessage')),
[t.stringLiteral(props.chartId)]
)
)
path.insertBefore(postMessageFun)
}
}
})

const { code } = transform(generator(ast, {}, transformJs).code, {
presets: [
'es2015',
['stage-3', { decoratorsBeforeExport: true }],
],
plugins: ['transform-modules-umd'],
})
const chartDom = document.createElement('div')
const height = `${props.chartHeight || 350}px`
chartDom.style.height = height
chartDom.id = props.chartId
chartContainer.value.appendChild(chartDom)
const script = document.createElement('script')
script.innerHTML = code
chartContainer.value.appendChild(script)
window[`chart_${props.chartId}`].setStyles(isDark.value ? 'dark' : 'light')
} else {
window[`chart_${props.chartId}`]?.resize()
}

})
observer.value.observe(chartContainer.value)
}
Expand All @@ -229,7 +237,7 @@ watch(isDark, (newValue) => {
onUnmounted(() => {
if (!!props.chartId) {
if (observer.value && chartContainer.value) {
observer.value.unobserve(chartContainer.value)
observer.value.unobserve(chartContainer.value)
}
if (window.klinecharts) {
window.klinecharts.dispose(props.chartId)
Expand All @@ -245,7 +253,7 @@ onUnmounted(() => {
<div
ref="chartContainer"
class="content-item chart">
<Loading v-if="loading"/>
<Loading v-if="loading" className="loading"/>
</div>
<div
class="code-action-container"
Expand Down Expand Up @@ -339,6 +347,12 @@ h3 + .chart-preview {
min-height: 350px;
}

.loading {
background-color: var(--vp-code-block-bg);
border-top-left-radius: 8px;
border-top-right-radius: 8px;
}

.code-action-container {
display: flex;
align-items: center;
Expand Down
46 changes: 35 additions & 11 deletions docs/@components/Loading.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
<template>
<div class="loading">
<div :class="rootClass">
<div class="loader"/>
</div>
</template>

<style scoped>
<script setup>
import { computed } from 'vue'

const props = defineProps({
className: {
type: String,
default: ''
}
})

const rootClass = computed(() => {
return props.className ? `loading ${props.className}` : 'loading'
})
</script>

<style scoped>
.loading {
display: flex;
position: absolute;
Expand All @@ -16,25 +30,35 @@
top: 0;
width: 100%;
height: 100%;
z-index: 10;
background-color: var(--vp-code-block-bg);
border-top-left-radius: 8px;
border-top-right-radius: 8px;
z-index: 100;
color: var(--vp-c-indigo-1);
}

.loader {
width: 14px;
aspect-ratio: 1;
border-radius: 50%;
background: var(--custom-red);
background-color: currentColor;
animation: l2 1.5s infinite;
}
@keyframes l2 {
0%,
100%{transform:translate(-35px);box-shadow: 0 0 var(--vp-c-indigo-1), 0 0 var(--custom-green)}
40% {transform:translate( 35px);box-shadow: -15px 0 var(--vp-c-indigo-1), -30px 0 var(--custom-green)}
50% {transform:translate( 35px);box-shadow: 0 0 var(--vp-c-indigo-1), 0 0 var(--custom-green)}
90% {transform:translate(-35px);box-shadow: 15px 0 var(--vp-c-indigo-1), 30px 0 var(--custom-green)}
100% {
transform: translate(-32px);
box-shadow: 0 0 currentColor, 0 0 currentColor;
}
40% {
transform:translate(32px);
box-shadow: -18px 0 currentColor, -36px 0 currentColor;
}
50% {
transform:translate(32px);
box-shadow: 0 0 currentColor, 0 0 currentColor;
}
90% {
transform:translate(-32px);
box-shadow: 18px 0 currentColor, 36px 0 currentColor;
}
}
</style>

21 changes: 21 additions & 0 deletions docs/@components/Logo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<template>
<svg
:width="props.size"
:height="props.size"
fill="var(--vp-c-indigo-1)"
viewBox="0 0 60 60">
<path d="M27.70969009399414,17.502239227294922L32.70968869399414,17.502239227294922L32.70968869399414,42.49776122729492L27.70969009399414,42.49776122729492L27.70969009399414,17.502239227294922Z"/>
<path d="M43.591396,4.343317L43.591396,3.2574797C39.505386,1.1825904,34.892475,0,29.999985,0C13.430093,0,0,13.427691,0,29.994619C0,39.724049,4.6344047,48.356907,11.806443,53.839802L11.806443,47.131336C7.591393,42.659016,4.9999919,36.627853,4.9999919,29.994619C4.9999919,16.190645,16.193541,4.9990978,29.999985,4.9990978C33.021488,4.9990978,35.913963,5.5366359,38.59137,6.5257206L38.59137,26.844654L43.591362,26.844654L43.591396,4.343317Z"/>
<path d="M48.591386797485356,6.46121883392334L48.591386797485356,13.28795953392334C52.58062179748535,17.71726783392334,54.999978797485355,23.57644783392334,54.999978797485355,29.99465283392334C54.999978797485355,43.79862883392334,43.80642879748535,54.99017583392334,29.999984797485354,54.99017583392334C27.129003797485353,54.99017583392334,24.37631849748535,54.50637683392334,21.806443697485353,53.61407783392334L21.806443697485353,33.08011683392334L16.80645179748535,33.08011683392334L16.80645179748535,55.58145383392334L16.80645179748535,56.94678783392334C20.784941897485353,58.90343383392334,25.26880929748535,60.00000283392334,29.999984797485354,60.00000283392334C46.56987579748535,60.00000283392334,59.999967797485354,46.57231083392334,59.999967797485354,30.00538183392334C60.01073279748535,20.44793783392334,55.54837579748535,11.95484253392334,48.591386797485356,6.46121883392334Z"/>
</svg>
</template>

<script setup>
const props = defineProps({
size: {
type: Number,
default: 60
}
})
</script>

Loading