Commit 7db0c5c49f23a4ab4958b3f73d47516deafa6166

Authored by vben
1 parent 10cd4fcd

fix: add an example of markdown embedded in the form #138

CHANGELOG.zh_CN.md
... ... @@ -4,6 +4,7 @@
4 4  
5 5 - 新增 `v-ripple`水波纹指令
6 6 - 新增左侧菜单混合模式
  7 +- 新增 markdown 嵌入表单内示例
7 8  
8 9 ### 🐛 Bug Fixes
9 10  
... ...
src/components/Container/src/ScrollContainer.vue
... ... @@ -4,6 +4,7 @@
4 4 :wrapClass="`scrollbar__wrap`"
5 5 :viewClass="`scrollbar__view`"
6 6 class="scroll-container"
  7 + v-bind="$attrs"
7 8 >
8 9 <slot />
9 10 </Scrollbar>
... ...
src/components/Markdown/src/index.vue
... ... @@ -2,14 +2,25 @@
2 2 <div class="markdown" ref="wrapRef" />
3 3 </template>
4 4 <script lang="ts">
5   - import { defineComponent, ref, onMounted, unref, onUnmounted, nextTick, watchEffect } from 'vue';
  5 + import {
  6 + defineComponent,
  7 + ref,
  8 + onMounted,
  9 + unref,
  10 + onUnmounted,
  11 + nextTick,
  12 + // watch,
  13 + computed,
  14 + } from 'vue';
6 15 import Vditor from 'vditor';
7 16 import 'vditor/dist/index.css';
8 17  
9 18 import { propTypes } from '/@/utils/propTypes';
  19 + import { useLocale } from '/@/hooks/web/useLocale';
10 20  
  21 + type Lang = 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' | undefined;
