diff --git a/packages/actionsheet/index.js b/packages/actionsheet/index.js deleted file mode 100644 index 6af3d1313..000000000 --- a/packages/actionsheet/index.js +++ /dev/null @@ -1,98 +0,0 @@ -import { use } from '../utils'; -import { PopupMixin } from '../mixins/popup'; -import Icon from '../icon'; -import Loading from '../loading'; -import Popup from '../popup'; - -const [sfc, bem] = use('actionsheet'); - -export default sfc({ - props: { - ...PopupMixin.props, - title: String, - actions: Array, - cancelText: String, - overlay: { - type: Boolean, - default: true - }, - closeOnClickOverlay: { - type: Boolean, - default: true - } - }, - - methods: { - onSelect(event, item) { - event.stopPropagation(); - - if (!item.disabled && !item.loading) { - if (item.callback) { - item.callback(item); - } - - this.$emit('select', item); - } - }, - - onCancel() { - this.$emit('input', false); - this.$emit('cancel'); - } - }, - - render(h) { - const { title, cancelText, onCancel } = this; - - const Header = () => ( -
- {title} - -
- ); - - const Option = item => ( -
{ - this.onSelect(event, item); - }} - > - {item.loading ? ( - - ) : ( - [ - {item.name}, - item.subname && {item.subname} - ] - )} -
- ); - - const Footer = cancelText ? ( -
- {cancelText} -
- ) : ( -
{this.slots()}
- ); - - return ( - { - this.$emit('input', value); - }} - > - {title ? Header() : this.actions.map(Option)} - {Footer} - - ); - } -}); diff --git a/packages/actionsheet/index.tsx b/packages/actionsheet/index.tsx new file mode 100644 index 000000000..72d12312d --- /dev/null +++ b/packages/actionsheet/index.tsx @@ -0,0 +1,119 @@ +import { use } from '../utils'; +import { emit, inherit } from '../utils/functional'; +import { PopupMixin } from '../mixins/popup'; +import Icon from '../icon'; +import Loading from '../loading'; +import Popup from '../popup'; + +// Types +import { CreateElement, RenderContext } from 'vue/types'; +import { DefaultSlots } from '../utils/use/sfc'; +import { PopupMixinProps } from '../mixins/popup/type'; + +export type ActionsheetItem = { + name: string; + subname?: string; + loading?: boolean; + disabled?: boolean; + className?: string; + callback?: (item: ActionsheetItem) => void; +}; + +export type ActionsheetProps = PopupMixinProps & { + title?: string; + actions: ActionsheetItem[]; + cancelText?: string; +}; + +const [sfc, bem] = use('actionsheet'); + +function Actionsheet( + h: CreateElement, + props: ActionsheetProps, + slots: DefaultSlots, + ctx: RenderContext +) { + const { title, cancelText } = props; + + const onCancel = () => { + emit(ctx, 'input', false); + emit(ctx, 'cancel'); + }; + + const Header = () => ( +
+ {title} + +
+ ); + + const Option = (item: ActionsheetItem) => ( +
{ + event.stopPropagation(); + + if (!item.disabled && !item.loading) { + if (item.callback) { + item.callback(item); + } + + emit(ctx, 'select', item); + } + }} + > + {item.loading ? ( + + ) : ( + [ + {item.name}, + item.subname && {item.subname} + ] + )} +
+ ); + + const Footer = cancelText ? ( +
+ {cancelText} +
+ ) : ( +
{slots.default && slots.default()}
+ ); + + return ( + { + emit(ctx, 'input', value); + }} + {...inherit(ctx)} + > + {title ? Header() : props.actions.map(Option)} + {Footer} + + ); +} + +Actionsheet.props = { + ...PopupMixin.props, + title: String, + actions: Array, + cancelText: String, + overlay: { + type: Boolean, + default: true + }, + closeOnClickOverlay: { + type: Boolean, + default: true + } +}; + +export default sfc(Actionsheet); diff --git a/packages/actionsheet/test/index.spec.js b/packages/actionsheet/test/index.spec.js index b51ff3792..e3b5933d7 100644 --- a/packages/actionsheet/test/index.spec.js +++ b/packages/actionsheet/test/index.spec.js @@ -3,6 +3,10 @@ import Actionsheet from '..'; test('callback events', () => { const callback = jest.fn(); + const onInput = jest.fn(); + const onCancel = jest.fn(); + const onSelect = jest.fn(); + const wrapper = mount(Actionsheet, { propsData: { value: true, @@ -11,6 +15,13 @@ test('callback events', () => { { name: 'Option', disabled: true } ], cancelText: 'Cancel' + }, + context: { + on: { + input: onInput, + cancel: onCancel, + select: onSelect + } } }); @@ -20,9 +31,9 @@ test('callback events', () => { wrapper.find('.van-actionsheet__cancel').trigger('click'); expect(callback.mock.calls.length).toBe(1); - expect(wrapper.emitted('cancel')).toBeTruthy(); - expect(wrapper.emitted('input')[0][0]).toBeFalsy(); - expect(wrapper.emitted('select')[0][0]).toBeTruthy(); - expect(wrapper.emitted('select')[0][1]).toBeFalsy(); + expect(onCancel.mock.calls.length).toBeTruthy(); + expect(onInput.mock.calls[0][0]).toBeFalsy(); + expect(onSelect.mock.calls[0][0]).toBeTruthy(); + expect(onSelect.mock.calls[0][1]).toBeFalsy(); expect(wrapper).toMatchSnapshot(); }); diff --git a/packages/mixins/popup/type.ts b/packages/mixins/popup/type.ts new file mode 100644 index 000000000..9694ad6e7 --- /dev/null +++ b/packages/mixins/popup/type.ts @@ -0,0 +1,13 @@ +export type GetContainer = (container: HTMLElement) => void; + +export type PopupMixinProps = { + value: boolean; + zIndex: string | number; + overlay?: boolean; + lockScroll: boolean; + lazyRender: boolean; + overlayClass?: any; + overlayStyle?: object | object[]; + getContainer?: string | GetContainer; + closeOnClickOverlay?: boolean; +};