refactor: align
parent
7315bfd03e
commit
184957e3c7
|
@ -1,181 +0,0 @@
|
||||||
import { nextTick, defineComponent } from 'vue';
|
|
||||||
import PropTypes from '../_util/vue-types';
|
|
||||||
import { alignElement, alignPoint } from 'dom-align';
|
|
||||||
import addEventListener from '../vc-util/Dom/addEventListener';
|
|
||||||
import { isWindow, buffer, isSamePoint, restoreFocus, monitorResize } from './util';
|
|
||||||
import { cloneElement } from '../_util/vnode';
|
|
||||||
import { getSlot, findDOMNode } from '../_util/props-util';
|
|
||||||
import useBuffer from './hooks/useBuffer';
|
|
||||||
import isVisible from '../vc-util/Dom/isVisible';
|
|
||||||
|
|
||||||
function getElement(func) {
|
|
||||||
if (typeof func !== 'function' || !func) return null;
|
|
||||||
return func();
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPoint(point) {
|
|
||||||
if (typeof point !== 'object' || !point) return null;
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default defineComponent({
|
|
||||||
props: {
|
|
||||||
childrenProps: PropTypes.object,
|
|
||||||
align: PropTypes.object.isRequired,
|
|
||||||
target: PropTypes.oneOfType([PropTypes.func, PropTypes.object]).def(() => window),
|
|
||||||
monitorBufferTime: PropTypes.number.def(50),
|
|
||||||
monitorWindowResize: PropTypes.looseBool.def(false),
|
|
||||||
disabled: PropTypes.looseBool.def(false),
|
|
||||||
},
|
|
||||||
setup() {
|
|
||||||
return {
|
|
||||||
aligned: false,
|
|
||||||
sourceResizeMonitor: { cancel: () => {} },
|
|
||||||
resizeMonitor: { cancel: () => {} },
|
|
||||||
cacheInfo: {},
|
|
||||||
};
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
this.prevProps = { ...this.$props };
|
|
||||||
const [forceAlign, cancelForceAlign] = useBuffer(this.goAlign, 0);
|
|
||||||
return {
|
|
||||||
forceAlign,
|
|
||||||
cancelForceAlign,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
nextTick(() => {
|
|
||||||
const props = this.$props;
|
|
||||||
// if parent ref not attached .... use document.getElementById
|
|
||||||
!this.aligned && this.forceAlign();
|
|
||||||
if (!props.disabled && props.monitorWindowResize) {
|
|
||||||
this.startMonitorWindowResize();
|
|
||||||
}
|
|
||||||
this.startMonitorElementResize();
|
|
||||||
this.updateCache();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
updated() {
|
|
||||||
nextTick(() => {
|
|
||||||
const prevProps = this.prevProps;
|
|
||||||
const props = this.$props;
|
|
||||||
let reAlign = false;
|
|
||||||
if (!props.disabled) {
|
|
||||||
if (prevProps.disabled) {
|
|
||||||
reAlign = true;
|
|
||||||
} else {
|
|
||||||
const { element: lastElement, point: lastPoint } = this.cacheInfo;
|
|
||||||
const currentElement = getElement(props.target);
|
|
||||||
const currentPoint = getPoint(props.target);
|
|
||||||
if (isWindow(lastElement) && isWindow(currentElement)) {
|
|
||||||
// Skip if is window
|
|
||||||
reAlign = false;
|
|
||||||
} else if (
|
|
||||||
(lastElement && !currentElement && currentPoint) || // Change from element to point
|
|
||||||
(lastPoint && currentPoint && currentElement) // Change from point to element
|
|
||||||
) {
|
|
||||||
reAlign = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reAlign) {
|
|
||||||
this.forceAlign();
|
|
||||||
} else {
|
|
||||||
this.startMonitorElementResize();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (props.monitorWindowResize && !props.disabled) {
|
|
||||||
this.startMonitorWindowResize();
|
|
||||||
} else {
|
|
||||||
this.stopMonitorWindowResize();
|
|
||||||
}
|
|
||||||
this.prevProps = { ...this.$props };
|
|
||||||
this.updateCache();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
beforeUnmount() {
|
|
||||||
this.stopMonitorWindowResize();
|
|
||||||
this.resizeMonitor?.cancel();
|
|
||||||
this.sourceResizeMonitor?.cancel();
|
|
||||||
this.cancelForceAlign();
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
updateCache() {
|
|
||||||
const element = getElement(this.$props.target);
|
|
||||||
const point = getPoint(this.$props.target);
|
|
||||||
this.cacheInfo = {
|
|
||||||
element,
|
|
||||||
point,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
startMonitorElementResize() {
|
|
||||||
const props = this.$props;
|
|
||||||
const { element: lastElement, point: lastPoint } = this.cacheInfo;
|
|
||||||
const currentElement = getElement(props.target);
|
|
||||||
const currentPoint = getPoint(props.target);
|
|
||||||
const source = findDOMNode(this);
|
|
||||||
const { sourceResizeMonitor, resizeMonitor } = this;
|
|
||||||
if (source !== sourceResizeMonitor.element) {
|
|
||||||
sourceResizeMonitor?.cancel();
|
|
||||||
sourceResizeMonitor.element = source;
|
|
||||||
sourceResizeMonitor.cancel = monitorResize(source, this.forceAlign);
|
|
||||||
}
|
|
||||||
if (lastElement !== currentElement || !isSamePoint(lastPoint, currentPoint)) {
|
|
||||||
this.forceAlign();
|
|
||||||
// Add resize observer
|
|
||||||
if (resizeMonitor.element !== currentElement) {
|
|
||||||
resizeMonitor?.cancel();
|
|
||||||
resizeMonitor.element = currentElement;
|
|
||||||
resizeMonitor.cancel = monitorResize(currentElement, this.forceAlign);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
startMonitorWindowResize() {
|
|
||||||
if (!this.resizeHandler) {
|
|
||||||
this.bufferMonitor = buffer(this.forceAlign, this.$props.monitorBufferTime);
|
|
||||||
this.resizeHandler = addEventListener(window, 'resize', this.bufferMonitor);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
stopMonitorWindowResize() {
|
|
||||||
if (this.resizeHandler) {
|
|
||||||
this.bufferMonitor.clear();
|
|
||||||
this.resizeHandler.remove();
|
|
||||||
this.resizeHandler = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
goAlign() {
|
|
||||||
const { disabled, target, align } = this.$props;
|
|
||||||
if (!disabled && target) {
|
|
||||||
const source = findDOMNode(this);
|
|
||||||
let result;
|
|
||||||
const element = getElement(target);
|
|
||||||
const point = getPoint(target);
|
|
||||||
|
|
||||||
// IE lose focus after element realign
|
|
||||||
// We should record activeElement and restore later
|
|
||||||
const activeElement = document.activeElement;
|
|
||||||
if (element && isVisible(element)) {
|
|
||||||
result = alignElement(source, element, align);
|
|
||||||
} else if (point) {
|
|
||||||
result = alignPoint(source, point, align);
|
|
||||||
}
|
|
||||||
restoreFocus(activeElement, source);
|
|
||||||
this.aligned = true;
|
|
||||||
this.$attrs.onAlign && result && this.$attrs.onAlign(source, result);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { childrenProps } = this.$props;
|
|
||||||
const child = getSlot(this);
|
|
||||||
if (child && childrenProps) {
|
|
||||||
return cloneElement(child[0], childrenProps);
|
|
||||||
}
|
|
||||||
return child && child[0];
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
import {
|
||||||
|
defineComponent,
|
||||||
|
PropType,
|
||||||
|
ref,
|
||||||
|
computed,
|
||||||
|
onMounted,
|
||||||
|
onUpdated,
|
||||||
|
watch,
|
||||||
|
onUnmounted,
|
||||||
|
} from 'vue';
|
||||||
|
import { alignElement, alignPoint } from 'dom-align';
|
||||||
|
import addEventListener from '../vc-util/Dom/addEventListener';
|
||||||
|
import { cloneElement } from '../_util/vnode';
|
||||||
|
import isVisible from '../vc-util/Dom/isVisible';
|
||||||
|
|
||||||
|
import { isSamePoint, restoreFocus, monitorResize } from './util';
|
||||||
|
import { AlignType, AlignResult, TargetType, TargetPoint } from './interface';
|
||||||
|
import useBuffer from './hooks/useBuffer';
|
||||||
|
|
||||||
|
type OnAlign = (source: HTMLElement, result: AlignResult) => void;
|
||||||
|
|
||||||
|
export interface AlignProps {
|
||||||
|
align: AlignType;
|
||||||
|
target: TargetType;
|
||||||
|
onAlign?: OnAlign;
|
||||||
|
monitorBufferTime?: number;
|
||||||
|
monitorWindowResize?: boolean;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alignProps = {
|
||||||
|
align: Object as PropType<AlignType>,
|
||||||
|
target: [Object, Function] as PropType<TargetType>,
|
||||||
|
onAlign: Function as PropType<OnAlign>,
|
||||||
|
monitorBufferTime: Number,
|
||||||
|
monitorWindowResize: Boolean,
|
||||||
|
disabled: Boolean,
|
||||||
|
};
|
||||||
|
|
||||||
|
interface MonitorRef {
|
||||||
|
element?: HTMLElement;
|
||||||
|
cancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RefAlign {
|
||||||
|
forceAlign: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElement(func: TargetType) {
|
||||||
|
if (typeof func !== 'function') return null;
|
||||||
|
return func();
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPoint(point: TargetType) {
|
||||||
|
if (typeof point !== 'object' || !point) return null;
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'Align',
|
||||||
|
props: alignProps,
|
||||||
|
emits: ['align'],
|
||||||
|
setup(props, { expose, slots }) {
|
||||||
|
const cacheRef = ref<{ element?: HTMLElement; point?: TargetPoint }>({});
|
||||||
|
const nodeRef = ref();
|
||||||
|
const forceAlignPropsRef = computed(() => ({
|
||||||
|
disabled: props.disabled,
|
||||||
|
target: props.target,
|
||||||
|
onAlign: props.onAlign,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const [forceAlign, cancelForceAlign] = useBuffer(
|
||||||
|
() => {
|
||||||
|
const {
|
||||||
|
disabled: latestDisabled,
|
||||||
|
target: latestTarget,
|
||||||
|
onAlign: latestOnAlign,
|
||||||
|
} = forceAlignPropsRef.value;
|
||||||
|
if (!latestDisabled && latestTarget && nodeRef.value && nodeRef.value.$el) {
|
||||||
|
const source = nodeRef.value.$el;
|
||||||
|
|
||||||
|
let result: AlignResult;
|
||||||
|
const element = getElement(latestTarget);
|
||||||
|
const point = getPoint(latestTarget);
|
||||||
|
|
||||||
|
cacheRef.value.element = element;
|
||||||
|
cacheRef.value.point = point;
|
||||||
|
|
||||||
|
// IE lose focus after element realign
|
||||||
|
// We should record activeElement and restore later
|
||||||
|
const { activeElement } = document;
|
||||||
|
|
||||||
|
// We only align when element is visible
|
||||||
|
if (element && isVisible(element)) {
|
||||||
|
result = alignElement(source, element, props.align);
|
||||||
|
} else if (point) {
|
||||||
|
result = alignPoint(source, point, props.align);
|
||||||
|
}
|
||||||
|
|
||||||
|
restoreFocus(activeElement, source);
|
||||||
|
|
||||||
|
if (latestOnAlign && result) {
|
||||||
|
latestOnAlign(source, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
computed(() => props.monitorBufferTime),
|
||||||
|
);
|
||||||
|
|
||||||
|
// ===================== Effect =====================
|
||||||
|
// Listen for target updated
|
||||||
|
const resizeMonitor = ref<MonitorRef>({
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
// Listen for source updated
|
||||||
|
const sourceResizeMonitor = ref<MonitorRef>({
|
||||||
|
cancel: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
const goAlign = () => {
|
||||||
|
const target = props.target;
|
||||||
|
const element = getElement(target);
|
||||||
|
const point = getPoint(target);
|
||||||
|
|
||||||
|
if (nodeRef.value && nodeRef.value.$el !== sourceResizeMonitor.value.element) {
|
||||||
|
sourceResizeMonitor.value.cancel();
|
||||||
|
sourceResizeMonitor.value.element = nodeRef.value.$el;
|
||||||
|
sourceResizeMonitor.value.cancel = monitorResize(nodeRef.value.$el, forceAlign);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cacheRef.value.element !== element || !isSamePoint(cacheRef.value.point, point)) {
|
||||||
|
forceAlign();
|
||||||
|
|
||||||
|
// Add resize observer
|
||||||
|
if (resizeMonitor.value.element !== element) {
|
||||||
|
resizeMonitor.value.cancel();
|
||||||
|
resizeMonitor.value.element = element;
|
||||||
|
resizeMonitor.value.cancel = monitorResize(element, forceAlign);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
goAlign();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUpdated(() => {
|
||||||
|
goAlign();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Listen for disabled change
|
||||||
|
watch(
|
||||||
|
() => props.disabled,
|
||||||
|
disabled => {
|
||||||
|
if (!disabled) {
|
||||||
|
forceAlign();
|
||||||
|
} else {
|
||||||
|
cancelForceAlign();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
);
|
||||||
|
|
||||||
|
// Listen for window resize
|
||||||
|
const winResizeRef = ref<{ remove: Function }>(null);
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.monitorWindowResize,
|
||||||
|
monitorWindowResize => {
|
||||||
|
if (monitorWindowResize) {
|
||||||
|
if (!winResizeRef.value) {
|
||||||
|
winResizeRef.value = addEventListener(window, 'resize', forceAlign);
|
||||||
|
}
|
||||||
|
} else if (winResizeRef.value) {
|
||||||
|
winResizeRef.value.remove();
|
||||||
|
winResizeRef.value = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ flush: 'post' },
|
||||||
|
);
|
||||||
|
onUnmounted(() => {
|
||||||
|
resizeMonitor.value.cancel();
|
||||||
|
sourceResizeMonitor.value.cancel();
|
||||||
|
if (winResizeRef.value) winResizeRef.value.remove();
|
||||||
|
cancelForceAlign();
|
||||||
|
});
|
||||||
|
|
||||||
|
expose({
|
||||||
|
forceAlign: () => forceAlign(true),
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
const child = slots?.default();
|
||||||
|
if (child) {
|
||||||
|
return cloneElement(child[0], { ref: nodeRef });
|
||||||
|
}
|
||||||
|
return child && child[0];
|
||||||
|
};
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,4 +1,6 @@
|
||||||
export default (callback: () => boolean, buffer: number) => {
|
import { ComputedRef } from '@vue/reactivity';
|
||||||
|
|
||||||
|
export default (callback: () => boolean, buffer: ComputedRef<number>) => {
|
||||||
let called = false;
|
let called = false;
|
||||||
let timeout = null;
|
let timeout = null;
|
||||||
|
|
||||||
|
@ -17,13 +19,13 @@ export default (callback: () => boolean, buffer: number) => {
|
||||||
cancelTrigger();
|
cancelTrigger();
|
||||||
timeout = window.setTimeout(() => {
|
timeout = window.setTimeout(() => {
|
||||||
called = false;
|
called = false;
|
||||||
}, buffer);
|
}, buffer.value);
|
||||||
} else {
|
} else {
|
||||||
cancelTrigger();
|
cancelTrigger();
|
||||||
timeout = window.setTimeout(() => {
|
timeout = window.setTimeout(() => {
|
||||||
called = false;
|
called = false;
|
||||||
trigger();
|
trigger();
|
||||||
}, buffer);
|
}, buffer.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
// based on vc-align 2.4.5
|
// based on rc-align 4.0.9
|
||||||
import Align from './Align';
|
import Align from './Align';
|
||||||
export default Align;
|
export default Align;
|
|
@ -0,0 +1,60 @@
|
||||||
|
/** Two char of 't' 'b' 'c' 'l' 'r'. Example: 'lt' */
|
||||||
|
export type AlignPoint = string;
|
||||||
|
|
||||||
|
export interface AlignType {
|
||||||
|
/**
|
||||||
|
* move point of source node to align with point of target node.
|
||||||
|
* Such as ['tr','cc'], align top right point of source node with center point of target node.
|
||||||
|
* Point can be 't'(top), 'b'(bottom), 'c'(center), 'l'(left), 'r'(right) */
|
||||||
|
points?: AlignPoint[];
|
||||||
|
/**
|
||||||
|
* offset source node by offset[0] in x and offset[1] in y.
|
||||||
|
* If offset contains percentage string value, it is relative to sourceNode region.
|
||||||
|
*/
|
||||||
|
offset?: number[];
|
||||||
|
/**
|
||||||
|
* offset target node by offset[0] in x and offset[1] in y.
|
||||||
|
* If targetOffset contains percentage string value, it is relative to targetNode region.
|
||||||
|
*/
|
||||||
|
targetOffset?: number[];
|
||||||
|
/**
|
||||||
|
* If adjustX field is true, will adjust source node in x direction if source node is invisible.
|
||||||
|
* If adjustY field is true, will adjust source node in y direction if source node is invisible.
|
||||||
|
*/
|
||||||
|
overflow?: {
|
||||||
|
adjustX?: boolean | number;
|
||||||
|
adjustY?: boolean | number;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* Whether use css right instead of left to position
|
||||||
|
*/
|
||||||
|
useCssRight?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether use css bottom instead of top to position
|
||||||
|
*/
|
||||||
|
useCssBottom?: boolean;
|
||||||
|
/**
|
||||||
|
* Whether use css transform instead of left/top/right/bottom to position if browser supports.
|
||||||
|
* Defaults to false.
|
||||||
|
*/
|
||||||
|
useCssTransform?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlignResult {
|
||||||
|
points: AlignPoint[];
|
||||||
|
offset: number[];
|
||||||
|
targetOffset: number[];
|
||||||
|
overflow: {
|
||||||
|
adjustX: boolean | number;
|
||||||
|
adjustY: boolean | number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TargetPoint {
|
||||||
|
clientX?: number;
|
||||||
|
clientY?: number;
|
||||||
|
pageX?: number;
|
||||||
|
pageY?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TargetType = (() => HTMLElement) | TargetPoint;
|
|
@ -1,25 +1,7 @@
|
||||||
import contains from '../vc-util/Dom/contains';
|
import contains from '../vc-util/Dom/contains';
|
||||||
export function buffer(fn, ms) {
|
import { TargetPoint } from './interface';
|
||||||
let timer;
|
|
||||||
|
|
||||||
function clear() {
|
export function isSamePoint(prev: TargetPoint, next: TargetPoint) {
|
||||||
if (timer) {
|
|
||||||
clearTimeout(timer);
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function bufferFn() {
|
|
||||||
clear();
|
|
||||||
timer = setTimeout(fn, ms);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferFn.clear = clear;
|
|
||||||
|
|
||||||
return bufferFn;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isSamePoint(prev, next) {
|
|
||||||
if (prev === next) return true;
|
if (prev === next) return true;
|
||||||
if (!prev || !next) return false;
|
if (!prev || !next) return false;
|
||||||
|
|
||||||
|
@ -34,27 +16,22 @@ export function isSamePoint(prev, next) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isWindow(obj) {
|
|
||||||
return obj && typeof obj === 'object' && obj.window === obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function isSimilarValue(val1, val2) {
|
|
||||||
const int1 = Math.floor(val1);
|
|
||||||
const int2 = Math.floor(val2);
|
|
||||||
return Math.abs(int1 - int2) <= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function restoreFocus(activeElement, container) {
|
export function restoreFocus(activeElement, container) {
|
||||||
// Focus back if is in the container
|
// Focus back if is in the container
|
||||||
if (activeElement !== document.activeElement && contains(container, activeElement)) {
|
if (
|
||||||
|
activeElement !== document.activeElement &&
|
||||||
|
contains(container, activeElement) &&
|
||||||
|
typeof activeElement.focus === 'function'
|
||||||
|
) {
|
||||||
activeElement.focus();
|
activeElement.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function monitorResize(element, callback) {
|
|
||||||
let prevWidth = null;
|
|
||||||
let prevHeight = null;
|
|
||||||
|
|
||||||
function onResize([{ target }]) {
|
export function monitorResize(element: HTMLElement, callback: Function) {
|
||||||
|
let prevWidth: number = null;
|
||||||
|
let prevHeight: number = null;
|
||||||
|
|
||||||
|
function onResize([{ target }]: ResizeObserverEntry[]) {
|
||||||
if (!document.documentElement.contains(target)) return;
|
if (!document.documentElement.contains(target)) return;
|
||||||
const { width, height } = target.getBoundingClientRect();
|
const { width, height } = target.getBoundingClientRect();
|
||||||
const fixedWidth = Math.floor(width);
|
const fixedWidth = Math.floor(width);
|
|
@ -207,7 +207,7 @@
|
||||||
"@simonwep/pickr": "~1.8.0",
|
"@simonwep/pickr": "~1.8.0",
|
||||||
"array-tree-filter": "^2.1.0",
|
"array-tree-filter": "^2.1.0",
|
||||||
"async-validator": "^3.3.0",
|
"async-validator": "^3.3.0",
|
||||||
"dom-align": "^1.10.4",
|
"dom-align": "^1.12.1",
|
||||||
"dom-scroll-into-view": "^2.0.0",
|
"dom-scroll-into-view": "^2.0.0",
|
||||||
"lodash-es": "^4.17.15",
|
"lodash-es": "^4.17.15",
|
||||||
"moment": "^2.27.0",
|
"moment": "^2.27.0",
|
||||||
|
|
2
v2-doc
2
v2-doc
|
@ -1 +1 @@
|
||||||
Subproject commit 4da56dac85f43ad7a288951cbf09d860ecf93bb4
|
Subproject commit a7013ae87f69dcbcf547f4b023255b8a7a775557
|
Loading…
Reference in New Issue