UNPKG

naive-ui

Version:

A Vue 3 Component Library. Fairly Complete, Theme Customizable, Uses TypeScript, Fast

186 lines 6.14 kB
import { createId } from 'seemly'; import { useMergedState } from 'vooks'; import { computed, defineComponent, h, provide, ref, toRef } from 'vue'; import { useConfig } from "../../_mixins/index.mjs"; import { call, createInjectionKey, throwError } from "../../_utils/index.mjs"; import NImagePreview from "./ImagePreview.mjs"; import { imagePreviewSharedProps } from "./interface.mjs"; export const imageGroupInjectionKey = createInjectionKey('n-image-group'); export const imageGroupProps = Object.assign(Object.assign({}, imagePreviewSharedProps), { srcList: Array, current: Number, defaultCurrent: { type: Number, default: 0 }, show: { type: Boolean, default: undefined }, defaultShow: Boolean, onUpdateShow: [Function, Array], 'onUpdate:show': [Function, Array], onUpdateCurrent: [Function, Array], 'onUpdate:current': [Function, Array] }); export default defineComponent({ name: 'ImageGroup', props: imageGroupProps, setup(props) { const { mergedClsPrefixRef } = useConfig(props); const groupId = `c${createId()}`; const previewInstRef = ref(null); const uncontrolledShowRef = ref(props.defaultShow); const controlledShowRef = toRef(props, 'show'); const mergedShowRef = useMergedState(controlledShowRef, uncontrolledShowRef); const registeredImageUrlMap = ref(new Map()); const mergedImageUrlMap = computed(() => { if (props.srcList) { const map = new Map(); props.srcList.forEach((url, index) => { map.set(`p${index}`, url); }); return map; } return registeredImageUrlMap.value; }); const imageIdListRef = computed(() => Array.from(mergedImageUrlMap.value.keys())); const imageCountGetter = () => imageIdListRef.value.length; function registerImageUrl(id, url) { if (props.srcList) { throwError('image-group', '`n-image` can\'t be placed inside `n-image-group` when image group\'s `src-list` prop is set.'); } const sid = `r${id}`; if (!registeredImageUrlMap.value.has(`r${sid}`)) { registeredImageUrlMap.value.set(sid, url); } return function unregisterPreviewUrl() { if (!registeredImageUrlMap.value.has(sid)) { registeredImageUrlMap.value.delete(sid); } }; } const uncontrolledCurrentRef = ref(props.defaultCurrent); const controlledCurrentRef = toRef(props, 'current'); const mergedCurrentRef = useMergedState(controlledCurrentRef, uncontrolledCurrentRef); const setCurrentIndex = index => { if (index !== mergedCurrentRef.value) { const { onUpdateCurrent, 'onUpdate:current': _onUpdateCurrent } = props; if (onUpdateCurrent) { call(onUpdateCurrent, index); } if (_onUpdateCurrent) { call(_onUpdateCurrent, index); } uncontrolledCurrentRef.value = index; } }; const currentId = computed(() => imageIdListRef.value[mergedCurrentRef.value]); const setCurrentId = nextId => { const nextIndex = imageIdListRef.value.indexOf(nextId); if (nextIndex !== mergedCurrentRef.value) { setCurrentIndex(nextIndex); } }; const currentUrl = computed(() => mergedImageUrlMap.value.get(currentId.value)); function doUpdateShow(value) { const { onUpdateShow, 'onUpdate:show': _onUpdateShow } = props; if (onUpdateShow) { call(onUpdateShow, value); } if (_onUpdateShow) { call(_onUpdateShow, value); } uncontrolledShowRef.value = value; } function onClose() { doUpdateShow(false); } const nextIndex = computed(() => { const findNext = (start, end) => { for (let i = start; i <= end; i++) { const id = imageIdListRef.value[i]; if (mergedImageUrlMap.value.get(id)) { return i; } } return undefined; }; const next = findNext(mergedCurrentRef.value + 1, imageCountGetter() - 1); return next === undefined ? findNext(0, mergedCurrentRef.value - 1) : next; }); const prevIndex = computed(() => { const findPrev = (start, end) => { for (let i = start; i >= end; i--) { const id = imageIdListRef.value[i]; if (mergedImageUrlMap.value.get(id)) { return i; } } return undefined; }; const prev = findPrev(mergedCurrentRef.value - 1, 0); return prev === undefined ? findPrev(imageCountGetter() - 1, mergedCurrentRef.value + 1) : prev; }); function go(step) { var _a, _b; if (step === 1) { prevIndex.value !== undefined && setCurrentIndex(nextIndex.value); (_a = props.onPreviewNext) === null || _a === void 0 ? void 0 : _a.call(props); } else { nextIndex.value !== undefined && setCurrentIndex(prevIndex.value); (_b = props.onPreviewPrev) === null || _b === void 0 ? void 0 : _b.call(props); } } provide(imageGroupInjectionKey, { mergedClsPrefixRef, registerImageUrl, setThumbnailEl: el => { var _a; (_a = previewInstRef.value) === null || _a === void 0 ? void 0 : _a.setThumbnailEl(el); }, toggleShow: imageId => { doUpdateShow(true); setCurrentId(imageId); }, groupId, renderToolbarRef: toRef(props, 'renderToolbar') }); return { mergedClsPrefix: mergedClsPrefixRef, previewInstRef, mergedShow: mergedShowRef, src: currentUrl, onClose, next: () => { go(1); }, prev: () => { go(-1); } }; }, render() { return h(NImagePreview, { theme: this.theme, themeOverrides: this.themeOverrides, ref: "previewInstRef", onPrev: this.prev, onNext: this.next, src: this.src, show: this.mergedShow, showToolbar: this.showToolbar, showToolbarTooltip: this.showToolbarTooltip, renderToolbar: this.renderToolbar, onClose: this.onClose }, this.$slots); } });