11 22 export default defineComponent({
12   - emits: ['update:value'],
  23 + emits: ['change'],
13 24 props: {
14 25 height: propTypes.number.def(360),
15 26 value: propTypes.string.def(''),
... ... @@ -19,17 +30,42 @@
19 30 const vditorRef = ref<Nullable<Vditor>>(null);
20 31 const initedRef = ref(false);
21 32  
  33 + const lang = ref<Lang>();
  34 +
  35 + const { getLang } = useLocale();
  36 +
  37 + const getCurrentLang = computed((): 'zh_CN' | 'en_US' | 'ja_JP' | 'ko_KR' => {
  38 + switch (unref(getLang)) {
  39 + case 'en':
  40 + lang.value = 'en_US';
  41 + break;
  42 + case 'ja':
  43 + lang.value = 'ja_JP';
  44 + break;
  45 + case 'ko':
  46 + lang.value = 'ko_KR';
  47 + break;
  48 + default:
  49 + lang.value = 'zh_CN';
  50 + }
  51 + return lang.value;
  52 + });
22 53 function init() {
23 54 const wrapEl = unref(wrapRef);
24 55 if (!wrapEl) return;
25 56 const bindValue = { ...attrs, ...props };
26 57 vditorRef.value = new Vditor(wrapEl, {
  58 + lang: unref(getCurrentLang),
27 59 mode: 'sv',
28 60 preview: {
29 61 actions: [],
30 62 },
31 63 input: (v) => {
32   - emit('update:value', v);
  64 + // emit('update:value', v);
  65 + emit('change', v);
  66 + },
  67 + blur: () => {
  68 + unref(vditorRef)?.setValue(props.value);
33 69 },
34 70 ...bindValue,
35 71 cache: {
... ... @@ -39,14 +75,20 @@
39 75 initedRef.value = true;
40 76 }
41 77  
42   - watchEffect(() => {
43   - nextTick(() => {
44   - const vditor = unref(vditorRef);
45   - if (unref(initedRef) && props.value && vditor) {
46   - vditor.setValue(props.value);
47   - }
48   - });
49   - });
  78 + // watch(
  79 + // () => props.value,
  80 + // () => {
  81 + // nextTick(() => {
  82 + // const vditor = unref(vditorRef);
  83 + // if (unref(initedRef) && props.value && vditor) {
  84 + // vditor.setValue(props.value);
  85 + // }
  86 + // });
  87 + // },
  88 + // {
  89 + // immediate: true,
  90 + // }
  91 + // );
50 92  
51 93 onMounted(() => {
52 94 nextTick(() => {
... ...
src/components/Scrollbar/index.ts
... ... @@ -5,7 +5,7 @@
5 5 import { withInstall } from '../util';
6 6  
7 7 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
8   -export const Scrollbar = createAsyncComponent(() => import('./src/Scrollbar'));
  8 +export const Scrollbar = createAsyncComponent(() => import('./src/index.vue'));
9 9  
10 10 withInstall(Scrollbar);
11 11  
... ...
src/components/Scrollbar/src/Bar.tsx deleted 100644 → 0
1   -import type { PropType } from 'vue';
2   -
3   -import { renderThumbStyle, BAR_MAP } from './util';
4   -import { defineComponent, computed, unref, inject, Ref, reactive, ref, onBeforeUnmount } from 'vue';
5   -import { on, off } from '/@/utils/domUtils';
6   -
7   -export default defineComponent({
8   - name: 'Bar',
9   - props: {
10   - vertical: {
11   - type: Boolean as PropType<boolean>,
12   - default: false,
13   - },
14   - size: String as PropType<string>,
15   - move: Number as PropType<number>,
16   - },
17   - setup(props) {
18   - const thumbRef = ref<Nullable<HTMLDivElement>>(null);
19   - const elRef = ref<Nullable<HTMLDivElement>>(null);
20   - const commonState = reactive<Indexable>({});
21   - const getBarRef = computed(() => {
22   - return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
23   - });
24   - const parentElRef = inject('scroll-bar-wrap') as Ref<Nullable<HTMLDivElement>>;
25   -
26   - function clickThumbHandler(e: any) {
27   - const { ctrlKey, button, currentTarget } = e;
28   - // prevent click event of right button
29   - if (ctrlKey || button === 2 || !currentTarget) {
30   - return;
31   - }
32   - startDrag(e);
33   - const bar = unref(getBarRef);
34   - commonState[bar.axis] =
35   - currentTarget[bar.offset] -
36   - (e[bar.client as keyof typeof e] - currentTarget.getBoundingClientRect()[bar.direction]);
37   - }
38   -
39   - function clickTrackHandler(e: any) {
40   - const bar = unref(getBarRef);
41   - const offset = Math.abs(e.target.getBoundingClientRect()[bar.direction] - e[bar.client]);
42   - const thumbEl = unref(thumbRef) as any;
43   - const parentEl = unref(parentElRef) as any;
44   - const el = unref(elRef) as any;
45   - if (!thumbEl || !el || !parentEl) return;
46   - const thumbHalf = thumbEl[bar.offset] / 2;
47   - const thumbPositionPercentage = ((offset - thumbHalf) * 100) / el[bar.offset];
48   - parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100;
49   - }
50   -
51   - function startDrag(e: Event) {
52   - e.stopImmediatePropagation();
53   - commonState.cursorDown = true;
54   -
55   - on(document, 'mousemove', mouseMoveDocumentHandler);
56   - on(document, 'mouseup', mouseUpDocumentHandler);
57   - document.onselectstart = () => false;
58   - }
59   -
60   - function mouseMoveDocumentHandler(e: any) {
61   - if (commonState.cursorDown === false) return;
62   - const bar = unref(getBarRef);
63   - const prevPage = commonState[bar.axis];
64   - const el = unref(elRef) as any;
65   - const parentEl = unref(parentElRef) as any;
66   - const thumbEl = unref(thumbRef) as any;
67   - if (!prevPage || !el || !thumbEl || !parentEl) return;
68   - const rect = el.getBoundingClientRect() as any;
69   - const offset = (rect[bar.direction] - e[bar.client]) * -1;
70   - const thumbClickPosition = thumbEl[bar.offset] - prevPage;
71   - const thumbPositionPercentage = ((offset - thumbClickPosition) * 100) / el[bar.offset];
72   -
73   - parentEl[bar.scroll] = (thumbPositionPercentage * parentEl[bar.scrollSize]) / 100;
74   - }
75   -
76   - function mouseUpDocumentHandler() {
77   - const bar = unref(getBarRef);
78   - commonState.cursorDown = false;
79   - commonState[bar.axis] = 0;
80   - off(document, 'mousemove', mouseMoveDocumentHandler);
81   - document.onselectstart = null;
82   - }
83   -
84   - onBeforeUnmount(() => {
85   - off(document, 'mouseup', mouseUpDocumentHandler);
86   - });
87   - return () => {
88   - const bar = unref(getBarRef);
89   - const { size, move } = props;
90   - return (
91   - <div
92   - class={['scrollbar__bar', 'is-' + bar.key]}
93   - onMousedown={clickTrackHandler}
94   - ref={elRef}
95   - >
96   - <div
97   - ref={thumbRef}
98   - class="scrollbar__thumb"
99   - onMousedown={clickThumbHandler}
100   - style={renderThumbStyle({ size, move, bar })}
101   - />
102   - </div>
103   - );
104   - };
105   - },
106   -});
src/components/Scrollbar/src/Scrollbar.tsx deleted 100644 → 0
1   -import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent';
2   -import scrollbarWidth from '/@/utils/scrollbarWidth';
3   -import { toObject } from './util';
4   -import Bar from './Bar';
5   -import { isString } from '/@/utils/is';
6   -import {
7   - defineComponent,
8   - PropType,
9   - unref,
10   - reactive,
11   - ref,
12   - provide,
13   - onMounted,
14   - nextTick,
15   - onBeforeUnmount,
16   -} from 'vue';
17   -import { getSlot } from '/@/utils/helper/tsxHelper';
18   -import './index.less';
19   -import { useExpose } from '/@/hooks/core/useExpose';
20   -import { ScrollbarType } from './types';
21   -
22   -export default defineComponent({
23   - name: 'Scrollbar',
24   - props: {
25   - native: Boolean as PropType<boolean>,
26   - wrapStyle: {
27   - type: Object as PropType<any>,
28   - },
29   - wrapClass: { type: String as PropType<string>, required: false },
30   - viewClass: { type: String as PropType<string> },
31   - viewStyle: { type: Object as PropType<any> },
32   - noresize: Boolean as PropType<boolean>,
33   - tag: {
34   - type: String as PropType<string>,
35   - default: 'div',
36   - },
37   - },
38   - setup(props, { slots }) {
39   - const resizeRef = ref<Nullable<HTMLDivElement>>(null);
40   - const wrapElRef = ref<Nullable<HTMLDivElement>>(null);
41   - provide('scroll-bar-wrap', wrapElRef);
42   - const state = reactive({
43   - sizeWidth: '0',
44   - sizeHeight: '0',
45   - moveX: 0,
46   - moveY: 0,
47   - });
48   -
49   - function handleScroll() {
50   - const warpEl = unref(wrapElRef);
51   - if (!warpEl) return;
52   - const { scrollTop, scrollLeft, clientHeight, clientWidth } = warpEl;
53   -
54   - state.moveY = (scrollTop * 100) / clientHeight;
55   - state.moveX = (scrollLeft * 100) / clientWidth;
56   - }
57   - function update() {
58   - const warpEl = unref(wrapElRef);
59   - if (!warpEl) return;
60   - const { scrollHeight, scrollWidth, clientHeight, clientWidth } = warpEl;
61   - const heightPercentage = (clientHeight * 100) / scrollHeight;
62   - const widthPercentage = (clientWidth * 100) / scrollWidth;
63   -
64   - state.sizeHeight = heightPercentage < 100 ? heightPercentage + '%' : '';
65   - state.sizeWidth = widthPercentage < 100 ? widthPercentage + '%' : '';
66   - }
67   -
68   - onMounted(() => {
69   - useExpose<ScrollbarType>({
70   - wrap: unref(wrapElRef),
71   - });
72   - const { native, noresize } = props;
73   - const resizeEl = unref(resizeRef);
74   - const warpEl = unref(wrapElRef);
75   - if (native || !resizeEl || !warpEl) return;
76   - nextTick(update);
77   - if (!noresize) {
78   - addResizeListener(resizeEl, update);
79   - addResizeListener(warpEl, update);
80   - }
81   - });
82   - onBeforeUnmount(() => {
83   - const { native, noresize } = props;
84   - const resizeEl = unref(resizeRef);
85   - const warpEl = unref(wrapElRef);
86   - if (native || !resizeEl || !warpEl) return;
87   - if (!noresize) {
88   - removeResizeListener(resizeEl, update);
89   - removeResizeListener(warpEl, update);
90   - }
91   - });
92   - return () => {
93   - const { native, tag, viewClass, viewStyle, wrapClass, wrapStyle } = props;
94   - let style: any = wrapStyle;
95   - const gutter = scrollbarWidth();
96   -
97   - if (gutter) {
98   - const gutterWith = `-${gutter}px`;
99   - const gutterStyle = `margin-bottom: ${gutterWith}; margin-right: ${gutterWith};`;
100   -
101   - if (Array.isArray(wrapStyle)) {
102   - style = toObject(wrapStyle);
103   - style.marginRight = style.marginBottom = gutterWith;
104   - } else if (isString(wrapStyle)) {
105   - style += gutterStyle;
106   - } else {
107   - style = gutterStyle;
108   - }
109   - }
110   -
111   - const Tag = tag as any;
112   - const view = (
113   - <Tag class={['scrollbar__view', viewClass]} style={viewStyle} ref={resizeRef}>
114   - {getSlot(slots)}
115   - </Tag>
116   - );
117   - const wrap = (
118   - <div
119   - ref={wrapElRef}
120   - style={style}
121   - onScroll={handleScroll}
122   - class={[wrapClass, 'scrollbar__wrap', gutter ? '' : 'scrollbar__wrap--hidden-default']}
123   - >
124   - {[view]}
125   - </div>
126   - );
127   - let nodes: any[] = [];
128   - const { moveX, sizeWidth, moveY, sizeHeight } = state;
129   - if (!native) {
130   - nodes = [
131   - wrap,
132   - /* eslint-disable */
133   - <Bar move={moveX} size={sizeWidth}></Bar>,
134   - <Bar vertical move={moveY} size={sizeHeight}></Bar>,
135   - ];
136   - } else {
137   - nodes = [
138   - <div ref="wrap" class={[wrapClass, 'scrollbar__wrap']} style={style}>
139   - {[view]}
140   - </div>,
141   - ];
142   - }
143   - return <div class="scrollbar">{nodes}</div>;
144   - };
145   - },
146   -});
src/components/Scrollbar/src/bar.ts 0 → 100644
  1 +import {
  2 + defineComponent,
  3 + h,
  4 + computed,
  5 + ref,
  6 + getCurrentInstance,
  7 + onUnmounted,
  8 + inject,
  9 + Ref,
  10 +} from 'vue';
  11 +import { on, off } from '/@/utils/domUtils';
  12 +
  13 +import { renderThumbStyle, BAR_MAP } from './util';
  14 +
  15 +export default defineComponent({
  16 + name: 'Bar',
  17 +
  18 + props: {
  19 + vertical: Boolean,
  20 + size: String,
  21 + move: Number,
  22 + },
  23 +
  24 + setup(props) {
  25 + const instance = getCurrentInstance();
  26 + const thumb = ref<any>(null);
  27 + const wrap = inject('scroll-bar-wrap', {} as Ref<Nullable<HTMLElement>>) as any;
  28 + const bar = computed(() => {
  29 + return BAR_MAP[props.vertical ? 'vertical' : 'horizontal'];
  30 + });
  31 + const barStore = ref<Indexable>({});
  32 + const cursorDown = ref<any>(null);
  33 + const clickThumbHandler = (e: any) => {
  34 + // prevent click event of right button
  35 + if (e.ctrlKey || e.button === 2) {
  36 + return;
  37 + }
  38 + startDrag(e);
  39 + barStore.value[bar.value.axis] =
  40 + e.currentTarget[bar.value.offset] -
  41 + (e[bar.value.client] - e.currentTarget.getBoundingClientRect()[bar.value.direction]);
  42 + };
  43 +
  44 + const clickTrackHandler = (e: any) => {
  45 + const offset = Math.abs(
  46 + e.target.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]
  47 + );
  48 + const thumbHalf = thumb.value[bar.value.offset] / 2;
  49 + const thumbPositionPercentage =
  50 + ((offset - thumbHalf) * 100) / instance?.vnode.el?.[bar.value.offset];
  51 +
  52 + wrap.value[bar.value.scroll] =
  53 + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
  54 + };
  55 + const startDrag = (e: any) => {
  56 + e.stopImmediatePropagation();
  57 + cursorDown.value = true;
  58 + on(document, 'mousemove', mouseMoveDocumentHandler);
  59 + on(document, 'mouseup', mouseUpDocumentHandler);
  60 + document.onselectstart = () => false;
  61 + };
  62 +
  63 + const mouseMoveDocumentHandler = (e: any) => {
  64 + if (cursorDown.value === false) return;
  65 + const prevPage = barStore.value[bar.value.axis];
  66 +
  67 + if (!prevPage) return;
  68 +
  69 + const offset =
  70 + (instance?.vnode.el?.getBoundingClientRect()[bar.value.direction] - e[bar.value.client]) *
  71 + -1;
  72 + const thumbClickPosition = thumb.value[bar.value.offset] - prevPage;
  73 + const thumbPositionPercentage =
  74 + ((offset - thumbClickPosition) * 100) / instance?.vnode.el?.[bar.value.offset];
  75 + wrap.value[bar.value.scroll] =
  76 + (thumbPositionPercentage * wrap.value[bar.value.scrollSize]) / 100;
  77 + };
  78 +
  79 + function mouseUpDocumentHandler() {
  80 + cursorDown.value = false;
  81 + barStore.value[bar.value.axis] = 0;
  82 + off(document, 'mousemove', mouseMoveDocumentHandler);
  83 + document.onselectstart = null;
  84 + }
  85 +
  86 + onUnmounted(() => {
  87 + off(document, 'mouseup', mouseUpDocumentHandler);
  88 + });
  89 +
  90 + return () =>
  91 + h(
  92 + 'div',
  93 + {
  94 + class: ['scrollbar__bar', 'is-' + bar.value.key],
  95 + onMousedown: clickTrackHandler,
  96 + },
  97 + h('div', {
  98 + ref: thumb,
  99 + class: 'scrollbar__thumb',
  100 + onMousedown: clickThumbHandler,
  101 + style: renderThumbStyle({
  102 + size: props.size,
  103 + move: props.move,
  104 + bar: bar.value,
  105 + }),
  106 + })
  107 + );
  108 + },
  109 +});
... ...
src/components/Scrollbar/src/index.less deleted 100644 → 0
1   -.scrollbar {
2   - position: relative;
3   - overflow: hidden;
4   -
5   - &__wrap {
6   - height: 100%;
7   - overflow: scroll;
8   -
9   - &--hidden-default {
10   - scrollbar-width: none;
11   -
12   - &::-webkit-scrollbar {
13   - width: 0;
14   - height: 0;
15   - }
16   - }
17   - }
18   -
19   - &__thumb {
20   - position: relative;
21   - display: block;
22   - width: 0;
23   - height: 0;
24   - cursor: pointer;
25   - background-color: rgba(144, 147, 153, 0.3);
26   - border-radius: inherit;
27   - transition: 0.3s background-color;
28   -
29   - &:hover {
30   - background-color: rgba(144, 147, 153, 0.5);
31   - }
32   - }
33   -
34   - &__bar {
35   - position: absolute;
36   - right: 2px;
37   - bottom: 2px;
38   - z-index: 1;
39   - border-radius: 4px;
40   - opacity: 0;
41   - -webkit-transition: opacity 80ms ease;
42   - transition: opacity 80ms ease;
43   -
44   - &.is-vertical {
45   - top: 2px;
46   - width: 5px;
47   -
48   - & > div {
49   - width: 100%;
50   - }
51   - }
52   -
53   - &.is-horizontal {
54   - left: 2px;
55   - height: 5px;
56   -
57   - & > div {
58   - height: 100%;
59   - }
60   - }
61   - }
62   -}
63   -
64   -.scrollbar:active > .scrollbar__bar,
65   -.scrollbar:focus > .scrollbar__bar,
66   -.scrollbar:hover > .scrollbar__bar {
67   - opacity: 1;
68   - transition: opacity 180ms ease;
69   -}
src/components/Scrollbar/src/index.vue 0 → 100644
  1 +<template>
  2 + <div class="scrollbar">
  3 + <div
  4 + ref="wrap"
  5 + :class="[wrapClass, 'scrollbar__wrap', native ? '' : 'scrollbar__wrap--hidden-default']"
  6 + :style="style"
  7 + @scroll="handleScroll"
  8 + >
  9 + <component :is="tag" ref="resize" :class="['scrollbar__view', viewClass]" :style="viewStyle">
  10 + <slot></slot>
  11 + </component>
  12 + </div>
  13 + <template v-if="!native">
  14 + <bar :move="moveX" :size="sizeWidth" />
  15 + <bar vertical :move="moveY" :size="sizeHeight" />
  16 + </template>
  17 + </div>
  18 +</template>
  19 +<script lang="ts">
  20 + import { addResizeListener, removeResizeListener } from '/@/utils/event/resizeEvent';
  21 +
  22 + import { toObject } from './util';
  23 + import {
  24 + defineComponent,
  25 + ref,
  26 + onMounted,
  27 + onBeforeUnmount,
  28 + nextTick,
  29 + provide,
  30 + computed,
  31 + } from 'vue';
  32 + import Bar from './bar';
  33 +
  34 + export default defineComponent({
  35 + name: 'Scrollbar',
  36 + components: { Bar },
  37 + props: {
  38 + native: {
  39 + type: Boolean,
  40 + default: false,
  41 + },
  42 + wrapStyle: {
  43 + type: [String, Array],
  44 + default: '',
  45 + },
  46 + wrapClass: {
  47 + type: [String, Array],
  48 + default: '',
  49 + },
  50 + viewClass: {
  51 + type: [String, Array],
  52 + default: '',
  53 + },
  54 + viewStyle: {
  55 + type: [String, Array],
  56 + default: '',
  57 + },
  58 + noresize: Boolean, // 如果 container 尺寸不会发生变化,最好设置它可以优化性能
  59 + tag: {
  60 + type: String,
  61 + default: 'div',
  62 + },
  63 + },
  64 + setup(props) {
  65 + const sizeWidth = ref('0');
  66 + const sizeHeight = ref('0');
  67 + const moveX = ref(0);
  68 + const moveY = ref(0);
  69 + const wrap = ref<any>(null);
  70 + const resize = ref<any>(null);
  71 +
  72 + provide('scroll-bar-wrap', wrap);
  73 +
  74 + const handleScroll = () => {
  75 + if (!props.native) {
  76 + moveY.value = (wrap.value.scrollTop * 100) / wrap.value.clientHeight;
  77 + moveX.value = (wrap.value.scrollLeft * 100) / wrap.value.clientWidth;
  78 + }
  79 + };
  80 +
  81 + const update = () => {
  82 + if (!wrap.value) return;
  83 +
  84 + const heightPercentage = (wrap.value.clientHeight * 100) / wrap.value.scrollHeight;
  85 + const widthPercentage = (wrap.value.clientWidth * 100) / wrap.value.scrollWidth;
  86 +
  87 + sizeHeight.value = heightPercentage < 100 ? heightPercentage + '%' : '';
  88 + sizeWidth.value = widthPercentage < 100 ? widthPercentage + '%' : '';
  89 + };
  90 +
  91 + onMounted(() => {
  92 + if (props.native) return;
  93 + nextTick(update);
  94 + !props.noresize && addResizeListener(resize.value, update);
  95 + });
  96 +
  97 + onBeforeUnmount(() => {
  98 + if (props.native) return;
  99 + !props.noresize && removeResizeListener(resize.value, update);
  100 + });
  101 + const style = computed(() => {
  102 + let style: any = props.wrapStyle;
  103 + if (Array.isArray(props.wrapStyle)) {
  104 + style = toObject(props.wrapStyle);
  105 + }
  106 + return style;
  107 + });
  108 + return {
  109 + moveX,
  110 + moveY,
  111 + sizeWidth,
  112 + sizeHeight,
  113 + style,
  114 + wrap,
  115 + resize,
  116 + update,
  117 + handleScroll,
  118 + };
  119 + },
  120 + });
  121 +</script>
  122 +<style lang="less">
  123 + .scrollbar {
  124 + position: relative;
  125 + height: 100%;
  126 + overflow: hidden;
  127 +
  128 + &__wrap {
  129 + height: 100%;
  130 + overflow: scroll;
  131 +
  132 + &--hidden-default {
  133 + scrollbar-width: none;
  134 +
  135 + &::-webkit-scrollbar {
  136 + display: none;
  137 + width: 0;
  138 + height: 0;
  139 + opacity: 0;
  140 + }
  141 + }
  142 + }
  143 +
  144 + &__thumb {
  145 + position: relative;
  146 + display: block;
  147 + width: 0;
  148 + height: 0;
  149 + cursor: pointer;
  150 + background-color: rgba(144, 147, 153, 0.3);
  151 + border-radius: inherit;
  152 + transition: 0.3s background-color;
  153 +
  154 + &:hover {
  155 + background-color: rgba(144, 147, 153, 0.5);
  156 + }
  157 + }
  158 +
  159 + &__bar {
  160 + position: absolute;
  161 + right: 2px;
  162 + bottom: 2px;
  163 + z-index: 1;
  164 + border-radius: 4px;
  165 + opacity: 0;
  166 + -webkit-transition: opacity 80ms ease;
  167 + transition: opacity 80ms ease;
  168 +
  169 + &.is-vertical {
  170 + top: 2px;
  171 + width: 6px;
  172 +
  173 + & > div {
  174 + width: 100%;
  175 + }
  176 + }
  177 +
  178 + &.is-horizontal {
  179 + left: 2px;
  180 + height: 6px;
  181 +
  182 + & > div {
  183 + height: 100%;
  184 + }
  185 + }
  186 + }
  187 + }
  188 +
  189 + .scrollbar:active > .scrollbar__bar,
  190 + .scrollbar:focus > .scrollbar__bar,
  191 + .scrollbar:hover > .scrollbar__bar {
  192 + opacity: 1;
  193 + transition: opacity 340ms ease-out;
  194 + }
  195 +</style>
... ...
src/components/Transition/src/ExpandTransition.vue
... ... @@ -59,6 +59,8 @@
59 59 if (el.scrollHeight !== 0) {
60 60 // for safari: add class after set height, or it will jump to zero height suddenly, weired
61 61 addClass(el, 'collapse-transition');
  62 + // in vue3.0.4, transitionProperty is set 'none' to avoid 'v-leave-from' issue
  63 + el.style.transitionProperty = 'height';
62 64 el.style.height = 0;
63 65 el.style.paddingTop = 0;
64 66 el.style.paddingBottom = 0;
... ...
src/locales/types.ts
1   -export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja';
  1 +export type LocaleType = 'zh_CN' | 'en' | 'ru' | 'ja' | 'ko';
... ...
src/router/menus/modules/demo/comp.ts
... ... @@ -180,6 +180,16 @@ const menu: MenuModule = {
180 180 {
181 181 path: 'markdown',
182 182 name: t('routes.demo.editor.markdown'),
  183 + children: [
  184 + {
  185 + path: 'index',
  186 + name: t('routes.demo.editor.tinymceBasic'),
  187 + },
  188 + {
  189 + path: 'editor',
  190 + name: t('routes.demo.editor.tinymceForm'),
  191 + },
  192 + ],
183 193 },
184 194 {
185 195 path: 'tinymce',
... ...
src/router/routes/modules/demo/comp.ts
... ... @@ -288,12 +288,32 @@ const comp: AppRouteModule = {
288 288 children: [
289 289 {
290 290 path: 'markdown',
  291 + component: getParentLayout('MarkdownDemo'),
291 292 name: 'MarkdownDemo',
292   - component: () => import('/@/views/demo/editor/Markdown.vue'),
293 293 meta: {
294 294 title: t('routes.demo.editor.markdown'),
295 295 },
  296 + redirect: '/comp/editor/markdown/index',
  297 + children: [
  298 + {
  299 + path: 'index',
  300 + name: 'MarkDownBasicDemo',
  301 + component: () => import('/@/views/demo/editor/markdown/index.vue'),
  302 + meta: {
  303 + title: t('routes.demo.editor.tinymceBasic'),
  304 + },
  305 + },
  306 + {
  307 + path: 'editor',
  308 + name: 'MarkDownFormDemo',
  309 + component: () => import('/@/views/demo/editor/markdown/Editor.vue'),
  310 + meta: {
  311 + title: t('routes.demo.editor.tinymceForm'),
  312 + },
  313 + },
  314 + ],
296 315 },
  316 +
297 317 {
298 318 path: 'tinymce',
299 319 component: getParentLayout('TinymceDemo'),
... ...
src/views/demo/editor/markdown/Editor.vue 0 → 100644
  1 +<template>
  2 + <div class="m-4">
  3 + <CollapseContainer title="MarkDown表单">
  4 + <BasicForm
  5 + :labelWidth="100"
  6 + :schemas="schemas"
  7 + :actionColOptions="{ span: 24 }"
  8 + @submit="handleSubmit"
  9 + >
  10 + </BasicForm>
  11 + </CollapseContainer>
  12 + </div>
  13 +</template>
  14 +<script lang="ts">
  15 + import { defineComponent, h } from 'vue';
  16 + import { BasicForm, FormSchema } from '/@/components/Form/index';
  17 + import { CollapseContainer } from '/@/components/Container/index';
  18 + import { useMessage } from '/@/hooks/web/useMessage';
  19 + import { MarkDown } from '/@/components/Markdown';
  20 +
  21 + const schemas: FormSchema[] = [
  22 + {
  23 + field: 'title',
  24 + component: 'Input',
  25 + label: 'title',
  26 + defaultValue: '标题',
  27 + rules: [{ required: true }],
  28 + },
  29 + {
  30 + field: 'markdown',
  31 + component: 'Input',
  32 + label: 'markdown',
  33 + defaultValue: 'defaultValue',
  34 + rules: [{ required: true, trigger: 'blur' }],
  35 + render: ({ model, field }) => {
  36 + return h(MarkDown, {
  37 + value: model[field],
  38 + onChange: (value: string) => {
  39 + model[field] = value;
  40 + },
  41 + });
  42 + },
  43 + },
  44 + ];
  45 + export default defineComponent({
  46 + components: { BasicForm, CollapseContainer },
  47 + setup() {
  48 + const { createMessage } = useMessage();
  49 +
  50 + return {
  51 + schemas,
  52 + handleSubmit: (values: any) => {
  53 + createMessage.success('click search,values:' + JSON.stringify(values));
  54 + },
  55 + };
  56 + },
  57 + });
  58 +</script>
... ...
src/views/demo/editor/Markdown.vue renamed to src/views/demo/editor/markdown/index.vue
1 1 <template>
2 2 <div class="p-4">
3 3 <a-button @click="toggleTheme" class="mb-2" type="primary">黑暗主题</a-button>
4   - <MarkDown v-model:value="value" ref="markDownRef" />
  4 + <MarkDown :value="value" @change="handleChange" ref="markDownRef" />
5 5 </div>
6 6 </template>
7 7 <script lang="ts">
... ... @@ -23,10 +23,16 @@
23 23 const vditor = markDown.getVditor();
24 24 vditor.setTheme('dark');
25 25 }
  26 +
  27 + function handleChange(v: string) {
  28 + valueRef.value = v;
  29 + }
  30 +
26 31 return {
27 32 value: valueRef,
28 33 toggleTheme,
29 34 markDownRef,
  35 + handleChange,
30 36 };
31 37 },
32 38 });
... ...
tsconfig.json
... ... @@ -15,16 +15,11 @@
15 15 "noUnusedLocals": true,
16 16 "noUnusedParameters": true,
17 17 "experimentalDecorators": true,
18   - "lib": [
19   - "dom",
20   - "esnext"
21   - ],
  18 + "lib": ["dom", "esnext"],
22 19 "incremental": true,
23 20 "skipLibCheck": true,
24 21 "paths": {
25   - "/@/*": [
26   - "src/*"
27   - ]
  22 + "/@/*": ["src/*"]
28 23 }
29 24 },
30 25 "plugins": [
... ... @@ -32,15 +27,6 @@
32 27 "name": "@vuedx/typescript-plugin-vue"
33 28 }
34 29 ],
35   - "include": [
36   - "src/**/*.ts",
37   - "src/**/*.d.ts",
38   - "src/**/*.tsx",
39   - "src/**/*.vue"
40   - ],
41   - "exclude": [
42   - "node_modules",
43   - "dist",
44   - "**/*.js"
45   - ]
  30 + "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
  31 + "exclude": ["node_modules", "dist", "**/*.js"]
46 32 }
... ...