diff --git a/src/collapse/index.js b/src/collapse/index.ts similarity index 62% rename from src/collapse/index.js rename to src/collapse/index.ts index 4b01579a7..9678fb4a9 100644 --- a/src/collapse/index.js +++ b/src/collapse/index.ts @@ -1,3 +1,3 @@ /* istanbul ignore file */ -export { default as NCollapse } from './src/Collapse.js' +export { default as NCollapse } from './src/Collapse' export { default as NCollapseItem } from './src/CollapseItem.vue' diff --git a/src/collapse/src/Collapse.js b/src/collapse/src/Collapse.ts similarity index 51% rename from src/collapse/src/Collapse.js rename to src/collapse/src/Collapse.ts index d8acba3cb..157a3a9fa 100644 --- a/src/collapse/src/Collapse.js +++ b/src/collapse/src/Collapse.ts @@ -1,27 +1,37 @@ -import { computed, h, markRaw, defineComponent } from 'vue' +import { + computed, + h, + defineComponent, + PropType, + toRef, + reactive, + provide +} from 'vue' import { intersection } from 'lodash-es' import { useTheme } from '../../_mixins' import { call, warn } from '../../_utils' import { collapseLight } from '../styles' -import style from './styles/index.cssr.js' +import type { CollapseThemeVars } from '../styles' +import style from './styles/index.cssr' + +export interface NCollapseInjection { + arrowPlacement: 'left' | 'right' + displayDirective: 'if' | 'show' + expandedNames: string | string[] + collectedItemNames: string[] + toggleItem(collapse: boolean, name: string, event: MouseEvent): void +} export default defineComponent({ name: 'Collapse', - provide () { - return { - NCollapse: this - } - }, props: { ...useTheme.props, expandedNames: { - type: [Array, String], + type: [Array, String] as PropType, default: undefined }, arrowPlacement: { - validator (value) { - return ['left', 'right'].includes(value) - }, + type: String as PropType<'left' | 'right'>, default: 'left' }, accordion: { @@ -29,9 +39,7 @@ export default defineComponent({ default: false }, displayDirective: { - validator (value) { - return ['if', 'show'].includes(value) - }, + type: String as PropType<'if' | 'show'>, default: 'if' }, onItemHeaderClick: { @@ -40,12 +48,13 @@ export default defineComponent({ }, // eslint-disable-next-line vue/prop-name-casing 'onUpdate:expandedNames': { - type: Function, + type: Function as PropType<(expandedNames: string[]) => void>, default: undefined }, // deprecated onExpandedNamesChange: { - validator () { + type: Function, + validator: () => { if (__DEV__) { warn( 'collapse', @@ -58,15 +67,72 @@ export default defineComponent({ } }, setup (props) { - const themeRef = useTheme( + const collectedItemNames: string[] = [] + const themeRef = useTheme( 'Collapse', 'Collapse', style, collapseLight, props ) + function doUpdateExpandedNames (names: string[]) { + const { + 'onUpdate:expandedNames': updateExpandedNames, + onExpandedNamesChange + } = props + if (updateExpandedNames) call(updateExpandedNames, names) + if (onExpandedNamesChange) call(onExpandedNamesChange, names) + } + function doItemHeaderClick (info: { + name: string + expanded: boolean + event: MouseEvent + }) { + const { onItemHeaderClick } = props + if (onItemHeaderClick) call(onItemHeaderClick, info) + } + function toggleItem (collapse: boolean, name: string, event: MouseEvent) { + const { accordion, expandedNames } = props + if (accordion) { + if (collapse) { + doUpdateExpandedNames([name]) + doItemHeaderClick({ name, expanded: true, event }) + } else { + doUpdateExpandedNames([]) + doItemHeaderClick({ name, expanded: false, event }) + } + } else { + if (!Array.isArray(expandedNames)) { + doUpdateExpandedNames([name]) + doItemHeaderClick({ name, expanded: true, event }) + } else { + const activeNames = intersection(expandedNames, collectedItemNames) + const index = activeNames.findIndex( + (activeName) => name === activeName + ) + if (~index) { + activeNames.splice(index, 1) + doUpdateExpandedNames(activeNames) + doItemHeaderClick({ name, expanded: false, event }) + } else { + activeNames.push(name) + doUpdateExpandedNames(activeNames) + doItemHeaderClick({ name, expanded: true, event }) + } + } + } + } + provide( + 'NCollapse', + reactive({ + arrowPlacement: toRef(props, 'arrowPlacement'), + displayDirective: toRef(props, 'displayDirective'), + expandedNames: toRef(props, 'expandedNames'), + collectedItemNames, + toggleItem + }) + ) return { - collectedItemNames: markRaw([]), mergedTheme: themeRef, cssVars: computed(() => { const { @@ -94,53 +160,6 @@ export default defineComponent({ }) } }, - methods: { - doUpdateExpandedNames (...args) { - const { - 'onUpdate:expandedNames': updateExpandedNames, - onExpandedNamesChange - } = this - if (updateExpandedNames) call(updateExpandedNames, ...args) - if (onExpandedNamesChange) call(onExpandedNamesChange, ...args) - }, - doItemHeaderClick (...args) { - const { onItemHeaderClick } = this - if (onItemHeaderClick) call(onItemHeaderClick, ...args) - }, - toggleItem (collapse, name, event) { - if (this.accordion) { - if (collapse) { - this.doUpdateExpandedNames([name]) - this.doItemHeaderClick({ name, expanded: true, event }) - } else { - this.doUpdateExpandedNames([]) - this.doItemHeaderClick({ name, expanded: false, event }) - } - } else { - if (!Array.isArray(this.expandedNames)) { - this.doUpdateExpandedNames([name]) - this.doItemHeaderClick({ name, expanded: true, event }) - } else { - const activeNames = intersection( - this.expandedNames, - this.collectedItemNames - ) - const index = activeNames.findIndex( - (activeName) => name === activeName - ) - if (~index) { - activeNames.splice(index, 1) - this.doUpdateExpandedNames(activeNames) - this.doItemHeaderClick({ name, expanded: false, event }) - } else { - activeNames.push(name) - this.doUpdateExpandedNames(activeNames) - this.doItemHeaderClick({ name, expanded: true, event }) - } - } - } - } - }, render () { return h( 'div', diff --git a/src/collapse/src/CollapseItem.vue b/src/collapse/src/CollapseItem.vue index 14cf4d3cb..6a0b02f56 100644 --- a/src/collapse/src/CollapseItem.vue +++ b/src/collapse/src/CollapseItem.vue @@ -36,12 +36,13 @@ -