diff --git a/CHANGELOG.md b/CHANGELOG.md index afb1ec8a6..0eedcb150 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,22 +4,8 @@ All notable changes to this project will be documented in this file. Dates are d Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). -#### [2.33.0](https://github.com/ant-design/ant-design-mini/compare/2.32.0...2.33.0) - -#### [2.32.0](https://github.com/ant-design/ant-design-mini/compare/2.31.2...2.32.0) - -- Detele functional mini [`#1204`](https://github.com/ant-design/ant-design-mini/pull/1204) -- feat: calendar组件去掉hook实现 [`#1201`](https://github.com/ant-design/ant-design-mini/pull/1201) -- feat: notice-bar微信版本支持icon插槽 [`#1196`](https://github.com/ant-design/ant-design-mini/pull/1196) -- Feat no hook picker [`#1199`](https://github.com/ant-design/ant-design-mini/pull/1199) -- feat: lazy component [`#1197`](https://github.com/ant-design/ant-design-mini/pull/1197) -- Feat no hook picker [`#1192`](https://github.com/ant-design/ant-design-mini/pull/1192) -- Feat no hook 2 [`#1189`](https://github.com/ant-design/ant-design-mini/pull/1189) - #### [2.31.2](https://github.com/ant-design/ant-design-mini/compare/2.31.1...2.31.2) -> 16 May 2024 - #### [2.31.1](https://github.com/ant-design/ant-design-mini/compare/2.31.0...2.31.1) > 16 May 2024 diff --git a/compiled/alipay/demo/pages/Calendar/collapse-container/cn-day/cn-day.js b/compiled/alipay/demo/pages/Calendar/collapse-container/cn-day/cn-day.js index b5675af23..a68de7a51 100644 --- a/compiled/alipay/demo/pages/Calendar/collapse-container/cn-day/cn-day.js +++ b/compiled/alipay/demo/pages/Calendar/collapse-container/cn-day/cn-day.js @@ -1,38 +1,21 @@ import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import Converter from './js-calendar-converter'; -import { Component, getValueFromProps } from '../../../../../src/_util/simply'; -Component({ +import { mountComponent } from '../../../../../src/_util/component'; +const CollapseContainer = (props) => { + var _a, _b, _c; + const time = dayjs((_a = props.cell) === null || _a === void 0 ? void 0 : _a.time); + const vs = Converter.solar2lunar(time.get('year'), time.get('month') + 1, time.get('date')); + if (vs === -1) { + return { + cnday: '', + }; + } + return { + cnday: vs.lunarFestival || vs.festival || vs.IDayCn, + festival: !!vs.festival || !!vs.lunarFestival, + unset: ((_b = props.cell) === null || _b === void 0 ? void 0 : _b.isSelectedBegin) || ((_c = props.cell) === null || _c === void 0 ? void 0 : _c.isSelectedEnd), + }; +}; +mountComponent(CollapseContainer, { cell: null, -}, { - updateData() { - const cell = getValueFromProps(this, 'cell'); - const time = dayjs(cell === null || cell === void 0 ? void 0 : cell.time); - const vs = Converter.solar2lunar(time.get('year'), time.get('month') + 1, time.get('date')); - if (vs === -1) { - this.setData({ - cnday: '', - }); - return; - } - this.setData({ - cnday: vs.lunarFestival || vs.festival || vs.IDayCn, - festival: !!vs.festival || !!vs.lunarFestival, - unset: (cell === null || cell === void 0 ? void 0 : cell.isSelectedBegin) || (cell === null || cell === void 0 ? void 0 : cell.isSelectedEnd), - }); - }, -}, { - cnday: '', - festival: '', - unset: '', -}, null, { - onInit() { - this.updateData(); - }, - didUpdate(prevProps) { - const cell = getValueFromProps(this, 'cell'); - if (!equal(prevProps.cell, cell)) { - this.updateData(); - } - }, }); diff --git a/compiled/alipay/demo/pages/Calendar/collapse-container/collapse-container.js b/compiled/alipay/demo/pages/Calendar/collapse-container/collapse-container.js index c430dba14..eb2ee114b 100644 --- a/compiled/alipay/demo/pages/Calendar/collapse-container/collapse-container.js +++ b/compiled/alipay/demo/pages/Calendar/collapse-container/collapse-container.js @@ -1,30 +1,19 @@ -import { Component, getValueFromProps } from '../../../../src/_util/simply'; -Component({ +import { useEvent, useState } from 'functional-mini/component'; +import { mountComponent } from '../../../../src/_util/component'; +const CollapseContainer = (props) => { + var _a; + const [collapse, setCollapse] = useState((_a = props.defaultCollapse) !== null && _a !== void 0 ? _a : true); + useEvent('handleToggle', () => { + setCollapse((v) => !v); + }); + return { + collapse, + internalHide: props.hide, + containerTitle: props.title, + }; +}; +mountComponent(CollapseContainer, { hide: false, defaultCollapse: null, title: '', -}, { - handleToggle() { - const { collapse } = this.data; - this.setData({ - collapse: !collapse, - }); - }, -}, { - collapse: true, - internalHide: false, - containerTitle: '', -}, null, { - onInit() { - const [defaultCollapse, hide, title] = getValueFromProps(this, [ - 'defaultCollapse', - 'hide', - 'title', - ]); - this.setData({ - collapse: defaultCollapse !== null && defaultCollapse !== void 0 ? defaultCollapse : true, - internalHide: hide, - containerTitle: title, - }); - }, }); diff --git a/compiled/alipay/src/ActionSheet/index.json b/compiled/alipay/src/ActionSheet/index.json index bea48a2cb..e1a7501d8 100644 --- a/compiled/alipay/src/ActionSheet/index.json +++ b/compiled/alipay/src/ActionSheet/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-popup": "../Popup/index" } diff --git a/compiled/alipay/src/Avatar/index.json b/compiled/alipay/src/Avatar/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Avatar/index.json +++ b/compiled/alipay/src/Avatar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Badge/index.json b/compiled/alipay/src/Badge/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Badge/index.json +++ b/compiled/alipay/src/Badge/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Button/index.json b/compiled/alipay/src/Button/index.json index bdf0e3a8f..f6bbf1425 100644 --- a/compiled/alipay/src/Button/index.json +++ b/compiled/alipay/src/Button/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "loading": "../Loading/index", "ant-icon": "../Icon/index" diff --git a/compiled/alipay/src/Calendar/index.json b/compiled/alipay/src/Calendar/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Calendar/index.json +++ b/compiled/alipay/src/Calendar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Calendar/index.ts b/compiled/alipay/src/Calendar/index.ts index 738161432..5e12a4af9 100644 --- a/compiled/alipay/src/Calendar/index.ts +++ b/compiled/alipay/src/Calendar/index.ts @@ -1,223 +1,244 @@ import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; -import { Component, triggerEvent, getValueFromProps } from '../_util/simply'; +import { + useComponent, + useEvent, + useReady, + useState, + useEffect, +} from 'functional-mini/component'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { triggerRefEvent } from '../_util/hooks/useReportRef'; +import { hasValue, useMergedState } from '../_util/hooks/useMergedState'; import { CalendarValue, CellState, defaultLocaleText, - CalendarDefaultProps, + ICalendarProps, } from './props'; import { + defaultMonthRange, getMonthListFromRange, getSelectionModeFromValue, renderCells, getScrollIntoViewId, } from './utils'; -import mixinValue from '../mixins/value'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; - -Component( - CalendarDefaultProps, - { - getInstance() { - if (this.$id) { - return my; - } - return this; - }, - async getBoundingClientRect(query: string) { - return await getInstanceBoundingClientRect(this.getInstance(), query); - }, - scrollIntoView(value) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - }, - clickCell(e) { - const time = e.currentTarget.dataset.time; - const clickDate = dayjs(time.time); - if (time.disabled) { - return; - } - const value = this.getValue(); - const selectionModeFromValue = getSelectionModeFromValue(value); - const selectionMode = - getValueFromProps(this, 'selectionMode') ?? - selectionModeFromValue ?? - 'range'; - if (selectionMode === 'range') { - if (Array.isArray(value)) { - if (value.length === 1) { - const current = value[0]; - if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) { - this.updateValue([clickDate.toDate().getTime()]); - } else { - this.updateValue([value[0], clickDate.toDate().getTime()]); - } + +function getBoundingClientRect(instance: any, selector: string) { + return new Promise((resolve, reject) => { + instance + .createSelectorQuery() + .select(selector) + .boundingClientRect() + .exec((ret) => { + if (ret && ret[0]) { + resolve(ret[0]); + } else { + reject(); + } + }); + }); +} + +const Calendar = (props: ICalendarProps) => { + const localeText = Object.assign({}, defaultLocaleText, props.localeText); + + const markItems = [...localeText.weekdayNames]; + const weekStartsOn = props.weekStartsOn; + if (weekStartsOn === 'Sunday') { + const item = markItems.pop(); + if (item) markItems.unshift(item); + } + + const [value, setValue] = useMergedState(props.defaultValue, { + value: props.value, + }); + + const [scrollIntoViewId, setScrollIntoViewId] = useState(''); + + useEvent('scrollIntoView', (value) => { + updateScrollIntoViewId(getScrollIntoViewId(value)); + }); + + triggerRefEvent(); + + // scroll 触发滚动之后需要重置 scrollIntoViewId + function updateScrollIntoViewId(id) { + setScrollIntoViewId(id); + + const timer = setTimeout(() => { + setScrollIntoViewId(''); + clearTimeout(timer); + }); + } + + const selectionModeFromValue = getSelectionModeFromValue(value); + const selectionMode = + props.selectionMode ?? selectionModeFromValue ?? 'range'; + + const { triggerEvent } = useComponentEvent(props); + function updateValue(newValue: CalendarValue) { + const isControl = hasValue(props.value); + triggerEvent('change', newValue); + if (!isControl) { + setValue(newValue); + } + } + + useEvent('clickCell', (e) => { + const time = e.currentTarget.dataset.time; + const clickDate = dayjs(time.time); + if (time.disabled) { + return; + } + if (selectionMode === 'range') { + if (Array.isArray(value)) { + if (value.length === 1) { + const current = value[0]; + if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) { + updateValue([clickDate.toDate().getTime()]); } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([value[0], clickDate.toDate().getTime()]); } } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([clickDate.toDate().getTime()]); } - } else if (selectionMode === 'single') { - this.updateValue(clickDate.toDate().getTime()); - } - }, - setCurrentMonth(e) { - this.setData({ headerState: e.month }); - }, - measurement() { - const { elementSize } = this.data; - // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 - // 此时需要重新计算 - if (!elementSize || elementSize.cellHight === 0) { - this.measurementFn(); + } else { + updateValue([clickDate.toDate().getTime()]); } - }, - measurementFn() { - Promise.all([ - this.getBoundingClientRect('.ant-calendar-body-container'), - this.getBoundingClientRect('.ant-calendar-cells'), - this.getBoundingClientRect('.ant-calendar-title-container'), - ]) - .then(([bodyContainer, cellContainer, Title]) => { - // 滚动的时候 top 和 bottom 等尺寸会变 - // 所以只能依赖 height 来计算 - const paddingHeight = - bodyContainer.height - cellContainer.height - Title.height; - const monthTitleHeight = Title.height + paddingHeight; - const cellHight = - cellContainer.height / (this.data.monthList[0].cells.length / 7); - this.setData({ - elementSize: { - monthTitleHeight, - cellHight, - paddingHeight, - }, - }); - }) - .catch(() => { - this.setData({ elementSize: null }); - }); - }, - - // scroll 触发滚动之后需要重置 scrollIntoViewId - updateScrollIntoViewId(id) { - this.setData({ scrollIntoViewId: id }); - const timer = setTimeout(() => { - this.setData({ scrollIntoViewId: '' }); - clearTimeout(timer); - }); - }, + } else if (selectionMode === 'single') { + updateValue(clickDate.toDate().getTime()); + } + }); - updateValue(newValue: CalendarValue) { - triggerEvent(this, 'change', newValue); - if (!this.isControlled()) { - this.update(newValue); - } - }, - updateData() { - const [monthRange, plocaleText, pweekStartsOn, onFormatter] = - getValueFromProps(this, [ - 'monthRange', - 'localeText', - 'weekStartsOn', - 'onFormatter', - ]); - const localeText = Object.assign({}, defaultLocaleText, plocaleText); - const markItems = [...localeText.weekdayNames]; - const weekStartsOn = pweekStartsOn; - if (weekStartsOn === 'Sunday') { - const item = markItems.pop(); - if (item) markItems.unshift(item); - } - const value = this.getValue(); - const monthList = getMonthListFromRange( - dayjs(monthRange?.[0]), - dayjs(monthRange?.[1]) - ).map((p) => { - let cells = renderCells(p, weekStartsOn, value, localeText); - if (onFormatter && typeof onFormatter === 'function') { - cells = cells.map((o): CellState => { - const { + const monthList = getMonthListFromRange( + dayjs(props.monthRange[0]), + dayjs(props.monthRange[1]) + ).map((p) => { + let cells = renderCells(p, weekStartsOn, value, localeText); + if (props.onFormatter && typeof props.onFormatter === 'function') { + cells = cells.map((o): CellState => { + const { + time, + top, + bottom, + disabled, + isSelectedBegin, + isSelectedEnd, + isSelected, + } = o; + const newState = + props.onFormatter( + { time, - top, - bottom, + top: top ? { ...top } : undefined, + bottom: bottom ? { ...bottom } : undefined, disabled, isSelectedBegin, isSelectedEnd, isSelected, - } = o; - const newState = - onFormatter( - { - time, - top: top ? { ...top } : undefined, - bottom: bottom ? { ...bottom } : undefined, - disabled, - isSelectedBegin, - isSelectedEnd, - isSelected, - }, - value - ) ?? {}; - const result = { ...o }; - if (typeof newState === 'object') { - // 只允许修改三个字段 - ['top', 'bottom', 'disabled'].forEach((key) => { - if (key in newState) { - result[key] = newState[key]; - } - }); + }, + value + ) ?? {}; + const result = { ...o }; + if (typeof newState === 'object') { + // 只允许修改三个字段 + ['top', 'bottom', 'disabled'].forEach((key) => { + if (key in newState) { + result[key] = newState[key]; } - return result; }); } - return { - title: p.format(localeText.title), - cells, - }; + return result; }); + } + return { + title: p.format(localeText.title), + cells, + }; + }); - this.setData({ markItems, monthList }); - }, - }, - { - elementSize: null, - markItems: [], - monthList: [], - headerState: 0, - scrollIntoViewId: '', - }, - [mixinValue()], - { - didMount() { - this.updateData(); - this.measurementFn(); - // 初始化默认值时,滚动到选中位置 - const [value, defaultValue] = getValueFromProps(this, [ - 'value', - 'defaultValue', - ]); - if (this.isControlled()) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - } else { - defaultValue && - this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue)); - } - }, - didUpdate(prevProps, prevData) { - if (!this.isEqualValue(prevData)) { - // 滚动到已选的位置 - const changedScrollIntoView = getValueFromProps( - this, - 'changedScrollIntoView' - ); - changedScrollIntoView && - this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue())); - } - if (!equal(prevProps, this.props) || !this.isEqualValue(prevData)) { - this.updateData(); - } - }, + const [headerState, setHeaderState] = useState(0); + + useEvent('setCurrentMonth', (e) => { + setHeaderState(e.month); + }); + + const [elementSize, setElementSize] = useState<{ + monthTitleHeight: number; + cellHight: number; + paddingHeight: number; + }>(null); + + const componentInstance = useComponent(); + + function measurement() { + Promise.all([ + getBoundingClientRect(componentInstance, '.ant-calendar-body-container'), + getBoundingClientRect(componentInstance, '.ant-calendar-cells'), + getBoundingClientRect(componentInstance, '.ant-calendar-title-container'), + ]) + .then(([bodyContainer, cellContainer, Title]) => { + // 滚动的时候 top 和 bottom 等尺寸会变 + // 所以只能依赖 height 来计算 + const paddingHeight = + bodyContainer.height - cellContainer.height - Title.height; + const monthTitleHeight = Title.height + paddingHeight; + const cellHight = + cellContainer.height / (monthList[0].cells.length / 7); + setElementSize({ + monthTitleHeight, + cellHight, + paddingHeight, + }); + }) + .catch(() => { + setElementSize(null); + }); } -); + + useEffect(() => { + // 滚动到已选的位置 + props.changedScrollIntoView && + updateScrollIntoViewId(getScrollIntoViewId(value)); + }, [value]); + + useReady(() => { + measurement(); + // 初始化默认值时,滚动到选中位置 + const isControl = hasValue(props.value); + if (isControl) { + updateScrollIntoViewId(getScrollIntoViewId(props.value)); + } else { + props.defaultValue && + updateScrollIntoViewId(getScrollIntoViewId(props.defaultValue)); + } + }, []); + + useEvent('measurement', () => { + // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 + // 此时需要重新计算 + if (!elementSize || elementSize.cellHight === 0) { + measurement(); + } + }); + + return { + elementSize, + markItems, + monthList, + headerState, + scrollIntoViewId, + }; +}; + +mountComponent(Calendar, { + defaultValue: null, + value: null, + selectionMode: 'range', + monthRange: defaultMonthRange(), + weekStartsOn: 'Sunday', + localeText: defaultLocaleText, + onFormatter: null, + changedScrollIntoView: null, +}); diff --git a/compiled/alipay/src/Calendar/props.ts b/compiled/alipay/src/Calendar/props.ts index e06386972..54891430c 100644 --- a/compiled/alipay/src/Calendar/props.ts +++ b/compiled/alipay/src/Calendar/props.ts @@ -1,5 +1,4 @@ import { IBaseProps } from '../_util/base'; -import { defaultMonthRange } from './utils'; export interface CalendarDate { year: number; @@ -143,14 +142,3 @@ export interface ICalendarProps extends IBaseProps { currentValue: CalendarValue ) => Pick; } - -export const CalendarDefaultProps = { - defaultValue: null, - value: null, - selectionMode: 'range', - monthRange: defaultMonthRange(), - weekStartsOn: 'Sunday', - localeText: defaultLocaleText, - onFormatter: null, - changedScrollIntoView: null, -}; diff --git a/compiled/alipay/src/Checkbox/CheckboxGroup/index.json b/compiled/alipay/src/Checkbox/CheckboxGroup/index.json index a29721990..c7460b750 100644 --- a/compiled/alipay/src/Checkbox/CheckboxGroup/index.json +++ b/compiled/alipay/src/Checkbox/CheckboxGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/compiled/alipay/src/Checkbox/index.json b/compiled/alipay/src/Checkbox/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Checkbox/index.json +++ b/compiled/alipay/src/Checkbox/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Checklist/ChecklistItem/index.json b/compiled/alipay/src/Checklist/ChecklistItem/index.json index ffa3220f6..3a037cbf8 100644 --- a/compiled/alipay/src/Checklist/ChecklistItem/index.json +++ b/compiled/alipay/src/Checklist/ChecklistItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index" } diff --git a/compiled/alipay/src/Checklist/index.json b/compiled/alipay/src/Checklist/index.json index 6fdd09a19..402e290e9 100644 --- a/compiled/alipay/src/Checklist/index.json +++ b/compiled/alipay/src/Checklist/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-checklist-item": "./ChecklistItem/index", "ant-icon": "../Icon/index" diff --git a/compiled/alipay/src/Collapse/index.json b/compiled/alipay/src/Collapse/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Collapse/index.json +++ b/compiled/alipay/src/Collapse/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Container/index.json b/compiled/alipay/src/Container/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Container/index.json +++ b/compiled/alipay/src/Container/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/DatePicker/RangePicker/hooks.ts b/compiled/alipay/src/DatePicker/RangePicker/hooks.ts new file mode 100644 index 000000000..c9b08d127 --- /dev/null +++ b/compiled/alipay/src/DatePicker/RangePicker/hooks.ts @@ -0,0 +1,76 @@ +import { useEvent as useStableCallback } from '../../_util/hooks/useEvent'; +import dayjs from 'dayjs'; +import { useCallback } from 'functional-mini/component'; + +export const useFormatValue = (props) => { + function defaultFormat(date, valueStrs) { + const { format, splitCharacter } = props; + if (format && valueStrs && valueStrs[0] && valueStrs[1]) { + return valueStrs.join(`${splitCharacter}`); + } + return ''; + } + + const onFormat = useStableCallback((realValue) => { + const { onFormat, format } = props; + const formatValueByProps = + onFormat && + onFormat( + realValue, + realValue + ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) + : null + ); + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; + } + return defaultFormat( + realValue, + realValue + ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) + : null + ); + }); + return onFormat; +}; + +export function useMinAndMax() { + const getMin = useStableCallback((min) => { + return min ? dayjs(min as any) : dayjs().subtract(10, 'year'); + }); + + const getMax = useStableCallback((max) => { + return max ? dayjs(max as any) : dayjs().add(10, 'year'); + }); + + return { + getMin, + getMax, + }; +} + +function defaultFormatLabel(type, value) { + const suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return `${value}${suffixMap[type]}`; +} +export const useFormatLabel = (onFormatLabel) => { + return useCallback( + (type, value) => { + if (typeof onFormatLabel === 'function') { + const formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { + return String(formatValueByProps); + } + } + return defaultFormatLabel(type, value); + }, + [onFormatLabel] + ); +}; diff --git a/compiled/alipay/src/DatePicker/RangePicker/index.axml b/compiled/alipay/src/DatePicker/RangePicker/index.axml index 6022c2427..389862bda 100644 --- a/compiled/alipay/src/DatePicker/RangePicker/index.axml +++ b/compiled/alipay/src/DatePicker/RangePicker/index.axml @@ -23,7 +23,7 @@ formattedValueText="{{ formattedValueText }}" className="ant-range-picker {{ className || '' }}" popClassName="{{ !currentStartDate || !currentEndDate ? 'ant-range-picker-confirm-disabled' : '' }} {{ popClassName || '' }}" - visible="{{ visible }}" + visible="{{ state.visible }}" style="{{ style }}" animationType="{{ animationType }}" options="{{ columns }}" diff --git a/compiled/alipay/src/DatePicker/RangePicker/index.json b/compiled/alipay/src/DatePicker/RangePicker/index.json index c124b8511..b2e493fb4 100644 --- a/compiled/alipay/src/DatePicker/RangePicker/index.json +++ b/compiled/alipay/src/DatePicker/RangePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index", "ant-picker": "../../Picker/index" diff --git a/compiled/alipay/src/DatePicker/RangePicker/index.ts b/compiled/alipay/src/DatePicker/RangePicker/index.ts index 6623c5956..a9e9dc70a 100644 --- a/compiled/alipay/src/DatePicker/RangePicker/index.ts +++ b/compiled/alipay/src/DatePicker/RangePicker/index.ts @@ -1,356 +1,183 @@ -import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { DateRangePickerDefaultProps } from './props'; +import { useState, useEvent, useEffect, useMemo } from 'functional-mini/component'; +import { DateRangePickerFunctionalProps, IDateRangePickerProps } from './props'; import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from '../util'; -import computed from '../../mixins/computed'; -import mixinValue from '../../mixins/value'; - -Component( - DateRangePickerDefaultProps, - { - // visible受控判断 - isVisibleControlled() { - return 'visible' in getValueFromProps(this); - }, - computed() { - const { currentStartDate, currentEndDate, pickerType } = this.data; - const format = getValueFromProps(this, 'format'); +import { useMixState } from '../../_util/hooks/useMixState'; +import { useFormatValue, useMinAndMax, useFormatLabel } from './hooks'; +import { useDateState } from './useDateState'; +import { mountComponent } from '../../_util/component'; +import { PickerValue } from '../props'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; - if (pickerType) +const RangePicker = (props: IDateRangePickerProps) => { + const [realValue, { isControlled, update }] = useMixState( + props.defaultValue, + { + value: props.value, + postState(value) { return { - currentStartValueStr: currentStartDate - ? dayjs(currentStartDate).format(format) - : '', - currentEndValueStr: currentEndDate - ? dayjs(currentEndDate).format(format) - : '', + valid: true, + value: + value && value[0] && value[1] + ? ([ + dayjs(value[0]).toDate(), + dayjs(value[1]).toDate(), + ] as PickerValue[]) + : undefined, }; - }, - getMin(min) { - return min ? dayjs(min as any) : dayjs().subtract(10, 'year'); - }, - - getMax(max) { - return max ? dayjs(max as any) : dayjs().add(10, 'year'); - }, - // didUpdate、弹窗打开、切换pickerType触发 - setCurrentValue(currentProps) { - const { pickerVisible } = this; // 隐藏状态下从CValue触发,展开状态使用当前数据 - const { precision } = currentProps; - const { pickerType, columns } = this.data; - const realValue = this.getValue(); - let { currentStartDate, currentEndDate } = this.data; - const currentStartDateByCValue = realValue?.[0] || null; - const currentEndDateByCValue = realValue?.[1] || null; + }, + } + ); + const { dateState, init, changeType, updateValue } = useDateState(props); + const { triggerEvent, triggerEventValues, triggerEventOnly } = + useComponentEvent(props); + const [{ columns, currentValue }, doUpdateColumns] = useState({ + currentValue: [], + columns: [], + }); + const onFormat = useFormatValue(props); + const { currentStartValueStr, currentEndValueStr } = useMemo(() => { + return { + currentStartValueStr: dateState.start + ? dayjs(dateState.start).format(props.format) + : '', + currentEndValueStr: dateState.end + ? dayjs(dateState.end).format(props.format) + : '', + }; + }, [props.format, dateState.start, dateState.end]); - // 展开状态,说明在切换pickerType - if (pickerVisible) { - if (pickerType === 'start') { - if (!currentStartDate) { - currentStartDate = currentEndDate; - } - } else { - // pickerType=end start已存在 - // 结束时间默认选中开始 - if (!currentEndDate) { - currentEndDate = currentStartDate; - } - } - } else { - // 否则是在从cValue初始化 - currentStartDate = currentStartDateByCValue; - currentEndDate = currentEndDateByCValue; - // 开始默认取优先取当前时间,不在时间范围内取开始时间 - if (!currentStartDate) { - const min = this.getMin(currentProps.min).toDate(); - const { max } = currentProps; - currentStartDate = new Date(); - if ( - (min && dayjs(currentStartDate).isBefore(min, precision)) || - (max && dayjs(currentStartDate).isAfter(max, precision)) || - (currentEndDateByCValue && - currentStartDate > currentEndDateByCValue) - ) { - currentStartDate = min; - } - } - } - const currentValue = getValueByDate( - pickerType === 'start' ? currentStartDate : currentEndDate, - precision - ); - const newColumns = this.generateData(currentValue, currentProps); - if (!equal(newColumns, columns)) { - this.setData({ columns: newColumns }, () => { - this.setData({ - currentStartDate, - currentEndDate, - currentValue, - formattedValueText: this.onFormat(), - }); - }); - } else { - this.setData({ - currentStartDate, - currentEndDate, - currentValue, - formattedValueText: this.onFormat(), - }); - } - }, - /** - * 生成选项数据,didmound、picker change、打开弹窗、切换picker type触发 - */ - generateData(currentValue, currentProps) { - const { precision, min: propsMin, max: propsMax } = currentProps; - const min = this.getMin(propsMin); - const max = this.getMax(propsMax); - if (max < min) { - return []; - } - let currentPickerDay = dayjs(); - if (currentValue.length > 0) { - currentPickerDay = dayjs(getDateByValue(currentValue)); - } - if (currentPickerDay < min || currentPickerDay > max) { - currentPickerDay = min; - } + const onFormatLabel = useFormatLabel(props.onFormatLabel); - const newColumns = getRangeData( - precision, - min, - max, - currentPickerDay, - this.onFormatLabel.bind(this) - ); - return newColumns; - }, + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); - onChange(selectedIdx) { - let [selectedIndex] = resolveEventValues(getValidValue(selectedIdx)); - const [format, precision, pmax, pmin] = getValueFromProps(this, [ - 'format', - 'precision', - 'max', - 'min', - ]); - let date = getDateByValue(selectedIndex); - const min = this.getMin(pmin); - const max = this.getMax(pmax); - if (dayjs(date).isBefore(min)) { - date = min.toDate(); - selectedIndex = getValueByDate(date, precision); - } - if (dayjs(date).isAfter(max)) { - date = max.toDate(); - selectedIndex = getValueByDate(date, precision); - } - const { pickerType, columns, currentEndDate, currentStartDate } = - this.data; - const newData: any = { - currentValue: selectedIndex, - formattedValueText: this.onFormat(), - }; - if (pickerType === 'start') { - newData.currentStartDate = date; - if (currentEndDate && dayjs(date).isAfter(currentEndDate)) { - newData.currentEndDate = null; - } - } else { - newData.currentEndDate = date; - if (currentStartDate && dayjs(date).isBefore(currentStartDate)) { - newData.currentStartDate = null; - } - } - const newColumns = this.generateData( - selectedIndex, - getValueFromProps(this) - ); - if (!equal(newColumns, columns)) { - this.setData( - { - columns: newColumns, - }, - () => { - this.setData(newData); - triggerEventValues(this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); - } + useEffect(() => { + setTimeout(() => { + if (visible) { + const state = init(realValue); + const currentValue = getValueByDate( + state.pickerType === 'start' ? state.start : state.end, + props.precision ); - } else { - this.setData(newData); - triggerEventValues(this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); + updateColumns(currentValue, props); } - }, + }) + }, [visible]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, + function updateColumns(currentValue, currentProps) { + const { precision, min: propsMin, max: propsMax } = currentProps; + const min = getMin(propsMin); + const max = getMax(propsMax); + if (max < min) { + return []; + } + let currentPickerDay = dayjs(); + if (currentValue.length > 0) { + currentPickerDay = dayjs(getDateByValue(currentValue)); + } + if (currentPickerDay < min || currentPickerDay > max) { + currentPickerDay = min; + } - onOk() { - const format = getValueFromProps(this, 'format'); - const { currentStartDate, currentEndDate } = this.data; - const realValue = [currentStartDate, currentEndDate] as any; - if (!this.isControlled()) { - this.update(realValue); - } - triggerEventValues(this, 'ok', [ - realValue, - realValue.map((v) => dayjs(v).format(format)), - ]); - }, - onFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - const formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return String(formatValueByProps); - } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel(type, value) { - const suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return `${value}${suffixMap[type]}`; - }, - defaultFormat(date, valueStrs) { - const [format, splitCharacter] = getValueFromProps(this, [ - 'format', - 'splitCharacter', - ]); - if (format && valueStrs && valueStrs[0] && valueStrs[1]) { - return valueStrs.join(`${splitCharacter}`); - } - return ''; - }, - onFormat() { - const [onFormat, format] = getValueFromProps(this, [ - 'onFormat', - 'format', - ]); - const realValue = this.getValue(); - const formatValueByProps = - onFormat && - onFormat( - realValue, - realValue - ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) - : null - ); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat( - realValue, - realValue - ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) - : null - ); - }, - /** - * 显示/隐藏切换 - * @param visible - */ - onVisibleChange(visible) { - if (!this.isVisibleControlled() && visible) { - this.setData({ pickerType: 'start' }); - this.setCurrentValue(getValueFromProps(this)); - this.pickerVisible = visible; - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - onChangeCurrentPickerType(e) { - const { type } = e.currentTarget.dataset; - const { pickerType } = this.data; - if (type !== pickerType) { - this.setData({ - pickerType: type, - }); - this.setCurrentValue(getValueFromProps(this)); - } - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、切换开始结束、picker变化时更新 - columns: [], // 当前可选项,didmound、弹窗打开、切换开始结束、picker变化时更新 - pickerType: 'start' as 'start' | 'end', - currentStartDate: null, // 展开时开始时间,date格式,有value,则取value[0],否则取当天,需要判断当天是否在可选范围内 - currentEndDate: null, // 展开时开始时间,date格式,有value,则取value[1],否则取开始时间 - forceUpdate: 0, // 强制更新picker组件,已知需处理的情况:value超限,但是需要更新format,由于picker的参数均未变化,无法触发picker的渲染 - formattedValueText: '', - }, - [ - mixinValue({ - transformValue(value) { - return { - value: - value && value[0] && value[1] - ? [dayjs(value[0]).toDate(), dayjs(value[1]).toDate()] - : undefined, - needUpdate: true, - }; - }, - }), - computed(), - ], - { - pickerVisible: false, - didMount() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, + const newColumns = getRangeData( + precision, + min, + max, + currentPickerDay, + onFormatLabel + ); + doUpdateColumns({ columns: newColumns, currentValue }); + } - didUpdate(prevProps, prevData) { - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.setData({ visible }); - this.setCurrentValue(currentProps); - this.pickerVisible = visible; - } + const formattedValueText = onFormat(realValue); - if (!this.isEqualValue(prevData)) { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - if (this.pickerVisible) { - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - this.setCurrentValue(currentProps); - } - } - }, - } -); + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible); + }); + + useEvent('onChangeCurrentPickerType', (e) => { + const { type } = e.currentTarget.dataset; + const state = changeType(type) as any; + const currentValue = getValueByDate( + state.pickerType === 'start' ? state.start : state.end, + props.precision + ); + updateColumns(currentValue, props); + }); + const { getMin, getMax } = useMinAndMax(); + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + useEvent('onChange', (event) => { + let [selectedIndex] = resolveEventValues(event); + selectedIndex = getValidValue(selectedIndex); + const { format, precision } = props; + let date = getDateByValue(selectedIndex); + const min = getMin(props.min); + const max = getMax(props.max); + if (dayjs(date).isBefore(min)) { + date = min.toDate(); + selectedIndex = getValueByDate(date, precision); + } + if (dayjs(date).isAfter(max)) { + date = max.toDate(); + selectedIndex = getValueByDate(date, precision); + } + updateColumns(selectedIndex, props); + updateValue(date); + triggerEventValues('pickerChange', [ + dateState.pickerType, + date, + dayjs(date).format(format), + ]); + }); + + useEvent('onOk', () => { + const { format } = props; + const { start, end } = dateState; + const realValue = [start, end] as any; + if (!isControlled) { + update(realValue); + } + triggerEventValues('ok', [ + realValue, + realValue.map((v) => dayjs(v).format(format)), + ]); + }); + + return { + state: { + visible + }, + formattedValueText, + realValue, + columns, + currentValue, + currentStartDate: dateState.start, + currentEndDate: dateState.end, + currentEndValueStr, + currentStartValueStr, + pickerType: dateState.pickerType, + }; +}; + +mountComponent(RangePicker, DateRangePickerFunctionalProps); diff --git a/compiled/alipay/src/DatePicker/RangePicker/props.ts b/compiled/alipay/src/DatePicker/RangePicker/props.ts index c4eb953b9..379713fac 100644 --- a/compiled/alipay/src/DatePicker/RangePicker/props.ts +++ b/compiled/alipay/src/DatePicker/RangePicker/props.ts @@ -155,6 +155,18 @@ export interface IDateRangePickerProps extends IBaseProps { } export const DateRangePickerDefaultProps: Partial = { + okText: '确定', + cancelText: '取消', + maskClosable: true, + placeholder: '请选择', + format: 'YYYY/MM/DD', + splitCharacter: '-', + startPlaceholder: '未选择', + endPlaceholder: '未选择', + precision: 'day', +}; + +export const DateRangePickerFunctionalProps: Partial = { visible: null, defaultVisible: null, animationType: 'transform', @@ -176,5 +188,4 @@ export const DateRangePickerDefaultProps: Partial = { popStyle: '', disabled: false, onFormatLabel: null, - onFormat: null, }; diff --git a/compiled/alipay/src/DatePicker/RangePicker/useDateState.ts b/compiled/alipay/src/DatePicker/RangePicker/useDateState.ts new file mode 100644 index 000000000..2105420bd --- /dev/null +++ b/compiled/alipay/src/DatePicker/RangePicker/useDateState.ts @@ -0,0 +1,94 @@ +import dayjs from 'dayjs'; +import { useState } from 'functional-mini/component'; +import { useMinAndMax } from './hooks'; + +export function useDateState(props) { + const { getMin } = useMinAndMax(); + + const [dateState, setDateState] = useState({ + pickerType: 'start', + start: null, + end: null, + }); + + const init = (realValue) => { + let currentStartDate = realValue?.[0]; + const currentEndDate = realValue?.[1]; + if (!currentStartDate) { + const min = getMin(props.min).toDate(); + const { max } = props; + currentStartDate = new Date(); + if ( + (min && dayjs(currentStartDate).isBefore(min, props.precision)) || + (max && dayjs(currentStartDate).isAfter(max, props.precision)) || + (currentEndDate && currentStartDate > currentEndDate) + ) { + currentStartDate = min; + } + } + const newState = { + pickerType: 'start', + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + const changeType = (newType) => { + let currentStartDate = dateState.start; + let currentEndDate = dateState.end; + + if (newType === 'start') { + if (!currentStartDate) { + currentStartDate = currentEndDate; + } + } else { + // pickerType=end start已存在 + // 结束时间默认选中开始 + if (!currentEndDate) { + currentEndDate = currentStartDate; + } + } + + const newState = { + pickerType: newType, + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + + function updateValue(newValue) { + setDateState((old) => { + if (old.pickerType === 'start') { + let newEnd = old.end; + if (old.end && dayjs(newValue).isAfter(old.end)) { + newEnd = null; + } + + return { + ...old, + start: newValue, + end: newEnd, + }; + } + let newStart = old.start; + if (old.start && dayjs(newValue).isBefore(old.start)) { + newStart = null; + } + return { + ...old, + end: newValue, + start: newStart, + }; + }); + } + + return { + updateValue, + dateState, + init, + changeType, + }; +} diff --git a/compiled/alipay/src/DatePicker/index.axml b/compiled/alipay/src/DatePicker/index.axml index e51e07456..7fc40cc39 100644 --- a/compiled/alipay/src/DatePicker/index.axml +++ b/compiled/alipay/src/DatePicker/index.axml @@ -1,7 +1,7 @@ { - this.setData({ - currentValue, - formattedValueText: this.onFormat(), - }); - } - ); - } - }, +const DatePicker = (props: IDatePickerProps) => { + const [realValue, { isControlled, update }] = useMixState( + props.defaultValue, + { + value: props.value, + postState(value) { + if (value) { + return { + valid: true, + value: dayjs(value).toDate(), + }; + } + return { + valid: true, + value: undefined, + }; + }, + } + ); - // 生成选项数据,didmound、picker change、打开弹窗触发 - generateData(currentValue, currentProps) { - const { precision, min: propsMin, max: propsMax } = currentProps; - const min = this.getMin(propsMin); - const max = this.getMax(propsMax); - if (max < min) { - return []; - } - let currentPickerDay = dayjs(); - if (currentValue.length > 0) { - currentPickerDay = dayjs(getDateByValue(currentValue)); - } - if (currentPickerDay < min || currentPickerDay > max) { - currentPickerDay = min; - } - const newColumns = getRangeData( - precision, - min, - max, - currentPickerDay, - this.onFormatLabel.bind(this) - ); - return newColumns; - }, - onFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - const formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { + function defaultFormat(value, valueStr) { + if (props.format && valueStr) { + return valueStr; + } + return ''; + } + const { triggerEvent, triggerEventValues, triggerEventOnly } = + useComponentEvent(props); + + function onFormatLabel(type, value) { + const { onFormatLabel } = props; + if (typeof onFormatLabel === 'function') { + const formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { return String(formatValueByProps); } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel(type, value) { - const suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return `${value}${suffixMap[type]}`; - }, - onChange(selectedIdx) { - const [pmin, pmax, format, precision] = getValueFromProps(this, [ - 'min', - 'max', - 'format', - 'precision', - ]); - let [selectedIndex] = resolveEventValues(getValidValue(selectedIdx)); - let date = getDateByValue(selectedIndex); - const min = this.getMin(pmin); - const max = this.getMax(pmax); - if (dayjs(date).isBefore(min)) { - date = min.toDate(); - selectedIndex = getValueByDate(date, precision); - } - if (dayjs(date).isAfter(max)) { - date = max.toDate(); - selectedIndex = getValueByDate(date, precision); - } - const newColumns = this.generateData( - selectedIndex, - getValueFromProps(this) - ); + } + return defaultFormatLabel(type, value); + } + function defaultFormatLabel(type, value) { + const suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return `${value}${suffixMap[type]}`; + } - if (!equal(newColumns, this.data.columns)) { - this.setData( - { - columns: newColumns, - }, - () => { - this.setData({ currentValue: selectedIndex }); - const date = getDateByValue(selectedIndex); - triggerEventValues(this, 'pickerChange', [ - date, - dayjs(date).format(format), - ]); - } - ); - } else { - this.setData({ currentValue: selectedIndex }); - const date = getDateByValue(selectedIndex); + const [{ value, columns }, setState] = useState({ + value: [], + columns: [], + }); + + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); - triggerEventValues(this, 'pickerChange', [ - date, - dayjs(date).format(format), - ]); + useEffect(() => { + setTimeout(() => { + if (visible) { + updateDateColumnsAndValue(true); + } else { + updateDateColumnsAndValue(false); } - }, + }) + }, [visible]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, + function generateData(currentValue, currentProps) { + const { precision, min: propsMin, max: propsMax } = currentProps; + const min = getMin(propsMin); + const max = getMax(propsMax); + if (max < min) { + return []; + } + let currentPickerDay = dayjs(); + if (currentValue.length > 0) { + currentPickerDay = dayjs(getDateByValue(currentValue)); + } + if (currentPickerDay < min || currentPickerDay > max) { + currentPickerDay = min; + } + const newColumns = getRangeData( + precision, + min, + max, + currentPickerDay, + onFormatLabel + ); + return newColumns; + } - onOk() { - const { currentValue } = this.data; - const format = getValueFromProps(this, 'format'); - const date = getDateByValue(currentValue); - if (!this.isControlled()) { - this.update(date); - } - triggerEventValues(this, 'ok', [date, dayjs(date).format(format)]); - }, - defaultFormat(value, valueStr) { - const format = getValueFromProps(this, 'format'); - if (format && valueStr) { - return valueStr; - } - return ''; - }, - onFormat() { - const [format, onFormat] = getValueFromProps(this, [ - 'format', - 'onFormat', - ]); - const realValue = this.getValue(); - const formatValueByProps = - onFormat && - onFormat(realValue, realValue ? dayjs(realValue).format(format) : null); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; + function getCurrentValueWithCValue(currentProps) { + const { min, max, precision } = currentProps; + if (realValue) { + return getValueByDate(realValue, precision); + } else { + const now = new Date(); + if ( + !(min && dayjs(now).isBefore(dayjs(min as any), precision)) && + !(max && dayjs(now).isAfter(dayjs(max as any), precision)) + ) { + return getValueByDate(now, precision); + } else { + return getValueByDate(getMin(min).toDate(), precision); } - return this.defaultFormat( + } + } + + function updateDateColumnsAndValue(visible) { + if (visible) { + const currentValue = getCurrentValueWithCValue(props); + const newColumns = generateData(currentValue, props); + setState({ + value: currentValue, + columns: newColumns, + }); + } else { + setState({ + value: [], + columns: [], + }); + } + } + + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible, {}); + }); + + useEvent('onChange', (event) => { + let [selectedIndex] = resolveEventValues(event); + selectedIndex = getValidValue(selectedIndex); + const { format, precision } = props; + let date = getDateByValue(selectedIndex); + const min = getMin(props.min); + const max = getMax(props.max); + if (dayjs(date).isBefore(min)) { + date = min.toDate(); + selectedIndex = getValueByDate(date, precision); + } + if (dayjs(date).isAfter(max)) { + date = max.toDate(); + selectedIndex = getValueByDate(date, precision); + } + const newColumns = generateData(selectedIndex, props); + + setState({ + columns: newColumns, + value: selectedIndex, + }); + + const pickDate = getDateByValue(selectedIndex); + triggerEventValues( + 'pickerChange', + [pickDate, dayjs(pickDate).format(format)], + {} + ); + }); + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + useEvent('onOk', () => { + const { format } = props; + const date = getDateByValue(value); + if (!isControlled) { + update(date); + } + triggerEventValues('ok', [date, dayjs(date).format(format)], {}); + }); + + const formattedValueText = useMemo(() => { + const { onFormat, format } = props; + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat( realValue, realValue ? dayjs(realValue).format(format) : null ); - }, - onVisibleChange(visible) { - this.pickerVisible = visible; - if (!this.isVisibleControlled() && visible) { - this.setCurrentValue(getValueFromProps(this)); - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、picker变化时更新 - formattedValueText: '', - columns: [], // 可选项,didmound、弹窗打开、picker变化时更新 - forceUpdate: 0, // 强制更新picker组件,已知需处理的情况:value超限,但是需要更新format,由于picker的参数均未变化,无法触发picker的渲染 - visible: null, - }, - [ - mixinValue({ - transformValue(value) { - return { - value: value ? dayjs(value).toDate() : undefined, - needUpdate: true, - }; - }, - }), - ], - { - pickerVisible: false, - onInit() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, - didUpdate(prevProps, prevData) { - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.pickerVisible = visible; - this.setData({ visible }); - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } - } - if (!this.isEqualValue(prevData)) { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; } - }, - } -); + } + return defaultFormat( + realValue, + realValue ? dayjs(realValue).format(format) : null + ); + }, [realValue]); + + return { + state: { + visible + }, + formattedValueText, + currentValue: visible ? value : realValue, + columns, + }; +}; + +mountComponent(DatePicker, DatePickerFunctionalProps); diff --git a/compiled/alipay/src/DatePicker/props.ts b/compiled/alipay/src/DatePicker/props.ts index ec39f925d..b8989cd59 100644 --- a/compiled/alipay/src/DatePicker/props.ts +++ b/compiled/alipay/src/DatePicker/props.ts @@ -138,6 +138,15 @@ export interface IDatePickerProps extends IBaseProps { } export const DatePickerDefaultProps: IDatePickerProps = { + okText: '确定', + cancelText: '取消', + maskClosable: true, + placeholder: '请选择', + format: 'YYYY/MM/DD', + precision: 'day', +}; + +export const DatePickerFunctionalProps: IDatePickerProps = { visible: null, defaultVisible: null, animationType: 'transform', @@ -156,5 +165,4 @@ export const DatePickerDefaultProps: IDatePickerProps = { popStyle: '', disabled: false, onFormatLabel: null, - onFormat: null, }; diff --git a/compiled/alipay/src/DatePicker/util.ts b/compiled/alipay/src/DatePicker/util.ts index 08fd43f82..3328717c1 100644 --- a/compiled/alipay/src/DatePicker/util.ts +++ b/compiled/alipay/src/DatePicker/util.ts @@ -18,7 +18,7 @@ const precisionLengthRecord = { }; function getYears(min: Dayjs, max: Dayjs, format) { - return getArray(min.year(), max.year(), format.bind(this, 'year')); + return getArray(min.year(), max.year(), format.bind(null, 'year')); } function getMonths(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { @@ -41,7 +41,7 @@ function getMonths(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { end = max.month() + 1; } - return getArray(start, end, format.bind(this, 'month')); + return getArray(start, end, format.bind(null, 'month')); } function getDates(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { @@ -53,10 +53,10 @@ function getDates(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('date', end).isAfter(max)) { end = max.date(); } - return getArray(start, end, format.bind(this, 'day')); + return getArray(start, end, format.bind(null, 'day')); } -function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 23; if (currentPicker.clone().set('hour', start).isBefore(min)) { @@ -65,9 +65,9 @@ function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('hour', end).isAfter(max)) { end = max.hour(); } - return getArray(start, end, format.bind(this, 'hour')); + return getArray(start, end, format.bind(null, 'hour')); } -function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 59; if (currentPicker.clone().set('minute', start).isBefore(min)) { @@ -76,9 +76,9 @@ function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('minute', end).isAfter(max)) { end = max.minute(); } - return getArray(start, end, format.bind(this, 'minute')); + return getArray(start, end, format.bind(null, 'minute')); } -function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 59; if (currentPicker.clone().set('second', start).isBefore(min)) { @@ -87,7 +87,7 @@ function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('second', end).isAfter(max)) { end = max.second(); } - return getArray(start, end, format.bind(this, 'second')); + return getArray(start, end, format.bind(null, 'second')); } export function getRangeData( precision: keyof typeof precisionLengthRecord, @@ -155,7 +155,6 @@ export function getValueByDate( 'getSeconds', ]; const value = []; - if (!date) return value; for (let i = 0; i < precisionLengthRecord[precision]; i++) { value.push(date[fields[i]]()); if (i === 1) { diff --git a/compiled/alipay/src/Divider/index.json b/compiled/alipay/src/Divider/index.json index cf1e493a1..ac34bd704 100644 --- a/compiled/alipay/src/Divider/index.json +++ b/compiled/alipay/src/Divider/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { } } diff --git a/compiled/alipay/src/Empty/index.json b/compiled/alipay/src/Empty/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Empty/index.json +++ b/compiled/alipay/src/Empty/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Form/FormCascaderPicker/index.json b/compiled/alipay/src/Form/FormCascaderPicker/index.json index 83597fe6f..9cc26fa6a 100644 --- a/compiled/alipay/src/Form/FormCascaderPicker/index.json +++ b/compiled/alipay/src/Form/FormCascaderPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-cascader-picker": "../../Picker/CascaderPicker/index", diff --git a/compiled/alipay/src/Form/FormCascaderPicker/index.ts b/compiled/alipay/src/Form/FormCascaderPicker/index.ts index b4ccc867b..82fafb831 100644 --- a/compiled/alipay/src/Form/FormCascaderPicker/index.ts +++ b/compiled/alipay/src/Form/FormCascaderPicker/index.ts @@ -1,48 +1,56 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormCascaderPickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( FormCascaderPickerDefaultProps, - { - onOk(value, option, e) { - const v = resolveEventValues(value, option); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(value, option, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(value, option), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'cancel', e); - }, - onChange(value, options, e) { - triggerEventValues(this, 'change', resolveEventValues(value, options), e); - }, - handleFormat(value, option) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(value, option); + FormCascaderPickerProps, +} from './props'; + +const FormCascaderPicker = (props: FormCascaderPickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (value, option, e) => { + emit('onChange', value); + triggerEventValues('ok', [value, option], e); + }); + + useMultipleValueHandleCustomEvent('onPickerChange', (value, option, e) => { + triggerEventValues('pickerChange', [value, option], e); + }); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useEvent( + 'handleFormat', + (value, option) => { + if (props.onFormat) { + return props.onFormat(value, option); } }, - }, - {}, - [createForm()], - { - } -); + { handleResult: true } + ); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('cancel', e); + }); + + useMultipleValueHandleCustomEvent('onChange', (value, options, e) => { + triggerEventValues('change', [value, options], e); + }); + + return { + formData, + }; +}; + +mountComponent(FormCascaderPicker, FormCascaderPickerDefaultProps); diff --git a/compiled/alipay/src/Form/FormCascaderPicker/props.ts b/compiled/alipay/src/Form/FormCascaderPicker/props.ts index 924717f0d..e7de550b9 100644 --- a/compiled/alipay/src/Form/FormCascaderPicker/props.ts +++ b/compiled/alipay/src/Form/FormCascaderPicker/props.ts @@ -1,8 +1,8 @@ import { - CascaderDefaultProps, + CascaderFunctionalProps, ICascaderProps, } from '../../Picker/CascaderPicker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormCascaderPickerProps extends ICascaderProps, FormItemProps { /** @@ -13,7 +13,7 @@ export interface FormCascaderPickerProps extends ICascaderProps, FormItemProps { export const FormCascaderPickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...CascaderDefaultProps, + ...FormItemFunctionalProps, + ...CascaderFunctionalProps, arrow: false, }; diff --git a/compiled/alipay/src/Form/FormCheckboxGroup/index.json b/compiled/alipay/src/Form/FormCheckboxGroup/index.json index a257669cb..a7aba7f79 100644 --- a/compiled/alipay/src/Form/FormCheckboxGroup/index.json +++ b/compiled/alipay/src/Form/FormCheckboxGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "checkbox-group": "../../Checkbox/CheckboxGroup/index" diff --git a/compiled/alipay/src/Form/FormCheckboxGroup/index.ts b/compiled/alipay/src/Form/FormCheckboxGroup/index.ts index 703fd3539..92c773f20 100644 --- a/compiled/alipay/src/Form/FormCheckboxGroup/index.ts +++ b/compiled/alipay/src/Form/FormCheckboxGroup/index.ts @@ -1,16 +1,21 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { FormCheckboxGroupDefaultProps } from './props'; -import { resolveEventValue } from '../../_util/platform'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormCheckboxGroupDefaultProps, FormCheckboxGroupProps } from './props'; -Component( - FormCheckboxGroupDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormCheckboxGroup = (props: FormCheckboxGroupProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormCheckboxGroup, FormCheckboxGroupDefaultProps); diff --git a/compiled/alipay/src/Form/FormCheckboxGroup/props.ts b/compiled/alipay/src/Form/FormCheckboxGroup/props.ts index 3321bd084..fcc3d1168 100644 --- a/compiled/alipay/src/Form/FormCheckboxGroup/props.ts +++ b/compiled/alipay/src/Form/FormCheckboxGroup/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { CheckboxGroupDefaultProps, ICheckboxGroupProps, @@ -13,7 +13,7 @@ export interface FormCheckboxGroupProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { position, ...rest } = CheckboxGroupDefaultProps; export const FormCheckboxGroupDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, checkboxPosition: 'horizontal', }; diff --git a/compiled/alipay/src/Form/FormDatePicker/index.json b/compiled/alipay/src/Form/FormDatePicker/index.json index 190c929df..a99473a3c 100644 --- a/compiled/alipay/src/Form/FormDatePicker/index.json +++ b/compiled/alipay/src/Form/FormDatePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-date-picker": "../../DatePicker/index", diff --git a/compiled/alipay/src/Form/FormDatePicker/index.ts b/compiled/alipay/src/Form/FormDatePicker/index.ts index e458a1df9..a5308b49a 100644 --- a/compiled/alipay/src/Form/FormDatePicker/index.ts +++ b/compiled/alipay/src/Form/FormDatePicker/index.ts @@ -1,52 +1,67 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormDatePickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormDatePickerDefaultProps, - { - onOk(date, dateStr, e) { - const v = resolveEventValues(date, dateStr); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(date, dateStr, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(date, dateStr), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'dismissPicker', e); - }, + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormDatePickerDefaultProps, FormDatePickerProps } from './props'; +import { platform } from '../../_util/platform'; + +const FormDatePicker = (props: FormDatePickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (date, dateStr, e) => { + emit('onChange', platform() === 'wechat' ? date.getTime() : date); + triggerEventValues('ok', [date, dateStr], e); + }); - handleFormat(date, dateStr) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(date, dateStr); + useMultipleValueHandleCustomEvent('onPickerChange', (date, dateStr, e) => { + triggerEventValues('pickerChange', [date, dateStr], e); + }); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('dismissPicker', e); + }); + + useEvent( + 'handleFormat', + (date, dateStr) => { + if (props.onFormat) { + return props.onFormat(date, dateStr); } }, - handleFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - if (onFormatLabel) { - return onFormatLabel(type, value); + { + handleResult: true, + } + ); + + useEvent( + 'handleFormatLabel', + (type, value) => { + if (props.onFormatLabel) { + return props.onFormatLabel(type, value); } }, - }, - {}, - [createForm()], - { - } + { + handleResult: true, + } + ); + + return { + formData, + }; +}; + +mountComponent( + FormDatePicker, + FormDatePickerDefaultProps as FormDatePickerProps ); diff --git a/compiled/alipay/src/Form/FormDatePicker/props.ts b/compiled/alipay/src/Form/FormDatePicker/props.ts index 491125606..56d3c8be4 100644 --- a/compiled/alipay/src/Form/FormDatePicker/props.ts +++ b/compiled/alipay/src/Form/FormDatePicker/props.ts @@ -1,8 +1,8 @@ import { - DatePickerDefaultProps, + DatePickerFunctionalProps, IDatePickerProps, } from '../../DatePicker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormDatePickerProps extends IDatePickerProps, FormItemProps { /** @@ -12,7 +12,7 @@ export interface FormDatePickerProps extends IDatePickerProps, FormItemProps { } export const FormDatePickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...DatePickerDefaultProps, + ...FormItemFunctionalProps, + ...DatePickerFunctionalProps, arrow: false, }; diff --git a/compiled/alipay/src/Form/FormImageUpload/index.json b/compiled/alipay/src/Form/FormImageUpload/index.json index 5d38464c7..c3adc9767 100644 --- a/compiled/alipay/src/Form/FormImageUpload/index.json +++ b/compiled/alipay/src/Form/FormImageUpload/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "image-upload": "../../ImageUpload/index" } -} +} \ No newline at end of file diff --git a/compiled/alipay/src/Form/FormImageUpload/index.ts b/compiled/alipay/src/Form/FormImageUpload/index.ts index 88743ca4b..0d32fe42d 100644 --- a/compiled/alipay/src/Form/FormImageUpload/index.ts +++ b/compiled/alipay/src/Form/FormImageUpload/index.ts @@ -1,62 +1,83 @@ -import { Component, triggerEvent, getValueFromProps } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormImageUploadDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormImageUploadDefaultProps, - { - handleRef(imageUpload) { - this.imageUpload = imageUpload; - }, - onChange(value) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value)); - }, - onPreview(file) { - triggerEvent(this, 'preview', resolveEventValue(file)); - }, - onChooseImageError(err) { - triggerEvent(this, 'chooseImageError', resolveEventValue(err)); - }, +import { useEvent, useRef, useEffect } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormImageUploadDefaultProps, FormImageUploadProps } from './props'; + +interface ImageUploadRef { + update(value: FormImageUploadProps['fileList']); +} + +const FormImageUpload = (props: FormImageUploadProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + const imageUploadRef = useRef(); + + useHandleCustomEvent('handleRef', (imageUpload: ImageUploadRef) => { + imageUploadRef.current = imageUpload; + }); - handleUpload(localFile) { - const onUpload = getValueFromProps(this, 'onUpload'); - if (!onUpload) { + useEffect(() => { + if (imageUploadRef.current) { + imageUploadRef.current.update(formData.value); + } + }, [formData.value]); + + useHandleCustomEvent('onChange', (value) => { + emit('onChange', value); + triggerEvent('change', value); + }); + + useEvent( + 'handleUpload', + (localFile) => { + if (!props.onUpload) { throw new Error('need props onUpload'); } - return onUpload(localFile); + return props.onUpload(localFile); }, - handleRemove(file) { - const onRemove = getValueFromProps(this, 'onRemove'); - if (onRemove) { - return onRemove(file); + { + handleResult: true, + } + ); + + useEvent( + 'handleRemove', + (file) => { + if (props.onRemove) { + return props.onRemove(file); } }, - handleBeforeUpload(localFileList) { - const onBeforeUpload = getValueFromProps(this, 'onBeforeUpload'); - if (onBeforeUpload) { - return onBeforeUpload(localFileList); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onPreview', (file, e) => { + triggerEvent('preview', file, e); + }); + + useEvent( + 'handleBeforeUpload', + (localFileList) => { + if (props.onBeforeUpload) { + return props.onBeforeUpload(localFileList); } }, - }, - {}, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.imageUpload && this.imageUpload.update(this.data.formData.value); - }, - }, - }), - ], - { - } -); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onChooseImageError', (err, e) => { + triggerEvent('chooseImageError', err, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormImageUpload, FormImageUploadDefaultProps); diff --git a/compiled/alipay/src/Form/FormImageUpload/props.ts b/compiled/alipay/src/Form/FormImageUpload/props.ts index fb3a2ad6d..44a2630fc 100644 --- a/compiled/alipay/src/Form/FormImageUpload/props.ts +++ b/compiled/alipay/src/Form/FormImageUpload/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IUploaderProps, UploaderDefaultProps, @@ -11,6 +11,6 @@ export interface FormImageUploadProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { defaultFileList, ...rest } = UploaderDefaultProps; export const FormImageUploadDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, }; diff --git a/compiled/alipay/src/Form/FormInput/index.json b/compiled/alipay/src/Form/FormInput/index.json index 4753b1bb0..c5ed09788 100644 --- a/compiled/alipay/src/Form/FormInput/index.json +++ b/compiled/alipay/src/Form/FormInput/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-input": "../../Input/index" diff --git a/compiled/alipay/src/Form/FormInput/index.ts b/compiled/alipay/src/Form/FormInput/index.ts index 10442a590..4ed54950d 100644 --- a/compiled/alipay/src/Form/FormInput/index.ts +++ b/compiled/alipay/src/Form/FormInput/index.ts @@ -1,43 +1,49 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormInputDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormInputDefaultProps, - { - handleRef(input) { - this.input = input; - }, - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(value, e) { - triggerEvent(this, 'blur', resolveEventValue(value), e); - }, - onFocus(value, e) { - triggerEvent(this, 'focus', resolveEventValue(value), e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - }, - null, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.input && this.input.update(this.data.formData.value); - }, - }, - }), - ] -); +import { useEffect, useRef } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormInputFunctionalProps, FormInputProps } from './props'; + +interface InputRef { + update(value: string); +} + +const FormInput = (props: FormInputProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + const inputRef = useRef(); + + useHandleCustomEvent('handleRef', (input: InputRef) => { + inputRef.current = input; + }); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.update(formData.value); + } + }, [formData]); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onBlur', (value, e) => { + triggerEvent('blur', value, e); + }); + + useHandleCustomEvent('onFocus', (value, e) => { + triggerEvent('focus', value, e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormInput, FormInputFunctionalProps); diff --git a/compiled/alipay/src/Form/FormInput/props.ts b/compiled/alipay/src/Form/FormInput/props.ts index 4b8293287..d367bf0de 100644 --- a/compiled/alipay/src/Form/FormInput/props.ts +++ b/compiled/alipay/src/Form/FormInput/props.ts @@ -1,5 +1,5 @@ -import { FormItemProps, FormItemDefaultProps } from '../FormItem/props'; -import { InputProps, InputDefaultProps } from '../../Input/props'; +import { FormItemProps, FormItemFunctionalProps } from '../FormItem/props'; +import { InputProps, InputFunctionalProps } from '../../Input/props'; export interface FormInputProps extends Omit, @@ -8,10 +8,12 @@ export interface FormInputProps inputClassStyle: string; } +export const FormInputDefaultProps: Partial = {}; + // eslint-disable-next-line @typescript-eslint/no-unused-vars -const { value, defaultValue, name, ...rest } = InputDefaultProps; -export const FormInputDefaultProps: FormInputProps = { - ...FormItemDefaultProps, +const { value, defaultValue, name, ...rest } = InputFunctionalProps; +export const FormInputFunctionalProps: FormInputProps = { + ...FormItemFunctionalProps, ...rest, inputClassName: '', inputClassStyle: ' ', diff --git a/compiled/alipay/src/Form/FormItem/index.json b/compiled/alipay/src/Form/FormItem/index.json index 7b25f207e..12ce40723 100644 --- a/compiled/alipay/src/Form/FormItem/index.json +++ b/compiled/alipay/src/Form/FormItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "popover": "../../Popover/index", "ant-icon": "../../Icon/index" diff --git a/compiled/alipay/src/Form/FormItem/index.ts b/compiled/alipay/src/Form/FormItem/index.ts index 76988ab1a..6948b6957 100644 --- a/compiled/alipay/src/Form/FormItem/index.ts +++ b/compiled/alipay/src/Form/FormItem/index.ts @@ -1,5 +1,6 @@ -import { Component } from '../../_util/simply'; -import { FormItemDefaultProps } from './props'; +import { mountComponent } from '../../_util/component'; +import { FormItemProps, FormItemFunctionalProps } from './props'; -Component(FormItemDefaultProps, null, null, null, { -}); +const FormItem = () => {}; + +mountComponent(FormItem, FormItemFunctionalProps); diff --git a/compiled/alipay/src/Form/FormItem/props.ts b/compiled/alipay/src/Form/FormItem/props.ts index 10cf56ced..a556a58e3 100644 --- a/compiled/alipay/src/Form/FormItem/props.ts +++ b/compiled/alipay/src/Form/FormItem/props.ts @@ -19,7 +19,12 @@ export interface FormItemProps extends IBaseProps { dependencies?: string[]; } -export const FormItemDefaultProps: FormItemProps = { +export const FormItemDefaultProps: Partial = { + position: 'horizontal', + requiredMark: 'asterisk', +}; + +export const FormItemFunctionalProps: FormItemProps = { name: null, label: null, labelWidth: null, diff --git a/compiled/alipay/src/Form/FormPicker/index.json b/compiled/alipay/src/Form/FormPicker/index.json index c0b9103e0..dc690762e 100644 --- a/compiled/alipay/src/Form/FormPicker/index.json +++ b/compiled/alipay/src/Form/FormPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-picker": "../../Picker/index", diff --git a/compiled/alipay/src/Form/FormPicker/index.ts b/compiled/alipay/src/Form/FormPicker/index.ts index a2de13ba5..fc759232a 100644 --- a/compiled/alipay/src/Form/FormPicker/index.ts +++ b/compiled/alipay/src/Form/FormPicker/index.ts @@ -1,41 +1,50 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormPickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormPickerDefaultProps, - { - onOk(value, column, e) { - const v = resolveEventValues(value, column); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onChange(value, column, e) { - triggerEventValues(this, 'change', resolveEventValues(value, column), e); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'cancel', e); - }, + useHandleCustomEvent, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormPickerDefaultProps, FormPickerProps } from './props'; + +const FormPicker = (props: FormPickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (value, column, e) => { + emit('onChange', value); + triggerEventValues('ok', [value, column], e); + }); - handleFormat(value, column) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(value, column); + useMultipleValueHandleCustomEvent('onChange', (value, column, e) => { + triggerEventValues('change', [value, column], e); + }); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useEvent( + 'handleFormat', + (value, column) => { + if (props.onFormat) { + return props.onFormat(value, column); } }, - }, - {}, - [createForm()], - { - } -); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onDismissPicker', (e) => { + triggerEventOnly('cancel', e); + }); + + return { + formData, + }; +}; + +mountComponent(FormPicker, FormPickerDefaultProps as FormPickerProps); diff --git a/compiled/alipay/src/Form/FormPicker/props.ts b/compiled/alipay/src/Form/FormPicker/props.ts index 858ab1531..715176d77 100644 --- a/compiled/alipay/src/Form/FormPicker/props.ts +++ b/compiled/alipay/src/Form/FormPicker/props.ts @@ -1,5 +1,5 @@ -import { IPickerProps, PickerDefaultProps } from '../../Picker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { IPickerProps, PickerFunctionalProps } from '../../Picker/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormPickerProps extends IPickerProps, FormItemProps { /** @@ -9,7 +9,7 @@ export interface FormPickerProps extends IPickerProps, FormItemProps { } export const FormPickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...PickerDefaultProps, + ...FormItemFunctionalProps, + ...PickerFunctionalProps, arrow: false, }; diff --git a/compiled/alipay/src/Form/FormRadioGroup/index.json b/compiled/alipay/src/Form/FormRadioGroup/index.json index 3741e2c7b..266076e3f 100644 --- a/compiled/alipay/src/Form/FormRadioGroup/index.json +++ b/compiled/alipay/src/Form/FormRadioGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-radio-group": "../../Radio/RadioGroup/index" diff --git a/compiled/alipay/src/Form/FormRadioGroup/index.ts b/compiled/alipay/src/Form/FormRadioGroup/index.ts index cd7cb476b..bf301b68f 100644 --- a/compiled/alipay/src/Form/FormRadioGroup/index.ts +++ b/compiled/alipay/src/Form/FormRadioGroup/index.ts @@ -1,16 +1,25 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormRadioGroupDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormRadioGroupDefaultProps, FormRadioGroupProps } from './props'; -Component( - FormRadioGroupDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] +const FormRadioGroup = (props: FormRadioGroupProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent( + FormRadioGroup, + FormRadioGroupDefaultProps as FormRadioGroupProps ); diff --git a/compiled/alipay/src/Form/FormRadioGroup/props.ts b/compiled/alipay/src/Form/FormRadioGroup/props.ts index 97f22cc74..6f236366f 100644 --- a/compiled/alipay/src/Form/FormRadioGroup/props.ts +++ b/compiled/alipay/src/Form/FormRadioGroup/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IRadioGroupProps, RadioGroupDefaultProps, @@ -18,7 +18,7 @@ const { value, defaultValue, position, name, ...rest } = RadioGroupDefaultProps; export const FormRadioGroupDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, radioPosition: 'horizontal', }; diff --git a/compiled/alipay/src/Form/FormRangePicker/index.json b/compiled/alipay/src/Form/FormRangePicker/index.json index 24e7b435a..09d909562 100644 --- a/compiled/alipay/src/Form/FormRangePicker/index.json +++ b/compiled/alipay/src/Form/FormRangePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-range-picker": "../../DatePicker/RangePicker/index", diff --git a/compiled/alipay/src/Form/FormRangePicker/index.ts b/compiled/alipay/src/Form/FormRangePicker/index.ts index 77310be66..79cbadb2b 100644 --- a/compiled/alipay/src/Form/FormRangePicker/index.ts +++ b/compiled/alipay/src/Form/FormRangePicker/index.ts @@ -1,52 +1,78 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormRangePickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormRangePickerDefaultProps, - { - onOk(date, dateStr, e) { - const v = resolveEventValues(date, dateStr); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(type, date, dateStr, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(type, date, dateStr), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'dismissPicker', e); - }, + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { platform } from '../../_util/platform'; +import { useFormItem } from '../use-form-item'; +import { FormRangePickerDefaultProps, FormRangePickerProps } from './props'; + +const FormDatePicker = (props: FormRangePickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (date, dateStr, e) => { + emit( + 'onChange', + date.map((o: Date) => { + if (platform() === 'wechat') { + return o.getTime(); + } + return o; + }) + ); + triggerEventValues('ok', [date, dateStr], e); + }); - handleFormat(date, dateStr) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(date, dateStr); + useMultipleValueHandleCustomEvent( + 'onPickerChange', + (type, date, dateStr, e) => { + triggerEventValues('pickerChange', [type, date, dateStr], e); + } + ); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('dismissPicker', e); + }); + + useEvent( + 'handleFormat', + (date, dateStr) => { + if (props.onFormat) { + return props.onFormat(date, dateStr); } }, - handleFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - if (onFormatLabel) { - return onFormatLabel(type, value); + { + handleResult: true, + } + ); + + useEvent( + 'handleFormatLabel', + (type, value) => { + if (props.onFormatLabel) { + return props.onFormatLabel(type, value); } }, - }, - {}, - [createForm()], - { - } + { + handleResult: true, + } + ); + + return { + formData, + }; +}; + +mountComponent( + FormDatePicker, + FormRangePickerDefaultProps as FormRangePickerProps ); diff --git a/compiled/alipay/src/Form/FormRangePicker/props.ts b/compiled/alipay/src/Form/FormRangePicker/props.ts index eba7a9cca..6a4d4779f 100644 --- a/compiled/alipay/src/Form/FormRangePicker/props.ts +++ b/compiled/alipay/src/Form/FormRangePicker/props.ts @@ -1,6 +1,6 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IDateRangePickerProps } from '../../DatePicker/RangePicker/props'; -import { DateRangePickerDefaultProps } from '../../DatePicker/RangePicker/props'; +import { DateRangePickerFunctionalProps } from '../../DatePicker/RangePicker/props'; export interface FormRangePickerProps extends IDateRangePickerProps, @@ -12,7 +12,7 @@ export interface FormRangePickerProps } export const FormRangePickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...DateRangePickerDefaultProps, + ...FormItemFunctionalProps, + ...DateRangePickerFunctionalProps, arrow: false, }; diff --git a/compiled/alipay/src/Form/FormRate/index.json b/compiled/alipay/src/Form/FormRate/index.json index a070eadf5..184e99870 100644 --- a/compiled/alipay/src/Form/FormRate/index.json +++ b/compiled/alipay/src/Form/FormRate/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "icon": "../../Icon/index", diff --git a/compiled/alipay/src/Form/FormRate/index.ts b/compiled/alipay/src/Form/FormRate/index.ts index c7cd8471d..01f7b5d3e 100644 --- a/compiled/alipay/src/Form/FormRate/index.ts +++ b/compiled/alipay/src/Form/FormRate/index.ts @@ -1,16 +1,22 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormRateDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormRateDefaultProps, FormRateProps } from './props'; -Component( - FormRateDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormRate = (props: FormRateProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormRate, FormRateDefaultProps); diff --git a/compiled/alipay/src/Form/FormRate/props.ts b/compiled/alipay/src/Form/FormRate/props.ts index 3a121e4d9..6e2baf5b4 100644 --- a/compiled/alipay/src/Form/FormRate/props.ts +++ b/compiled/alipay/src/Form/FormRate/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IRateProps, RateDefaultProps } from '../../Rate/props'; export interface FormRateProps @@ -12,7 +12,7 @@ export interface FormRateProps const { defaultValue, ...rest } = RateDefaultProps; export const FormRateDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, rateClassName: '', rateStyle: '', diff --git a/compiled/alipay/src/Form/FormSelector/index.json b/compiled/alipay/src/Form/FormSelector/index.json index 0216a4933..7e631fbaf 100644 --- a/compiled/alipay/src/Form/FormSelector/index.json +++ b/compiled/alipay/src/Form/FormSelector/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "selector": "../../Selector/index" diff --git a/compiled/alipay/src/Form/FormSelector/index.ts b/compiled/alipay/src/Form/FormSelector/index.ts index 05665a750..c21799f9c 100644 --- a/compiled/alipay/src/Form/FormSelector/index.ts +++ b/compiled/alipay/src/Form/FormSelector/index.ts @@ -1,23 +1,30 @@ -import { Component, triggerEventValues } from '../../_util/simply'; -import { resolveEventValues } from '../../_util/platform'; -import { FormSelectorDefaultProps } from './props'; -import { createForm } from '../form'; +import { useMultipleValueHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSelectorDefaultProps, FormSelectorProps } from './props'; -Component( - FormSelectorDefaultProps, - { - onChange(value, item, e) { - const v = resolveEventValues(value, item); - this.emit('onChange', v[0]); - triggerEventValues(this, 'change', v, e); - }, - onSelectMax(value, item, e) { - triggerEventValues(this, 'selectMax', resolveEventValues(value, item), e); - }, - onSelectMin(value, item, e) { - triggerEventValues(this, 'selectMin', resolveEventValues(value, item), e); - }, - }, - null, - [createForm()] -); +const FormSelector = (props: FormSelectorProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEventValues } = useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onChange', (value, item, e) => { + emit('onChange', value); + triggerEventValues('change', [value, item], e); + }); + + useMultipleValueHandleCustomEvent('onSelectMax', (value, item, e) => { + triggerEventValues('selectMax', [value, item], e); + }); + + useMultipleValueHandleCustomEvent('onSelectMin', (value, item, e) => { + triggerEventValues('selectMin', [value, item], e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSelector, FormSelectorDefaultProps); diff --git a/compiled/alipay/src/Form/FormSelector/props.ts b/compiled/alipay/src/Form/FormSelector/props.ts index cb35bfff1..f6c753d6c 100644 --- a/compiled/alipay/src/Form/FormSelector/props.ts +++ b/compiled/alipay/src/Form/FormSelector/props.ts @@ -1,9 +1,9 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISelectorProps, SelectorDefaultProps } from '../../Selector/props'; export interface FormSelectorProps extends ISelectorProps, FormItemProps {} export const FormSelectorDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...SelectorDefaultProps, }; diff --git a/compiled/alipay/src/Form/FormSlider/index.json b/compiled/alipay/src/Form/FormSlider/index.json index fc1f84fb4..85b540714 100644 --- a/compiled/alipay/src/Form/FormSlider/index.json +++ b/compiled/alipay/src/Form/FormSlider/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "slider": "../../Slider/index" } -} +} \ No newline at end of file diff --git a/compiled/alipay/src/Form/FormSlider/index.ts b/compiled/alipay/src/Form/FormSlider/index.ts index faf1ee86a..3e19b209d 100644 --- a/compiled/alipay/src/Form/FormSlider/index.ts +++ b/compiled/alipay/src/Form/FormSlider/index.ts @@ -1,19 +1,26 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormSliderDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSliderDefaultProps, FormSliderProps } from './props'; -Component( - FormSliderDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onAfterChange(value, e) { - triggerEvent(this, 'afterChange', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormSlider = (props: FormSliderProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onAfterChange', (value, e) => { + emit('onChange', value); + triggerEvent('afterChange', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSlider, FormSliderDefaultProps); diff --git a/compiled/alipay/src/Form/FormSlider/props.ts b/compiled/alipay/src/Form/FormSlider/props.ts index 1936cfd9c..82063124f 100644 --- a/compiled/alipay/src/Form/FormSlider/props.ts +++ b/compiled/alipay/src/Form/FormSlider/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISliderProps, sliderDefaultProps } from '../../Slider/props'; export interface FormSliderProps @@ -12,7 +12,7 @@ export interface FormSliderProps const { value, defaultValue, ...rest } = sliderDefaultProps; export const FormSliderDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, sliderClassName: '', sliderStyle: '', diff --git a/compiled/alipay/src/Form/FormStepper/index.json b/compiled/alipay/src/Form/FormStepper/index.json index cd7f470ce..2dbd1e5d2 100644 --- a/compiled/alipay/src/Form/FormStepper/index.json +++ b/compiled/alipay/src/Form/FormStepper/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "stepper": "../../Stepper/index" } -} +} \ No newline at end of file diff --git a/compiled/alipay/src/Form/FormStepper/index.ts b/compiled/alipay/src/Form/FormStepper/index.ts index 5af8a241f..b9de5d6a7 100644 --- a/compiled/alipay/src/Form/FormStepper/index.ts +++ b/compiled/alipay/src/Form/FormStepper/index.ts @@ -1,25 +1,36 @@ -import { Component, triggerEvent, triggerEventOnly } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormStepperDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { + useHandleCustomEvent, + useHandleCustomEventOnly, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormStepperDefaultProps, FormStepperProps } from './props'; -Component( - FormStepperDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(e) { - triggerEventOnly(this, 'blur', e); - }, - onFocus(e) { - triggerEventOnly(this, 'focus', e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormStepper = (props: FormStepperProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent, triggerEventOnly } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEventOnly('onBlur', (e) => { + triggerEventOnly('blur', e); + }); + + useHandleCustomEventOnly('onFocus', (e) => { + triggerEventOnly('focus', e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormStepper, FormStepperDefaultProps); diff --git a/compiled/alipay/src/Form/FormStepper/props.ts b/compiled/alipay/src/Form/FormStepper/props.ts index 70b6cbfac..c43b1a45d 100644 --- a/compiled/alipay/src/Form/FormStepper/props.ts +++ b/compiled/alipay/src/Form/FormStepper/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IStepperProps, StepperDefaultProps } from '../../Stepper/props'; export interface FormStepperProps @@ -12,7 +12,7 @@ export interface FormStepperProps const { value, defaultValue, ...rest } = StepperDefaultProps; export const FormStepperDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, stepperClassName: '', stepperStyle: '', diff --git a/compiled/alipay/src/Form/FormSwitch/index.json b/compiled/alipay/src/Form/FormSwitch/index.json index d8e535a8d..8c5946e15 100644 --- a/compiled/alipay/src/Form/FormSwitch/index.json +++ b/compiled/alipay/src/Form/FormSwitch/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "switch": "../../Switch/index" } -} +} \ No newline at end of file diff --git a/compiled/alipay/src/Form/FormSwitch/index.ts b/compiled/alipay/src/Form/FormSwitch/index.ts index 7463dbcb7..ab1e58ff0 100644 --- a/compiled/alipay/src/Form/FormSwitch/index.ts +++ b/compiled/alipay/src/Form/FormSwitch/index.ts @@ -1,16 +1,21 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormSwitchDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSwitchDefaultProps, FormSwitchProps } from './props'; -Component( - FormSwitchDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormSwitch = (props: FormSwitchProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSwitch, FormSwitchDefaultProps); diff --git a/compiled/alipay/src/Form/FormSwitch/props.ts b/compiled/alipay/src/Form/FormSwitch/props.ts index aace47688..c1cea32d1 100644 --- a/compiled/alipay/src/Form/FormSwitch/props.ts +++ b/compiled/alipay/src/Form/FormSwitch/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISwitchProps, SwitchDefaultProps } from '../../Switch/props'; export interface FormSwitchProps @@ -11,7 +11,7 @@ export interface FormSwitchProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { checked, defaultChecked, ...rest } = SwitchDefaultProps; export const FormSwitchDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, switchClassName: '', switchStyle: '', diff --git a/compiled/alipay/src/Form/FormTextarea/index.json b/compiled/alipay/src/Form/FormTextarea/index.json index 12bd9d977..11d1ec17a 100644 --- a/compiled/alipay/src/Form/FormTextarea/index.json +++ b/compiled/alipay/src/Form/FormTextarea/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-textarea": "../../Input/Textarea/index" diff --git a/compiled/alipay/src/Form/FormTextarea/index.ts b/compiled/alipay/src/Form/FormTextarea/index.ts index 6ebccef70..25102baba 100644 --- a/compiled/alipay/src/Form/FormTextarea/index.ts +++ b/compiled/alipay/src/Form/FormTextarea/index.ts @@ -1,47 +1,49 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormTextareaDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormTextareaDefaultProps, - { - handleRef(input) { - this.input = input; - }, - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(value, e) { - triggerEvent(this, 'blur', resolveEventValue(value), e); - }, - onFocus(value, e) { - triggerEvent(this, 'focus', resolveEventValue(value), e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - onClear(value, e) { - this.emit('onChange', ''); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.input && this.input.update(this.data.formData.value); - }, - }, - }), - ] -); +import { useEffect, useRef } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormTextareaDefaultProps, FormTextareaProps } from './props'; + +type TextareaRef = { + update(value: string): void; +}; + +const FormTextarea = (props: FormTextareaProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + const inputRef = useRef(); + + useHandleCustomEvent('handleRef', (input: TextareaRef) => { + inputRef.current = input; + }); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.update(formData.value); + } + }, [formData]); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onBlur', (value, e) => { + triggerEvent('blur', value, e); + }); + + useHandleCustomEvent('onFocus', (value, e) => { + triggerEvent('focus', value, e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormTextarea, FormTextareaDefaultProps as FormTextareaProps); diff --git a/compiled/alipay/src/Form/FormTextarea/props.ts b/compiled/alipay/src/Form/FormTextarea/props.ts index 4ee6f12b6..a444d1f64 100644 --- a/compiled/alipay/src/Form/FormTextarea/props.ts +++ b/compiled/alipay/src/Form/FormTextarea/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps } from './../FormItem/props'; +import { FormItemFunctionalProps } from './../FormItem/props'; import { FormItemProps } from '../FormItem/props'; import { TextareaDefaultProps, @@ -12,6 +12,6 @@ export interface FormTextareaProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { value, defaultValue, name, ...rest } = TextareaDefaultProps; export const FormTextareaDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, }; diff --git a/compiled/alipay/src/Form/createComponent.ts b/compiled/alipay/src/Form/createComponent.ts new file mode 100644 index 000000000..db9b000d4 --- /dev/null +++ b/compiled/alipay/src/Form/createComponent.ts @@ -0,0 +1,51 @@ +import { FromItemRef, EventTrigger, Value, Values } from './form'; + +function createComponent({ props = {}, data = {}, methods = {} as any }) { + Component({ + props, + data: { + ...data, + formData: { + value: undefined, + status: 'default', + required: false, + errors: [], + }, + }, + ref() { + const formItemRef: FromItemRef = { + setFormData: (values: Values) => { + this.setData({ + ...this.data, + formData: { + ...this.data.formData, + ...values, + }, + }); + }, + getFormData: () => { + return this.data.formData; + }, + on: (callback: (trigger: EventTrigger, value?: Value) => void) => { + this.emit = callback; + }, + getProps: () => { + return this.props; + }, + }; + return formItemRef; + }, + didUnmount() { + this.emit('didUnmount'); + }, + deriveDataFromProps(nextProps) { + this.emit('deriveDataFromProps', nextProps); + }, + methods: { + ...methods, + emit(trigger: EventTrigger, value?: Value) {}, + }, + }); +} + +export default createComponent; diff --git a/compiled/alipay/src/Form/form.ts b/compiled/alipay/src/Form/form.ts index f53a9fdcb..da385baa3 100644 --- a/compiled/alipay/src/Form/form.ts +++ b/compiled/alipay/src/Form/form.ts @@ -9,7 +9,6 @@ import AsyncValidator, { ValidateMessages, } from 'async-validator'; import { IMixin4Legacy } from '@mini-types/alipay'; -import { getValueFromProps } from '../_util/simply'; export { Value, Values }; export type Validator = ( @@ -859,7 +858,7 @@ export class Form { } export function createForm({ methods = {} } = {}) { - let mixin = { + return { data: { formData: { value: undefined, @@ -867,7 +866,6 @@ export function createForm({ methods = {} } = {}) { errors: [], }, }, - didUnmount() { this.emit('didUnmount'); }, @@ -892,7 +890,7 @@ export function createForm({ methods = {} } = {}) { this.emit = callback; }, getProps() { - return getValueFromProps(this); + return this.props; }, ...methods, }, @@ -913,6 +911,4 @@ export function createForm({ methods = {} } = {}) { getProps: Record; } >; - - return mixin; } diff --git a/compiled/alipay/src/Form/use-form-item.ts b/compiled/alipay/src/Form/use-form-item.ts new file mode 100644 index 000000000..b65508720 --- /dev/null +++ b/compiled/alipay/src/Form/use-form-item.ts @@ -0,0 +1,76 @@ +import { Value, Values } from 'async-validator'; +import { + useState, + useEvent, + useRef, + useEffect, +} from 'functional-mini/component'; +import { triggerRefEvent } from '../_util/hooks/useReportRef'; +import { EventTrigger } from './form'; + +type EventCallback = ( + trigger: EventTrigger, + value?: Value, + extraInfo?: any +) => void; + +export const useFormItem = (props) => { + const [formData, setFormDate] = useState({ + value: undefined, + status: 'default', + required: false, + errors: [], + }); + + const formRef = useRef(formData); + const emitRef = useRef(null); + + useEvent('setFormData', (values: Values) => { + setFormDate((old) => { + const newValue = { + ...old, + ...values, + }; + formRef.current = newValue; + return newValue; + }); + }); + + useEvent('getFormData', () => { + return formRef.current; + }); + + useEvent('on', (callback: EventCallback) => { + emitRef.current = callback; + }); + + const originalProps = useRef(); + + useEvent('getProps', () => { + return props; + }); + + useEffect(() => { + return () => { + emit('didUnmount'); + }; + }, []); + + function emit(event: EventTrigger, value?: any, extraInfo?: any) { + if (emitRef.current) { + emitRef.current(event, value, extraInfo); + } + } + // 这个必须要放在后面。 + triggerRefEvent(); + + useEffect(() => { + emit('deriveDataFromProps', props, originalProps.current); + originalProps.current = props; + }, [props]); + + return { + formData, + emit, + }; +}; diff --git a/compiled/alipay/src/Grid/index.json b/compiled/alipay/src/Grid/index.json index e014257aa..bf001147d 100644 --- a/compiled/alipay/src/Grid/index.json +++ b/compiled/alipay/src/Grid/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "image-icon": "../ImageIcon/index", "ant-pagination": "../Pagination/index" diff --git a/compiled/alipay/src/GuideTour/index.json b/compiled/alipay/src/GuideTour/index.json index 953dedaa1..9c14b8442 100644 --- a/compiled/alipay/src/GuideTour/index.json +++ b/compiled/alipay/src/GuideTour/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "mask": "../Mask/index", "ant-button": "../Button/index", diff --git a/compiled/alipay/src/Icon/index.json b/compiled/alipay/src/Icon/index.json index dc5676ea5..32640e0dc 100644 --- a/compiled/alipay/src/Icon/index.json +++ b/compiled/alipay/src/Icon/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" -} + "component": true +} \ No newline at end of file diff --git a/compiled/alipay/src/ImageIcon/index.json b/compiled/alipay/src/ImageIcon/index.json index 6501ab9c0..07a8bdbc4 100644 --- a/compiled/alipay/src/ImageIcon/index.json +++ b/compiled/alipay/src/ImageIcon/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index" } diff --git a/compiled/alipay/src/ImageUpload/index.json b/compiled/alipay/src/ImageUpload/index.json index 4ca3a28c9..b0463b66e 100644 --- a/compiled/alipay/src/ImageUpload/index.json +++ b/compiled/alipay/src/ImageUpload/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "loading": "../Loading/index" } -} +} \ No newline at end of file diff --git a/compiled/alipay/src/ImageUpload/index.ts b/compiled/alipay/src/ImageUpload/index.ts index 19d01115b..1759b273b 100644 --- a/compiled/alipay/src/ImageUpload/index.ts +++ b/compiled/alipay/src/ImageUpload/index.ts @@ -182,7 +182,7 @@ Component( transformValue(fileList = []) { return { needUpdate: true, - value: (fileList || []).map((item) => { + value: fileList.map((item) => { const file = { ...item, }; diff --git a/compiled/alipay/src/IndexBar/index.json b/compiled/alipay/src/IndexBar/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/IndexBar/index.json +++ b/compiled/alipay/src/IndexBar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Input/InputBlur/index.json b/compiled/alipay/src/Input/InputBlur/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Input/InputBlur/index.json +++ b/compiled/alipay/src/Input/InputBlur/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Input/Textarea/index.json b/compiled/alipay/src/Input/Textarea/index.json index ffa3220f6..3a037cbf8 100644 --- a/compiled/alipay/src/Input/Textarea/index.json +++ b/compiled/alipay/src/Input/Textarea/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index" } diff --git a/compiled/alipay/src/Input/index.json b/compiled/alipay/src/Input/index.json index 6501ab9c0..07a8bdbc4 100644 --- a/compiled/alipay/src/Input/index.json +++ b/compiled/alipay/src/Input/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index" } diff --git a/compiled/alipay/src/Input/index.ts b/compiled/alipay/src/Input/index.ts index ead72384e..bd26fb610 100644 --- a/compiled/alipay/src/Input/index.ts +++ b/compiled/alipay/src/Input/index.ts @@ -1,9 +1,9 @@ import { Component, triggerEvent } from '../_util/simply'; -import { InputDefaultProps } from './props'; +import { InputFunctionalProps } from './props'; import mixinValue from '../mixins/value'; Component( - InputDefaultProps, + InputFunctionalProps, { onChange(e) { const value = e.detail.value; diff --git a/compiled/alipay/src/Input/props.ts b/compiled/alipay/src/Input/props.ts index 5e61d4f95..475bb5ead 100644 --- a/compiled/alipay/src/Input/props.ts +++ b/compiled/alipay/src/Input/props.ts @@ -64,7 +64,7 @@ export interface InputProps extends IBaseProps { onConfirm?: (value: string, e: any) => void; } -export const InputDefaultProps: InputProps = { +export const InputFunctionalProps: InputProps = { type: null, value: null, defaultValue: null, diff --git a/compiled/alipay/src/List/ListItem/index.json b/compiled/alipay/src/List/ListItem/index.json index 40bda8aea..7dc253d62 100644 --- a/compiled/alipay/src/List/ListItem/index.json +++ b/compiled/alipay/src/List/ListItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index", "image-icon": "../../ImageIcon/index" diff --git a/compiled/alipay/src/List/index.json b/compiled/alipay/src/List/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/List/index.json +++ b/compiled/alipay/src/List/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Loading/index.json b/compiled/alipay/src/Loading/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Loading/index.json +++ b/compiled/alipay/src/Loading/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Mask/index.json b/compiled/alipay/src/Mask/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Mask/index.json +++ b/compiled/alipay/src/Mask/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Modal/index.json b/compiled/alipay/src/Modal/index.json index 5d1d91f50..6eaf614ee 100644 --- a/compiled/alipay/src/Modal/index.json +++ b/compiled/alipay/src/Modal/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-button": "../Button/index", "ant-icon": "../Icon/index", diff --git a/compiled/alipay/src/NoticeBar/index.axml b/compiled/alipay/src/NoticeBar/index.axml index 797a1ed50..6c4ff49da 100644 --- a/compiled/alipay/src/NoticeBar/index.axml +++ b/compiled/alipay/src/NoticeBar/index.axml @@ -16,7 +16,6 @@ type="SoundOutline" /> - 展示一组消息通知。 @@ -18,21 +18,20 @@ toc: content 用于当前页面内信息的通知,是一种较醒目的页面内通知方式。 ## 代码示例 - ## API -| 属性 | 说明 | 类型 | 默认值 | -| ------------- | ---------------------------------------------------------------------------------------------- | ------------ | ------- | -| className | 类名 | string | - | -| enableMarquee | 是否开启滚动动画 | boolean | false | -| extra | 自定义右侧内容 | slot | - | -| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot (微信版本需要设置 slotIcon) | string | - | -| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | -| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | -| style | 样式 | string | - | -| title | 标题 | string\|slot | - | -| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | -| slotIcon | 微信版本需要通过此字段启用 icon 位置的插槽 | boolean | - | -| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | +| 属性 | 说明 | 类型 | 默认值 | +| ---------- | ---------------------- | ----------- | ------ | +| className | 类名 | string | - | +| enableMarquee | 是否开启滚动动画 | boolean | false | +| extra | 自定义右侧内容 | slot | - | +| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot | slot \| string | - | +| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | +| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | +| style | 样式 | string | - | +| title | 标题 | string\|slot | - | +| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | +| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | + diff --git a/compiled/alipay/src/NoticeBar/props.ts b/compiled/alipay/src/NoticeBar/props.ts index ca69033dc..6468108a4 100644 --- a/compiled/alipay/src/NoticeBar/props.ts +++ b/compiled/alipay/src/NoticeBar/props.ts @@ -25,17 +25,15 @@ export interface INoticeBarProps extends IBaseProps { * @description 是否开启滚动动画 * @default false */ + enableMarquee: boolean; /** * @description 是否循环滚动,enableMarquee 为 true 时有效 * @default false */ + loop: boolean; - /** - * @description 微信版本需要通过此字段启用 icon 位置的插槽 - * @default false - */ - slotIcon?: boolean; + /** * @description 点击图标(箭头或者叉,由mode属性决定)的事件回调 */ @@ -44,6 +42,7 @@ export interface INoticeBarProps extends IBaseProps { * @description 行动点点击回调 * @param 当前点击的行动点序号 */ + onActionTap: (index: number) => void; } @@ -53,5 +52,4 @@ export const NoticeBarDefaultProps: Partial = { mode: null, enableMarquee: false, loop: false, - slotIcon: false, }; diff --git a/compiled/alipay/src/NumberKeyboard/index.json b/compiled/alipay/src/NumberKeyboard/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/NumberKeyboard/index.json +++ b/compiled/alipay/src/NumberKeyboard/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Pagination/index.json b/compiled/alipay/src/Pagination/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Pagination/index.json +++ b/compiled/alipay/src/Pagination/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Picker/CascaderPicker/index.axml b/compiled/alipay/src/Picker/CascaderPicker/index.axml index c4bd56dff..306e2a524 100644 --- a/compiled/alipay/src/Picker/CascaderPicker/index.axml +++ b/compiled/alipay/src/Picker/CascaderPicker/index.axml @@ -4,7 +4,7 @@ animationType="{{ animationType }}" popClassName="ant-cascader-picker-popup {{ popClassName || '' }}" popStyle="{{ popStyle }}" - visible="{{ visible }}" + visible="{{ state.visible }}" options="{{ columns }}" value="{{ currentValue }}" disabled="{{ disabled }}" diff --git a/compiled/alipay/src/Picker/CascaderPicker/index.json b/compiled/alipay/src/Picker/CascaderPicker/index.json index a0bae1545..208399c82 100644 --- a/compiled/alipay/src/Picker/CascaderPicker/index.json +++ b/compiled/alipay/src/Picker/CascaderPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-picker": "../index" } diff --git a/compiled/alipay/src/Picker/CascaderPicker/index.ts b/compiled/alipay/src/Picker/CascaderPicker/index.ts index b21aec9d1..aeaa0cddf 100644 --- a/compiled/alipay/src/Picker/CascaderPicker/index.ts +++ b/compiled/alipay/src/Picker/CascaderPicker/index.ts @@ -1,186 +1,149 @@ -import { - Component, - getValueFromProps, - triggerEvent, - triggerEventOnly, - triggerEventValues, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { CascaderDefaultProps } from './props'; -import equal from 'fast-deep-equal'; -import mixinValue from '../../mixins/value'; - -Component( - CascaderDefaultProps, - { - // visible受控判断 - isVisibleControlled() { - return 'visible' in getValueFromProps(this); - }, - initColumns() { - const [options, visible, defaultVisible, value, defaultValue] = - getValueFromProps(this, [ - 'options', - 'visible', - 'defaultVisible', - 'value', - 'defaultValue', - ]); - - const realValue = value || defaultValue || []; - const columns = this.getterColumns(realValue, options); - - // 首次无需校验value有效性,onOk时会校验 - this.setData({ - columns, - visible: this.isVisibleControlled() ? visible : defaultVisible, - currentValue: realValue, - formattedValueText: this.onFormat(), - }); - }, - getterColumns(value, options) { - const getColumns = (options, value, columns = []) => { - columns.push(options.map((v) => ({ value: v.value, label: v.label }))); - const currentOption = - options.find((v) => v.value === value?.[columns.length - 1]) || - options[0]; - if (currentOption?.children?.length > 0) { - return getColumns(currentOption.children, value, columns); - } - return columns; - }; - return getColumns(options, value); - }, - // 获取有效value,若从x项开始在columns里找不到,则从此项开始都选第一条 - getValidValue(value, columns) { - const result = []; - for (let i = 0; i < columns.length; i++) { - if (!columns[i].some((v) => v?.value === value?.[i])) { - result.push(...columns.slice(i).map((v) => v?.[0]?.value)); - break; - } else { - result[i] = value[i]; - } - } - return result; - }, - getOptionByValue(value) { - const options = getValueFromProps(this, 'options'); - if (!(value?.length > 0)) return null; - const result = []; - let item = options.find((v) => v.value === value[0]); - for (let i = 0; i < value.length; i++) { - if (!item) { - return null; - } - result.push({ - value: item.value, - label: item.label, - }); - item = item.children?.find((v) => v.value === value[i + 1]); - } - return result; - }, - onChange(selectedVal) { - let [selectedValue] = resolveEventValues(selectedVal); - const options = getValueFromProps(this, 'options'); - const { columns } = this.data; - const newColumns = this.getterColumns(selectedValue, options); - // columns没变化说明selectedValue在范围内,无需重置 - const newData: any = {}; - if (!equal(columns, newColumns)) { - selectedValue = this.getValidValue(selectedValue, newColumns); - newData.columns = newColumns; - } - newData.currentValue = selectedValue; - this.setData(newData); - triggerEventValues(this, 'change', [ - selectedValue, - this.getOptionByValue(selectedValue), - ]); - }, - async onOk() { - const { currentValue } = this.data; - const options = getValueFromProps(this, 'options'); - const newColumns = this.getterColumns(currentValue, options); - const validValue = this.getValidValue(currentValue, newColumns); - if (!this.isControlled()) { - this.update(validValue); - } - triggerEventValues(this, 'ok', [ - validValue, - this.getOptionByValue(validValue), - ]); - }, - onVisibleChange(visible) { - const options = getValueFromProps(this, 'options'); - const { columns } = this.data; - const realValue = this.getValue(); - if (!this.isVisibleControlled() && visible) { - const newColumns = this.getterColumns(realValue, options); - - if (!equal(columns, newColumns)) { - this.setData({ columns: newColumns }, () => { - this.setData({ - currentValue: this.getValidValue(realValue, newColumns), - formattedValueText: this.onFormat(), - }); - }); - } - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - defaultFormat(value, options) { - if (options) { - return options.map((v) => v.label).join(''); +import { useEvent, useMemo, useEffect, useState } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useComponentUpdateEffect } from '../../_util/hooks/useLayoutEffect'; +import { useMixState } from '../../_util/hooks/useMixState'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; +import { CascaderFunctionalProps, ICascaderProps } from './props'; +import { defaultFormat, getterColumns, getValidValue } from './utils'; + +const CascaderPicker = (props: ICascaderProps) => { + const [ + realValue, + { isControlled: isRealValueControlled, update: updateRealValue }, + ] = useMixState(props.defaultValue, { + value: props.value, + }); + const [{ value, columns }, setState] = useState(() => { + const value = props.value || props.defaultValue || []; + const columns = getterColumns( + props.value || props.defaultValue, + props.options + ); + return { columns, value: value }; + }); + + const { triggerEventOnly, triggerEventValues, triggerEvent } = + useComponentEvent(props); + + useComponentUpdateEffect(() => { + const newColumns = getterColumns(props.value, props.options); + const value = getValidValue(props.value, newColumns); + setState({ value, columns: newColumns }); + }, [ + props.value, + props.options, + /** + * 这里不要删 + * + * 1. picker 触发 onOk + * 2. 更新 realValue + * 3. picker 触发 onFormat (此时 realValue 未更新) + * 4. 依赖里的 realValue 更新 + * 5. 触发组件再次渲染 + * 6. 此时 onFormat 读取到最新的realValue + */ + realValue, + ]); + + function getOptionByValue(value, options) { + if (!(value?.length > 0)) return null; + const result = []; + let item = options.find((v) => v.value === value[0]); + for (let i = 0; i < value.length; i++) { + if (!item) { + return null; } - return ''; - }, - onFormat() { - const realValue = this.getValue(); - const onFormat = getValueFromProps(this, 'onFormat'); - const formatValueByProps = - onFormat && onFormat(realValue, this.getOptionByValue(realValue)); - if (formatValueByProps !== undefined && formatValueByProps !== null) { + result.push({ + value: item.value, + label: item.label, + }); + item = item.children?.find((v) => v.value === value[i + 1]); + } + return result; + } + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + const formattedValueText = useMemo(() => { + const { onFormat } = props; + + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat( + realValue, + getOptionByValue(realValue, props.options) + ); + + if (typeof formatValueByProps !== 'undefined') { return formatValueByProps; } - return this.defaultFormat(realValue, this.getOptionByValue(realValue)); - }, + } + return defaultFormat(realValue, getOptionByValue(realValue, props.options)); + }, [realValue]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、picker变化时更新 - columns: [], // 可选项,didmound、弹窗打开、picker变化时更新 - formattedValueText: '', - visible: false, - }, - [mixinValue()], - { - onInit() { - this.initColumns(); - }, - didUpdate(prevProps, prevData) { - const options = getValueFromProps(this, 'options'); - if (!equal(options, prevProps.options)) { - const { currentValue } = this.data; - const newColumns = this.getterColumns(currentValue, options); - this.setData({ - columns: newColumns, - }); - } - if (!this.isEqualValue(prevData)) { - const realValue = this.getValue(); - const newColumns = this.getterColumns(realValue, options); - const currentValue = this.getValidValue(realValue, newColumns); - this.setData({ currentValue, formattedValueText: this.onFormat() }); - } - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.setData({ visible }); + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); + useEffect(() => { + setTimeout(() => { + if (visible) { + const newColumns = getterColumns(realValue, props.options); + const currentValue = getValidValue(realValue, newColumns); + setState({ value: currentValue, columns: newColumns }); } + }) + }, [visible]); + + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible); + }); + + useEvent('onOk', () => { + // 完成时再次校验value,避免visible状态下props无效 + const validValue = getValidValue(value, columns); + + if (!isRealValueControlled) { + setTimeout(() => { + updateRealValue(validValue); + }) + } + + triggerEventValues('ok', [ + validValue, + getOptionByValue(validValue, props.options), + ]); + }); + + useEvent('onChange', (event) => { + const [selectedValue] = resolveEventValues(event); + const newColumns = getterColumns(selectedValue, props.options); + const value = getValidValue(selectedValue, newColumns); + setState({ value, columns: newColumns }); + triggerEventValues('change', [ + selectedValue, + getOptionByValue(selectedValue, props.options), + ]); + }); + + return { + state: { + visible }, - } -); + formattedValueText, + currentValue: value, + columns, + }; +}; + +mountComponent(CascaderPicker, CascaderFunctionalProps); diff --git a/compiled/alipay/src/Picker/CascaderPicker/props.ts b/compiled/alipay/src/Picker/CascaderPicker/props.ts index 09b589ae9..2d2b2d38d 100644 --- a/compiled/alipay/src/Picker/CascaderPicker/props.ts +++ b/compiled/alipay/src/Picker/CascaderPicker/props.ts @@ -121,6 +121,14 @@ export interface ICascaderProps extends IBaseProps { } export const CascaderDefaultProps: Partial = { + placeholder: '请选择', + okText: '确定', + cancelText: '取消', + disabled: false, + maskClosable: false, +}; + +export const CascaderFunctionalProps: Partial = { visible: null, defaultVisible: null, animationType: 'transform', diff --git a/compiled/alipay/src/Picker/index.axml b/compiled/alipay/src/Picker/index.axml index 5d01e2c43..8f795ba1e 100644 --- a/compiled/alipay/src/Picker/index.axml +++ b/compiled/alipay/src/Picker/index.axml @@ -31,7 +31,7 @@ animationType="{{ animationType }}" destroyOnClose onClose="onMaskDismiss" - visible="{{ visible }}"> + visible="{{ state.visible }}"> { - const formatValue = this.getterFormatText(); - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - formatValue, - selectedIndex, - visible: this.isVisibleControlled() ? visible : defaultVisible, - }); - } - ); - }, - getterColumns(options) { - let columns = []; - if (options.length > 0) { - if (options.every((item) => Array.isArray(item))) { - this.single = false; - columns = options.slice(); - } else { - this.single = true; - columns = [options]; - } - } - return columns; - }, - defaultFormat(value, column) { - if (Array.isArray(column)) { - return column - .filter((c) => c !== undefined) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; - }, - getterFormatText() { - const [onFormat, formattedValueText] = getValueFromProps(this, [ - 'onFormat', - 'formattedValueText', - ]); - if (typeof formattedValueText === 'string') { - return formattedValueText; - } - const { columns } = this.data; - const realValue = this.getValue(); - const { matchedColumn } = getStrictMatchedItemByValue( - columns, - realValue, - this.single - ); - const formatValueByProps = onFormat && onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat(realValue, matchedColumn); - }, - getterSelectedIndex() { - const selectedIndex = []; - const columns = this.data.columns; - const realValue = this.getValue(); - let value = realValue || []; - if (this.single) { - value = [realValue]; - } - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - let index = column.findIndex((c) => { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - } - return selectedIndex; - }, +const Picker = (props: IPickerProps) => { + const [value, { isControlled: isValueControlled, update: updateValue }] = + useMixState(props.defaultValue ?? [], { + value: props.value, + }); - onOpen() { - const disabled = getValueFromProps(this, 'disabled'); - if (!disabled) { - this.tempSelectedIndex = null; - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex, - }); - this.triggerPicker(true); - } - }, + const { triggerEvent, triggerEventOnly, triggerEventValues } = + useComponentEvent(props); - triggerPicker(visible) { - this.setData({ - visible, - }); - triggerEvent(this, 'visibleChange', visible); - }, + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); + const singleRef = useRef(false); + const selectIndexRef = useRef(null); - onMaskDismiss() { - const maskClosable = getValueFromProps(this, 'maskClosable'); - if (!maskClosable) { - return; - } - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); - }, + function triggerPicker(newVisibleValue: boolean) { + updateVisible(newVisibleValue); + triggerEvent('visibleChange', newVisibleValue); + } - onCancel() { - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); - }, + const [selectedIndex, setSelectedIndex] = useState([]); + + const columns = useMemo(() => { + return getterColumns(props.options, singleRef); + }, [props.options]); + + useEffect(() => { + selectIndexRef.current = null; + setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); + }, [columns, value]); + + const formatValue = useMemo(() => { + if (typeof props.formattedValueText === 'string') { + return props.formattedValueText; + } + const formatValue = getterFormatText( + columns, + value, + props.onFormat, + singleRef + ); + return formatValue; + }, [props.formattedValueText, visible, columns, value, props.onFormat]); + + useEvent('onOpen', () => { + if (props.disabled) { + return; + } + selectIndexRef.current = null; + const selectedIndex = getterSelectedIndex(columns, value, singleRef); + setSelectedIndex(selectedIndex); + triggerPicker(true); + }); + + useEvent('onCancel', () => { + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'cancel' } }); + }); + + useEvent('onMaskDismiss', () => { + if (!props.maskClosable) { + return; + } + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'mask' } }); + }); + + useEvent('onChange', (e) => { + const { value: selectedIndex } = e.detail; + const { matchedColumn, matchedValues } = getMatchedItemByIndex( + columns, + selectedIndex, + singleRef + ); + selectIndexRef.current = selectedIndex; + setSelectedIndex(selectedIndex); + triggerEventValues('change', [matchedValues, matchedColumn], e); + }); - onChange(e) { - const { value: selectedIndex } = e.detail; - this.tempSelectedIndex = selectedIndex; - this.isChangingPickerView = true; - const { matchedColumn, matchedValues } = getMatchedItemByIndex( - this.data.columns, - this.tempSelectedIndex, - this.single + useEvent('onOk', () => { + let result; + if (selectIndexRef.current) { + result = getMatchedItemByIndex( + columns, + selectIndexRef.current, + singleRef ); - this.setData({ - selectedIndex, - }); - triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); - }, + } else { + result = getMatchedItemByValue(columns, value, singleRef); + } - async onOk() { - let result; - if (this.tempSelectedIndex) { - result = getMatchedItemByIndex( - this.data.columns, - this.tempSelectedIndex, - this.single - ); - } else { - result = getMatchedItemByValue( - this.data.columns, - this.getValue(), - this.single - ); - } - const { matchedColumn, matchedValues } = result; - this.triggerPicker(false); - if (!this.isControlled()) { - this.update(matchedValues); - } - triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); - }, - }, - { - formatValue: '', - columns: [], - visible: false, - selectedIndex: [], - }, - [ - mixinValue({ - transformValue(value) { - return { - needUpdate: true, - value: value === undefined ? [] : value, - }; - }, - }), - ], - { - tempSelectedIndex: null, - single: false, - isChangingPickerView: false, - onInit() { - this.initData(); + const { matchedColumn, matchedValues } = result; + + triggerPicker(false); + if (!isValueControlled) { + updateValue(matchedValues); + } + triggerEventValues('ok', [matchedValues, matchedColumn]); + }); + + return { + formatValue, + selectedIndex, + columns, + state: { + visible, }, - didUpdate(prevProps) { - const options = getValueFromProps(this, 'options'); - if (!equal(options, prevProps.options)) { - const newColums = this.getterColumns(options); - this.setData( - { - columns: newColums, - }, - () => { - // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 - if (!this.isChangingPickerView) { - this.tempSelectedIndex = null; - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex, - }); - } - } - ); - } - const value = getValueFromProps(this, 'value'); - if (!equal(prevProps.value, value)) { - const selectedIndex = this.getterSelectedIndex(); - this.tempSelectedIndex = null; - this.setData({ - selectedIndex, - }); - } - const visible = getValueFromProps(this, 'visible'); - if (!equal(prevProps.visible, visible)) { - this.setData({ visible }); - } - const formatValue = this.getterFormatText(); - const formattedValueText = getValueFromProps(this, 'formattedValueText'); - if ( - formatValue !== this.data.formatValue || - prevProps.formattedValueText !== formattedValueText - ) { - this.setData({ - formatValue, - }); - } - this.isChangingPickerView = false; + mixin: { + value, }, - } -); + }; +}; + +mountComponent(Picker, PickerFunctionalProps); diff --git a/compiled/alipay/src/Picker/props.ts b/compiled/alipay/src/Picker/props.ts index 3d2eab5a1..e5c75a091 100644 --- a/compiled/alipay/src/Picker/props.ts +++ b/compiled/alipay/src/Picker/props.ts @@ -54,7 +54,7 @@ export interface IPickerProps extends IBaseProps { * @default '请选择' */ placeholder: string; - /** + /** * @description 空状态提示文案 * @default '暂无数据' */ @@ -131,6 +131,17 @@ export interface IPickerProps extends IBaseProps { } export const PickerDefaultProps: Partial = { + okText: '确定', + cancelText: '取消', + disabled: false, + maskClosable: false, + options: [], + placeholder: '请选择', + defaultValue: [], + emptyText: '暂无数据' +}; + +export const PickerFunctionalProps: Partial = { formattedValueText: null, visible: null, defaultVisible: null, @@ -147,5 +158,5 @@ export const PickerDefaultProps: Partial = { popStyle: '', maskClosable: true, onFormat: null, - emptyText: '暂无数据', + emptyText: '暂无数据' }; diff --git a/compiled/alipay/src/Picker/utils.ts b/compiled/alipay/src/Picker/utils.ts index e3a9a1eb0..9ec50878d 100644 --- a/compiled/alipay/src/Picker/utils.ts +++ b/compiled/alipay/src/Picker/utils.ts @@ -1,3 +1,5 @@ +import { PickerValue } from './props'; + function getColumnValue(columnItem) { if (typeof columnItem === 'object') return columnItem.value; return columnItem; @@ -12,7 +14,7 @@ export function getStrictMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = (value || [])[i]; + const compareValue = value[i]; index = column.findIndex((c) => { const columnValue = getColumnValue(c); return columnValue === compareValue; @@ -27,8 +29,8 @@ export function getStrictMatchedItemByValue(columns, value, single) { } // 如果找不到value对应的item项目,返回第一项 -export function getMatchedItemByValue(columns, value, single) { - if (single) { +export function getMatchedItemByValue(columns, value, singleRef) { + if (singleRef.current) { value = [value]; } const matchedValues = []; @@ -36,7 +38,7 @@ export function getMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = (value || [])[i]; + const compareValue = value[i]; if (compareValue === undefined || compareValue === null) { index = 0; } else { @@ -52,8 +54,8 @@ export function getMatchedItemByValue(columns, value, single) { matchedValues[i] = getColumnValue(column[index]); } return { - matchedColumn: single ? matchedColumn[0] : matchedColumn, - matchedValues: single ? matchedValues[0] : matchedValues, + matchedColumn: singleRef.current ? matchedColumn[0] : matchedColumn, + matchedValues: singleRef.current ? matchedValues[0] : matchedValues, }; } @@ -82,7 +84,75 @@ export function getMatchedItemByIndex(columns, selectedIndex, single) { } return { - matchedColumn: single ? matchedColumn[0] : matchedColumn, - matchedValues: single ? matchedValues[0] : matchedValues, + matchedColumn: single.current ? matchedColumn[0] : matchedColumn, + matchedValues: single.current ? matchedValues[0] : matchedValues, }; } + +export function getterColumns(options: PickerValue[], singleRef) { + let columns = []; + if (options.length > 0) { + if (options.every((item) => Array.isArray(item))) { + singleRef.current = false; + columns = options.slice(); + } else { + singleRef.current = true; + columns = [options]; + } + } + return columns; +} + +export function defaultFormat(value, column) { + if (Array.isArray(column)) { + return column + .filter((c) => c !== undefined) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); + } + return (column && column.label) || column || ''; +} + +export function getterFormatText(columns, realValue, onFormat, singleRef) { + const { matchedColumn } = getStrictMatchedItemByValue( + columns, + realValue, + singleRef.current + ); + + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined) { + return formatValueByProps; + } + } + return defaultFormat(realValue, matchedColumn); +} + +export function getterSelectedIndex(columns, realValue, sinefileRef) { + const selectedIndex = []; + let value = realValue || []; + if (sinefileRef.current) { + value = [realValue]; + } + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + const compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + let index = column.findIndex((c) => { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + } + return selectedIndex; +} diff --git a/compiled/alipay/src/Popover/index.json b/compiled/alipay/src/Popover/index.json index 6083004a5..0c9094440 100644 --- a/compiled/alipay/src/Popover/index.json +++ b/compiled/alipay/src/Popover/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "mask": "../Mask/index" } diff --git a/compiled/alipay/src/Popup/index.json b/compiled/alipay/src/Popup/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Popup/index.json +++ b/compiled/alipay/src/Popup/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Progress/index.json b/compiled/alipay/src/Progress/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Progress/index.json +++ b/compiled/alipay/src/Progress/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Radio/RadioGroup/index.json b/compiled/alipay/src/Radio/RadioGroup/index.json index 857c3e722..787ac5732 100644 --- a/compiled/alipay/src/Radio/RadioGroup/index.json +++ b/compiled/alipay/src/Radio/RadioGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/compiled/alipay/src/Radio/index.json b/compiled/alipay/src/Radio/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Radio/index.json +++ b/compiled/alipay/src/Radio/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/RareWordsKeyboard/index.json b/compiled/alipay/src/RareWordsKeyboard/index.json index 63e881845..6b2389527 100644 --- a/compiled/alipay/src/RareWordsKeyboard/index.json +++ b/compiled/alipay/src/RareWordsKeyboard/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "result": "../Result/index", diff --git a/compiled/alipay/src/RareWordsKeyboard/index.ts b/compiled/alipay/src/RareWordsKeyboard/index.ts index 05a98e55c..2f8181793 100644 --- a/compiled/alipay/src/RareWordsKeyboard/index.ts +++ b/compiled/alipay/src/RareWordsKeyboard/index.ts @@ -1,141 +1,159 @@ -import { Component, triggerEvent, triggerEventOnly } from '../_util/simply'; import { PINYIN_MAP } from './constants'; -import { RareWordsKeyboardProps } from './props'; +import { RareWordsKeyboardProps, IRareWordsKeyboardProps } from './props'; import { formatZDatas, loadFontFace, matchWordsRecommend } from './utils'; import { ZDATAS } from './zdatas'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; +import '../_util/assert-component2'; +import { useEffect, useEvent, useState } from 'functional-mini/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { mountComponent } from '../_util/component'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; const wordsData = formatZDatas(ZDATAS.datas); -Component( - RareWordsKeyboardProps, - { - getInstance() { - if (this.$id) { - return my; - } - return this; - }, - async getBoundingClientRect(query: string) { - return await getInstanceBoundingClientRect(this.getInstance(), query); - }, - // 隐藏键盘,失去焦点 - handleHide() { - this.setData({ - inputValue: [], - matchWordsList: [], - displayStr: '', - showMoreWords: false, - }); - triggerEventOnly(this, 'close'); - }, - - // 点击键盘key值 - handleKeyClick(e) { - if (this.data.loading) return; - const { value = '' } = e.currentTarget.dataset; - if (!value) return; - const inputValue = [...this.data.inputValue, value]; - this.setData({ - inputValue: [...inputValue], - ...this.computeMatchWords(inputValue), - }); - }, - - // 点击删除 - handleDelete() { - const inputValue = [...this.data.inputValue]; - if (this.data.inputValue.length === 0) return; - inputValue.pop(); - this.setData({ - inputValue: [...inputValue], - ...this.computeMatchWords(inputValue), - }); - }, - - // 计算展示值和候选字列表 - computeMatchWords(inputValue) { - const displayStr = Array.isArray(inputValue) - ? inputValue.join('') - : inputValue; - const curMatchWords = matchWordsRecommend(wordsData, displayStr); - return { - displayStr, - matchWordsList: curMatchWords, - }; - }, - - // 点击查看更多 - hanleLookMore() { - if (this.data.matchWordsList.length <= this.data.maxDisplayNum) { - this.handleHide(); - return; - } - this.setData({ - showMoreWords: !this.data.showMoreWords, - }); - }, - - // 计算每行可以展示的最大字数 - async computeMaxDisplayNum() { - const [singleWords, wordsWrap] = await Promise.all([ - this.getBoundingClientRect( - '.ant-rare-words-keyboard-match_words_hidden' - ), - this.getBoundingClientRect( - '.ant-rare-words-keyboard-match_words_inner' - ), - ]); - if (!wordsWrap?.width || !singleWords?.width) return; - const maxDisplayNumInOneLine = parseInt( - (wordsWrap?.width / singleWords?.width).toString(), - 10 - ); - this.setData({ maxDisplayNum: maxDisplayNumInOneLine }); - }, - - // 加载字体 - loadFont() { - this.setData({ - loading: true, - }); - loadFontFace() - .then(() => { - this.setData({ showErrorPage: false, loading: false }); - }) - .catch((err) => { - this.setData({ showErrorPage: true, loading: false }); - triggerEvent(this, 'error', err); - }); - }, - - // 点击重试 - handleRetry() { - this.loadFont(); - }, - - handleWordClick(e) { - const { value = '' } = e.currentTarget.dataset; - if (!value) return; - triggerEvent(this, 'change', value); - this.handleHide(); - }, - }, - { +const RareWordsKeyboard = (props: IRareWordsKeyboardProps) => { + const [fontState, setFontState] = useState({ + showErrorPage: false, // 是否展示错误页 loading: false, + }); + const [maxDisplayNum, setMaxDisplayNum] = useState(0); + const [keyboardState, setKeyboardState] = useState({ inputValue: [], // 已输入的字符数组 displayStr: '', // 已输入的字符串 matchWordsList: [], // 候选字列表 showMoreWords: false, // 是否展示更多候选字 - pinyinMaps: PINYIN_MAP, // 拼音键盘 - maxDisplayNum: 0, // 一行最多展示的字数 - showErrorPage: false, // 是否展示错误页 - }, - null, - { - didMount() { - this.loadFont(); - this.computeMaxDisplayNum(); - }, + }); + + const { triggerEvent, triggerEventOnly } = useComponentEvent(props); + + const handleHide = useStableCallback(() => { + setKeyboardState({ + inputValue: [], + matchWordsList: [], + displayStr: '', + showMoreWords: false, + }); + triggerEventOnly('close'); + }); + + // 计算展示值和候选字列表 + function computeMatchWords(inputValue) { + const displayStr = Array.isArray(inputValue) + ? inputValue.join('') + : inputValue; + const curMatchWords = matchWordsRecommend(wordsData, displayStr); + return { + displayStr, + matchWordsList: curMatchWords, + }; + } + function loadFont() { + setFontState((pre) => { + return { + ...pre, + loading: true, + }; + }); + loadFontFace() + .then(() => { + setFontState({ showErrorPage: false, loading: false }); + }) + .catch((err) => { + setFontState({ showErrorPage: true, loading: false }); + triggerEvent('error', err); + }); + } + + const { getBoundingClientRect } = useInstanceBoundingClientRect(); + async function computeMaxDisplayNum() { + const [singleWords, wordsWrap] = await Promise.all([ + getBoundingClientRect('.ant-rare-words-keyboard-match_words_hidden'), + getBoundingClientRect('.ant-rare-words-keyboard-match_words_inner'), + ]); + if (!wordsWrap?.width || !singleWords?.width) return; + const maxDisplayNumInOneLine = parseInt( + (wordsWrap?.width / singleWords?.width).toString(), + 10 + ); + setMaxDisplayNum(maxDisplayNumInOneLine); } -); + + useEffect(() => { + loadFont(); + computeMaxDisplayNum(); + }, []); + + useEvent('handleRetry', () => { + loadFont(); + }); + + useEvent('handleWordClick', (e) => { + const { value = '' } = e.currentTarget.dataset; + if (!value) return; + triggerEvent('change', value); + handleHide(); + }); + + useEvent('hanleLookMore', () => { + if (keyboardState.matchWordsList.length <= maxDisplayNum) { + handleHide(); + return; + } + setKeyboardState((old) => { + return { + ...old, + showMoreWords: !old.showMoreWords, + }; + }); + }); + + // 隐藏键盘,失去焦点 + useEvent('handleHide', () => { + handleHide(); + }); + + // 点击键盘key值 + useEvent('handleKeyClick', (e) => { + if (fontState.loading) { + return; + } + const { value = '' } = e.target.dataset; + if (!value) { + return; + } + + setKeyboardState((old) => { + const inputValue = [...old.inputValue, value]; + return { + ...old, + inputValue, + ...computeMatchWords(inputValue), + }; + }); + }); + + // 点击删除 + useEvent('handleDelete', () => { + if (keyboardState.inputValue.length === 0) { + return; + } + setKeyboardState((old) => { + const inputValue = [...old.inputValue]; + inputValue.pop(); + return { + ...old, + inputValue: [...inputValue], + ...computeMatchWords(inputValue), + }; + }); + }); + + return { + ...fontState, + maxDisplayNum, + ...keyboardState, + pinyinMaps: PINYIN_MAP, // 拼音键盘 + }; +}; + +mountComponent(RareWordsKeyboard, RareWordsKeyboardProps); diff --git a/compiled/alipay/src/Rate/index.json b/compiled/alipay/src/Rate/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Rate/index.json +++ b/compiled/alipay/src/Rate/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Result/index.json b/compiled/alipay/src/Result/index.json index 5b3034c4a..188dcef68 100644 --- a/compiled/alipay/src/Result/index.json +++ b/compiled/alipay/src/Result/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "image-icon": "../ImageIcon/index" diff --git a/compiled/alipay/src/Selector/index.json b/compiled/alipay/src/Selector/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Selector/index.json +++ b/compiled/alipay/src/Selector/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/Avatar/index.json b/compiled/alipay/src/Skeleton/Avatar/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Skeleton/Avatar/index.json +++ b/compiled/alipay/src/Skeleton/Avatar/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/Button/index.json b/compiled/alipay/src/Skeleton/Button/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Skeleton/Button/index.json +++ b/compiled/alipay/src/Skeleton/Button/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/Input/index.json b/compiled/alipay/src/Skeleton/Input/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Skeleton/Input/index.json +++ b/compiled/alipay/src/Skeleton/Input/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/Paragraph/index.json b/compiled/alipay/src/Skeleton/Paragraph/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Skeleton/Paragraph/index.json +++ b/compiled/alipay/src/Skeleton/Paragraph/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/Title/index.json b/compiled/alipay/src/Skeleton/Title/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/alipay/src/Skeleton/Title/index.json +++ b/compiled/alipay/src/Skeleton/Title/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/alipay/src/Skeleton/index.json b/compiled/alipay/src/Skeleton/index.json index 85c588cb3..04b9328d7 100644 --- a/compiled/alipay/src/Skeleton/index.json +++ b/compiled/alipay/src/Skeleton/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "avatar": "./Avatar/index", "paragraph": "./Paragraph/index", diff --git a/compiled/alipay/src/Slider/index.json b/compiled/alipay/src/Slider/index.json index adb9f384f..66ee617da 100644 --- a/compiled/alipay/src/Slider/index.json +++ b/compiled/alipay/src/Slider/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "popover": "../Popover/index" } diff --git a/compiled/alipay/src/Slider/index.ts b/compiled/alipay/src/Slider/index.ts index 663a16ff4..7e5dfc94f 100644 --- a/compiled/alipay/src/Slider/index.ts +++ b/compiled/alipay/src/Slider/index.ts @@ -261,7 +261,11 @@ Component( typeof this.onChangeValue === 'undefined' ? this.getValue() : this.onChangeValue; - if (emit && !this.isSliderValueEqual(this.onChangeValue, value)) { + if ( + emit && + getValueFromProps(this, 'onChange') && + !this.isSliderValueEqual(this.onChangeValue, value) + ) { this.onChangeValue = value; triggerEvent(this, 'change', value); } diff --git a/compiled/alipay/src/Stepper/index.json b/compiled/alipay/src/Stepper/index.json index 4ea7f8f97..12bdacc36 100644 --- a/compiled/alipay/src/Stepper/index.json +++ b/compiled/alipay/src/Stepper/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-button": "../Button/index", "ant-input": "../Input/InputBlur/index" diff --git a/compiled/alipay/src/Steps/index.json b/compiled/alipay/src/Steps/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Steps/index.json +++ b/compiled/alipay/src/Steps/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/SwipeAction/index.json b/compiled/alipay/src/SwipeAction/index.json index dc5676ea5..32640e0dc 100644 --- a/compiled/alipay/src/SwipeAction/index.json +++ b/compiled/alipay/src/SwipeAction/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" -} + "component": true +} \ No newline at end of file diff --git a/compiled/alipay/src/Switch/index.json b/compiled/alipay/src/Switch/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Switch/index.json +++ b/compiled/alipay/src/Switch/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/TabBar/index.json b/compiled/alipay/src/TabBar/index.json index 5b443dea3..a7c04bf5b 100644 --- a/compiled/alipay/src/TabBar/index.json +++ b/compiled/alipay/src/TabBar/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-badge": "../Badge/index", "image-icon": "../ImageIcon/index" diff --git a/compiled/alipay/src/Tabs/index.json b/compiled/alipay/src/Tabs/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/alipay/src/Tabs/index.json +++ b/compiled/alipay/src/Tabs/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/alipay/src/Tabs/index.ts b/compiled/alipay/src/Tabs/index.ts index 001807816..81c0ec37b 100644 --- a/compiled/alipay/src/Tabs/index.ts +++ b/compiled/alipay/src/Tabs/index.ts @@ -1,162 +1,175 @@ -import { Component, triggerEvent, getValueFromProps } from '../_util/simply'; -import { TabsDefaultProps } from './props'; -import createValue from '../mixins/value'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; +import { useState } from 'functional-mini/compat'; +import { + useDidMount, + useEvent, + useReady, + useRef, +} from 'functional-mini/component'; +import '../_util/assert-component2'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; +import { useComponentUpdateEffect } from '../_util/hooks/useLayoutEffect'; +import { useMixState } from '../_util/hooks/useMixState'; +import { ITabsProps, TabsFunctionalProps } from './props'; -Component( - TabsDefaultProps, - { - getInstance() { - if (this.$id) { - return my; - } - return this; - }, - get$Id() { - return this.$id ? `-${this.$id}` : ''; - }, - async getBoundingClientRect(query: string) { - return await getInstanceBoundingClientRect(this.getInstance(), query); - }, - async updateFade() { - this.setData({ - leftFade: !!this.scrollLeft, - }); - const items = getValueFromProps(this, 'items'); - const [view, item] = await Promise.all([ - this.getBoundingClientRect(`#ant-tabs-bar-scroll-view${this.get$Id()}`), - this.getBoundingClientRect( - `#ant-tabs-bar-item${this.get$Id()}-${items.length - 1}` - ), - ]); - if (!item || !view) { - return; - } - this.setData({ - rightFade: item.left + item.width / 2 > view.width, - }); - }, - async updateScroll() { - const current = this.getValue(); - const [view, item] = await Promise.all([ - this.getBoundingClientRect(`#ant-tabs-bar-scroll-view${this.get$Id()}`), - this.getBoundingClientRect( - `#ant-tabs-bar-item${this.get$Id()}-${current}` - ), - ]); +const Tabs = (props: ITabsProps) => { + const [currentValue, { isControlled, update }] = useMixState( + props.defaultCurrent, + { + value: props.current, + } + ); - if (!view || !item) { - return; - } + const [state, updateState] = useState({ + scrollLeft: 0, + scrollTop: 0, + leftFade: false, + rightFade: false, + }); + const scrollRef = useRef({ scrollLeft: 0, scrollTop: 0 }); - const [direction, scrollMode] = getValueFromProps(this, [ - 'direction', - 'scrollMode', - ]); - if (direction === 'vertical') { - let scrollTop = this.scrollTop || 0; - let needScroll = false; - if (scrollMode === 'center') { - needScroll = true; - scrollTop += - item.top - view.top - Math.max((view.height - item.height) / 2, 0); - } else { - const distance = item.top - view.top; - if (distance < 0) { - scrollTop += distance; - needScroll = true; - } else if (distance + item.height > view.height) { - scrollTop += Math.min( - distance + item.height - view.height, - distance - ); - needScroll = true; - } - } - if (needScroll) { - if (scrollTop === this.data.scrollTop) { - scrollTop += Math.random(); - } - this.setData({ - scrollTop, - }); - } - return; - } - let scrollLeft = this.scrollLeft || 0; + const { triggerEvent } = useComponentEvent(props); + + const updatePartState = (part) => { + updateState((old) => { + return { + ...old, + ...part, + }; + }); + }; + + const { getBoundingClientRectWithBuilder, getBoundingClientRect } = + useInstanceBoundingClientRect(); + + const updateFade = useStableCallback(async () => { + updatePartState({ + leftFade: !!scrollRef.current.scrollLeft, + }); + const [view, item] = await Promise.all([ + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-scroll-view${id}` + ), + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-item${id}-${props.items.length - 1}` + ), + ]); + if (!item || !view) { + return; + } + updatePartState({ + rightFade: item.left + item.width / 2 > view.width, + }); + }); + + const updateScroll = useStableCallback(async () => { + const current = currentValue; + const [view, item] = await Promise.all([ + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-scroll-view${id}` + ), + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-item${id}-${current}` + ), + ]); + if (!view || !item) { + return; + } + + if (props.direction === 'vertical') { + let scrollTop = scrollRef.current.scrollTop || 0; let needScroll = false; - if (scrollMode === 'center') { + if (props.scrollMode === 'center') { needScroll = true; - scrollLeft += - item.left - view.left - Math.max((view.width - item.width) / 2, 0); + scrollTop += + item.top - view.top - Math.max((view.height - item.height) / 2, 0); } else { - const distance = item.left - view.left; + const distance = item.top - view.top; if (distance < 0) { - scrollLeft += distance; + scrollTop += distance; needScroll = true; - } else if (distance + item.width > view.width) { - scrollLeft += Math.min(distance + item.width - view.width, distance); + } else if (distance + item.height > view.height) { + scrollTop += Math.min(distance + item.height - view.height, distance); needScroll = true; } } if (needScroll) { - if (scrollLeft === this.data.scrollLeft) { - scrollLeft += Math.random(); + if (scrollTop === state.scrollTop) { + scrollTop += Math.random(); } - this.setData({ - scrollLeft, + updatePartState({ + scrollTop, }); - this.updateFade(); } - }, - async onScroll(e) { - const direction = getValueFromProps(this, 'direction'); - if (direction === 'vertical') { - this.scrollTop = e.detail.scrollTop; - return; - } - this.scrollLeft = e.detail.scrollLeft; - this.updateFade(); - }, - onChange(e) { - const index = parseInt(e.currentTarget.dataset.index, 10); - const items = getValueFromProps(this, 'items'); - if (items[index].disabled) { - return; - } - if (this.getValue() === index) { - return; + return; + } + let scrollLeft = scrollRef.current.scrollLeft || 0; + let needScroll = false; + if (props.scrollMode === 'center') { + needScroll = true; + scrollLeft += + item.left - view.left - Math.max((view.width - item.width) / 2, 0); + } else { + const distance = item.left - view.left; + if (distance < 0) { + scrollLeft += distance; + needScroll = true; + } else if (distance + item.width > view.width) { + scrollLeft += Math.min(distance + item.width - view.width, distance); + needScroll = true; } - if (!this.isControlled()) { - this.update(index); + } + if (needScroll) { + if (scrollLeft === state.scrollLeft) { + scrollLeft += Math.random(); } + updatePartState({ + scrollLeft, + }); + updateFade(); + } + }); - triggerEvent(this, 'change', index, e); - }, - }, - { - scrollLeft: 0, - scrollTop: 0, - leftFade: false, - rightFade: false, - }, - [ - createValue({ - valueKey: 'current', - defaultValueKey: 'defaultCurrent', - }), - ], - { - scrollLeft: 0, - scrollTop: 0, - didMount() { - this.updateScroll(); - }, - didUpdate(prevProps, prevData) { - const items = getValueFromProps(this, 'items'); - if (prevProps.items !== items || !this.isEqualValue(prevData)) { - this.updateScroll(); - } + useEvent('onScroll', async (e) => { + if (props.direction === 'vertical') { + scrollRef.current.scrollTop = e.detail.scrollTop; + return; + } + scrollRef.current.scrollLeft = e.detail.scrollLeft; + updateFade(); + }); + + useEvent('onChange', async (e) => { + const index = parseInt(e.currentTarget.dataset.index, 10); + if (props.items[index].disabled) { + return; + } + if (currentValue === index) { + return; + } + if (!isControlled) { + update(index); + } + triggerEvent('change', index, e); + }); + + useDidMount(() => { + updateScroll(); + }, []); + + useComponentUpdateEffect(() => { + updateScroll(); + }, [props.items, currentValue]); + + + return { + mixin: { + value: currentValue, }, - } -); + ...state, + }; +}; + +mountComponent(Tabs, TabsFunctionalProps); diff --git a/compiled/alipay/src/Tabs/props.ts b/compiled/alipay/src/Tabs/props.ts index 7bb52cd9b..1bd4707be 100644 --- a/compiled/alipay/src/Tabs/props.ts +++ b/compiled/alipay/src/Tabs/props.ts @@ -58,6 +58,13 @@ export interface ITabsProps extends IBaseProps { } export const TabsDefaultProps: Partial = { + type: 'basic', + defaultCurrent: 0, + items: [], + scrollMode: 'edge', +}; + +export const TabsFunctionalProps: Partial = { type: 'basic', direction: 'horizontal', current: null, diff --git a/compiled/alipay/src/Tag/index.json b/compiled/alipay/src/Tag/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/alipay/src/Tag/index.json +++ b/compiled/alipay/src/Tag/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/alipay/src/Toast/index.json b/compiled/alipay/src/Toast/index.json index 1d101cb6b..0918a24ce 100644 --- a/compiled/alipay/src/Toast/index.json +++ b/compiled/alipay/src/Toast/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "am-icon": "../Icon/index", "mask": "../Mask/index", diff --git a/compiled/alipay/src/_util/component.ts b/compiled/alipay/src/_util/component.ts new file mode 100644 index 000000000..05c423a77 --- /dev/null +++ b/compiled/alipay/src/_util/component.ts @@ -0,0 +1,27 @@ +import { alipayComponent, wechatComponent } from 'functional-mini/component'; + +function removeNullProps(props) { + const newProps = {}; + for (const key in props) { + if (props[key] !== null) { + newProps[key] = props[key]; + } + } + return newProps; +} + +export function mountComponent( + Hooks: (props: T) => unknown, + defaultProps: T +) { + + Component( + alipayComponent(Hooks, removeNullProps(mergeDefaultProps(defaultProps))) + ); +} + +function mergeDefaultProps(defaultProps: Record = {}) { + return { + ...defaultProps, + }; +} diff --git a/compiled/alipay/src/_util/hooks/useComponentEvent.ts b/compiled/alipay/src/_util/hooks/useComponentEvent.ts new file mode 100644 index 000000000..1e2d7d31b --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useComponentEvent.ts @@ -0,0 +1,77 @@ +import { useComponent } from 'functional-mini/component'; +import fmtEvent from '../fmtEvent'; +import { useEvent } from './useEvent'; + +export function useComponentEvent(props: T) { + const component = useComponent(); + const triggerEvent = useEvent( + (eventName: string, value: unknown, e?: any) => { + // 首字母大写,然后加上 on + + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](value, fmtEvent(props, e)); + } + + } + ); + + const triggerEventValues = useEvent( + (eventName: string, values: any[], e?: any) => { + // 首字母大写,然后加上 on + + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](...values, fmtEvent(props, e)); + } + + } + ); + const triggerEventOnly = useEvent((eventName: string, e?: any) => { + // 首字母大写,然后加上 on + + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + + }); + + const alipayForwardCatchEvent = useEvent((eventName: string, e: any) => { + // 首字母大写,然后加上 catch + + const alipayCallbackName = + 'catch' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + }); + + const alipayForwardEvent = useEvent((eventName: string, e: any) => { + // 首字母大写,然后加上 on + + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + }); + + return { + triggerEvent, + triggerEventValues, + triggerEventOnly, + // 转发 catch 事件 + alipayForwardCatchEvent, + // 转发事件 + alipayForwardEvent, + }; +} diff --git a/compiled/alipay/src/_util/hooks/useEvent.ts b/compiled/alipay/src/_util/hooks/useEvent.ts new file mode 100644 index 000000000..665c6e811 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useEvent.ts @@ -0,0 +1,18 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useEvent.ts + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as React from 'functional-mini/compat'; + +// eslint-disable-next-line @typescript-eslint/ban-types +export function useEvent(callback: T): T { + const fnRef = React.useRef(); + fnRef.current = callback; + + const memoFn = React.useCallback( + ((...args: any) => fnRef.current?.(...args)) as any, + [] + ); + + return memoFn; +} diff --git a/compiled/alipay/src/_util/hooks/useHandleCustomEvent.ts b/compiled/alipay/src/_util/hooks/useHandleCustomEvent.ts new file mode 100644 index 000000000..e66d98d27 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useHandleCustomEvent.ts @@ -0,0 +1,56 @@ +import { useEvent } from 'functional-mini/component'; +import { platform } from '../platform'; + +export type EventHandler = (value: T, e: any) => void; + +export const useHandleCustomEvent = ( + eventName: string, + handler: EventHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (eventOrValue: any, alipayEvent?: any) => { + if (platform() === 'alipay') { + return handler(eventOrValue, alipayEvent); + } + + } + ); +}; + +export type MultipleValueEventHandler = (...args: any[]) => void; + +export const useMultipleValueHandleCustomEvent = ( + eventName: string, + handler: MultipleValueEventHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (...args: any[]) => { + if (platform() === 'alipay') { + return handler(...args); + } + + } + ); +}; + +export type EventOnlyHandler = (e: any) => void; + +export const useHandleCustomEventOnly = ( + eventName: string, + handler: EventOnlyHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (event) => { + if (platform() === 'alipay') { + return handler(event); + } + + } + ); +}; diff --git a/compiled/alipay/src/_util/hooks/useInstanceBoundingClientRect.ts b/compiled/alipay/src/_util/hooks/useInstanceBoundingClientRect.ts new file mode 100644 index 000000000..467a457bb --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useInstanceBoundingClientRect.ts @@ -0,0 +1,37 @@ +import { useComponent } from 'functional-mini/component'; +import { getInstanceBoundingClientRect } from '../jsapi/get-instance-bounding-client-rect'; + +export const useInstanceBoundingClientRect = () => { + const instance = useComponent(); + function getInstance() { + if (instance.$id) { + return my; + } + return instance; + } + + async function getBoundingClientRectWithId(prefix: string) { + return await getInstanceBoundingClientRect( + getInstance(), + `${prefix}${instance.$id ? `-${instance.$id}` : ''}` + ); + } + async function getBoundingClientRect(query: string) { + return await getInstanceBoundingClientRect(getInstance(), query); + } + + async function getBoundingClientRectWithBuilder( + builder: (id: string) => string + ) { + return await getInstanceBoundingClientRect( + getInstance(), + builder(instance.$id ? `-${instance.$id}` : '') + ); + } + + return { + getBoundingClientRect, + getBoundingClientRectWithId, + getBoundingClientRectWithBuilder, + }; +}; diff --git a/compiled/alipay/src/_util/hooks/useLayoutEffect.ts b/compiled/alipay/src/_util/hooks/useLayoutEffect.ts new file mode 100644 index 000000000..896935268 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useLayoutEffect.ts @@ -0,0 +1,39 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useLayoutEffect.ts + */ + +import * as React from 'functional-mini/compat'; + +/** + * Wrap `React.useLayoutEffect` which will not throw warning message in test env + */ +const useInternalLayoutEffect = React.useEffect; + +const useLayoutEffect = (callback: (mount: boolean) => void, deps?: any) => { + const firstMountRef = React.useRef(true); + + useInternalLayoutEffect(() => { + return callback(firstMountRef.current); + }, deps); + + // We tell react that first mount has passed + useInternalLayoutEffect(() => { + firstMountRef.current = false; + return () => { + firstMountRef.current = true; + }; + }, []); +}; + +export const useComponentUpdateEffect: typeof React.useEffect = ( + callback, + deps +) => { + useLayoutEffect((firstMount) => { + if (!firstMount) { + return callback(); + } + }, deps); +}; + +export default useLayoutEffect; diff --git a/compiled/alipay/src/_util/hooks/useMergedState.ts b/compiled/alipay/src/_util/hooks/useMergedState.ts new file mode 100644 index 000000000..37148ac85 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useMergedState.ts @@ -0,0 +1,81 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useMergedState.ts + */ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { useSafeState as useState } from './useState'; +import { supportUndefinedProperty } from '../platform'; + +type Updater = ( + updater: T | ((origin: T) => T), + ignoreDestroy?: boolean +) => void; + +/** We only think `undefined` is empty */ +export function hasValue(value: any) { + if (supportUndefinedProperty()) { + return value !== undefined; + } + return value !== null && value !== undefined; +} + +/** + * Similar to `useState` but will use props value if provided. + * Note that internal use rc-util `useState` hook. + */ +export function useMergedState( + defaultStateValue: T | (() => T), + option?: { + defaultValue?: T | (() => T); + value?: T; + onChange?: (value: T, prevValue: T) => void; + postState?: (value: T) => T; + } +): [R, Updater] { + const { defaultValue, value, onChange, postState } = option || {}; + + // ======================= Init ======================= + const [innerValue, setInnerValue] = useState(() => { + if (hasValue(value)) { + return value; + } else if (hasValue(defaultValue)) { + return typeof defaultValue === 'function' + ? (defaultValue as any)() + : defaultValue; + } else { + return typeof defaultStateValue === 'function' + ? (defaultStateValue as any)() + : defaultStateValue; + } + }); + + const mergedValue = hasValue(value) ? value : innerValue; + const postMergedValue = postState ? postState(mergedValue) : mergedValue; + + // ====================== Change ====================== + const onChangeFn = useEvent(onChange); + + const [prevValue, setPrevValue] = useState<[T]>([mergedValue]); + + useComponentUpdateEffect(() => { + const prev = prevValue[0]; + if (innerValue !== prev) { + onChangeFn(innerValue, prev); + } + }, [prevValue]); + + // Sync value back to `undefined` when it from control to un-control + useComponentUpdateEffect(() => { + if (!hasValue(value)) { + setInnerValue(value); + } + }, [value]); + + // ====================== Update ====================== + const triggerChange: Updater = useEvent((updater, ignoreDestroy) => { + setInnerValue(updater, ignoreDestroy); + setPrevValue([mergedValue], ignoreDestroy); + }); + + return [postMergedValue as unknown as R, triggerChange]; +} diff --git a/compiled/alipay/src/_util/hooks/useMixState.ts b/compiled/alipay/src/_util/hooks/useMixState.ts new file mode 100644 index 000000000..d558a71fd --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useMixState.ts @@ -0,0 +1,109 @@ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { hasValue } from './useMergedState'; +import { useSafeState as useState } from './useState'; + +type Updater = ( + updater: T | ((old: T) => T), + ignoreDestroy?: boolean +) => void; + +export function useMixState( + defaultStateValue: T | (() => T), + option?: { + defaultValue?: T | (() => T); + value?: T; + postState?: ( + value: T, + option?: O + ) => { valid: true; value: T } | { valid: false }; + } +): [ + R, + { + isControlled: boolean; + triggerUpdater: (value: (old: T) => T, option?: O) => void; + update( + value: T, + option?: O + ): { changed: true; newValue: T } | { changed: false }; + } +] { + const { + defaultValue, + value, + postState = (v) => ({ valid: true, value: v }), + } = option || {}; + + // ======================= Init ======================= + const [innerValue, setInnerValue] = useState(() => { + let v; + if (hasValue(value)) { + v = value; + } else if (hasValue(defaultValue)) { + v = + typeof defaultValue === 'function' + ? (defaultValue as any)() + : defaultValue; + } else { + v = + typeof defaultStateValue === 'function' + ? (defaultStateValue as any)() + : defaultStateValue; + } + const state = postState(v); + if (state.valid) { + return state.value; + } + }); + + const state = postState(value); + const merge = hasValue(value) && state.valid ? state.value : innerValue; + + useComponentUpdateEffect(() => { + const state = postState(value); + if (state.valid) { + setInnerValue(state.value); + } + }, [value]); + + const isControlled = hasValue(value); + const triggerChange: Updater = useEvent((newState, ignoreDestroy) => { + setInnerValue(newState, ignoreDestroy); + }); + + const triggerUpdate = useEvent((value, option) => { + const state = postState(value, option); + if (state.valid && state.value !== innerValue) { + triggerChange(state.value); + return { changed: true, newValue: state.value }; + } + return { changed: false }; + }); + + const triggerUpdater: (value: (old: T) => T, option?: O) => void = useEvent( + (getValue, option) => { + if (isControlled) { + getValue(merge); + } else { + triggerChange((old: T): T => { + const newValue = getValue(old); + const state = postState(newValue, option); + if (state.valid && state.value !== innerValue) { + return state.value; + } + return old; + }); + } + } + ); + + return [ + merge as unknown as R, + { + isControlled, + update: triggerUpdate as any, + triggerUpdater, + }, + ]; +} diff --git a/compiled/alipay/src/_util/hooks/useReportRef.ts b/compiled/alipay/src/_util/hooks/useReportRef.ts new file mode 100644 index 000000000..553fc85c4 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useReportRef.ts @@ -0,0 +1,4 @@ +import { useComponent, useEffect } from 'functional-mini/component'; + +export const triggerRefEvent = () => { +}; diff --git a/compiled/alipay/src/_util/hooks/useState.ts b/compiled/alipay/src/_util/hooks/useState.ts new file mode 100644 index 000000000..2c80b46b7 --- /dev/null +++ b/compiled/alipay/src/_util/hooks/useState.ts @@ -0,0 +1,46 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useState.ts + */ + +import * as React from 'functional-mini/compat'; + +type Updater = T | ((prevValue: T) => T); + +export type SetState = ( + nextValue: Updater, + /** + * Will not update state when destroyed. + * Developer should make sure this is safe to ignore. + */ + ignoreDestroy?: boolean +) => void; + +/** + * Same as React.useState but `setState` accept `ignoreDestroy` param to not to setState after destroyed. + * We do not make this auto is to avoid real memory leak. + * Developer should confirm it's safe to ignore themselves. + */ +export function useSafeState( + defaultValue?: T | (() => T) +): [T, SetState] { + const destroyRef = React.useRef(false); + const [value, setValue] = React.useState(defaultValue); + + React.useEffect(() => { + destroyRef.current = false; + + return () => { + destroyRef.current = true; + }; + }, []); + + function safeSetState(updater: Updater, ignoreDestroy?: boolean) { + if (ignoreDestroy && destroyRef.current) { + return; + } + + setValue(updater); + } + + return [value, safeSetState]; +} diff --git a/compiled/alipay/src/_util/platform.ts b/compiled/alipay/src/_util/platform.ts index 490665bfc..1225f7ec9 100644 --- a/compiled/alipay/src/_util/platform.ts +++ b/compiled/alipay/src/_util/platform.ts @@ -21,9 +21,9 @@ export function resolveEventValue(value) { return value; } -export function resolveEventValues(args1: any, args2?: any, ...rest) { +export function resolveEventValues(args1: any, args2?: any) { - return [args1, args2, ...rest]; + return [args1, args2]; } export function isOldSDKVersion() { diff --git a/compiled/alipay/src/_util/triggerComonentEvent.ts b/compiled/alipay/src/_util/triggerComonentEvent.ts new file mode 100644 index 000000000..c01678048 --- /dev/null +++ b/compiled/alipay/src/_util/triggerComonentEvent.ts @@ -0,0 +1,6 @@ +export function triggerComponentEvent(instance, propsName, event) { + + if (instance.props[propsName]) { + instance.props[propsName](event); + } +} diff --git a/compiled/alipay/src/mixins/computed.ts b/compiled/alipay/src/mixins/computed.ts index 610c7ec69..2df987908 100644 --- a/compiled/alipay/src/mixins/computed.ts +++ b/compiled/alipay/src/mixins/computed.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import deepEqual from 'fast-deep-equal'; -import { getValueFromProps } from '../_util/simply'; function computedData(this: any) { - const nextData = this.computed(getValueFromProps(this)); + const nextData = this.computed(this.props); // 浅比较就行了 const changedData = Object.keys(nextData).reduce((prev, item) => { // 移除 _ $ 开头的保留 props @@ -30,17 +29,11 @@ function computedData(this: any) { this.setData(changedData); } -export default function () { - let mixin = { - didMount(): void { - computedData.call(this); - }, - didUpdate(): void { - computedData.call(this); - }, - - }; - - - return mixin; -} +export default { + didMount(): void { + computedData.call(this); + }, + didUpdate(): void { + computedData.call(this); + }, +}; diff --git a/compiled/wechat/demo/pages/Calendar/collapse-container/cn-day/cn-day.js b/compiled/wechat/demo/pages/Calendar/collapse-container/cn-day/cn-day.js index 3f3e09a87..a68de7a51 100644 --- a/compiled/wechat/demo/pages/Calendar/collapse-container/cn-day/cn-day.js +++ b/compiled/wechat/demo/pages/Calendar/collapse-container/cn-day/cn-day.js @@ -1,41 +1,21 @@ import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import Converter from './js-calendar-converter'; -import { Component, getValueFromProps } from '../../../../../src/_util/simply'; -Component({ +import { mountComponent } from '../../../../../src/_util/component'; +const CollapseContainer = (props) => { + var _a, _b, _c; + const time = dayjs((_a = props.cell) === null || _a === void 0 ? void 0 : _a.time); + const vs = Converter.solar2lunar(time.get('year'), time.get('month') + 1, time.get('date')); + if (vs === -1) { + return { + cnday: '', + }; + } + return { + cnday: vs.lunarFestival || vs.festival || vs.IDayCn, + festival: !!vs.festival || !!vs.lunarFestival, + unset: ((_b = props.cell) === null || _b === void 0 ? void 0 : _b.isSelectedBegin) || ((_c = props.cell) === null || _c === void 0 ? void 0 : _c.isSelectedEnd), + }; +}; +mountComponent(CollapseContainer, { cell: null, -}, { - updateData() { - const cell = getValueFromProps(this, 'cell'); - const time = dayjs(cell === null || cell === void 0 ? void 0 : cell.time); - const vs = Converter.solar2lunar(time.get('year'), time.get('month') + 1, time.get('date')); - if (vs === -1) { - this.setData({ - cnday: '', - }); - return; - } - this.setData({ - cnday: vs.lunarFestival || vs.festival || vs.IDayCn, - festival: !!vs.festival || !!vs.lunarFestival, - unset: (cell === null || cell === void 0 ? void 0 : cell.isSelectedBegin) || (cell === null || cell === void 0 ? void 0 : cell.isSelectedEnd), - }); - }, -}, { - cnday: '', - festival: '', - unset: '', -}, null, { - attached() { - this.updateData(); - }, - observers: { - '**': function (data) { - const prevData = this._prevData || this.data; - this._prevData = { ...data }; - if (!equal(prevData.cell, data.cell)) { - this.updateData(); - } - }, - }, }); diff --git a/compiled/wechat/demo/pages/Calendar/collapse-container/collapse-container.js b/compiled/wechat/demo/pages/Calendar/collapse-container/collapse-container.js index b2f8e043a..eb2ee114b 100644 --- a/compiled/wechat/demo/pages/Calendar/collapse-container/collapse-container.js +++ b/compiled/wechat/demo/pages/Calendar/collapse-container/collapse-container.js @@ -1,30 +1,19 @@ -import { Component, getValueFromProps } from '../../../../src/_util/simply'; -Component({ +import { useEvent, useState } from 'functional-mini/component'; +import { mountComponent } from '../../../../src/_util/component'; +const CollapseContainer = (props) => { + var _a; + const [collapse, setCollapse] = useState((_a = props.defaultCollapse) !== null && _a !== void 0 ? _a : true); + useEvent('handleToggle', () => { + setCollapse((v) => !v); + }); + return { + collapse, + internalHide: props.hide, + containerTitle: props.title, + }; +}; +mountComponent(CollapseContainer, { hide: false, defaultCollapse: null, title: '', -}, { - handleToggle() { - const { collapse } = this.data; - this.setData({ - collapse: !collapse, - }); - }, -}, { - collapse: true, - internalHide: false, - containerTitle: '', -}, null, { - attached() { - const [defaultCollapse, hide, title] = getValueFromProps(this, [ - 'defaultCollapse', - 'hide', - 'title', - ]); - this.setData({ - collapse: defaultCollapse !== null && defaultCollapse !== void 0 ? defaultCollapse : true, - internalHide: hide, - containerTitle: title, - }); - }, }); diff --git a/compiled/wechat/demo/pages/NoticeBar/index.wxml b/compiled/wechat/demo/pages/NoticeBar/index.wxml index 1fa5c1ebf..6b30b0909 100644 --- a/compiled/wechat/demo/pages/NoticeBar/index.wxml +++ b/compiled/wechat/demo/pages/NoticeBar/index.wxml @@ -53,9 +53,7 @@ - + 不展示图标 diff --git a/compiled/wechat/package.json b/compiled/wechat/package.json index 3ff979971..fb85b12e2 100644 --- a/compiled/wechat/package.json +++ b/compiled/wechat/package.json @@ -4,6 +4,7 @@ "async-validator": "^4.0.7", "dayjs": "^1.11.10", "fast-deep-equal": "3.1.3", + "functional-mini": "^0.17.0", "tslib": "2.5.0" }, "repository": "git@github.com:ant-design/ant-design-mini.git" diff --git a/compiled/wechat/src/ActionSheet/index.json b/compiled/wechat/src/ActionSheet/index.json index bea48a2cb..e1a7501d8 100644 --- a/compiled/wechat/src/ActionSheet/index.json +++ b/compiled/wechat/src/ActionSheet/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-popup": "../Popup/index" } diff --git a/compiled/wechat/src/Avatar/index.json b/compiled/wechat/src/Avatar/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Avatar/index.json +++ b/compiled/wechat/src/Avatar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/Badge/index.json b/compiled/wechat/src/Badge/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Badge/index.json +++ b/compiled/wechat/src/Badge/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/Button/index.json b/compiled/wechat/src/Button/index.json index bdf0e3a8f..f6bbf1425 100644 --- a/compiled/wechat/src/Button/index.json +++ b/compiled/wechat/src/Button/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "loading": "../Loading/index", "ant-icon": "../Icon/index" diff --git a/compiled/wechat/src/Calendar/index.js b/compiled/wechat/src/Calendar/index.js index 3b584f9fd..9885518f6 100644 --- a/compiled/wechat/src/Calendar/index.js +++ b/compiled/wechat/src/Calendar/index.js @@ -9,42 +9,6 @@ var __assign = (this && this.__assign) || function () { }; return __assign.apply(this, arguments); }; -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { @@ -55,82 +19,137 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { return to.concat(ar || Array.prototype.slice.call(from)); }; import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; -import { Component, triggerEvent, getValueFromProps } from '../_util/simply'; -import { defaultLocaleText, CalendarDefaultProps, } from './props'; -import { getMonthListFromRange, getSelectionModeFromValue, renderCells, getScrollIntoViewId, } from './utils'; -import mixinValue from '../mixins/value'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; -Component(CalendarDefaultProps, { - getInstance: function () { - if (this.$id) { - return my; - } - return this; - }, - getBoundingClientRect: function (query) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), query)]; - case 1: return [2 /*return*/, _a.sent()]; - } - }); +import { useComponent, useEvent, useReady, useState, useEffect, } from 'functional-mini/component'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { triggerRefEvent } from '../_util/hooks/useReportRef'; +import { hasValue, useMergedState } from '../_util/hooks/useMergedState'; +import { defaultLocaleText, } from './props'; +import { defaultMonthRange, getMonthListFromRange, getSelectionModeFromValue, renderCells, getScrollIntoViewId, } from './utils'; +function getBoundingClientRect(instance, selector) { + return new Promise(function (resolve, reject) { + instance + .createSelectorQuery() + .select(selector) + .boundingClientRect() + .exec(function (ret) { + if (ret && ret[0]) { + resolve(ret[0]); + } + else { + reject(); + } + }); + }); +} +var Calendar = function (props) { + var _a, _b; + var localeText = Object.assign({}, defaultLocaleText, props.localeText); + var markItems = __spreadArray([], localeText.weekdayNames, true); + var weekStartsOn = props.weekStartsOn; + if (weekStartsOn === 'Sunday') { + var item = markItems.pop(); + if (item) + markItems.unshift(item); + } + var _c = useMergedState(props.defaultValue, { + value: props.value, + }), value = _c[0], setValue = _c[1]; + var _d = useState(''), scrollIntoViewId = _d[0], setScrollIntoViewId = _d[1]; + useEvent('scrollIntoView', function (value) { + updateScrollIntoViewId(getScrollIntoViewId(value)); + }); + triggerRefEvent(); + // scroll 触发滚动之后需要重置 scrollIntoViewId + function updateScrollIntoViewId(id) { + setScrollIntoViewId(id); + var timer = setTimeout(function () { + setScrollIntoViewId(''); + clearTimeout(timer); }); - }, - scrollIntoView: function (value) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - }, - clickCell: function (e) { - var _a, _b; + } + var selectionModeFromValue = getSelectionModeFromValue(value); + var selectionMode = (_b = (_a = props.selectionMode) !== null && _a !== void 0 ? _a : selectionModeFromValue) !== null && _b !== void 0 ? _b : 'range'; + var triggerEvent = useComponentEvent(props).triggerEvent; + function updateValue(newValue) { + var isControl = hasValue(props.value); + triggerEvent('change', newValue); + if (!isControl) { + setValue(newValue); + } + } + useEvent('clickCell', function (e) { var time = e.currentTarget.dataset.time; var clickDate = dayjs(time.time); if (time.disabled) { return; } - var value = this.getValue(); - var selectionModeFromValue = getSelectionModeFromValue(value); - var selectionMode = (_b = (_a = getValueFromProps(this, 'selectionMode')) !== null && _a !== void 0 ? _a : selectionModeFromValue) !== null && _b !== void 0 ? _b : 'range'; if (selectionMode === 'range') { if (Array.isArray(value)) { if (value.length === 1) { var current = value[0]; if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([clickDate.toDate().getTime()]); } else { - this.updateValue([value[0], clickDate.toDate().getTime()]); + updateValue([value[0], clickDate.toDate().getTime()]); } } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([clickDate.toDate().getTime()]); } } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([clickDate.toDate().getTime()]); } } else if (selectionMode === 'single') { - this.updateValue(clickDate.toDate().getTime()); + updateValue(clickDate.toDate().getTime()); } - }, - setCurrentMonth: function (e) { - this.setData({ headerState: e.month }); - }, - measurement: function () { - var elementSize = this.data.elementSize; - // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 - // 此时需要重新计算 - if (!elementSize || elementSize.cellHight === 0) { - this.measurementFn(); + }); + var monthList = getMonthListFromRange(dayjs(props.monthRange[0]), dayjs(props.monthRange[1])).map(function (p) { + var cells = renderCells(p, weekStartsOn, value, localeText); + if (props.onFormatter && typeof props.onFormatter === 'function') { + cells = cells.map(function (o) { + var _a; + var time = o.time, top = o.top, bottom = o.bottom, disabled = o.disabled, isSelectedBegin = o.isSelectedBegin, isSelectedEnd = o.isSelectedEnd, isSelected = o.isSelected; + var newState = (_a = props.onFormatter({ + time: time, + top: top ? __assign({}, top) : undefined, + bottom: bottom ? __assign({}, bottom) : undefined, + disabled: disabled, + isSelectedBegin: isSelectedBegin, + isSelectedEnd: isSelectedEnd, + isSelected: isSelected, + }, value)) !== null && _a !== void 0 ? _a : {}; + var result = __assign({}, o); + if (typeof newState === 'object') { + // 只允许修改三个字段 + ['top', 'bottom', 'disabled'].forEach(function (key) { + if (key in newState) { + result[key] = newState[key]; + } + }); + } + return result; + }); } - }, - measurementFn: function () { - var _this = this; + return { + title: p.format(localeText.title), + cells: cells, + }; + }); + var _e = useState(0), headerState = _e[0], setHeaderState = _e[1]; + useEvent('setCurrentMonth', function (e) { + setHeaderState(e.month); + }); + var _f = useState(null), elementSize = _f[0], setElementSize = _f[1]; + var componentInstance = useComponent(); + function measurement() { Promise.all([ - this.getBoundingClientRect('.ant-calendar-body-container'), - this.getBoundingClientRect('.ant-calendar-cells'), - this.getBoundingClientRect('.ant-calendar-title-container'), + getBoundingClientRect(componentInstance, '.ant-calendar-body-container'), + getBoundingClientRect(componentInstance, '.ant-calendar-cells'), + getBoundingClientRect(componentInstance, '.ant-calendar-title-container'), ]) .then(function (_a) { var bodyContainer = _a[0], cellContainer = _a[1], Title = _a[2]; @@ -138,148 +157,56 @@ Component(CalendarDefaultProps, { // 所以只能依赖 height 来计算 var paddingHeight = bodyContainer.height - cellContainer.height - Title.height; var monthTitleHeight = Title.height + paddingHeight; - var cellHight = cellContainer.height / (_this.data.monthList[0].cells.length / 7); - _this.setData({ - elementSize: { - monthTitleHeight: monthTitleHeight, - cellHight: cellHight, - paddingHeight: paddingHeight, - }, + var cellHight = cellContainer.height / (monthList[0].cells.length / 7); + setElementSize({ + monthTitleHeight: monthTitleHeight, + cellHight: cellHight, + paddingHeight: paddingHeight, }); }) .catch(function () { - _this.setData({ elementSize: null }); - }); - }, - // scroll 触发滚动之后需要重置 scrollIntoViewId - updateScrollIntoViewId: function (id) { - var _this = this; - this.setData({ scrollIntoViewId: id }); - var timer = setTimeout(function () { - _this.setData({ scrollIntoViewId: '' }); - clearTimeout(timer); + setElementSize(null); }); - }, - updateValue: function (newValue) { - triggerEvent(this, 'change', newValue); - if (!this.isControlled()) { - this.update(newValue); - } - }, - updateData: function () { - var _a = getValueFromProps(this, [ - 'monthRange', - 'localeText', - 'weekStartsOn', - 'onFormatter', - ]), monthRange = _a[0], plocaleText = _a[1], pweekStartsOn = _a[2], onFormatter = _a[3]; - var localeText = Object.assign({}, defaultLocaleText, plocaleText); - var markItems = __spreadArray([], localeText.weekdayNames, true); - var weekStartsOn = pweekStartsOn; - if (weekStartsOn === 'Sunday') { - var item = markItems.pop(); - if (item) - markItems.unshift(item); - } - var value = this.getValue(); - var monthList = getMonthListFromRange(dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[0]), dayjs(monthRange === null || monthRange === void 0 ? void 0 : monthRange[1])).map(function (p) { - var cells = renderCells(p, weekStartsOn, value, localeText); - if (onFormatter && typeof onFormatter === 'function') { - cells = cells.map(function (o) { - var _a; - var time = o.time, top = o.top, bottom = o.bottom, disabled = o.disabled, isSelectedBegin = o.isSelectedBegin, isSelectedEnd = o.isSelectedEnd, isSelected = o.isSelected; - var newState = (_a = onFormatter({ - time: time, - top: top ? __assign({}, top) : undefined, - bottom: bottom ? __assign({}, bottom) : undefined, - disabled: disabled, - isSelectedBegin: isSelectedBegin, - isSelectedEnd: isSelectedEnd, - isSelected: isSelected, - }, value)) !== null && _a !== void 0 ? _a : {}; - var result = __assign({}, o); - if (typeof newState === 'object') { - // 只允许修改三个字段 - ['top', 'bottom', 'disabled'].forEach(function (key) { - if (key in newState) { - result[key] = newState[key]; - } - }); - } - return result; - }); - } - return { - title: p.format(localeText.title), - cells: cells, - }; - }); - this.setData({ markItems: markItems, monthList: monthList }); - }, -}, { - elementSize: null, - markItems: [], - monthList: [], - headerState: 0, - scrollIntoViewId: '', -}, [mixinValue()], { - didMount: function () { - this.updateData(); - this.measurementFn(); + } + useEffect(function () { + // 滚动到已选的位置 + props.changedScrollIntoView && + updateScrollIntoViewId(getScrollIntoViewId(value)); + }, [value]); + useReady(function () { + measurement(); // 初始化默认值时,滚动到选中位置 - var _a = getValueFromProps(this, [ - 'value', - 'defaultValue', - ]), value = _a[0], defaultValue = _a[1]; - if (this.isControlled()) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); + var isControl = hasValue(props.value); + if (isControl) { + updateScrollIntoViewId(getScrollIntoViewId(props.value)); } else { - defaultValue && - this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue)); + props.defaultValue && + updateScrollIntoViewId(getScrollIntoViewId(props.defaultValue)); } - }, - didUpdate: function (prevProps, prevData) { - if (!this.isEqualValue(prevData)) { - // 滚动到已选的位置 - var changedScrollIntoView = getValueFromProps(this, 'changedScrollIntoView'); - changedScrollIntoView && - this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue())); - } - if (!equal(prevProps, this.props) || !this.isEqualValue(prevData)) { - this.updateData(); - } - }, - attached: function () { - this.updateData(); - this.measurementFn(); - // 初始化默认值时,滚动到选中位置 - var _a = getValueFromProps(this, [ - 'value', - 'defaultValue', - ]), value = _a[0], defaultValue = _a[1]; - if (this.isControlled()) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - } - else { - defaultValue && - this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue)); + }, []); + useEvent('measurement', function () { + // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 + // 此时需要重新计算 + if (!elementSize || elementSize.cellHight === 0) { + measurement(); } - this.triggerEvent('ref', this); - }, - observers: { - '**': function (data) { - var prevData = this._prevData || this.data; - this._prevData = __assign({}, data); - if (!equal(prevData, data)) { - this.updateData(); - } - }, - 'mixin.value': function () { - // 滚动到已选的位置 - var changedScrollIntoView = getValueFromProps(this, 'changedScrollIntoView'); - changedScrollIntoView && - this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue())); - }, - }, + }); + return { + elementSize: elementSize, + markItems: markItems, + monthList: monthList, + headerState: headerState, + scrollIntoViewId: scrollIntoViewId, + }; +}; +mountComponent(Calendar, { + defaultValue: null, + value: null, + selectionMode: 'range', + monthRange: defaultMonthRange(), + weekStartsOn: 'Sunday', + localeText: defaultLocaleText, + onFormatter: null, + changedScrollIntoView: null, }); diff --git a/compiled/wechat/src/Calendar/index.json b/compiled/wechat/src/Calendar/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Calendar/index.json +++ b/compiled/wechat/src/Calendar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/Calendar/props.js b/compiled/wechat/src/Calendar/props.js index bdf434103..20e66c29a 100644 --- a/compiled/wechat/src/Calendar/props.js +++ b/compiled/wechat/src/Calendar/props.js @@ -1,4 +1,3 @@ -import { defaultMonthRange } from './utils'; export var defaultLocaleText = { weekdayNames: ['一', '二', '三', '四', '五', '六', '日'], title: 'YYYY年MM月', @@ -7,13 +6,3 @@ export var defaultLocaleText = { end: '结束', startAndEnd: '开始/结束', }; -export var CalendarDefaultProps = { - defaultValue: null, - value: null, - selectionMode: 'range', - monthRange: defaultMonthRange(), - weekStartsOn: 'Sunday', - localeText: defaultLocaleText, - onFormatter: null, - changedScrollIntoView: null, -}; diff --git a/compiled/wechat/src/Checkbox/CheckboxGroup/index.json b/compiled/wechat/src/Checkbox/CheckboxGroup/index.json index a29721990..c7460b750 100644 --- a/compiled/wechat/src/Checkbox/CheckboxGroup/index.json +++ b/compiled/wechat/src/Checkbox/CheckboxGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/compiled/wechat/src/Checkbox/index.json b/compiled/wechat/src/Checkbox/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Checkbox/index.json +++ b/compiled/wechat/src/Checkbox/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/Checklist/ChecklistItem/index.json b/compiled/wechat/src/Checklist/ChecklistItem/index.json index ffa3220f6..3a037cbf8 100644 --- a/compiled/wechat/src/Checklist/ChecklistItem/index.json +++ b/compiled/wechat/src/Checklist/ChecklistItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index" } diff --git a/compiled/wechat/src/Checklist/index.json b/compiled/wechat/src/Checklist/index.json index 6fdd09a19..402e290e9 100644 --- a/compiled/wechat/src/Checklist/index.json +++ b/compiled/wechat/src/Checklist/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-checklist-item": "./ChecklistItem/index", "ant-icon": "../Icon/index" diff --git a/compiled/wechat/src/Collapse/index.json b/compiled/wechat/src/Collapse/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Collapse/index.json +++ b/compiled/wechat/src/Collapse/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/Container/index.json b/compiled/wechat/src/Container/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Container/index.json +++ b/compiled/wechat/src/Container/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/DatePicker/RangePicker/hooks.js b/compiled/wechat/src/DatePicker/RangePicker/hooks.js new file mode 100644 index 000000000..2ff50ca2b --- /dev/null +++ b/compiled/wechat/src/DatePicker/RangePicker/hooks.js @@ -0,0 +1,60 @@ +import { useEvent as useStableCallback } from '../../_util/hooks/useEvent'; +import dayjs from 'dayjs'; +import { useCallback } from 'functional-mini/component'; +export var useFormatValue = function (props) { + function defaultFormat(date, valueStrs) { + var format = props.format, splitCharacter = props.splitCharacter; + if (format && valueStrs && valueStrs[0] && valueStrs[1]) { + return valueStrs.join("".concat(splitCharacter)); + } + return ''; + } + var onFormat = useStableCallback(function (realValue) { + var onFormat = props.onFormat, format = props.format; + var formatValueByProps = onFormat && + onFormat(realValue, realValue + ? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); }) + : null); + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; + } + return defaultFormat(realValue, realValue + ? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); }) + : null); + }); + return onFormat; +}; +export function useMinAndMax() { + var getMin = useStableCallback(function (min) { + return min ? dayjs(min) : dayjs().subtract(10, 'year'); + }); + var getMax = useStableCallback(function (max) { + return max ? dayjs(max) : dayjs().add(10, 'year'); + }); + return { + getMin: getMin, + getMax: getMax, + }; +} +function defaultFormatLabel(type, value) { + var suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return "".concat(value).concat(suffixMap[type]); +} +export var useFormatLabel = function (onFormatLabel) { + return useCallback(function (type, value) { + if (typeof onFormatLabel === 'function') { + var formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { + return String(formatValueByProps); + } + } + return defaultFormatLabel(type, value); + }, [onFormatLabel]); +}; diff --git a/compiled/wechat/src/DatePicker/RangePicker/index.js b/compiled/wechat/src/DatePicker/RangePicker/index.js index 75f2283da..7458e5fcc 100644 --- a/compiled/wechat/src/DatePicker/RangePicker/index.js +++ b/compiled/wechat/src/DatePicker/RangePicker/index.js @@ -1,105 +1,62 @@ -import { Component, triggerEvent, triggerEventValues, triggerEventOnly, getValueFromProps, } from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { DateRangePickerDefaultProps } from './props'; +import { useState, useEvent, useEffect, useMemo } from 'functional-mini/component'; +import { DateRangePickerFunctionalProps } from './props'; import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from '../util'; -import computed from '../../mixins/computed'; -import mixinValue from '../../mixins/value'; -Component(DateRangePickerDefaultProps, { - // visible受控判断 - isVisibleControlled: function () { - return getValueFromProps(this, 'visible') !== null; - }, - computed: function () { - var _a = this.data, currentStartDate = _a.currentStartDate, currentEndDate = _a.currentEndDate, pickerType = _a.pickerType; - var format = getValueFromProps(this, 'format'); - if (pickerType) +import { useMixState } from '../../_util/hooks/useMixState'; +import { useFormatValue, useMinAndMax, useFormatLabel } from './hooks'; +import { useDateState } from './useDateState'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; +var RangePicker = function (props) { + var _a = useMixState(props.defaultValue, { + value: props.value, + postState: function (value) { return { - currentStartValueStr: currentStartDate - ? dayjs(currentStartDate).format(format) - : '', - currentEndValueStr: currentEndDate - ? dayjs(currentEndDate).format(format) - : '', + valid: true, + value: value && value[0] && value[1] + ? [ + dayjs(value[0]).toDate(), + dayjs(value[1]).toDate(), + ] + : undefined, }; - }, - getMin: function (min) { - return min ? dayjs(min) : dayjs().subtract(10, 'year'); - }, - getMax: function (max) { - return max ? dayjs(max) : dayjs().add(10, 'year'); - }, - // didUpdate、弹窗打开、切换pickerType触发 - setCurrentValue: function (currentProps) { - var _this = this; - var pickerVisible = this.pickerVisible; // 隐藏状态下从CValue触发,展开状态使用当前数据 - var precision = currentProps.precision; - var _a = this.data, pickerType = _a.pickerType, columns = _a.columns; - var realValue = this.getValue(); - var _b = this.data, currentStartDate = _b.currentStartDate, currentEndDate = _b.currentEndDate; - var currentStartDateByCValue = (realValue === null || realValue === void 0 ? void 0 : realValue[0]) || null; - var currentEndDateByCValue = (realValue === null || realValue === void 0 ? void 0 : realValue[1]) || null; - // 展开状态,说明在切换pickerType - if (pickerVisible) { - if (pickerType === 'start') { - if (!currentStartDate) { - currentStartDate = currentEndDate; - } - } - else { - // pickerType=end start已存在 - // 结束时间默认选中开始 - if (!currentEndDate) { - currentEndDate = currentStartDate; - } - } - } - else { - // 否则是在从cValue初始化 - currentStartDate = currentStartDateByCValue; - currentEndDate = currentEndDateByCValue; - // 开始默认取优先取当前时间,不在时间范围内取开始时间 - if (!currentStartDate) { - var min = this.getMin(currentProps.min).toDate(); - var max = currentProps.max; - currentStartDate = new Date(); - if ((min && dayjs(currentStartDate).isBefore(min, precision)) || - (max && dayjs(currentStartDate).isAfter(max, precision)) || - (currentEndDateByCValue && - currentStartDate > currentEndDateByCValue)) { - currentStartDate = min; - } + }, + }), realValue = _a[0], _b = _a[1], isControlled = _b.isControlled, update = _b.update; + var _c = useDateState(props), dateState = _c.dateState, init = _c.init, changeType = _c.changeType, updateValue = _c.updateValue; + var _d = useComponentEvent(props), triggerEvent = _d.triggerEvent, triggerEventValues = _d.triggerEventValues, triggerEventOnly = _d.triggerEventOnly; + var _e = useState({ + currentValue: [], + columns: [], + }), _f = _e[0], columns = _f.columns, currentValue = _f.currentValue, doUpdateColumns = _e[1]; + var onFormat = useFormatValue(props); + var _g = useMemo(function () { + return { + currentStartValueStr: dateState.start + ? dayjs(dateState.start).format(props.format) + : '', + currentEndValueStr: dateState.end + ? dayjs(dateState.end).format(props.format) + : '', + }; + }, [props.format, dateState.start, dateState.end]), currentStartValueStr = _g.currentStartValueStr, currentEndValueStr = _g.currentEndValueStr; + var onFormatLabel = useFormatLabel(props.onFormatLabel); + var _h = useMixState(props.defaultVisible, { + value: props.visible, + }), visible = _h[0], updateVisible = _h[1].update; + useEffect(function () { + setTimeout(function () { + if (visible) { + var state = init(realValue); + var currentValue_1 = getValueByDate(state.pickerType === 'start' ? state.start : state.end, props.precision); + updateColumns(currentValue_1, props); } - } - var currentValue = getValueByDate(pickerType === 'start' ? currentStartDate : currentEndDate, precision); - var newColumns = this.generateData(currentValue, currentProps); - if (!equal(newColumns, columns)) { - this.setData({ columns: newColumns }, function () { - _this.setData({ - currentStartDate: currentStartDate, - currentEndDate: currentEndDate, - currentValue: currentValue, - formattedValueText: _this.onFormat(), - }); - }); - } - else { - this.setData({ - currentStartDate: currentStartDate, - currentEndDate: currentEndDate, - currentValue: currentValue, - formattedValueText: this.onFormat(), - }); - } - }, - /** - * 生成选项数据,didmound、picker change、打开弹窗、切换picker type触发 - */ - generateData: function (currentValue, currentProps) { + }); + }, [visible]); + function updateColumns(currentValue, currentProps) { var precision = currentProps.precision, propsMin = currentProps.min, propsMax = currentProps.max; - var min = this.getMin(propsMin); - var max = this.getMax(propsMax); + var min = getMin(propsMin); + var max = getMax(propsMax); if (max < min) { return []; } @@ -110,21 +67,37 @@ Component(DateRangePickerDefaultProps, { if (currentPickerDay < min || currentPickerDay > max) { currentPickerDay = min; } - var newColumns = getRangeData(precision, min, max, currentPickerDay, this.onFormatLabel.bind(this)); - return newColumns; - }, - onChange: function (selectedIdx) { - var _this = this; - var selectedIndex = resolveEventValues(getValidValue(selectedIdx))[0]; - var _a = getValueFromProps(this, [ - 'format', - 'precision', - 'max', - 'min', - ]), format = _a[0], precision = _a[1], pmax = _a[2], pmin = _a[3]; + var newColumns = getRangeData(precision, min, max, currentPickerDay, onFormatLabel); + doUpdateColumns({ columns: newColumns, currentValue: currentValue }); + } + var formattedValueText = onFormat(realValue); + useEvent('onVisibleChange', function (event) { + var visible = resolveEventValue(event); + if (visible) { + updateVisible(true); + } + else { + updateVisible(false); + } + triggerEvent('visibleChange', visible); + }); + useEvent('onChangeCurrentPickerType', function (e) { + var type = e.currentTarget.dataset.type; + var state = changeType(type); + var currentValue = getValueByDate(state.pickerType === 'start' ? state.start : state.end, props.precision); + updateColumns(currentValue, props); + }); + var _j = useMinAndMax(), getMin = _j.getMin, getMax = _j.getMax; + useEvent('onCancel', function (e) { + triggerEventOnly('cancel', e); + }); + useEvent('onChange', function (event) { + var selectedIndex = resolveEventValues(event)[0]; + selectedIndex = getValidValue(selectedIndex); + var format = props.format, precision = props.precision; var date = getDateByValue(selectedIndex); - var min = this.getMin(pmin); - var max = this.getMax(pmax); + var min = getMin(props.min); + var max = getMax(props.max); if (dayjs(date).isBefore(min)) { date = min.toDate(); selectedIndex = getValueByDate(date, precision); @@ -133,183 +106,39 @@ Component(DateRangePickerDefaultProps, { date = max.toDate(); selectedIndex = getValueByDate(date, precision); } - var _b = this.data, pickerType = _b.pickerType, columns = _b.columns, currentEndDate = _b.currentEndDate, currentStartDate = _b.currentStartDate; - var newData = { - currentValue: selectedIndex, - formattedValueText: this.onFormat(), - }; - if (pickerType === 'start') { - newData.currentStartDate = date; - if (currentEndDate && dayjs(date).isAfter(currentEndDate)) { - newData.currentEndDate = null; - } - } - else { - newData.currentEndDate = date; - if (currentStartDate && dayjs(date).isBefore(currentStartDate)) { - newData.currentStartDate = null; - } - } - var newColumns = this.generateData(selectedIndex, getValueFromProps(this)); - if (!equal(newColumns, columns)) { - this.setData({ - columns: newColumns, - }, function () { - _this.setData(newData); - triggerEventValues(_this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); - }); - } - else { - this.setData(newData); - triggerEventValues(this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); - } - }, - onCancel: function (e) { - triggerEventOnly(this, 'cancel', e); - }, - onOk: function () { - var format = getValueFromProps(this, 'format'); - var _a = this.data, currentStartDate = _a.currentStartDate, currentEndDate = _a.currentEndDate; - var realValue = [currentStartDate, currentEndDate]; - if (!this.isControlled()) { - this.update(realValue); - } - triggerEventValues(this, 'ok', [ + updateColumns(selectedIndex, props); + updateValue(date); + triggerEventValues('pickerChange', [ + dateState.pickerType, + date, + dayjs(date).format(format), + ]); + }); + useEvent('onOk', function () { + var format = props.format; + var start = dateState.start, end = dateState.end; + var realValue = [start, end]; + if (!isControlled) { + update(realValue); + } + triggerEventValues('ok', [ realValue, realValue.map(function (v) { return dayjs(v).format(format); }), ]); - }, - onFormatLabel: function (type, value) { - var onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - var formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return String(formatValueByProps); - } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel: function (type, value) { - var suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return "".concat(value).concat(suffixMap[type]); - }, - defaultFormat: function (date, valueStrs) { - var _a = getValueFromProps(this, [ - 'format', - 'splitCharacter', - ]), format = _a[0], splitCharacter = _a[1]; - if (format && valueStrs && valueStrs[0] && valueStrs[1]) { - return valueStrs.join("".concat(splitCharacter)); - } - return ''; - }, - onFormat: function () { - var _a = getValueFromProps(this, [ - 'onFormat', - 'format', - ]), onFormat = _a[0], format = _a[1]; - var realValue = this.getValue(); - var formatValueByProps = onFormat && - onFormat(realValue, realValue - ? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); }) - : null); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat(realValue, realValue - ? realValue.map(function (v) { return (v ? dayjs(v).format(format) : null); }) - : null); - }, - /** - * 显示/隐藏切换 - * @param visible - */ - onVisibleChange: function (visible) { - if (!this.isVisibleControlled() && visible) { - this.setData({ pickerType: 'start' }); - this.setCurrentValue(getValueFromProps(this)); - this.pickerVisible = visible; - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - onChangeCurrentPickerType: function (e) { - var type = e.currentTarget.dataset.type; - var pickerType = this.data.pickerType; - if (type !== pickerType) { - this.setData({ - pickerType: type, - }); - this.setCurrentValue(getValueFromProps(this)); - } - }, -}, { - currentValue: [], - columns: [], - pickerType: 'start', - currentStartDate: null, - currentEndDate: null, - forceUpdate: 0, - formattedValueText: '', -}, [ - mixinValue({ - transformValue: function (value) { - return { - value: value && value[0] && value[1] - ? [dayjs(value[0]).toDate(), dayjs(value[1]).toDate()] - : undefined, - needUpdate: true, - }; - }, - }), - computed(), -], { - pickerVisible: false, - created: function () { - this.pickerVisible = false; - var _a = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]), visible = _a[0], defaultVisible = _a[1]; - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, - observers: { - 'visible': function (data) { - var prevVisible = this._prevVisible; - this._prevVisible = data; - var currentProps = getValueFromProps(this); - var visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && prevVisible !== visible) { - this.setData({ visible: visible }); - this.setCurrentValue(currentProps); - this.pickerVisible = visible; - } - }, - 'mixin.value': function () { - var currentProps = getValueFromProps(this); - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - if (this.pickerVisible) { - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - this.setCurrentValue(currentProps); - } + }); + return { + state: { + visible: visible }, - }, -}); + formattedValueText: formattedValueText, + realValue: realValue, + columns: columns, + currentValue: currentValue, + currentStartDate: dateState.start, + currentEndDate: dateState.end, + currentEndValueStr: currentEndValueStr, + currentStartValueStr: currentStartValueStr, + pickerType: dateState.pickerType, + }; +}; +mountComponent(RangePicker, DateRangePickerFunctionalProps); diff --git a/compiled/wechat/src/DatePicker/RangePicker/index.json b/compiled/wechat/src/DatePicker/RangePicker/index.json index c124b8511..b2e493fb4 100644 --- a/compiled/wechat/src/DatePicker/RangePicker/index.json +++ b/compiled/wechat/src/DatePicker/RangePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index", "ant-picker": "../../Picker/index" diff --git a/compiled/wechat/src/DatePicker/RangePicker/index.wxml b/compiled/wechat/src/DatePicker/RangePicker/index.wxml index 33cce0d2c..43bdeaaa4 100644 --- a/compiled/wechat/src/DatePicker/RangePicker/index.wxml +++ b/compiled/wechat/src/DatePicker/RangePicker/index.wxml @@ -23,7 +23,7 @@ formattedValueText="{{ formattedValueText }}" className="ant-range-picker {{ className || '' }}" popClassName="{{ !currentStartDate || !currentEndDate ? 'ant-range-picker-confirm-disabled' : '' }} {{ popClassName || '' }}" - visible="{{ visible }}" + visible="{{ state.visible }}" style="{{ style }}" animationType="{{ animationType }}" options="{{ columns }}" diff --git a/compiled/wechat/src/DatePicker/RangePicker/props.js b/compiled/wechat/src/DatePicker/RangePicker/props.js index dcaa595a7..0149ec640 100644 --- a/compiled/wechat/src/DatePicker/RangePicker/props.js +++ b/compiled/wechat/src/DatePicker/RangePicker/props.js @@ -1,4 +1,15 @@ export var DateRangePickerDefaultProps = { + okText: '确定', + cancelText: '取消', + maskClosable: true, + placeholder: '请选择', + format: 'YYYY/MM/DD', + splitCharacter: '-', + startPlaceholder: '未选择', + endPlaceholder: '未选择', + precision: 'day', +}; +export var DateRangePickerFunctionalProps = { visible: null, defaultVisible: null, animationType: 'transform', @@ -20,5 +31,4 @@ export var DateRangePickerDefaultProps = { popStyle: '', disabled: false, onFormatLabel: null, - onFormat: null, }; diff --git a/compiled/wechat/src/DatePicker/RangePicker/useDateState.js b/compiled/wechat/src/DatePicker/RangePicker/useDateState.js new file mode 100644 index 000000000..c72977796 --- /dev/null +++ b/compiled/wechat/src/DatePicker/RangePicker/useDateState.js @@ -0,0 +1,88 @@ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +import dayjs from 'dayjs'; +import { useState } from 'functional-mini/component'; +import { useMinAndMax } from './hooks'; +export function useDateState(props) { + var getMin = useMinAndMax().getMin; + var _a = useState({ + pickerType: 'start', + start: null, + end: null, + }), dateState = _a[0], setDateState = _a[1]; + var init = function (realValue) { + var currentStartDate = realValue === null || realValue === void 0 ? void 0 : realValue[0]; + var currentEndDate = realValue === null || realValue === void 0 ? void 0 : realValue[1]; + if (!currentStartDate) { + var min = getMin(props.min).toDate(); + var max = props.max; + currentStartDate = new Date(); + if ((min && dayjs(currentStartDate).isBefore(min, props.precision)) || + (max && dayjs(currentStartDate).isAfter(max, props.precision)) || + (currentEndDate && currentStartDate > currentEndDate)) { + currentStartDate = min; + } + } + var newState = { + pickerType: 'start', + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + var changeType = function (newType) { + var currentStartDate = dateState.start; + var currentEndDate = dateState.end; + if (newType === 'start') { + if (!currentStartDate) { + currentStartDate = currentEndDate; + } + } + else { + // pickerType=end start已存在 + // 结束时间默认选中开始 + if (!currentEndDate) { + currentEndDate = currentStartDate; + } + } + var newState = { + pickerType: newType, + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + function updateValue(newValue) { + setDateState(function (old) { + if (old.pickerType === 'start') { + var newEnd = old.end; + if (old.end && dayjs(newValue).isAfter(old.end)) { + newEnd = null; + } + return __assign(__assign({}, old), { start: newValue, end: newEnd }); + } + var newStart = old.start; + if (old.start && dayjs(newValue).isBefore(old.start)) { + newStart = null; + } + return __assign(__assign({}, old), { end: newValue, start: newStart }); + }); + } + return { + updateValue: updateValue, + dateState: dateState, + init: init, + changeType: changeType, + }; +} diff --git a/compiled/wechat/src/DatePicker/index.js b/compiled/wechat/src/DatePicker/index.js index 4f10fc387..551a37227 100644 --- a/compiled/wechat/src/DatePicker/index.js +++ b/compiled/wechat/src/DatePicker/index.js @@ -1,18 +1,97 @@ -import { Component, triggerEvent, triggerEventOnly, triggerEventValues, getValueFromProps, } from '../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../_util/platform'; -import { DatePickerDefaultProps } from './props'; import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; -import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from './util'; -import mixinValue from '../mixins/value'; -Component(DatePickerDefaultProps, { - // visible受控判断 - isVisibleControlled: function () { - return getValueFromProps(this, 'visible') !== null; - }, - // 当前选中的picker值,处理无cValue时的情况,优先取当前时间,不在时间范围内取开始时间 - getCurrentValueWithCValue: function (currentProps) { - var realValue = this.getValue(); +import { useEvent, useState, useEffect, useMemo } from 'functional-mini/component'; +import '../_util/assert-component2'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useMixState } from '../_util/hooks/useMixState'; +import { resolveEventValues, resolveEventValue } from '../_util/platform'; +import { DatePickerFunctionalProps } from './props'; +import { getDateByValue, getRangeData, getValidValue, getValueByDate, } from './util'; +function getMin(min) { + return min ? dayjs(min) : dayjs().subtract(10, 'year'); +} +function getMax(max) { + return max ? dayjs(max) : dayjs().add(10, 'year'); +} +var DatePicker = function (props) { + var _a = useMixState(props.defaultValue, { + value: props.value, + postState: function (value) { + if (value) { + return { + valid: true, + value: dayjs(value).toDate(), + }; + } + return { + valid: true, + value: undefined, + }; + }, + }), realValue = _a[0], _b = _a[1], isControlled = _b.isControlled, update = _b.update; + function defaultFormat(value, valueStr) { + if (props.format && valueStr) { + return valueStr; + } + return ''; + } + var _c = useComponentEvent(props), triggerEvent = _c.triggerEvent, triggerEventValues = _c.triggerEventValues, triggerEventOnly = _c.triggerEventOnly; + function onFormatLabel(type, value) { + var onFormatLabel = props.onFormatLabel; + if (typeof onFormatLabel === 'function') { + var formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { + return String(formatValueByProps); + } + } + return defaultFormatLabel(type, value); + } + function defaultFormatLabel(type, value) { + var suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return "".concat(value).concat(suffixMap[type]); + } + var _d = useState({ + value: [], + columns: [], + }), _e = _d[0], value = _e.value, columns = _e.columns, setState = _d[1]; + var _f = useMixState(props.defaultVisible, { + value: props.visible, + }), visible = _f[0], updateVisible = _f[1].update; + useEffect(function () { + setTimeout(function () { + if (visible) { + updateDateColumnsAndValue(true); + } + else { + updateDateColumnsAndValue(false); + } + }); + }, [visible]); + function generateData(currentValue, currentProps) { + var precision = currentProps.precision, propsMin = currentProps.min, propsMax = currentProps.max; + var min = getMin(propsMin); + var max = getMax(propsMax); + if (max < min) { + return []; + } + var currentPickerDay = dayjs(); + if (currentValue.length > 0) { + currentPickerDay = dayjs(getDateByValue(currentValue)); + } + if (currentPickerDay < min || currentPickerDay > max) { + currentPickerDay = min; + } + var newColumns = getRangeData(precision, min, max, currentPickerDay, onFormatLabel); + return newColumns; + } + function getCurrentValueWithCValue(currentProps) { var min = currentProps.min, max = currentProps.max, precision = currentProps.precision; if (realValue) { return getValueByDate(realValue, precision); @@ -24,83 +103,43 @@ Component(DatePickerDefaultProps, { return getValueByDate(now, precision); } else { - return getValueByDate(this.getMin(min).toDate(), precision); + return getValueByDate(getMin(min).toDate(), precision); } } - }, - getMin: function (min) { - return min ? dayjs(min) : dayjs().subtract(10, 'year'); - }, - getMax: function (max) { - return max ? dayjs(max) : dayjs().add(10, 'year'); - }, - /** - * didUpdate、弹窗打开触发 - */ - setCurrentValue: function (currentProps) { - var _this = this; - var currentValue = this.getCurrentValueWithCValue(currentProps); - var newColumns = this.generateData(currentValue, currentProps); - if (!equal(newColumns, this.data.columns)) { - this.setData({ + } + function updateDateColumnsAndValue(visible) { + if (visible) { + var currentValue = getCurrentValueWithCValue(props); + var newColumns = generateData(currentValue, props); + setState({ + value: currentValue, columns: newColumns, - }, function () { - _this.setData({ - currentValue: currentValue, - formattedValueText: _this.onFormat(), - }); }); } - }, - // 生成选项数据,didmound、picker change、打开弹窗触发 - generateData: function (currentValue, currentProps) { - var precision = currentProps.precision, propsMin = currentProps.min, propsMax = currentProps.max; - var min = this.getMin(propsMin); - var max = this.getMax(propsMax); - if (max < min) { - return []; - } - var currentPickerDay = dayjs(); - if (currentValue.length > 0) { - currentPickerDay = dayjs(getDateByValue(currentValue)); + else { + setState({ + value: [], + columns: [], + }); } - if (currentPickerDay < min || currentPickerDay > max) { - currentPickerDay = min; + } + useEvent('onVisibleChange', function (event) { + var visible = resolveEventValue(event); + if (visible) { + updateVisible(true); } - var newColumns = getRangeData(precision, min, max, currentPickerDay, this.onFormatLabel.bind(this)); - return newColumns; - }, - onFormatLabel: function (type, value) { - var onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - var formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return String(formatValueByProps); + else { + updateVisible(false); } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel: function (type, value) { - var suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return "".concat(value).concat(suffixMap[type]); - }, - onChange: function (selectedIdx) { - var _this = this; - var _a = getValueFromProps(this, [ - 'min', - 'max', - 'format', - 'precision', - ]), pmin = _a[0], pmax = _a[1], format = _a[2], precision = _a[3]; - var selectedIndex = resolveEventValues(getValidValue(selectedIdx))[0]; + triggerEvent('visibleChange', visible, {}); + }); + useEvent('onChange', function (event) { + var selectedIndex = resolveEventValues(event)[0]; + selectedIndex = getValidValue(selectedIndex); + var format = props.format, precision = props.precision; var date = getDateByValue(selectedIndex); - var min = this.getMin(pmin); - var max = this.getMax(pmax); + var min = getMin(props.min); + var max = getMax(props.max); if (dayjs(date).isBefore(min)) { date = min.toDate(); selectedIndex = getValueByDate(date, precision); @@ -109,120 +148,42 @@ Component(DatePickerDefaultProps, { date = max.toDate(); selectedIndex = getValueByDate(date, precision); } - var newColumns = this.generateData(selectedIndex, getValueFromProps(this)); - if (!equal(newColumns, this.data.columns)) { - this.setData({ - columns: newColumns, - }, function () { - _this.setData({ currentValue: selectedIndex }); - var date = getDateByValue(selectedIndex); - triggerEventValues(_this, 'pickerChange', [ - date, - dayjs(date).format(format), - ]); - }); - } - else { - this.setData({ currentValue: selectedIndex }); - var date_1 = getDateByValue(selectedIndex); - triggerEventValues(this, 'pickerChange', [ - date_1, - dayjs(date_1).format(format), - ]); - } - }, - onCancel: function (e) { - triggerEventOnly(this, 'cancel', e); - }, - onOk: function () { - var currentValue = this.data.currentValue; - var format = getValueFromProps(this, 'format'); - var date = getDateByValue(currentValue); - if (!this.isControlled()) { - this.update(date); - } - triggerEventValues(this, 'ok', [date, dayjs(date).format(format)]); - }, - defaultFormat: function (value, valueStr) { - var format = getValueFromProps(this, 'format'); - if (format && valueStr) { - return valueStr; - } - return ''; - }, - onFormat: function () { - var _a = getValueFromProps(this, [ - 'format', - 'onFormat', - ]), format = _a[0], onFormat = _a[1]; - var realValue = this.getValue(); - var formatValueByProps = onFormat && - onFormat(realValue, realValue ? dayjs(realValue).format(format) : null); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat(realValue, realValue ? dayjs(realValue).format(format) : null); - }, - onVisibleChange: function (visible) { - this.pickerVisible = visible; - if (!this.isVisibleControlled() && visible) { - this.setCurrentValue(getValueFromProps(this)); - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, -}, { - currentValue: [], - formattedValueText: '', - columns: [], - forceUpdate: 0, - visible: null, -}, [ - mixinValue({ - transformValue: function (value) { - return { - value: value ? dayjs(value).toDate() : undefined, - needUpdate: true, - }; - }, - }), -], { - pickerVisible: false, - created: function () { - this.pickerVisible = false; - var _a = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]), visible = _a[0], defaultVisible = _a[1]; - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), + var newColumns = generateData(selectedIndex, props); + setState({ + columns: newColumns, + value: selectedIndex, }); - }, - observers: { - 'mixin.value': function () { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - if (this.pickerVisible) { - this.setCurrentValue(getValueFromProps(this)); - } - }, - 'visible': function (data) { - var prevVisible = this._prevVisible; - this._prevVisible = data; - var currentProps = getValueFromProps(this); - var visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && prevVisible !== visible) { - this.pickerVisible = visible; - this.setData({ - visible: visible, - }); - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } + var pickDate = getDateByValue(selectedIndex); + triggerEventValues('pickerChange', [pickDate, dayjs(pickDate).format(format)], {}); + }); + useEvent('onCancel', function (e) { + triggerEventOnly('cancel', e); + }); + useEvent('onOk', function () { + var format = props.format; + var date = getDateByValue(value); + if (!isControlled) { + update(date); + } + triggerEventValues('ok', [date, dayjs(date).format(format)], {}); + }); + var formattedValueText = useMemo(function () { + var onFormat = props.onFormat, format = props.format; + if (typeof onFormat === 'function') { + var formatValueByProps = onFormat(realValue, realValue ? dayjs(realValue).format(format) : null); + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; } + } + return defaultFormat(realValue, realValue ? dayjs(realValue).format(format) : null); + }, [realValue]); + return { + state: { + visible: visible }, - }, -}); + formattedValueText: formattedValueText, + currentValue: visible ? value : realValue, + columns: columns, + }; +}; +mountComponent(DatePicker, DatePickerFunctionalProps); diff --git a/compiled/wechat/src/DatePicker/index.json b/compiled/wechat/src/DatePicker/index.json index e370585b1..ac7a29b19 100644 --- a/compiled/wechat/src/DatePicker/index.json +++ b/compiled/wechat/src/DatePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-picker": "../Picker/index" } diff --git a/compiled/wechat/src/DatePicker/index.wxml b/compiled/wechat/src/DatePicker/index.wxml index 78107a776..20260c37d 100644 --- a/compiled/wechat/src/DatePicker/index.wxml +++ b/compiled/wechat/src/DatePicker/index.wxml @@ -1,7 +1,7 @@ 展示一组消息通知。 @@ -18,21 +18,20 @@ toc: content 用于当前页面内信息的通知,是一种较醒目的页面内通知方式。 ## 代码示例 - ## API -| 属性 | 说明 | 类型 | 默认值 | -| ------------- | ---------------------------------------------------------------------------------------------- | ------------ | ------- | -| className | 类名 | string | - | -| enableMarquee | 是否开启滚动动画 | boolean | false | -| extra | 自定义右侧内容 | slot | - | -| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot (微信版本需要设置 slotIcon) | string | - | -| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | -| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | -| style | 样式 | string | - | -| title | 标题 | string\|slot | - | -| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | -| slotIcon | 微信版本需要通过此字段启用 icon 位置的插槽 | boolean | - | -| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | +| 属性 | 说明 | 类型 | 默认值 | +| ---------- | ---------------------- | ----------- | ------ | +| className | 类名 | string | - | +| enableMarquee | 是否开启滚动动画 | boolean | false | +| extra | 自定义右侧内容 | slot | - | +| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot | slot \| string | - | +| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | +| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | +| style | 样式 | string | - | +| title | 标题 | string\|slot | - | +| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | +| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | + diff --git a/compiled/wechat/src/NoticeBar/index.wxml b/compiled/wechat/src/NoticeBar/index.wxml index d75862294..04483b94e 100644 --- a/compiled/wechat/src/NoticeBar/index.wxml +++ b/compiled/wechat/src/NoticeBar/index.wxml @@ -2,12 +2,7 @@ wx:if="{{ show }}" class="ant-notice-bar {{ className || '' }} {{ type ? 'ant-notice-bar-' + type : '' }}" style="{{ style }}"> - - + 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; - } -}; -import { Component, getValueFromProps, triggerEvent, triggerEventOnly, triggerEventValues, } from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { CascaderDefaultProps } from './props'; -import equal from 'fast-deep-equal'; -import mixinValue from '../../mixins/value'; -Component(CascaderDefaultProps, { - // visible受控判断 - isVisibleControlled: function () { - return getValueFromProps(this, 'visible') !== null; - }, - initColumns: function () { - var _a = getValueFromProps(this, [ - 'options', - 'visible', - 'defaultVisible', - 'value', - 'defaultValue', - ]), options = _a[0], visible = _a[1], defaultVisible = _a[2], value = _a[3], defaultValue = _a[4]; - var realValue = value || defaultValue || []; - var columns = this.getterColumns(realValue, options); - // 首次无需校验value有效性,onOk时会校验 - this.setData({ - columns: columns, - visible: this.isVisibleControlled() ? visible : defaultVisible, - currentValue: realValue, - formattedValueText: this.onFormat(), - }); - }, - getterColumns: function (value, options) { - var getColumns = function (options, value, columns) { - var _a; - if (columns === void 0) { columns = []; } - columns.push(options.map(function (v) { return ({ value: v.value, label: v.label }); })); - var currentOption = options.find(function (v) { return v.value === (value === null || value === void 0 ? void 0 : value[columns.length - 1]); }) || - options[0]; - if (((_a = currentOption === null || currentOption === void 0 ? void 0 : currentOption.children) === null || _a === void 0 ? void 0 : _a.length) > 0) { - return getColumns(currentOption.children, value, columns); - } - return columns; - }; - return getColumns(options, value); - }, - // 获取有效value,若从x项开始在columns里找不到,则从此项开始都选第一条 - getValidValue: function (value, columns) { - var result = []; - var _loop_1 = function (i) { - if (!columns[i].some(function (v) { return (v === null || v === void 0 ? void 0 : v.value) === (value === null || value === void 0 ? void 0 : value[i]); })) { - result.push.apply(result, columns.slice(i).map(function (v) { var _a; return (_a = v === null || v === void 0 ? void 0 : v[0]) === null || _a === void 0 ? void 0 : _a.value; })); - return "break"; - } - else { - result[i] = value[i]; - } - }; - for (var i = 0; i < columns.length; i++) { - var state_1 = _loop_1(i); - if (state_1 === "break") - break; - } - return result; - }, - getOptionByValue: function (value) { +import { useEvent, useMemo, useEffect, useState } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useComponentUpdateEffect } from '../../_util/hooks/useLayoutEffect'; +import { useMixState } from '../../_util/hooks/useMixState'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; +import { CascaderFunctionalProps } from './props'; +import { defaultFormat, getterColumns, getValidValue } from './utils'; +var CascaderPicker = function (props) { + var _a = useMixState(props.defaultValue, { + value: props.value, + }), realValue = _a[0], _b = _a[1], isRealValueControlled = _b.isControlled, updateRealValue = _b.update; + var _c = useState(function () { + var value = props.value || props.defaultValue || []; + var columns = getterColumns(props.value || props.defaultValue, props.options); + return { columns: columns, value: value }; + }), _d = _c[0], value = _d.value, columns = _d.columns, setState = _c[1]; + var _e = useComponentEvent(props), triggerEventOnly = _e.triggerEventOnly, triggerEventValues = _e.triggerEventValues, triggerEvent = _e.triggerEvent; + useComponentUpdateEffect(function () { + var newColumns = getterColumns(props.value, props.options); + var value = getValidValue(props.value, newColumns); + setState({ value: value, columns: newColumns }); + }, [ + props.value, + props.options, + /** + * 这里不要删 + * + * 1. picker 触发 onOk + * 2. 更新 realValue + * 3. picker 触发 onFormat (此时 realValue 未更新) + * 4. 依赖里的 realValue 更新 + * 5. 触发组件再次渲染 + * 6. 此时 onFormat 读取到最新的realValue + */ + realValue, + ]); + function getOptionByValue(value, options) { var _a; - var options = getValueFromProps(this, 'options'); if (!((value === null || value === void 0 ? void 0 : value.length) > 0)) return null; var result = []; var item = options.find(function (v) { return v.value === value[0]; }); - var _loop_2 = function (i) { + var _loop_1 = function (i) { if (!item) { return { value: null }; } @@ -124,120 +52,77 @@ Component(CascaderDefaultProps, { item = (_a = item.children) === null || _a === void 0 ? void 0 : _a.find(function (v) { return v.value === value[i + 1]; }); }; for (var i = 0; i < value.length; i++) { - var state_2 = _loop_2(i); - if (typeof state_2 === "object") - return state_2.value; + var state_1 = _loop_1(i); + if (typeof state_1 === "object") + return state_1.value; } return result; - }, - onChange: function (selectedVal) { - var selectedValue = resolveEventValues(selectedVal)[0]; - var options = getValueFromProps(this, 'options'); - var columns = this.data.columns; - var newColumns = this.getterColumns(selectedValue, options); - // columns没变化说明selectedValue在范围内,无需重置 - var newData = {}; - if (!equal(columns, newColumns)) { - selectedValue = this.getValidValue(selectedValue, newColumns); - newData.columns = newColumns; + } + useEvent('onCancel', function (e) { + triggerEventOnly('cancel', e); + }); + var formattedValueText = useMemo(function () { + var onFormat = props.onFormat; + if (typeof onFormat === 'function') { + var formatValueByProps = onFormat(realValue, getOptionByValue(realValue, props.options)); + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; + } } - newData.currentValue = selectedValue; - this.setData(newData); - triggerEventValues(this, 'change', [ - selectedValue, - this.getOptionByValue(selectedValue), - ]); - }, - onOk: function () { - return __awaiter(this, void 0, void 0, function () { - var currentValue, options, newColumns, validValue; - return __generator(this, function (_a) { - currentValue = this.data.currentValue; - options = getValueFromProps(this, 'options'); - newColumns = this.getterColumns(currentValue, options); - validValue = this.getValidValue(currentValue, newColumns); - if (!this.isControlled()) { - this.update(validValue); - } - triggerEventValues(this, 'ok', [ - validValue, - this.getOptionByValue(validValue), - ]); - return [2 /*return*/]; - }); - }); - }, - onVisibleChange: function (visible) { - var _this = this; - var options = getValueFromProps(this, 'options'); - var columns = this.data.columns; - var realValue = this.getValue(); - if (!this.isVisibleControlled() && visible) { - var newColumns_1 = this.getterColumns(realValue, options); - if (!equal(columns, newColumns_1)) { - this.setData({ columns: newColumns_1 }, function () { - _this.setData({ - currentValue: _this.getValidValue(realValue, newColumns_1), - formattedValueText: _this.onFormat(), - }); - }); + return defaultFormat(realValue, getOptionByValue(realValue, props.options)); + }, [realValue]); + var _f = useMixState(props.defaultVisible, { + value: props.visible, + }), visible = _f[0], updateVisible = _f[1].update; + useEffect(function () { + setTimeout(function () { + if (visible) { + var newColumns = getterColumns(realValue, props.options); + var currentValue = getValidValue(realValue, newColumns); + setState({ value: currentValue, columns: newColumns }); } + }); + }, [visible]); + useEvent('onVisibleChange', function (event) { + var visible = resolveEventValue(event); + if (visible) { + updateVisible(true); } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - defaultFormat: function (value, options) { - if (options) { - return options.map(function (v) { return v.label; }).join(''); + else { + updateVisible(false); } - return ''; - }, - onFormat: function () { - var realValue = this.getValue(); - var onFormat = getValueFromProps(this, 'onFormat'); - var formatValueByProps = onFormat && onFormat(realValue, this.getOptionByValue(realValue)); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; + triggerEvent('visibleChange', visible); + }); + useEvent('onOk', function () { + // 完成时再次校验value,避免visible状态下props无效 + var validValue = getValidValue(value, columns); + if (!isRealValueControlled) { + setTimeout(function () { + updateRealValue(validValue); + }); } - return this.defaultFormat(realValue, this.getOptionByValue(realValue)); - }, - onCancel: function (e) { - triggerEventOnly(this, 'cancel', e); - }, -}, { - currentValue: [], - columns: [], - formattedValueText: '', - visible: false, -}, [mixinValue()], { - created: function () { - this.initColumns(); - }, - observers: { - '**': function (data) { - var prevData = this._prevData || this.data; - this._prevData = __assign({}, data); - var options = getValueFromProps(this, 'options'); - if (!equal(options, prevData.options)) { - var currentValue = this.data.currentValue; - var newColumns = this.getterColumns(currentValue, options); - this.setData({ - columns: newColumns, - }); - } - if (!this.isEqualValue(prevData)) { - var realValue = this.getValue(); - var newColumns = this.getterColumns(realValue, options); - var currentValue = this.getValidValue(realValue, newColumns); - this.setData({ currentValue: currentValue, formattedValueText: this.onFormat() }); - } - }, - 'visible': function (data) { - var prevVisible = this._prevVisible; - this._prevVisible = data; - var visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevVisible, visible)) { - this.setData({ visible: visible }); - } + triggerEventValues('ok', [ + validValue, + getOptionByValue(validValue, props.options), + ]); + }); + useEvent('onChange', function (event) { + var selectedValue = resolveEventValues(event)[0]; + var newColumns = getterColumns(selectedValue, props.options); + var value = getValidValue(selectedValue, newColumns); + setState({ value: value, columns: newColumns }); + triggerEventValues('change', [ + selectedValue, + getOptionByValue(selectedValue, props.options), + ]); + }); + return { + state: { + visible: visible }, - }, -}); + formattedValueText: formattedValueText, + currentValue: value, + columns: columns, + }; +}; +mountComponent(CascaderPicker, CascaderFunctionalProps); diff --git a/compiled/wechat/src/Picker/CascaderPicker/index.json b/compiled/wechat/src/Picker/CascaderPicker/index.json index a0bae1545..208399c82 100644 --- a/compiled/wechat/src/Picker/CascaderPicker/index.json +++ b/compiled/wechat/src/Picker/CascaderPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-picker": "../index" } diff --git a/compiled/wechat/src/Picker/CascaderPicker/index.wxml b/compiled/wechat/src/Picker/CascaderPicker/index.wxml index 1641aa68e..66ac9cfdc 100644 --- a/compiled/wechat/src/Picker/CascaderPicker/index.wxml +++ b/compiled/wechat/src/Picker/CascaderPicker/index.wxml @@ -4,7 +4,7 @@ animationType="{{ animationType }}" popClassName="ant-cascader-picker-popup {{ popClassName || '' }}" popStyle="{{ popStyle }}" - visible="{{ visible }}" + visible="{{ state.visible }}" options="{{ columns }}" value="{{ currentValue }}" disabled="{{ disabled }}" diff --git a/compiled/wechat/src/Picker/CascaderPicker/props.js b/compiled/wechat/src/Picker/CascaderPicker/props.js index 0ded11378..db8ed0d15 100644 --- a/compiled/wechat/src/Picker/CascaderPicker/props.js +++ b/compiled/wechat/src/Picker/CascaderPicker/props.js @@ -1,4 +1,11 @@ export var CascaderDefaultProps = { + placeholder: '请选择', + okText: '确定', + cancelText: '取消', + disabled: false, + maskClosable: false, +}; +export var CascaderFunctionalProps = { visible: null, defaultVisible: null, animationType: 'transform', diff --git a/compiled/wechat/src/Picker/index.js b/compiled/wechat/src/Picker/index.js index 77a45f12c..690a2527f 100644 --- a/compiled/wechat/src/Picker/index.js +++ b/compiled/wechat/src/Picker/index.js @@ -1,267 +1,92 @@ -var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { - function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } - return new (P || (P = Promise))(function (resolve, reject) { - function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } - function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } - function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } - step((generator = generator.apply(thisArg, _arguments || [])).next()); - }); -}; -var __generator = (this && this.__generator) || function (thisArg, body) { - var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; - return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; - function verb(n) { return function (v) { return step([n, v]); }; } - function step(op) { - if (f) throw new TypeError("Generator is already executing."); - while (g && (g = 0, op[0] && (_ = 0)), _) try { - if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; - if (y = 0, t) op = [op[0] & 2, t.value]; - switch (op[0]) { - case 0: case 1: t = op; break; - case 4: _.label++; return { value: op[1], done: false }; - case 5: _.label++; y = op[1]; op = [0]; continue; - case 7: op = _.ops.pop(); _.trys.pop(); continue; - default: - if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } - if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } - if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } - if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } - if (t[2]) _.ops.pop(); - _.trys.pop(); continue; - } - op = body.call(thisArg, _); - } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } - if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; +import { useEvent, useRef, useState, useEffect, useMemo, } from 'functional-mini/component'; +import '../_util/assert-component2'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useMixState } from '../_util/hooks/useMixState'; +import { PickerFunctionalProps } from './props'; +import { getMatchedItemByIndex, getMatchedItemByValue, getterColumns, getterFormatText, getterSelectedIndex, } from './utils'; +var Picker = function (props) { + var _a; + var _b = useMixState((_a = props.defaultValue) !== null && _a !== void 0 ? _a : [], { + value: props.value, + }), value = _b[0], _c = _b[1], isValueControlled = _c.isControlled, updateValue = _c.update; + var _d = useComponentEvent(props), triggerEvent = _d.triggerEvent, triggerEventOnly = _d.triggerEventOnly, triggerEventValues = _d.triggerEventValues; + var _e = useMixState(props.defaultVisible, { + value: props.visible, + }), visible = _e[0], updateVisible = _e[1].update; + var singleRef = useRef(false); + var selectIndexRef = useRef(null); + function triggerPicker(newVisibleValue) { + updateVisible(newVisibleValue); + triggerEvent('visibleChange', newVisibleValue); } -}; -import { Component, triggerEvent, triggerEventOnly, triggerEventValues, getValueFromProps, } from '../_util/simply'; -import { PickerDefaultProps } from './props'; -import { getMatchedItemByValue, getMatchedItemByIndex, getStrictMatchedItemByValue, } from './utils'; -import mixinValue from '../mixins/value'; -Component(PickerDefaultProps, { - // visible受控判断 - isVisibleControlled: function () { - return getValueFromProps(this, 'visible') !== null; - }, - initData: function () { - var _this = this; - var _a = getValueFromProps(this, [ - 'options', - 'visible', - 'defaultVisible', - ]), options = _a[0], visible = _a[1], defaultVisible = _a[2]; - var columns = this.getterColumns(options); - this.setData({ - columns: columns, - }, function () { - var formatValue = _this.getterFormatText(); - var selectedIndex = _this.getterSelectedIndex(); - _this.setData({ - formatValue: formatValue, - selectedIndex: selectedIndex, - visible: _this.isVisibleControlled() ? visible : defaultVisible, - }); - }); - }, - getterColumns: function (options) { - var columns = []; - if (options.length > 0) { - if (options.every(function (item) { return Array.isArray(item); })) { - this.single = false; - columns = options.slice(); - } - else { - this.single = true; - columns = [options]; - } + var _f = useState([]), selectedIndex = _f[0], setSelectedIndex = _f[1]; + var columns = useMemo(function () { + return getterColumns(props.options, singleRef); + }, [props.options]); + useEffect(function () { + selectIndexRef.current = null; + setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); + }, [columns, value]); + var formatValue = useMemo(function () { + if (typeof props.formattedValueText === 'string') { + return props.formattedValueText; } - return columns; - }, - defaultFormat: function (value, column) { - if (Array.isArray(column)) { - return column - .filter(function (c) { return c !== undefined; }) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; - }, - getterFormatText: function () { - var _a = getValueFromProps(this, [ - 'onFormat', - 'formattedValueText', - ]), onFormat = _a[0], formattedValueText = _a[1]; - if (typeof formattedValueText === 'string') { - return formattedValueText; + var formatValue = getterFormatText(columns, value, props.onFormat, singleRef); + return formatValue; + }, [props.formattedValueText, visible, columns, value, props.onFormat]); + useEvent('onOpen', function () { + if (props.disabled) { + return; } - var columns = this.data.columns; - var realValue = this.getValue(); - var matchedColumn = getStrictMatchedItemByValue(columns, realValue, this.single).matchedColumn; - var formatValueByProps = onFormat && onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; + selectIndexRef.current = null; + var selectedIndex = getterSelectedIndex(columns, value, singleRef); + setSelectedIndex(selectedIndex); + triggerPicker(true); + }); + useEvent('onCancel', function () { + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'cancel' } }); + }); + useEvent('onMaskDismiss', function () { + if (!props.maskClosable) { + return; } - return this.defaultFormat(realValue, matchedColumn); - }, - getterSelectedIndex: function () { - var selectedIndex = []; - var columns = this.data.columns; - var realValue = this.getValue(); - var value = realValue || []; - if (this.single) { - value = [realValue]; + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'mask' } }); + }); + useEvent('onChange', function (e) { + var selectedIndex = e.detail.value; + var _a = getMatchedItemByIndex(columns, selectedIndex, singleRef), matchedColumn = _a.matchedColumn, matchedValues = _a.matchedValues; + selectIndexRef.current = selectedIndex; + setSelectedIndex(selectedIndex); + triggerEventValues('change', [matchedValues, matchedColumn], e); + }); + useEvent('onOk', function () { + var result; + if (selectIndexRef.current) { + result = getMatchedItemByIndex(columns, selectIndexRef.current, singleRef); } - var _loop_1 = function (i) { - var column = columns[i]; - var compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - var index = column.findIndex(function (c) { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - }; - for (var i = 0; i < columns.length; i++) { - _loop_1(i); + else { + result = getMatchedItemByValue(columns, value, singleRef); } - return selectedIndex; - }, - onOpen: function () { - var disabled = getValueFromProps(this, 'disabled'); - if (!disabled) { - this.tempSelectedIndex = null; - var selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex: selectedIndex, - }); - this.triggerPicker(true); + var matchedColumn = result.matchedColumn, matchedValues = result.matchedValues; + triggerPicker(false); + if (!isValueControlled) { + updateValue(matchedValues); } - }, - triggerPicker: function (visible) { - this.setData({ + triggerEventValues('ok', [matchedValues, matchedColumn]); + }); + return { + formatValue: formatValue, + selectedIndex: selectedIndex, + columns: columns, + state: { visible: visible, - }); - triggerEvent(this, 'visibleChange', visible); - }, - onMaskDismiss: function () { - var maskClosable = getValueFromProps(this, 'maskClosable'); - if (!maskClosable) { - return; - } - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); - }, - onCancel: function () { - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); - }, - onChange: function (e) { - var selectedIndex = e.detail.value; - this.tempSelectedIndex = selectedIndex; - this.isChangingPickerView = true; - var _a = getMatchedItemByIndex(this.data.columns, this.tempSelectedIndex, this.single), matchedColumn = _a.matchedColumn, matchedValues = _a.matchedValues; - this.setData({ - selectedIndex: selectedIndex, - }); - triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); - }, - onOk: function () { - return __awaiter(this, void 0, void 0, function () { - var result, matchedColumn, matchedValues; - return __generator(this, function (_a) { - if (this.tempSelectedIndex) { - result = getMatchedItemByIndex(this.data.columns, this.tempSelectedIndex, this.single); - } - else { - result = getMatchedItemByValue(this.data.columns, this.getValue(), this.single); - } - matchedColumn = result.matchedColumn, matchedValues = result.matchedValues; - this.triggerPicker(false); - if (!this.isControlled()) { - this.update(matchedValues); - } - triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); - return [2 /*return*/]; - }); - }); - }, -}, { - formatValue: '', - columns: [], - visible: false, - selectedIndex: [], -}, [ - mixinValue({ - transformValue: function (value) { - return { - needUpdate: true, - value: value === undefined ? [] : value, - }; }, - }), -], { - tempSelectedIndex: null, - single: false, - isChangingPickerView: false, - created: function () { - this.initData(); - }, - observers: { - 'options': function () { - var _this = this; - var options = getValueFromProps(this, 'options'); - var newColums = this.getterColumns(options); - this.setData({ - columns: newColums, - }, function () { - // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 - if (!_this.isChangingPickerView) { - _this.tempSelectedIndex = null; - var selectedIndex = _this.getterSelectedIndex(); - _this.setData({ - selectedIndex: selectedIndex, - }); - } - _this.isChangingPickerView = false; - }); + mixin: { + value: value, }, - 'value': function () { - var selectedIndex = this.getterSelectedIndex(); - this.tempSelectedIndex = null; - this.setData({ - selectedIndex: selectedIndex, - }); - }, - 'visible': function () { - var visible = getValueFromProps(this, 'visible'); - if (this.data.visible !== visible) { - this.setData({ - visible: visible, - }); - } - }, - 'formattedValueText': function () { - var formattedValueText = getValueFromProps(this, 'formattedValueText'); - this.setData({ - formatValue: formattedValueText, - }); - }, - '**': function () { - var formatValue = this.getterFormatText(); - if (formatValue !== this.data.formatValue) { - this.setData({ - formatValue: formatValue, - }); - } - }, - }, -}); + }; +}; +mountComponent(Picker, PickerFunctionalProps); diff --git a/compiled/wechat/src/Picker/index.json b/compiled/wechat/src/Picker/index.json index bea48a2cb..e1a7501d8 100644 --- a/compiled/wechat/src/Picker/index.json +++ b/compiled/wechat/src/Picker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-popup": "../Popup/index" } diff --git a/compiled/wechat/src/Picker/index.wxml b/compiled/wechat/src/Picker/index.wxml index f6e2602d9..eb93daf3e 100644 --- a/compiled/wechat/src/Picker/index.wxml +++ b/compiled/wechat/src/Picker/index.wxml @@ -28,7 +28,7 @@ animationType="{{ animationType }}" destroyOnClose bind:close="onMaskDismiss" - visible="{{ visible }}"> + visible="{{ state.visible }}"> 0) { + if (options.every(function (item) { return Array.isArray(item); })) { + singleRef.current = false; + columns = options.slice(); + } + else { + singleRef.current = true; + columns = [options]; + } + } + return columns; +} +export function defaultFormat(value, column) { + if (Array.isArray(column)) { + return column + .filter(function (c) { return c !== undefined; }) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); + } + return (column && column.label) || column || ''; +} +export function getterFormatText(columns, realValue, onFormat, singleRef) { + var matchedColumn = getStrictMatchedItemByValue(columns, realValue, singleRef.current).matchedColumn; + if (typeof onFormat === 'function') { + var formatValueByProps = onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined) { + return formatValueByProps; + } + } + return defaultFormat(realValue, matchedColumn); +} +export function getterSelectedIndex(columns, realValue, sinefileRef) { + var selectedIndex = []; + var value = realValue || []; + if (sinefileRef.current) { + value = [realValue]; + } + var _loop_3 = function (i) { + var column = columns[i]; + var compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + var index = column.findIndex(function (c) { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + }; + for (var i = 0; i < columns.length; i++) { + _loop_3(i); + } + return selectedIndex; +} diff --git a/compiled/wechat/src/Popover/index.json b/compiled/wechat/src/Popover/index.json index 6083004a5..0c9094440 100644 --- a/compiled/wechat/src/Popover/index.json +++ b/compiled/wechat/src/Popover/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "mask": "../Mask/index" } diff --git a/compiled/wechat/src/Popup/index.json b/compiled/wechat/src/Popup/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Popup/index.json +++ b/compiled/wechat/src/Popup/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Progress/index.json b/compiled/wechat/src/Progress/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Progress/index.json +++ b/compiled/wechat/src/Progress/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/Radio/RadioGroup/index.json b/compiled/wechat/src/Radio/RadioGroup/index.json index 857c3e722..787ac5732 100644 --- a/compiled/wechat/src/Radio/RadioGroup/index.json +++ b/compiled/wechat/src/Radio/RadioGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/compiled/wechat/src/Radio/index.json b/compiled/wechat/src/Radio/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Radio/index.json +++ b/compiled/wechat/src/Radio/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/RareWordsKeyboard/index.js b/compiled/wechat/src/RareWordsKeyboard/index.js index 075292286..b31d099b8 100644 --- a/compiled/wechat/src/RareWordsKeyboard/index.js +++ b/compiled/wechat/src/RareWordsKeyboard/index.js @@ -54,60 +54,41 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { } return to.concat(ar || Array.prototype.slice.call(from)); }; -import { Component, triggerEvent, triggerEventOnly } from '../_util/simply'; import { PINYIN_MAP } from './constants'; import { RareWordsKeyboardProps } from './props'; import { formatZDatas, loadFontFace, matchWordsRecommend } from './utils'; import { ZDATAS } from './zdatas'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; +import '../_util/assert-component2'; +import { useEffect, useEvent, useState } from 'functional-mini/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { mountComponent } from '../_util/component'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; var wordsData = formatZDatas(ZDATAS.datas); -Component(RareWordsKeyboardProps, { - getInstance: function () { - if (this.$id) { - return my; - } - return this; - }, - getBoundingClientRect: function (query) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), query)]; - case 1: return [2 /*return*/, _a.sent()]; - } - }); - }); - }, - // 隐藏键盘,失去焦点 - handleHide: function () { - this.setData({ +var RareWordsKeyboard = function (props) { + var _a = useState({ + showErrorPage: false, + loading: false, + }), fontState = _a[0], setFontState = _a[1]; + var _b = useState(0), maxDisplayNum = _b[0], setMaxDisplayNum = _b[1]; + var _c = useState({ + inputValue: [], + displayStr: '', + matchWordsList: [], + showMoreWords: false, // 是否展示更多候选字 + }), keyboardState = _c[0], setKeyboardState = _c[1]; + var _d = useComponentEvent(props), triggerEvent = _d.triggerEvent, triggerEventOnly = _d.triggerEventOnly; + var handleHide = useStableCallback(function () { + setKeyboardState({ inputValue: [], matchWordsList: [], displayStr: '', showMoreWords: false, }); - triggerEventOnly(this, 'close'); - }, - // 点击键盘key值 - handleKeyClick: function (e) { - if (this.data.loading) - return; - var _a = e.currentTarget.dataset.value, value = _a === void 0 ? '' : _a; - if (!value) - return; - var inputValue = __spreadArray(__spreadArray([], this.data.inputValue, true), [value], false); - this.setData(__assign({ inputValue: __spreadArray([], inputValue, true) }, this.computeMatchWords(inputValue))); - }, - // 点击删除 - handleDelete: function () { - var inputValue = __spreadArray([], this.data.inputValue, true); - if (this.data.inputValue.length === 0) - return; - inputValue.pop(); - this.setData(__assign({ inputValue: __spreadArray([], inputValue, true) }, this.computeMatchWords(inputValue))); - }, + triggerEventOnly('close'); + }); // 计算展示值和候选字列表 - computeMatchWords: function (inputValue) { + function computeMatchWords(inputValue) { var displayStr = Array.isArray(inputValue) ? inputValue.join('') : inputValue; @@ -116,76 +97,93 @@ Component(RareWordsKeyboardProps, { displayStr: displayStr, matchWordsList: curMatchWords, }; - }, - // 点击查看更多 - hanleLookMore: function () { - if (this.data.matchWordsList.length <= this.data.maxDisplayNum) { - this.handleHide(); - return; - } - this.setData({ - showMoreWords: !this.data.showMoreWords, + } + function loadFont() { + setFontState(function (pre) { + return __assign(__assign({}, pre), { loading: true }); }); - }, - // 计算每行可以展示的最大字数 - computeMaxDisplayNum: function () { + loadFontFace() + .then(function () { + setFontState({ showErrorPage: false, loading: false }); + }) + .catch(function (err) { + setFontState({ showErrorPage: true, loading: false }); + triggerEvent('error', err); + }); + } + var getBoundingClientRect = useInstanceBoundingClientRect().getBoundingClientRect; + function computeMaxDisplayNum() { return __awaiter(this, void 0, void 0, function () { var _a, singleWords, wordsWrap, maxDisplayNumInOneLine; return __generator(this, function (_b) { switch (_b.label) { case 0: return [4 /*yield*/, Promise.all([ - this.getBoundingClientRect('.ant-rare-words-keyboard-match_words_hidden'), - this.getBoundingClientRect('.ant-rare-words-keyboard-match_words_inner'), + getBoundingClientRect('.ant-rare-words-keyboard-match_words_hidden'), + getBoundingClientRect('.ant-rare-words-keyboard-match_words_inner'), ])]; case 1: _a = _b.sent(), singleWords = _a[0], wordsWrap = _a[1]; if (!(wordsWrap === null || wordsWrap === void 0 ? void 0 : wordsWrap.width) || !(singleWords === null || singleWords === void 0 ? void 0 : singleWords.width)) return [2 /*return*/]; maxDisplayNumInOneLine = parseInt(((wordsWrap === null || wordsWrap === void 0 ? void 0 : wordsWrap.width) / (singleWords === null || singleWords === void 0 ? void 0 : singleWords.width)).toString(), 10); - this.setData({ maxDisplayNum: maxDisplayNumInOneLine }); + setMaxDisplayNum(maxDisplayNumInOneLine); return [2 /*return*/]; } }); }); - }, - // 加载字体 - loadFont: function () { - var _this = this; - this.setData({ - loading: true, - }); - loadFontFace() - .then(function () { - _this.setData({ showErrorPage: false, loading: false }); - }) - .catch(function (err) { - _this.setData({ showErrorPage: true, loading: false }); - triggerEvent(_this, 'error', err); - }); - }, - // 点击重试 - handleRetry: function () { - this.loadFont(); - }, - handleWordClick: function (e) { + } + useEffect(function () { + loadFont(); + computeMaxDisplayNum(); + }, []); + useEvent('handleRetry', function () { + loadFont(); + }); + useEvent('handleWordClick', function (e) { var _a = e.currentTarget.dataset.value, value = _a === void 0 ? '' : _a; if (!value) return; - triggerEvent(this, 'change', value); - this.handleHide(); - }, -}, { - loading: false, - inputValue: [], - displayStr: '', - matchWordsList: [], - showMoreWords: false, - pinyinMaps: PINYIN_MAP, - maxDisplayNum: 0, - showErrorPage: false, // 是否展示错误页 -}, null, { - attached: function () { - this.loadFont(); - this.computeMaxDisplayNum(); - }, -}); + triggerEvent('change', value); + handleHide(); + }); + useEvent('hanleLookMore', function () { + if (keyboardState.matchWordsList.length <= maxDisplayNum) { + handleHide(); + return; + } + setKeyboardState(function (old) { + return __assign(__assign({}, old), { showMoreWords: !old.showMoreWords }); + }); + }); + // 隐藏键盘,失去焦点 + useEvent('handleHide', function () { + handleHide(); + }); + // 点击键盘key值 + useEvent('handleKeyClick', function (e) { + if (fontState.loading) { + return; + } + var _a = e.target.dataset.value, value = _a === void 0 ? '' : _a; + if (!value) { + return; + } + setKeyboardState(function (old) { + var inputValue = __spreadArray(__spreadArray([], old.inputValue, true), [value], false); + return __assign(__assign(__assign({}, old), { inputValue: inputValue }), computeMatchWords(inputValue)); + }); + }); + // 点击删除 + useEvent('handleDelete', function () { + if (keyboardState.inputValue.length === 0) { + return; + } + setKeyboardState(function (old) { + var inputValue = __spreadArray([], old.inputValue, true); + inputValue.pop(); + return __assign(__assign(__assign({}, old), { inputValue: __spreadArray([], inputValue, true) }), computeMatchWords(inputValue)); + }); + }); + return __assign(__assign(__assign(__assign({}, fontState), { maxDisplayNum: maxDisplayNum }), keyboardState), { pinyinMaps: PINYIN_MAP }); +}; +mountComponent(RareWordsKeyboard, RareWordsKeyboardProps); diff --git a/compiled/wechat/src/RareWordsKeyboard/index.json b/compiled/wechat/src/RareWordsKeyboard/index.json index 63e881845..6b2389527 100644 --- a/compiled/wechat/src/RareWordsKeyboard/index.json +++ b/compiled/wechat/src/RareWordsKeyboard/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "result": "../Result/index", diff --git a/compiled/wechat/src/Rate/index.json b/compiled/wechat/src/Rate/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Rate/index.json +++ b/compiled/wechat/src/Rate/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/Result/index.json b/compiled/wechat/src/Result/index.json index 5b3034c4a..188dcef68 100644 --- a/compiled/wechat/src/Result/index.json +++ b/compiled/wechat/src/Result/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "image-icon": "../ImageIcon/index" diff --git a/compiled/wechat/src/Selector/index.json b/compiled/wechat/src/Selector/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Selector/index.json +++ b/compiled/wechat/src/Selector/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/Avatar/index.json b/compiled/wechat/src/Skeleton/Avatar/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Skeleton/Avatar/index.json +++ b/compiled/wechat/src/Skeleton/Avatar/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/Button/index.json b/compiled/wechat/src/Skeleton/Button/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Skeleton/Button/index.json +++ b/compiled/wechat/src/Skeleton/Button/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/Input/index.json b/compiled/wechat/src/Skeleton/Input/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Skeleton/Input/index.json +++ b/compiled/wechat/src/Skeleton/Input/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/Paragraph/index.json b/compiled/wechat/src/Skeleton/Paragraph/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Skeleton/Paragraph/index.json +++ b/compiled/wechat/src/Skeleton/Paragraph/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/Title/index.json b/compiled/wechat/src/Skeleton/Title/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/compiled/wechat/src/Skeleton/Title/index.json +++ b/compiled/wechat/src/Skeleton/Title/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/compiled/wechat/src/Skeleton/index.json b/compiled/wechat/src/Skeleton/index.json index 85c588cb3..04b9328d7 100644 --- a/compiled/wechat/src/Skeleton/index.json +++ b/compiled/wechat/src/Skeleton/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "avatar": "./Avatar/index", "paragraph": "./Paragraph/index", diff --git a/compiled/wechat/src/Slider/index.js b/compiled/wechat/src/Slider/index.js index 1bf3eee22..785c0766b 100644 --- a/compiled/wechat/src/Slider/index.js +++ b/compiled/wechat/src/Slider/index.js @@ -279,7 +279,9 @@ Component(sliderDefaultProps, { typeof this.onChangeValue === 'undefined' ? this.getValue() : this.onChangeValue; - if (emit && !this.isSliderValueEqual(this.onChangeValue, value)) { + if (emit && + getValueFromProps(this, 'onChange') && + !this.isSliderValueEqual(this.onChangeValue, value)) { this.onChangeValue = value; triggerEvent(this, 'change', value); } diff --git a/compiled/wechat/src/Slider/index.json b/compiled/wechat/src/Slider/index.json index adb9f384f..66ee617da 100644 --- a/compiled/wechat/src/Slider/index.json +++ b/compiled/wechat/src/Slider/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "popover": "../Popover/index" } diff --git a/compiled/wechat/src/Stepper/index.json b/compiled/wechat/src/Stepper/index.json index 4ea7f8f97..12bdacc36 100644 --- a/compiled/wechat/src/Stepper/index.json +++ b/compiled/wechat/src/Stepper/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-button": "../Button/index", "ant-input": "../Input/InputBlur/index" diff --git a/compiled/wechat/src/Steps/index.json b/compiled/wechat/src/Steps/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Steps/index.json +++ b/compiled/wechat/src/Steps/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/SwipeAction/index.json b/compiled/wechat/src/SwipeAction/index.json index dc5676ea5..32640e0dc 100644 --- a/compiled/wechat/src/SwipeAction/index.json +++ b/compiled/wechat/src/SwipeAction/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" -} + "component": true +} \ No newline at end of file diff --git a/compiled/wechat/src/Switch/index.json b/compiled/wechat/src/Switch/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Switch/index.json +++ b/compiled/wechat/src/Switch/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/TabBar/index.json b/compiled/wechat/src/TabBar/index.json index 5b443dea3..a7c04bf5b 100644 --- a/compiled/wechat/src/TabBar/index.json +++ b/compiled/wechat/src/TabBar/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-badge": "../Badge/index", "image-icon": "../ImageIcon/index" diff --git a/compiled/wechat/src/Tabs/index.js b/compiled/wechat/src/Tabs/index.js index 583d2b12c..3723cdac6 100644 --- a/compiled/wechat/src/Tabs/index.js +++ b/compiled/wechat/src/Tabs/index.js @@ -1,3 +1,14 @@ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { @@ -34,204 +45,177 @@ var __generator = (this && this.__generator) || function (thisArg, body) { if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; -import { Component, triggerEvent, getValueFromProps } from '../_util/simply'; -import { TabsDefaultProps } from './props'; -import createValue from '../mixins/value'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; -Component(TabsDefaultProps, { - getInstance: function () { - if (this.$id) { - return my; - } - return this; - }, - get$Id: function () { - return this.$id ? "-".concat(this.$id) : ''; - }, - getBoundingClientRect: function (query) { - return __awaiter(this, void 0, void 0, function () { - return __generator(this, function (_a) { - switch (_a.label) { - case 0: return [4 /*yield*/, getInstanceBoundingClientRect(this.getInstance(), query)]; - case 1: return [2 /*return*/, _a.sent()]; - } - }); +import { useState } from 'functional-mini/compat'; +import { useEvent, useReady, useRef, } from 'functional-mini/component'; +import '../_util/assert-component2'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; +import { useComponentUpdateEffect } from '../_util/hooks/useLayoutEffect'; +import { useMixState } from '../_util/hooks/useMixState'; +import { TabsFunctionalProps } from './props'; +var Tabs = function (props) { + var _a = useMixState(props.defaultCurrent, { + value: props.current, + }), currentValue = _a[0], _b = _a[1], isControlled = _b.isControlled, update = _b.update; + var _c = useState({ + scrollLeft: 0, + scrollTop: 0, + leftFade: false, + rightFade: false, + }), state = _c[0], updateState = _c[1]; + var scrollRef = useRef({ scrollLeft: 0, scrollTop: 0 }); + var triggerEvent = useComponentEvent(props).triggerEvent; + var updatePartState = function (part) { + updateState(function (old) { + return __assign(__assign({}, old), part); }); - }, - updateFade: function () { - return __awaiter(this, void 0, void 0, function () { - var items, _a, view, item; - return __generator(this, function (_b) { - switch (_b.label) { - case 0: - this.setData({ - leftFade: !!this.scrollLeft, - }); - items = getValueFromProps(this, 'items'); - return [4 /*yield*/, Promise.all([ - this.getBoundingClientRect("#ant-tabs-bar-scroll-view".concat(this.get$Id())), - this.getBoundingClientRect("#ant-tabs-bar-item".concat(this.get$Id(), "-").concat(items.length - 1)), - ])]; - case 1: - _a = _b.sent(), view = _a[0], item = _a[1]; - if (!item || !view) { - return [2 /*return*/]; - } - this.setData({ - rightFade: item.left + item.width / 2 > view.width, - }); + }; + var _d = useInstanceBoundingClientRect(), getBoundingClientRectWithBuilder = _d.getBoundingClientRectWithBuilder, getBoundingClientRect = _d.getBoundingClientRect; + var updateFade = useStableCallback(function () { return __awaiter(void 0, void 0, void 0, function () { + var _a, view, item; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + updatePartState({ + leftFade: !!scrollRef.current.scrollLeft, + }); + return [4 /*yield*/, Promise.all([ + getBoundingClientRectWithBuilder(function (id) { return "#ant-tabs-bar-scroll-view".concat(id); }), + getBoundingClientRectWithBuilder(function (id) { return "#ant-tabs-bar-item".concat(id, "-").concat(props.items.length - 1); }), + ])]; + case 1: + _a = _b.sent(), view = _a[0], item = _a[1]; + if (!item || !view) { return [2 /*return*/]; - } - }); + } + updatePartState({ + rightFade: item.left + item.width / 2 > view.width, + }); + return [2 /*return*/]; + } }); - }, - updateScroll: function () { - return __awaiter(this, void 0, void 0, function () { - var current, _a, view, item, _b, direction, scrollMode, scrollTop, needScroll_1, distance, scrollLeft, needScroll, distance; - return __generator(this, function (_c) { - switch (_c.label) { - case 0: - current = this.getValue(); - return [4 /*yield*/, Promise.all([ - this.getBoundingClientRect("#ant-tabs-bar-scroll-view".concat(this.get$Id())), - this.getBoundingClientRect("#ant-tabs-bar-item".concat(this.get$Id(), "-").concat(current)), - ])]; - case 1: - _a = _c.sent(), view = _a[0], item = _a[1]; - if (!view || !item) { - return [2 /*return*/]; - } - _b = getValueFromProps(this, [ - 'direction', - 'scrollMode', - ]), direction = _b[0], scrollMode = _b[1]; - if (direction === 'vertical') { - scrollTop = this.scrollTop || 0; - needScroll_1 = false; - if (scrollMode === 'center') { - needScroll_1 = true; - scrollTop += - item.top - view.top - Math.max((view.height - item.height) / 2, 0); - } - else { - distance = item.top - view.top; - if (distance < 0) { - scrollTop += distance; - needScroll_1 = true; - } - else if (distance + item.height > view.height) { - scrollTop += Math.min(distance + item.height - view.height, distance); - needScroll_1 = true; - } - } - if (needScroll_1) { - if (scrollTop === this.data.scrollTop) { - scrollTop += Math.random(); - } - this.setData({ - scrollTop: scrollTop, - }); - } - return [2 /*return*/]; - } - scrollLeft = this.scrollLeft || 0; - needScroll = false; - if (scrollMode === 'center') { - needScroll = true; - scrollLeft += - item.left - view.left - Math.max((view.width - item.width) / 2, 0); + }); }); + var updateScroll = useStableCallback(function () { return __awaiter(void 0, void 0, void 0, function () { + var current, _a, view, item, scrollTop, needScroll_1, distance, scrollLeft, needScroll, distance; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + current = currentValue; + return [4 /*yield*/, Promise.all([ + getBoundingClientRectWithBuilder(function (id) { return "#ant-tabs-bar-scroll-view".concat(id); }), + getBoundingClientRectWithBuilder(function (id) { return "#ant-tabs-bar-item".concat(id, "-").concat(current); }), + ])]; + case 1: + _a = _b.sent(), view = _a[0], item = _a[1]; + if (!view || !item) { + return [2 /*return*/]; + } + if (props.direction === 'vertical') { + scrollTop = scrollRef.current.scrollTop || 0; + needScroll_1 = false; + if (props.scrollMode === 'center') { + needScroll_1 = true; + scrollTop += + item.top - view.top - Math.max((view.height - item.height) / 2, 0); } else { - distance = item.left - view.left; + distance = item.top - view.top; if (distance < 0) { - scrollLeft += distance; - needScroll = true; + scrollTop += distance; + needScroll_1 = true; } - else if (distance + item.width > view.width) { - scrollLeft += Math.min(distance + item.width - view.width, distance); - needScroll = true; + else if (distance + item.height > view.height) { + scrollTop += Math.min(distance + item.height - view.height, distance); + needScroll_1 = true; } } - if (needScroll) { - if (scrollLeft === this.data.scrollLeft) { - scrollLeft += Math.random(); + if (needScroll_1) { + if (scrollTop === state.scrollTop) { + scrollTop += Math.random(); } - this.setData({ - scrollLeft: scrollLeft, + updatePartState({ + scrollTop: scrollTop, }); - this.updateFade(); } return [2 /*return*/]; - } - }); - }); - }, - onScroll: function (e) { - return __awaiter(this, void 0, void 0, function () { - var direction; - return __generator(this, function (_a) { - direction = getValueFromProps(this, 'direction'); - if (direction === 'vertical') { - this.scrollTop = e.detail.scrollTop; + } + scrollLeft = scrollRef.current.scrollLeft || 0; + needScroll = false; + if (props.scrollMode === 'center') { + needScroll = true; + scrollLeft += + item.left - view.left - Math.max((view.width - item.width) / 2, 0); + } + else { + distance = item.left - view.left; + if (distance < 0) { + scrollLeft += distance; + needScroll = true; + } + else if (distance + item.width > view.width) { + scrollLeft += Math.min(distance + item.width - view.width, distance); + needScroll = true; + } + } + if (needScroll) { + if (scrollLeft === state.scrollLeft) { + scrollLeft += Math.random(); + } + updatePartState({ + scrollLeft: scrollLeft, + }); + updateFade(); + } return [2 /*return*/]; - } - this.scrollLeft = e.detail.scrollLeft; - this.updateFade(); + } + }); + }); }); + useEvent('onScroll', function (e) { return __awaiter(void 0, void 0, void 0, function () { + return __generator(this, function (_a) { + if (props.direction === 'vertical') { + scrollRef.current.scrollTop = e.detail.scrollTop; return [2 /*return*/]; - }); + } + scrollRef.current.scrollLeft = e.detail.scrollLeft; + updateFade(); + return [2 /*return*/]; }); - }, - onChange: function (e) { - var index = parseInt(e.currentTarget.dataset.index, 10); - var items = getValueFromProps(this, 'items'); - if (items[index].disabled) { - return; - } - if (this.getValue() === index) { - return; - } - if (!this.isControlled()) { - this.update(index); - } - triggerEvent(this, 'change', index, e); - }, -}, { - scrollHeight: 0, - scrollLeft: 0, - scrollTop: 0, - leftFade: false, - rightFade: false, -}, [ - createValue({ - valueKey: 'current', - defaultValueKey: 'defaultCurrent', - }), -], { - scrollLeft: 0, - scrollTop: 0, - ready: function () { - var _this = this; - this.updateScroll(); - this.getBoundingClientRect('.ant-tabs-bar-item').then(function (res) { - var direction = getValueFromProps(_this, 'direction'); - if (res && res.height > 0 && direction !== 'vertical') { - _this.setData({ - scrollHeight: res.height, - }); + }); }); + useEvent('onChange', function (e) { return __awaiter(void 0, void 0, void 0, function () { + var index; + return __generator(this, function (_a) { + index = parseInt(e.currentTarget.dataset.index, 10); + if (props.items[index].disabled) { + return [2 /*return*/]; } - else { - _this.setData({ - scrollHeight: direction === 'vertical' ? 0 : 40, - }); + if (currentValue === index) { + return [2 /*return*/]; + } + if (!isControlled) { + update(index); + } + triggerEvent('change', index, e); + return [2 /*return*/]; + }); + }); }); + useComponentUpdateEffect(function () { + updateScroll(); + }, [props.items, currentValue]); + var _e = useState( + // vertical 模式下,不需要设置高度 + props.direction === 'vertical' ? 0 : 40), scrollHeight = _e[0], setScrollHeight = _e[1]; + useReady(function () { + updateScroll(); + getBoundingClientRect('.ant-tabs-bar-item').then(function (res) { + if (res && res.height > 0 && props.direction !== 'vertical') { + setScrollHeight(res.height); } }); - }, - observers: { - 'items': function () { - this.updateScroll(); - }, - 'mixin.current': function () { - this.updateScroll(); - }, - }, -}); + }, []); + return __assign({ scrollHeight: scrollHeight, mixin: { + value: currentValue, + } }, state); +}; +mountComponent(Tabs, TabsFunctionalProps); diff --git a/compiled/wechat/src/Tabs/index.json b/compiled/wechat/src/Tabs/index.json index dc5676ea5..467ce2945 100644 --- a/compiled/wechat/src/Tabs/index.json +++ b/compiled/wechat/src/Tabs/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/compiled/wechat/src/Tabs/props.js b/compiled/wechat/src/Tabs/props.js index 777b176b3..7587a207f 100644 --- a/compiled/wechat/src/Tabs/props.js +++ b/compiled/wechat/src/Tabs/props.js @@ -1,4 +1,10 @@ export var TabsDefaultProps = { + type: 'basic', + defaultCurrent: 0, + items: [], + scrollMode: 'edge', +}; +export var TabsFunctionalProps = { type: 'basic', direction: 'horizontal', current: null, diff --git a/compiled/wechat/src/Tag/index.json b/compiled/wechat/src/Tag/index.json index 6cf21ce24..090c137c7 100644 --- a/compiled/wechat/src/Tag/index.json +++ b/compiled/wechat/src/Tag/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/compiled/wechat/src/Toast/index.json b/compiled/wechat/src/Toast/index.json index 1d101cb6b..0918a24ce 100644 --- a/compiled/wechat/src/Toast/index.json +++ b/compiled/wechat/src/Toast/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "am-icon": "../Icon/index", "mask": "../Mask/index", diff --git a/compiled/wechat/src/_util/component.js b/compiled/wechat/src/_util/component.js new file mode 100644 index 000000000..6a4d6808d --- /dev/null +++ b/compiled/wechat/src/_util/component.js @@ -0,0 +1,34 @@ +var __assign = (this && this.__assign) || function () { + __assign = Object.assign || function(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) + t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; +import { wechatComponent } from 'functional-mini/component'; +function removeNullProps(props) { + var newProps = {}; + for (var key in props) { + if (props[key] !== null) { + newProps[key] = props[key]; + } + } + return newProps; +} +export function mountComponent(Hooks, defaultProps) { + Component(wechatComponent(Hooks, mergeDefaultProps(defaultProps), { + options: { + styleIsolation: 'shared', + multipleSlots: true, + virtualHost: true, + }, + })); +} +function mergeDefaultProps(defaultProps) { + if (defaultProps === void 0) { defaultProps = {}; } + return __assign({ className: '', style: '' }, defaultProps); +} diff --git a/compiled/wechat/src/_util/hooks/useComponentEvent.js b/compiled/wechat/src/_util/hooks/useComponentEvent.js new file mode 100644 index 000000000..a3ff760c4 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useComponentEvent.js @@ -0,0 +1,32 @@ +import { useComponent } from 'functional-mini/component'; +import { useEvent } from './useEvent'; +export function useComponentEvent(props) { + var component = useComponent(); + var triggerEvent = useEvent(function (eventName, value, e) { + // 首字母大写,然后加上 on + component.triggerEvent(eventName.toLocaleLowerCase(), value); + }); + var triggerEventValues = useEvent(function (eventName, values, e) { + // 首字母大写,然后加上 on + component.triggerEvent(eventName.toLocaleLowerCase(), values); + }); + var triggerEventOnly = useEvent(function (eventName, e) { + // 首字母大写,然后加上 on + component.triggerEvent(eventName.toLocaleLowerCase()); + }); + var alipayForwardCatchEvent = useEvent(function (eventName, e) { + // 首字母大写,然后加上 catch + }); + var alipayForwardEvent = useEvent(function (eventName, e) { + // 首字母大写,然后加上 on + }); + return { + triggerEvent: triggerEvent, + triggerEventValues: triggerEventValues, + triggerEventOnly: triggerEventOnly, + // 转发 catch 事件 + alipayForwardCatchEvent: alipayForwardCatchEvent, + // 转发事件 + alipayForwardEvent: alipayForwardEvent, + }; +} diff --git a/compiled/wechat/src/_util/hooks/useEvent.js b/compiled/wechat/src/_util/hooks/useEvent.js new file mode 100644 index 000000000..fe06a3759 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useEvent.js @@ -0,0 +1,28 @@ +var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { + if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { + if (ar || !(i in from)) { + if (!ar) ar = Array.prototype.slice.call(from, 0, i); + ar[i] = from[i]; + } + } + return to.concat(ar || Array.prototype.slice.call(from)); +}; +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useEvent.ts + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as React from 'functional-mini/compat'; +// eslint-disable-next-line @typescript-eslint/ban-types +export function useEvent(callback) { + var fnRef = React.useRef(); + fnRef.current = callback; + var memoFn = React.useCallback((function () { + var _a; + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + return (_a = fnRef.current) === null || _a === void 0 ? void 0 : _a.call.apply(_a, __spreadArray([fnRef], args, false)); + }), []); + return memoFn; +} diff --git a/compiled/wechat/src/_util/hooks/useHandleCustomEvent.js b/compiled/wechat/src/_util/hooks/useHandleCustomEvent.js new file mode 100644 index 000000000..bcce0902e --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useHandleCustomEvent.js @@ -0,0 +1,33 @@ +import { useEvent } from 'functional-mini/component'; +export var useHandleCustomEvent = function (eventName, handler) { + useEvent(eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function (eventOrValue, alipayEvent) { + return handler(eventOrValue.detail, eventOrValue); + }); +}; +export var useMultipleValueHandleCustomEvent = function (eventName, handler) { + useEvent(eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function () { + var args = []; + for (var _i = 0; _i < arguments.length; _i++) { + args[_i] = arguments[_i]; + } + var firstArgs = args[0]; + if (Array.isArray(firstArgs.detail)) { + var wechatArgs = firstArgs.detail.concat(firstArgs); + return handler.apply(void 0, wechatArgs); + } + else { + return handler([firstArgs.detail, firstArgs]); + } + }); +}; +export var useHandleCustomEventOnly = function (eventName, handler) { + useEvent(eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + function (event) { + return handler(event); + }); +}; diff --git a/compiled/wechat/src/_util/hooks/useInstanceBoundingClientRect.js b/compiled/wechat/src/_util/hooks/useInstanceBoundingClientRect.js new file mode 100644 index 000000000..13d90c699 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useInstanceBoundingClientRect.js @@ -0,0 +1,82 @@ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (g && (g = 0, op[0] && (_ = 0)), _) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +import { useComponent } from 'functional-mini/component'; +import { getInstanceBoundingClientRect } from '../jsapi/get-instance-bounding-client-rect'; +export var useInstanceBoundingClientRect = function () { + var instance = useComponent(); + function getInstance() { + if (instance.$id) { + return my; + } + return instance; + } + function getBoundingClientRectWithId(prefix) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, getInstanceBoundingClientRect(getInstance(), "".concat(prefix).concat(instance.$id ? "-".concat(instance.$id) : ''))]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + } + function getBoundingClientRect(query) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, getInstanceBoundingClientRect(getInstance(), query)]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + } + function getBoundingClientRectWithBuilder(builder) { + return __awaiter(this, void 0, void 0, function () { + return __generator(this, function (_a) { + switch (_a.label) { + case 0: return [4 /*yield*/, getInstanceBoundingClientRect(getInstance(), builder(instance.$id ? "-".concat(instance.$id) : ''))]; + case 1: return [2 /*return*/, _a.sent()]; + } + }); + }); + } + return { + getBoundingClientRect: getBoundingClientRect, + getBoundingClientRectWithId: getBoundingClientRectWithId, + getBoundingClientRectWithBuilder: getBoundingClientRectWithBuilder, + }; +}; diff --git a/compiled/wechat/src/_util/hooks/useLayoutEffect.js b/compiled/wechat/src/_util/hooks/useLayoutEffect.js new file mode 100644 index 000000000..ca2b92bfc --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useLayoutEffect.js @@ -0,0 +1,29 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useLayoutEffect.ts + */ +import * as React from 'functional-mini/compat'; +/** + * Wrap `React.useLayoutEffect` which will not throw warning message in test env + */ +var useInternalLayoutEffect = React.useEffect; +var useLayoutEffect = function (callback, deps) { + var firstMountRef = React.useRef(true); + useInternalLayoutEffect(function () { + return callback(firstMountRef.current); + }, deps); + // We tell react that first mount has passed + useInternalLayoutEffect(function () { + firstMountRef.current = false; + return function () { + firstMountRef.current = true; + }; + }, []); +}; +export var useComponentUpdateEffect = function (callback, deps) { + useLayoutEffect(function (firstMount) { + if (!firstMount) { + return callback(); + } + }, deps); +}; +export default useLayoutEffect; diff --git a/compiled/wechat/src/_util/hooks/useMergedState.js b/compiled/wechat/src/_util/hooks/useMergedState.js new file mode 100644 index 000000000..3d4af9027 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useMergedState.js @@ -0,0 +1,60 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useMergedState.ts + */ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { useSafeState as useState } from './useState'; +import { supportUndefinedProperty } from '../platform'; +/** We only think `undefined` is empty */ +export function hasValue(value) { + if (supportUndefinedProperty()) { + return value !== undefined; + } + return value !== null && value !== undefined; +} +/** + * Similar to `useState` but will use props value if provided. + * Note that internal use rc-util `useState` hook. + */ +export function useMergedState(defaultStateValue, option) { + var _a = option || {}, defaultValue = _a.defaultValue, value = _a.value, onChange = _a.onChange, postState = _a.postState; + // ======================= Init ======================= + var _b = useState(function () { + if (hasValue(value)) { + return value; + } + else if (hasValue(defaultValue)) { + return typeof defaultValue === 'function' + ? defaultValue() + : defaultValue; + } + else { + return typeof defaultStateValue === 'function' + ? defaultStateValue() + : defaultStateValue; + } + }), innerValue = _b[0], setInnerValue = _b[1]; + var mergedValue = hasValue(value) ? value : innerValue; + var postMergedValue = postState ? postState(mergedValue) : mergedValue; + // ====================== Change ====================== + var onChangeFn = useEvent(onChange); + var _c = useState([mergedValue]), prevValue = _c[0], setPrevValue = _c[1]; + useComponentUpdateEffect(function () { + var prev = prevValue[0]; + if (innerValue !== prev) { + onChangeFn(innerValue, prev); + } + }, [prevValue]); + // Sync value back to `undefined` when it from control to un-control + useComponentUpdateEffect(function () { + if (!hasValue(value)) { + setInnerValue(value); + } + }, [value]); + // ====================== Update ====================== + var triggerChange = useEvent(function (updater, ignoreDestroy) { + setInnerValue(updater, ignoreDestroy); + setPrevValue([mergedValue], ignoreDestroy); + }); + return [postMergedValue, triggerChange]; +} diff --git a/compiled/wechat/src/_util/hooks/useMixState.js b/compiled/wechat/src/_util/hooks/useMixState.js new file mode 100644 index 000000000..10f8c6908 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useMixState.js @@ -0,0 +1,73 @@ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { hasValue } from './useMergedState'; +import { useSafeState as useState } from './useState'; +export function useMixState(defaultStateValue, option) { + var _a = option || {}, defaultValue = _a.defaultValue, value = _a.value, _b = _a.postState, postState = _b === void 0 ? function (v) { return ({ valid: true, value: v }); } : _b; + // ======================= Init ======================= + var _c = useState(function () { + var v; + if (hasValue(value)) { + v = value; + } + else if (hasValue(defaultValue)) { + v = + typeof defaultValue === 'function' + ? defaultValue() + : defaultValue; + } + else { + v = + typeof defaultStateValue === 'function' + ? defaultStateValue() + : defaultStateValue; + } + var state = postState(v); + if (state.valid) { + return state.value; + } + }), innerValue = _c[0], setInnerValue = _c[1]; + var state = postState(value); + var merge = hasValue(value) && state.valid ? state.value : innerValue; + useComponentUpdateEffect(function () { + var state = postState(value); + if (state.valid) { + setInnerValue(state.value); + } + }, [value]); + var isControlled = hasValue(value); + var triggerChange = useEvent(function (newState, ignoreDestroy) { + setInnerValue(newState, ignoreDestroy); + }); + var triggerUpdate = useEvent(function (value, option) { + var state = postState(value, option); + if (state.valid && state.value !== innerValue) { + triggerChange(state.value); + return { changed: true, newValue: state.value }; + } + return { changed: false }; + }); + var triggerUpdater = useEvent(function (getValue, option) { + if (isControlled) { + getValue(merge); + } + else { + triggerChange(function (old) { + var newValue = getValue(old); + var state = postState(newValue, option); + if (state.valid && state.value !== innerValue) { + return state.value; + } + return old; + }); + } + }); + return [ + merge, + { + isControlled: isControlled, + update: triggerUpdate, + triggerUpdater: triggerUpdater, + }, + ]; +} diff --git a/compiled/wechat/src/_util/hooks/useReportRef.js b/compiled/wechat/src/_util/hooks/useReportRef.js new file mode 100644 index 000000000..71b766ed5 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useReportRef.js @@ -0,0 +1,7 @@ +import { useComponent, useEffect } from 'functional-mini/component'; +export var triggerRefEvent = function () { + var component = useComponent(); + useEffect(function () { + component.triggerEvent('ref', component); + }, []); +}; diff --git a/compiled/wechat/src/_util/hooks/useState.js b/compiled/wechat/src/_util/hooks/useState.js new file mode 100644 index 000000000..9effb3b72 --- /dev/null +++ b/compiled/wechat/src/_util/hooks/useState.js @@ -0,0 +1,26 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useState.ts + */ +import * as React from 'functional-mini/compat'; +/** + * Same as React.useState but `setState` accept `ignoreDestroy` param to not to setState after destroyed. + * We do not make this auto is to avoid real memory leak. + * Developer should confirm it's safe to ignore themselves. + */ +export function useSafeState(defaultValue) { + var destroyRef = React.useRef(false); + var _a = React.useState(defaultValue), value = _a[0], setValue = _a[1]; + React.useEffect(function () { + destroyRef.current = false; + return function () { + destroyRef.current = true; + }; + }, []); + function safeSetState(updater, ignoreDestroy) { + if (ignoreDestroy && destroyRef.current) { + return; + } + setValue(updater); + } + return [value, safeSetState]; +} diff --git a/compiled/wechat/src/_util/platform.js b/compiled/wechat/src/_util/platform.js index 3f1f4ddd4..311dbbb73 100644 --- a/compiled/wechat/src/_util/platform.js +++ b/compiled/wechat/src/_util/platform.js @@ -1,12 +1,3 @@ -var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { - if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { - if (ar || !(i in from)) { - if (!ar) ar = Array.prototype.slice.call(from, 0, i); - ar[i] = from[i]; - } - } - return to.concat(ar || Array.prototype.slice.call(from)); -}; import { compareVersion } from './compareVersion'; export function supportUndefinedProperty() { var support = true; @@ -25,14 +16,10 @@ export function resolveEventValue(value) { return value; } export function resolveEventValues(args1, args2) { - var rest = []; - for (var _i = 2; _i < arguments.length; _i++) { - rest[_i - 2] = arguments[_i]; - } if (platform() === 'wechat') { return args1.detail; } - return __spreadArray([args1, args2], rest, true); + return [args1, args2]; } export function isOldSDKVersion() { if (platform() === 'wechat') { diff --git a/compiled/wechat/src/_util/triggerComonentEvent.js b/compiled/wechat/src/_util/triggerComonentEvent.js new file mode 100644 index 000000000..68b4898f6 --- /dev/null +++ b/compiled/wechat/src/_util/triggerComonentEvent.js @@ -0,0 +1,3 @@ +export function triggerComponentEvent(instance, propsName, event) { + instance.triggerEvent(propsName, event.detail); +} diff --git a/compiled/wechat/src/mixins/computed.js b/compiled/wechat/src/mixins/computed.js index f6e25a887..0d08a2289 100644 --- a/compiled/wechat/src/mixins/computed.js +++ b/compiled/wechat/src/mixins/computed.js @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import deepEqual from 'fast-deep-equal'; -import { getValueFromProps } from '../_util/simply'; function computedData() { var _this = this; - var nextData = this.computed(getValueFromProps(this)); + var nextData = this.computed(this.props); // 浅比较就行了 var changedData = Object.keys(nextData).reduce(function (prev, item) { // 移除 _ $ 开头的保留 props @@ -25,18 +24,11 @@ function computedData() { } this.setData(changedData); } -export default function () { - var mixin = { - attached: function () { - computedData.call(this); - }, - observers: { - '**': function () { - computedData.call(this); - }, - }, - }; - // @ts-ignore - mixin = Behavior(mixin); - return mixin; -} +export default { + didMount: function () { + computedData.call(this); + }, + didUpdate: function () { + computedData.call(this); + }, +}; diff --git a/demo/pages/Calendar/collapse-container/cn-day/cn-day.ts b/demo/pages/Calendar/collapse-container/cn-day/cn-day.ts index c32f3c0e1..f3668babf 100644 --- a/demo/pages/Calendar/collapse-container/cn-day/cn-day.ts +++ b/demo/pages/Calendar/collapse-container/cn-day/cn-day.ts @@ -1,69 +1,31 @@ import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import Converter from './js-calendar-converter'; -import { Component, getValueFromProps } from '../../../../../src/_util/simply'; +import { mountComponent } from '../../../../../src/_util/component'; interface Props { cell: any; } -Component( - { - cell: null, - } as Props, - { - updateData() { - const cell = getValueFromProps(this, 'cell'); - const time = dayjs(cell?.time); - const vs = Converter.solar2lunar( - time.get('year'), - time.get('month') + 1, - time.get('date') - ); - if (vs === -1) { - this.setData({ - cnday: '', - }); - return; - } - this.setData({ - cnday: vs.lunarFestival || vs.festival || vs.IDayCn, - festival: !!vs.festival || !!vs.lunarFestival, - unset: cell?.isSelectedBegin || cell?.isSelectedEnd, - }); - }, - }, - { - cnday: '', - festival: '', - unset: '', - }, - null, - { - /// #if ALIPAY - onInit() { - this.updateData(); - }, - didUpdate(prevProps) { - const cell = getValueFromProps(this, 'cell'); - if (!equal(prevProps.cell, cell)) { - this.updateData(); - } - }, - /// #endif - /// #if WECHAT - attached() { - this.updateData(); - }, - observers: { - '**': function (data) { - const prevData = this._prevData || this.data; - this._prevData = { ...data }; - if (!equal(prevData.cell, data.cell)) { - this.updateData(); - } - }, - }, - /// #endif +const CollapseContainer = (props: Props) => { + const time = dayjs(props.cell?.time); + const vs = Converter.solar2lunar( + time.get('year'), + time.get('month') + 1, + time.get('date') + ); + if (vs === -1) { + return { + cnday: '', + }; } -); + + return { + cnday: vs.lunarFestival || vs.festival || vs.IDayCn, + festival: !!vs.festival || !!vs.lunarFestival, + unset: props.cell?.isSelectedBegin || props.cell?.isSelectedEnd, + }; +}; + +mountComponent(CollapseContainer, { + cell: null, +}); diff --git a/demo/pages/Calendar/collapse-container/collapse-container.ts b/demo/pages/Calendar/collapse-container/collapse-container.ts index 0afb9ada0..fd7e57d14 100644 --- a/demo/pages/Calendar/collapse-container/collapse-container.ts +++ b/demo/pages/Calendar/collapse-container/collapse-container.ts @@ -1,4 +1,5 @@ -import { Component, getValueFromProps } from '../../../../src/_util/simply'; +import { useEvent, useState } from 'functional-mini/component'; +import { mountComponent } from '../../../../src/_util/component'; export interface Props { hide?: boolean; @@ -7,55 +8,22 @@ export interface Props { handleClick?(id: string): void; } -Component( - { - hide: false, - defaultCollapse: null, - title: '', - } as Props, - { - handleToggle() { - const { collapse } = this.data; - this.setData({ - collapse: !collapse, - }); - }, - }, - { - collapse: true, - internalHide: false, - containerTitle: '', - }, - null, - { - /// #if ALIPAY - onInit() { - const [defaultCollapse, hide, title] = getValueFromProps(this, [ - 'defaultCollapse', - 'hide', - 'title', - ]); - this.setData({ - collapse: defaultCollapse ?? true, - internalHide: hide, - containerTitle: title, - }); - }, - /// #endif - /// #if WECHAT - attached() { - const [defaultCollapse, hide, title] = getValueFromProps(this, [ - 'defaultCollapse', - 'hide', - 'title', - ]); - this.setData({ - collapse: defaultCollapse ?? true, - internalHide: hide, - containerTitle: title, - }); - }, +const CollapseContainer = (props: Props) => { + const [collapse, setCollapse] = useState(props.defaultCollapse ?? true); - /// #endif - } -); + useEvent('handleToggle', () => { + setCollapse((v) => !v); + }); + + return { + collapse, + internalHide: props.hide, + containerTitle: props.title, + }; +}; + +mountComponent(CollapseContainer, { + hide: false, + defaultCollapse: null, + title: '', +}); diff --git a/demo/pages/NoticeBar/index.axml.tsx b/demo/pages/NoticeBar/index.axml.tsx index 9682514da..f827b099a 100644 --- a/demo/pages/NoticeBar/index.axml.tsx +++ b/demo/pages/NoticeBar/index.axml.tsx @@ -48,18 +48,10 @@ export default ({ typeList }: InternalData) => ( - {/* #if ALIPAY */} 不展示图标 - + - {/* #endif */} - {/* #if WECHAT */} - - 不展示图标 - - - {/* #endif */} ((resolve, reject) => { + instance + .createSelectorQuery() + .select(selector) + .boundingClientRect() + .exec((ret) => { + if (ret && ret[0]) { + resolve(ret[0]); + } else { + reject(); + } + }); + }); +} + +const Calendar = (props: ICalendarProps) => { + const localeText = Object.assign({}, defaultLocaleText, props.localeText); + + const markItems = [...localeText.weekdayNames]; + const weekStartsOn = props.weekStartsOn; + if (weekStartsOn === 'Sunday') { + const item = markItems.pop(); + if (item) markItems.unshift(item); + } + + const [value, setValue] = useMergedState(props.defaultValue, { + value: props.value, + }); + + const [scrollIntoViewId, setScrollIntoViewId] = useState(''); + + useEvent('scrollIntoView', (value) => { + updateScrollIntoViewId(getScrollIntoViewId(value)); + }); + + triggerRefEvent(); + + // scroll 触发滚动之后需要重置 scrollIntoViewId + function updateScrollIntoViewId(id) { + setScrollIntoViewId(id); + + const timer = setTimeout(() => { + setScrollIntoViewId(''); + clearTimeout(timer); + }); + } + + const selectionModeFromValue = getSelectionModeFromValue(value); + const selectionMode = + props.selectionMode ?? selectionModeFromValue ?? 'range'; + + const { triggerEvent } = useComponentEvent(props); + function updateValue(newValue: CalendarValue) { + const isControl = hasValue(props.value); + triggerEvent('change', newValue); + if (!isControl) { + setValue(newValue); + } + } + + useEvent('clickCell', (e) => { + const time = e.currentTarget.dataset.time; + const clickDate = dayjs(time.time); + if (time.disabled) { + return; + } + if (selectionMode === 'range') { + if (Array.isArray(value)) { + if (value.length === 1) { + const current = value[0]; + if (dayjs(clickDate.toDate().getTime()).isBefore(dayjs(current))) { + updateValue([clickDate.toDate().getTime()]); } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([value[0], clickDate.toDate().getTime()]); } } else { - this.updateValue([clickDate.toDate().getTime()]); + updateValue([clickDate.toDate().getTime()]); } - } else if (selectionMode === 'single') { - this.updateValue(clickDate.toDate().getTime()); - } - }, - setCurrentMonth(e) { - this.setData({ headerState: e.month }); - }, - measurement() { - const { elementSize } = this.data; - // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 - // 此时需要重新计算 - if (!elementSize || elementSize.cellHight === 0) { - this.measurementFn(); + } else { + updateValue([clickDate.toDate().getTime()]); } - }, - measurementFn() { - Promise.all([ - this.getBoundingClientRect('.ant-calendar-body-container'), - this.getBoundingClientRect('.ant-calendar-cells'), - this.getBoundingClientRect('.ant-calendar-title-container'), - ]) - .then(([bodyContainer, cellContainer, Title]) => { - // 滚动的时候 top 和 bottom 等尺寸会变 - // 所以只能依赖 height 来计算 - const paddingHeight = - bodyContainer.height - cellContainer.height - Title.height; - const monthTitleHeight = Title.height + paddingHeight; - const cellHight = - cellContainer.height / (this.data.monthList[0].cells.length / 7); - this.setData({ - elementSize: { - monthTitleHeight, - cellHight, - paddingHeight, - }, - }); - }) - .catch(() => { - this.setData({ elementSize: null }); - }); - }, - - // scroll 触发滚动之后需要重置 scrollIntoViewId - updateScrollIntoViewId(id) { - this.setData({ scrollIntoViewId: id }); - const timer = setTimeout(() => { - this.setData({ scrollIntoViewId: '' }); - clearTimeout(timer); - }); - }, + } else if (selectionMode === 'single') { + updateValue(clickDate.toDate().getTime()); + } + }); - updateValue(newValue: CalendarValue) { - triggerEvent(this, 'change', newValue); - if (!this.isControlled()) { - this.update(newValue); - } - }, - updateData() { - const [monthRange, plocaleText, pweekStartsOn, onFormatter] = - getValueFromProps(this, [ - 'monthRange', - 'localeText', - 'weekStartsOn', - 'onFormatter', - ]); - const localeText = Object.assign({}, defaultLocaleText, plocaleText); - const markItems = [...localeText.weekdayNames]; - const weekStartsOn = pweekStartsOn; - if (weekStartsOn === 'Sunday') { - const item = markItems.pop(); - if (item) markItems.unshift(item); - } - const value = this.getValue(); - const monthList = getMonthListFromRange( - dayjs(monthRange?.[0]), - dayjs(monthRange?.[1]) - ).map((p) => { - let cells = renderCells(p, weekStartsOn, value, localeText); - if (onFormatter && typeof onFormatter === 'function') { - cells = cells.map((o): CellState => { - const { + const monthList = getMonthListFromRange( + dayjs(props.monthRange[0]), + dayjs(props.monthRange[1]) + ).map((p) => { + let cells = renderCells(p, weekStartsOn, value, localeText); + if (props.onFormatter && typeof props.onFormatter === 'function') { + cells = cells.map((o): CellState => { + const { + time, + top, + bottom, + disabled, + isSelectedBegin, + isSelectedEnd, + isSelected, + } = o; + const newState = + props.onFormatter( + { time, - top, - bottom, + top: top ? { ...top } : undefined, + bottom: bottom ? { ...bottom } : undefined, disabled, isSelectedBegin, isSelectedEnd, isSelected, - } = o; - const newState = - onFormatter( - { - time, - top: top ? { ...top } : undefined, - bottom: bottom ? { ...bottom } : undefined, - disabled, - isSelectedBegin, - isSelectedEnd, - isSelected, - }, - value - ) ?? {}; - const result = { ...o }; - if (typeof newState === 'object') { - // 只允许修改三个字段 - ['top', 'bottom', 'disabled'].forEach((key) => { - if (key in newState) { - result[key] = newState[key]; - } - }); + }, + value + ) ?? {}; + const result = { ...o }; + if (typeof newState === 'object') { + // 只允许修改三个字段 + ['top', 'bottom', 'disabled'].forEach((key) => { + if (key in newState) { + result[key] = newState[key]; } - return result; }); } - return { - title: p.format(localeText.title), - cells, - }; + return result; }); + } + return { + title: p.format(localeText.title), + cells, + }; + }); - this.setData({ markItems, monthList }); - }, - }, - { - elementSize: null, - markItems: [], - monthList: [], - headerState: 0, - scrollIntoViewId: '', - }, - [mixinValue()], - { - didMount() { - this.updateData(); - this.measurementFn(); - // 初始化默认值时,滚动到选中位置 - const [value, defaultValue] = getValueFromProps(this, [ - 'value', - 'defaultValue', - ]); - if (this.isControlled()) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - } else { - defaultValue && - this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue)); - } - }, - didUpdate(prevProps, prevData) { - if (!this.isEqualValue(prevData)) { - // 滚动到已选的位置 - const changedScrollIntoView = getValueFromProps( - this, - 'changedScrollIntoView' - ); - changedScrollIntoView && - this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue())); - } - if (!equal(prevProps, this.props) || !this.isEqualValue(prevData)) { - this.updateData(); - } - }, - /// #if WECHAT - attached() { - this.updateData(); - this.measurementFn(); - // 初始化默认值时,滚动到选中位置 - const [value, defaultValue] = getValueFromProps(this, [ - 'value', - 'defaultValue', - ]); - if (this.isControlled()) { - this.updateScrollIntoViewId(getScrollIntoViewId(value)); - } else { - defaultValue && - this.updateScrollIntoViewId(getScrollIntoViewId(defaultValue)); - } - this.triggerEvent('ref', this); - }, + const [headerState, setHeaderState] = useState(0); - observers: { - '**': function (data) { - const prevData = this._prevData || this.data; - this._prevData = { ...data }; - if (!equal(prevData, data)) { - this.updateData(); - } - }, - 'mixin.value': function () { - // 滚动到已选的位置 - const changedScrollIntoView = getValueFromProps( - this, - 'changedScrollIntoView' - ); - changedScrollIntoView && - this.updateScrollIntoViewId(getScrollIntoViewId(this.getValue())); - }, - }, - /// #endif + useEvent('setCurrentMonth', (e) => { + setHeaderState(e.month); + }); + + const [elementSize, setElementSize] = useState<{ + monthTitleHeight: number; + cellHight: number; + paddingHeight: number; + }>(null); + + const componentInstance = useComponent(); + + function measurement() { + Promise.all([ + getBoundingClientRect(componentInstance, '.ant-calendar-body-container'), + getBoundingClientRect(componentInstance, '.ant-calendar-cells'), + getBoundingClientRect(componentInstance, '.ant-calendar-title-container'), + ]) + .then(([bodyContainer, cellContainer, Title]) => { + // 滚动的时候 top 和 bottom 等尺寸会变 + // 所以只能依赖 height 来计算 + const paddingHeight = + bodyContainer.height - cellContainer.height - Title.height; + const monthTitleHeight = Title.height + paddingHeight; + const cellHight = + cellContainer.height / (monthList[0].cells.length / 7); + setElementSize({ + monthTitleHeight, + cellHight, + paddingHeight, + }); + }) + .catch(() => { + setElementSize(null); + }); } -); + + useEffect(() => { + // 滚动到已选的位置 + props.changedScrollIntoView && + updateScrollIntoViewId(getScrollIntoViewId(value)); + }, [value]); + + useReady(() => { + measurement(); + // 初始化默认值时,滚动到选中位置 + const isControl = hasValue(props.value); + if (isControl) { + updateScrollIntoViewId(getScrollIntoViewId(props.value)); + } else { + props.defaultValue && + updateScrollIntoViewId(getScrollIntoViewId(props.defaultValue)); + } + }, []); + + useEvent('measurement', () => { + // 组件如果内嵌在 slot 里, 一定会被渲染出来, 但是此时 cellHight 为 0 + // 此时需要重新计算 + if (!elementSize || elementSize.cellHight === 0) { + measurement(); + } + }); + + return { + elementSize, + markItems, + monthList, + headerState, + scrollIntoViewId, + }; +}; + +mountComponent(Calendar, { + defaultValue: null, + value: null, + selectionMode: 'range', + monthRange: defaultMonthRange(), + weekStartsOn: 'Sunday', + localeText: defaultLocaleText, + onFormatter: null, + changedScrollIntoView: null, +}); diff --git a/src/Calendar/props.ts b/src/Calendar/props.ts index e06386972..54891430c 100644 --- a/src/Calendar/props.ts +++ b/src/Calendar/props.ts @@ -1,5 +1,4 @@ import { IBaseProps } from '../_util/base'; -import { defaultMonthRange } from './utils'; export interface CalendarDate { year: number; @@ -143,14 +142,3 @@ export interface ICalendarProps extends IBaseProps { currentValue: CalendarValue ) => Pick; } - -export const CalendarDefaultProps = { - defaultValue: null, - value: null, - selectionMode: 'range', - monthRange: defaultMonthRange(), - weekStartsOn: 'Sunday', - localeText: defaultLocaleText, - onFormatter: null, - changedScrollIntoView: null, -}; diff --git a/src/Checkbox/CheckboxGroup/index.json b/src/Checkbox/CheckboxGroup/index.json index a29721990..c7460b750 100644 --- a/src/Checkbox/CheckboxGroup/index.json +++ b/src/Checkbox/CheckboxGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/src/Checkbox/index.json b/src/Checkbox/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Checkbox/index.json +++ b/src/Checkbox/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Checklist/ChecklistItem/index.json b/src/Checklist/ChecklistItem/index.json index ffa3220f6..3a037cbf8 100644 --- a/src/Checklist/ChecklistItem/index.json +++ b/src/Checklist/ChecklistItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index" } diff --git a/src/Checklist/index.json b/src/Checklist/index.json index 6fdd09a19..402e290e9 100644 --- a/src/Checklist/index.json +++ b/src/Checklist/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-checklist-item": "./ChecklistItem/index", "ant-icon": "../Icon/index" diff --git a/src/Collapse/index.json b/src/Collapse/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Collapse/index.json +++ b/src/Collapse/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Container/index.json b/src/Container/index.json index dc5676ea5..467ce2945 100644 --- a/src/Container/index.json +++ b/src/Container/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/DatePicker/RangePicker/hooks.ts b/src/DatePicker/RangePicker/hooks.ts new file mode 100644 index 000000000..c9b08d127 --- /dev/null +++ b/src/DatePicker/RangePicker/hooks.ts @@ -0,0 +1,76 @@ +import { useEvent as useStableCallback } from '../../_util/hooks/useEvent'; +import dayjs from 'dayjs'; +import { useCallback } from 'functional-mini/component'; + +export const useFormatValue = (props) => { + function defaultFormat(date, valueStrs) { + const { format, splitCharacter } = props; + if (format && valueStrs && valueStrs[0] && valueStrs[1]) { + return valueStrs.join(`${splitCharacter}`); + } + return ''; + } + + const onFormat = useStableCallback((realValue) => { + const { onFormat, format } = props; + const formatValueByProps = + onFormat && + onFormat( + realValue, + realValue + ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) + : null + ); + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; + } + return defaultFormat( + realValue, + realValue + ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) + : null + ); + }); + return onFormat; +}; + +export function useMinAndMax() { + const getMin = useStableCallback((min) => { + return min ? dayjs(min as any) : dayjs().subtract(10, 'year'); + }); + + const getMax = useStableCallback((max) => { + return max ? dayjs(max as any) : dayjs().add(10, 'year'); + }); + + return { + getMin, + getMax, + }; +} + +function defaultFormatLabel(type, value) { + const suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return `${value}${suffixMap[type]}`; +} +export const useFormatLabel = (onFormatLabel) => { + return useCallback( + (type, value) => { + if (typeof onFormatLabel === 'function') { + const formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { + return String(formatValueByProps); + } + } + return defaultFormatLabel(type, value); + }, + [onFormatLabel] + ); +}; diff --git a/src/DatePicker/RangePicker/index.axml.tsx b/src/DatePicker/RangePicker/index.axml.tsx index 059e3053a..05be5418e 100644 --- a/src/DatePicker/RangePicker/index.axml.tsx +++ b/src/DatePicker/RangePicker/index.axml.tsx @@ -32,7 +32,7 @@ export default ( precision, }: TSXMLProps, { - visible, + state, formattedValueText, columns, currentValue, @@ -81,7 +81,7 @@ export default ( ? 'ant-range-picker-confirm-disabled' : '' } ${popClassName || ''}`} - visible={visible} + visible={state.visible} style={style} animationType={animationType} options={columns} diff --git a/src/DatePicker/RangePicker/index.json b/src/DatePicker/RangePicker/index.json index c124b8511..b2e493fb4 100644 --- a/src/DatePicker/RangePicker/index.json +++ b/src/DatePicker/RangePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index", "ant-picker": "../../Picker/index" diff --git a/src/DatePicker/RangePicker/index.ts b/src/DatePicker/RangePicker/index.ts index dd1a085ed..a9e9dc70a 100644 --- a/src/DatePicker/RangePicker/index.ts +++ b/src/DatePicker/RangePicker/index.ts @@ -1,400 +1,183 @@ -import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { DateRangePickerDefaultProps } from './props'; +import { useState, useEvent, useEffect, useMemo } from 'functional-mini/component'; +import { DateRangePickerFunctionalProps, IDateRangePickerProps } from './props'; import dayjs from 'dayjs'; -import equal from 'fast-deep-equal'; import { getRangeData, getDateByValue, getValueByDate, getValidValue, } from '../util'; -import computed from '../../mixins/computed'; -import mixinValue from '../../mixins/value'; - -Component( - DateRangePickerDefaultProps, - { - // visible受控判断 - isVisibleControlled() { - /// #if ALIPAY - return 'visible' in getValueFromProps(this); - /// #endif - /// #if WECHAT - return getValueFromProps(this, 'visible') !== null; - /// #endif - }, - computed() { - const { currentStartDate, currentEndDate, pickerType } = this.data; - const format = getValueFromProps(this, 'format'); +import { useMixState } from '../../_util/hooks/useMixState'; +import { useFormatValue, useMinAndMax, useFormatLabel } from './hooks'; +import { useDateState } from './useDateState'; +import { mountComponent } from '../../_util/component'; +import { PickerValue } from '../props'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; - if (pickerType) +const RangePicker = (props: IDateRangePickerProps) => { + const [realValue, { isControlled, update }] = useMixState( + props.defaultValue, + { + value: props.value, + postState(value) { return { - currentStartValueStr: currentStartDate - ? dayjs(currentStartDate).format(format) - : '', - currentEndValueStr: currentEndDate - ? dayjs(currentEndDate).format(format) - : '', + valid: true, + value: + value && value[0] && value[1] + ? ([ + dayjs(value[0]).toDate(), + dayjs(value[1]).toDate(), + ] as PickerValue[]) + : undefined, }; - }, - getMin(min) { - return min ? dayjs(min as any) : dayjs().subtract(10, 'year'); - }, - - getMax(max) { - return max ? dayjs(max as any) : dayjs().add(10, 'year'); - }, - // didUpdate、弹窗打开、切换pickerType触发 - setCurrentValue(currentProps) { - const { pickerVisible } = this; // 隐藏状态下从CValue触发,展开状态使用当前数据 - const { precision } = currentProps; - const { pickerType, columns } = this.data; - const realValue = this.getValue(); - let { currentStartDate, currentEndDate } = this.data; - const currentStartDateByCValue = realValue?.[0] || null; - const currentEndDateByCValue = realValue?.[1] || null; + }, + } + ); + const { dateState, init, changeType, updateValue } = useDateState(props); + const { triggerEvent, triggerEventValues, triggerEventOnly } = + useComponentEvent(props); + const [{ columns, currentValue }, doUpdateColumns] = useState({ + currentValue: [], + columns: [], + }); + const onFormat = useFormatValue(props); + const { currentStartValueStr, currentEndValueStr } = useMemo(() => { + return { + currentStartValueStr: dateState.start + ? dayjs(dateState.start).format(props.format) + : '', + currentEndValueStr: dateState.end + ? dayjs(dateState.end).format(props.format) + : '', + }; + }, [props.format, dateState.start, dateState.end]); - // 展开状态,说明在切换pickerType - if (pickerVisible) { - if (pickerType === 'start') { - if (!currentStartDate) { - currentStartDate = currentEndDate; - } - } else { - // pickerType=end start已存在 - // 结束时间默认选中开始 - if (!currentEndDate) { - currentEndDate = currentStartDate; - } - } - } else { - // 否则是在从cValue初始化 - currentStartDate = currentStartDateByCValue; - currentEndDate = currentEndDateByCValue; - // 开始默认取优先取当前时间,不在时间范围内取开始时间 - if (!currentStartDate) { - const min = this.getMin(currentProps.min).toDate(); - const { max } = currentProps; - currentStartDate = new Date(); - if ( - (min && dayjs(currentStartDate).isBefore(min, precision)) || - (max && dayjs(currentStartDate).isAfter(max, precision)) || - (currentEndDateByCValue && - currentStartDate > currentEndDateByCValue) - ) { - currentStartDate = min; - } - } - } - const currentValue = getValueByDate( - pickerType === 'start' ? currentStartDate : currentEndDate, - precision - ); - const newColumns = this.generateData(currentValue, currentProps); - if (!equal(newColumns, columns)) { - this.setData({ columns: newColumns }, () => { - this.setData({ - currentStartDate, - currentEndDate, - currentValue, - formattedValueText: this.onFormat(), - }); - }); - } else { - this.setData({ - currentStartDate, - currentEndDate, - currentValue, - formattedValueText: this.onFormat(), - }); - } - }, - /** - * 生成选项数据,didmound、picker change、打开弹窗、切换picker type触发 - */ - generateData(currentValue, currentProps) { - const { precision, min: propsMin, max: propsMax } = currentProps; - const min = this.getMin(propsMin); - const max = this.getMax(propsMax); - if (max < min) { - return []; - } - let currentPickerDay = dayjs(); - if (currentValue.length > 0) { - currentPickerDay = dayjs(getDateByValue(currentValue)); - } - if (currentPickerDay < min || currentPickerDay > max) { - currentPickerDay = min; - } + const onFormatLabel = useFormatLabel(props.onFormatLabel); - const newColumns = getRangeData( - precision, - min, - max, - currentPickerDay, - this.onFormatLabel.bind(this) - ); - return newColumns; - }, + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); - onChange(selectedIdx) { - let [selectedIndex] = resolveEventValues(getValidValue(selectedIdx)); - const [format, precision, pmax, pmin] = getValueFromProps(this, [ - 'format', - 'precision', - 'max', - 'min', - ]); - let date = getDateByValue(selectedIndex); - const min = this.getMin(pmin); - const max = this.getMax(pmax); - if (dayjs(date).isBefore(min)) { - date = min.toDate(); - selectedIndex = getValueByDate(date, precision); - } - if (dayjs(date).isAfter(max)) { - date = max.toDate(); - selectedIndex = getValueByDate(date, precision); - } - const { pickerType, columns, currentEndDate, currentStartDate } = - this.data; - const newData: any = { - currentValue: selectedIndex, - formattedValueText: this.onFormat(), - }; - if (pickerType === 'start') { - newData.currentStartDate = date; - if (currentEndDate && dayjs(date).isAfter(currentEndDate)) { - newData.currentEndDate = null; - } - } else { - newData.currentEndDate = date; - if (currentStartDate && dayjs(date).isBefore(currentStartDate)) { - newData.currentStartDate = null; - } - } - const newColumns = this.generateData( - selectedIndex, - getValueFromProps(this) - ); - if (!equal(newColumns, columns)) { - this.setData( - { - columns: newColumns, - }, - () => { - this.setData(newData); - triggerEventValues(this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); - } + useEffect(() => { + setTimeout(() => { + if (visible) { + const state = init(realValue); + const currentValue = getValueByDate( + state.pickerType === 'start' ? state.start : state.end, + props.precision ); - } else { - this.setData(newData); - triggerEventValues(this, 'pickerChange', [ - pickerType, - date, - dayjs(date).format(format), - ]); + updateColumns(currentValue, props); } - }, + }) + }, [visible]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, + function updateColumns(currentValue, currentProps) { + const { precision, min: propsMin, max: propsMax } = currentProps; + const min = getMin(propsMin); + const max = getMax(propsMax); + if (max < min) { + return []; + } + let currentPickerDay = dayjs(); + if (currentValue.length > 0) { + currentPickerDay = dayjs(getDateByValue(currentValue)); + } + if (currentPickerDay < min || currentPickerDay > max) { + currentPickerDay = min; + } - onOk() { - const format = getValueFromProps(this, 'format'); - const { currentStartDate, currentEndDate } = this.data; - const realValue = [currentStartDate, currentEndDate] as any; - if (!this.isControlled()) { - this.update(realValue); - } - triggerEventValues(this, 'ok', [ - realValue, - realValue.map((v) => dayjs(v).format(format)), - ]); - }, - onFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - const formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return String(formatValueByProps); - } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel(type, value) { - const suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return `${value}${suffixMap[type]}`; - }, - defaultFormat(date, valueStrs) { - const [format, splitCharacter] = getValueFromProps(this, [ - 'format', - 'splitCharacter', - ]); - if (format && valueStrs && valueStrs[0] && valueStrs[1]) { - return valueStrs.join(`${splitCharacter}`); - } - return ''; - }, - onFormat() { - const [onFormat, format] = getValueFromProps(this, [ - 'onFormat', - 'format', - ]); - const realValue = this.getValue(); - const formatValueByProps = - onFormat && - onFormat( - realValue, - realValue - ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) - : null - ); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat( - realValue, - realValue - ? realValue.map((v) => (v ? dayjs(v).format(format) : null)) - : null - ); - }, - /** - * 显示/隐藏切换 - * @param visible - */ - onVisibleChange(visible) { - if (!this.isVisibleControlled() && visible) { - this.setData({ pickerType: 'start' }); - this.setCurrentValue(getValueFromProps(this)); - this.pickerVisible = visible; - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - onChangeCurrentPickerType(e) { - const { type } = e.currentTarget.dataset; - const { pickerType } = this.data; - if (type !== pickerType) { - this.setData({ - pickerType: type, - }); - this.setCurrentValue(getValueFromProps(this)); - } - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、切换开始结束、picker变化时更新 - columns: [], // 当前可选项,didmound、弹窗打开、切换开始结束、picker变化时更新 - pickerType: 'start' as 'start' | 'end', - currentStartDate: null, // 展开时开始时间,date格式,有value,则取value[0],否则取当天,需要判断当天是否在可选范围内 - currentEndDate: null, // 展开时开始时间,date格式,有value,则取value[1],否则取开始时间 - forceUpdate: 0, // 强制更新picker组件,已知需处理的情况:value超限,但是需要更新format,由于picker的参数均未变化,无法触发picker的渲染 - formattedValueText: '', - }, - [ - mixinValue({ - transformValue(value) { - return { - value: - value && value[0] && value[1] - ? [dayjs(value[0]).toDate(), dayjs(value[1]).toDate()] - : undefined, - needUpdate: true, - }; - }, - }), - computed(), - ], - { - pickerVisible: false, - /// #if ALIPAY - didMount() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, + const newColumns = getRangeData( + precision, + min, + max, + currentPickerDay, + onFormatLabel + ); + doUpdateColumns({ columns: newColumns, currentValue }); + } - didUpdate(prevProps, prevData) { - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.setData({ visible }); - this.setCurrentValue(currentProps); - this.pickerVisible = visible; - } + const formattedValueText = onFormat(realValue); - if (!this.isEqualValue(prevData)) { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - if (this.pickerVisible) { - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - this.setCurrentValue(currentProps); - } - } - }, - /// #endif - /// #if WECHAT - created() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, - observers: { - 'visible': function (data) { - const prevVisible = this._prevVisible; - this._prevVisible = data; - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && prevVisible !== visible) { - this.setData({ visible }); - this.setCurrentValue(currentProps); - this.pickerVisible = visible; - } - }, - 'mixin.value': function () { - const currentProps = getValueFromProps(this); - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - if (this.pickerVisible) { - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - this.setCurrentValue(currentProps); - } - }, - }, - /// #endif - } -); + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible); + }); + + useEvent('onChangeCurrentPickerType', (e) => { + const { type } = e.currentTarget.dataset; + const state = changeType(type) as any; + const currentValue = getValueByDate( + state.pickerType === 'start' ? state.start : state.end, + props.precision + ); + updateColumns(currentValue, props); + }); + const { getMin, getMax } = useMinAndMax(); + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + useEvent('onChange', (event) => { + let [selectedIndex] = resolveEventValues(event); + selectedIndex = getValidValue(selectedIndex); + const { format, precision } = props; + let date = getDateByValue(selectedIndex); + const min = getMin(props.min); + const max = getMax(props.max); + if (dayjs(date).isBefore(min)) { + date = min.toDate(); + selectedIndex = getValueByDate(date, precision); + } + if (dayjs(date).isAfter(max)) { + date = max.toDate(); + selectedIndex = getValueByDate(date, precision); + } + updateColumns(selectedIndex, props); + updateValue(date); + triggerEventValues('pickerChange', [ + dateState.pickerType, + date, + dayjs(date).format(format), + ]); + }); + + useEvent('onOk', () => { + const { format } = props; + const { start, end } = dateState; + const realValue = [start, end] as any; + if (!isControlled) { + update(realValue); + } + triggerEventValues('ok', [ + realValue, + realValue.map((v) => dayjs(v).format(format)), + ]); + }); + + return { + state: { + visible + }, + formattedValueText, + realValue, + columns, + currentValue, + currentStartDate: dateState.start, + currentEndDate: dateState.end, + currentEndValueStr, + currentStartValueStr, + pickerType: dateState.pickerType, + }; +}; + +mountComponent(RangePicker, DateRangePickerFunctionalProps); diff --git a/src/DatePicker/RangePicker/props.ts b/src/DatePicker/RangePicker/props.ts index c4eb953b9..379713fac 100644 --- a/src/DatePicker/RangePicker/props.ts +++ b/src/DatePicker/RangePicker/props.ts @@ -155,6 +155,18 @@ export interface IDateRangePickerProps extends IBaseProps { } export const DateRangePickerDefaultProps: Partial = { + okText: '确定', + cancelText: '取消', + maskClosable: true, + placeholder: '请选择', + format: 'YYYY/MM/DD', + splitCharacter: '-', + startPlaceholder: '未选择', + endPlaceholder: '未选择', + precision: 'day', +}; + +export const DateRangePickerFunctionalProps: Partial = { visible: null, defaultVisible: null, animationType: 'transform', @@ -176,5 +188,4 @@ export const DateRangePickerDefaultProps: Partial = { popStyle: '', disabled: false, onFormatLabel: null, - onFormat: null, }; diff --git a/src/DatePicker/RangePicker/useDateState.ts b/src/DatePicker/RangePicker/useDateState.ts new file mode 100644 index 000000000..2105420bd --- /dev/null +++ b/src/DatePicker/RangePicker/useDateState.ts @@ -0,0 +1,94 @@ +import dayjs from 'dayjs'; +import { useState } from 'functional-mini/component'; +import { useMinAndMax } from './hooks'; + +export function useDateState(props) { + const { getMin } = useMinAndMax(); + + const [dateState, setDateState] = useState({ + pickerType: 'start', + start: null, + end: null, + }); + + const init = (realValue) => { + let currentStartDate = realValue?.[0]; + const currentEndDate = realValue?.[1]; + if (!currentStartDate) { + const min = getMin(props.min).toDate(); + const { max } = props; + currentStartDate = new Date(); + if ( + (min && dayjs(currentStartDate).isBefore(min, props.precision)) || + (max && dayjs(currentStartDate).isAfter(max, props.precision)) || + (currentEndDate && currentStartDate > currentEndDate) + ) { + currentStartDate = min; + } + } + const newState = { + pickerType: 'start', + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + const changeType = (newType) => { + let currentStartDate = dateState.start; + let currentEndDate = dateState.end; + + if (newType === 'start') { + if (!currentStartDate) { + currentStartDate = currentEndDate; + } + } else { + // pickerType=end start已存在 + // 结束时间默认选中开始 + if (!currentEndDate) { + currentEndDate = currentStartDate; + } + } + + const newState = { + pickerType: newType, + start: currentStartDate, + end: currentEndDate, + }; + setDateState(newState); + return newState; + }; + + function updateValue(newValue) { + setDateState((old) => { + if (old.pickerType === 'start') { + let newEnd = old.end; + if (old.end && dayjs(newValue).isAfter(old.end)) { + newEnd = null; + } + + return { + ...old, + start: newValue, + end: newEnd, + }; + } + let newStart = old.start; + if (old.start && dayjs(newValue).isBefore(old.start)) { + newStart = null; + } + return { + ...old, + end: newValue, + start: newStart, + }; + }); + } + + return { + updateValue, + dateState, + init, + changeType, + }; +} diff --git a/src/DatePicker/index.axml.tsx b/src/DatePicker/index.axml.tsx index f6e8701e6..2ac838947 100644 --- a/src/DatePicker/index.axml.tsx +++ b/src/DatePicker/index.axml.tsx @@ -19,12 +19,12 @@ export default ( maskClosable, popClassName, }: TSXMLProps, - { visible, columns, currentValue, formattedValueText }: InternalData + { state, columns, currentValue, formattedValueText }: InternalData ) => ( { - this.setData({ - currentValue, - formattedValueText: this.onFormat(), - }); - } - ); - } - }, +const DatePicker = (props: IDatePickerProps) => { + const [realValue, { isControlled, update }] = useMixState( + props.defaultValue, + { + value: props.value, + postState(value) { + if (value) { + return { + valid: true, + value: dayjs(value).toDate(), + }; + } + return { + valid: true, + value: undefined, + }; + }, + } + ); - // 生成选项数据,didmound、picker change、打开弹窗触发 - generateData(currentValue, currentProps) { - const { precision, min: propsMin, max: propsMax } = currentProps; - const min = this.getMin(propsMin); - const max = this.getMax(propsMax); - if (max < min) { - return []; - } - let currentPickerDay = dayjs(); - if (currentValue.length > 0) { - currentPickerDay = dayjs(getDateByValue(currentValue)); - } - if (currentPickerDay < min || currentPickerDay > max) { - currentPickerDay = min; - } - const newColumns = getRangeData( - precision, - min, - max, - currentPickerDay, - this.onFormatLabel.bind(this) - ); - return newColumns; - }, - onFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - const formatValueByProps = onFormatLabel && onFormatLabel(type, value); - if (formatValueByProps !== undefined && formatValueByProps !== null) { + function defaultFormat(value, valueStr) { + if (props.format && valueStr) { + return valueStr; + } + return ''; + } + const { triggerEvent, triggerEventValues, triggerEventOnly } = + useComponentEvent(props); + + function onFormatLabel(type, value) { + const { onFormatLabel } = props; + if (typeof onFormatLabel === 'function') { + const formatValueByProps = onFormatLabel(type, value); + if (typeof formatValueByProps !== 'undefined') { return String(formatValueByProps); } - return this.defaultFormatLabel(type, value); - }, - defaultFormatLabel(type, value) { - const suffixMap = { - year: '年', - month: '月', - day: '日', - hour: '时', - minute: '分', - second: '秒', - }; - return `${value}${suffixMap[type]}`; - }, - onChange(selectedIdx) { - const [pmin, pmax, format, precision] = getValueFromProps(this, [ - 'min', - 'max', - 'format', - 'precision', - ]); - let [selectedIndex] = resolveEventValues(getValidValue(selectedIdx)); - let date = getDateByValue(selectedIndex); - const min = this.getMin(pmin); - const max = this.getMax(pmax); - if (dayjs(date).isBefore(min)) { - date = min.toDate(); - selectedIndex = getValueByDate(date, precision); - } - if (dayjs(date).isAfter(max)) { - date = max.toDate(); - selectedIndex = getValueByDate(date, precision); - } - const newColumns = this.generateData( - selectedIndex, - getValueFromProps(this) - ); + } + return defaultFormatLabel(type, value); + } + function defaultFormatLabel(type, value) { + const suffixMap = { + year: '年', + month: '月', + day: '日', + hour: '时', + minute: '分', + second: '秒', + }; + return `${value}${suffixMap[type]}`; + } - if (!equal(newColumns, this.data.columns)) { - this.setData( - { - columns: newColumns, - }, - () => { - this.setData({ currentValue: selectedIndex }); - const date = getDateByValue(selectedIndex); - triggerEventValues(this, 'pickerChange', [ - date, - dayjs(date).format(format), - ]); - } - ); - } else { - this.setData({ currentValue: selectedIndex }); - const date = getDateByValue(selectedIndex); + const [{ value, columns }, setState] = useState({ + value: [], + columns: [], + }); - triggerEventValues(this, 'pickerChange', [ - date, - dayjs(date).format(format), - ]); + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); + + useEffect(() => { + setTimeout(() => { + if (visible) { + updateDateColumnsAndValue(true); + } else { + updateDateColumnsAndValue(false); } - }, + }) + }, [visible]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, + function generateData(currentValue, currentProps) { + const { precision, min: propsMin, max: propsMax } = currentProps; + const min = getMin(propsMin); + const max = getMax(propsMax); + if (max < min) { + return []; + } + let currentPickerDay = dayjs(); + if (currentValue.length > 0) { + currentPickerDay = dayjs(getDateByValue(currentValue)); + } + if (currentPickerDay < min || currentPickerDay > max) { + currentPickerDay = min; + } + const newColumns = getRangeData( + precision, + min, + max, + currentPickerDay, + onFormatLabel + ); + return newColumns; + } - onOk() { - const { currentValue } = this.data; - const format = getValueFromProps(this, 'format'); - const date = getDateByValue(currentValue); - if (!this.isControlled()) { - this.update(date); - } - triggerEventValues(this, 'ok', [date, dayjs(date).format(format)]); - }, - defaultFormat(value, valueStr) { - const format = getValueFromProps(this, 'format'); - if (format && valueStr) { - return valueStr; - } - return ''; - }, - onFormat() { - const [format, onFormat] = getValueFromProps(this, [ - 'format', - 'onFormat', - ]); - const realValue = this.getValue(); - const formatValueByProps = - onFormat && - onFormat(realValue, realValue ? dayjs(realValue).format(format) : null); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; + function getCurrentValueWithCValue(currentProps) { + const { min, max, precision } = currentProps; + if (realValue) { + return getValueByDate(realValue, precision); + } else { + const now = new Date(); + if ( + !(min && dayjs(now).isBefore(dayjs(min as any), precision)) && + !(max && dayjs(now).isAfter(dayjs(max as any), precision)) + ) { + return getValueByDate(now, precision); + } else { + return getValueByDate(getMin(min).toDate(), precision); } - return this.defaultFormat( + } + } + + function updateDateColumnsAndValue(visible) { + if (visible) { + const currentValue = getCurrentValueWithCValue(props); + const newColumns = generateData(currentValue, props); + setState({ + value: currentValue, + columns: newColumns, + }); + } else { + setState({ + value: [], + columns: [], + }); + } + } + + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible, {}); + }); + + useEvent('onChange', (event) => { + let [selectedIndex] = resolveEventValues(event); + selectedIndex = getValidValue(selectedIndex); + const { format, precision } = props; + let date = getDateByValue(selectedIndex); + const min = getMin(props.min); + const max = getMax(props.max); + if (dayjs(date).isBefore(min)) { + date = min.toDate(); + selectedIndex = getValueByDate(date, precision); + } + if (dayjs(date).isAfter(max)) { + date = max.toDate(); + selectedIndex = getValueByDate(date, precision); + } + const newColumns = generateData(selectedIndex, props); + + setState({ + columns: newColumns, + value: selectedIndex, + }); + + const pickDate = getDateByValue(selectedIndex); + triggerEventValues( + 'pickerChange', + [pickDate, dayjs(pickDate).format(format)], + {} + ); + }); + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + useEvent('onOk', () => { + const { format } = props; + const date = getDateByValue(value); + if (!isControlled) { + update(date); + } + triggerEventValues('ok', [date, dayjs(date).format(format)], {}); + }); + + const formattedValueText = useMemo(() => { + const { onFormat, format } = props; + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat( realValue, realValue ? dayjs(realValue).format(format) : null ); - }, - onVisibleChange(visible) { - this.pickerVisible = visible; - if (!this.isVisibleControlled() && visible) { - this.setCurrentValue(getValueFromProps(this)); - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、picker变化时更新 - formattedValueText: '', - columns: [], // 可选项,didmound、弹窗打开、picker变化时更新 - forceUpdate: 0, // 强制更新picker组件,已知需处理的情况:value超限,但是需要更新format,由于picker的参数均未变化,无法触发picker的渲染 - visible: null, - }, - [ - mixinValue({ - transformValue(value) { - return { - value: value ? dayjs(value).toDate() : undefined, - needUpdate: true, - }; - }, - }), - ], - { - pickerVisible: false, - /// #if ALIPAY - onInit() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, - didUpdate(prevProps, prevData) { - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.pickerVisible = visible; - this.setData({ visible }); - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } - } - if (!this.isEqualValue(prevData)) { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } + if (typeof formatValueByProps !== 'undefined') { + return formatValueByProps; } - }, - /// #endif - /// #if WECHAT - created() { - this.pickerVisible = false; - const [visible, defaultVisible] = getValueFromProps(this, [ - 'visible', - 'defaultVisible', - ]); - this.setData({ - visible: this.isVisibleControlled() ? visible : defaultVisible, - formattedValueText: this.onFormat(), - }); - }, - observers: { - 'mixin.value': function () { - this.setData({ - forceUpdate: this.data.forceUpdate + 1, - formattedValueText: this.onFormat(), - }); - // 展开状态才更新picker的数据,否则下次triggerVisible触发 - if (this.pickerVisible) { - this.setCurrentValue(getValueFromProps(this)); - } - }, - 'visible': function (data) { - const prevVisible = this._prevVisible; - this._prevVisible = data; - const currentProps = getValueFromProps(this); - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && prevVisible !== visible) { - this.pickerVisible = visible; - this.setData({ - visible, - }); - if (this.pickerVisible) { - this.setCurrentValue(currentProps); - } - } - }, - }, - /// #endif - } -); + } + return defaultFormat( + realValue, + realValue ? dayjs(realValue).format(format) : null + ); + }, [realValue]); + + return { + state: { + visible + }, + formattedValueText, + currentValue: visible ? value : realValue, + columns, + }; +}; + +mountComponent(DatePicker, DatePickerFunctionalProps); diff --git a/src/DatePicker/props.ts b/src/DatePicker/props.ts index ec39f925d..b8989cd59 100644 --- a/src/DatePicker/props.ts +++ b/src/DatePicker/props.ts @@ -138,6 +138,15 @@ export interface IDatePickerProps extends IBaseProps { } export const DatePickerDefaultProps: IDatePickerProps = { + okText: '确定', + cancelText: '取消', + maskClosable: true, + placeholder: '请选择', + format: 'YYYY/MM/DD', + precision: 'day', +}; + +export const DatePickerFunctionalProps: IDatePickerProps = { visible: null, defaultVisible: null, animationType: 'transform', @@ -156,5 +165,4 @@ export const DatePickerDefaultProps: IDatePickerProps = { popStyle: '', disabled: false, onFormatLabel: null, - onFormat: null, }; diff --git a/src/DatePicker/util.ts b/src/DatePicker/util.ts index 08fd43f82..3328717c1 100644 --- a/src/DatePicker/util.ts +++ b/src/DatePicker/util.ts @@ -18,7 +18,7 @@ const precisionLengthRecord = { }; function getYears(min: Dayjs, max: Dayjs, format) { - return getArray(min.year(), max.year(), format.bind(this, 'year')); + return getArray(min.year(), max.year(), format.bind(null, 'year')); } function getMonths(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { @@ -41,7 +41,7 @@ function getMonths(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { end = max.month() + 1; } - return getArray(start, end, format.bind(this, 'month')); + return getArray(start, end, format.bind(null, 'month')); } function getDates(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { @@ -53,10 +53,10 @@ function getDates(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('date', end).isAfter(max)) { end = max.date(); } - return getArray(start, end, format.bind(this, 'day')); + return getArray(start, end, format.bind(null, 'day')); } -function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 23; if (currentPicker.clone().set('hour', start).isBefore(min)) { @@ -65,9 +65,9 @@ function getHours(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('hour', end).isAfter(max)) { end = max.hour(); } - return getArray(start, end, format.bind(this, 'hour')); + return getArray(start, end, format.bind(null, 'hour')); } -function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 59; if (currentPicker.clone().set('minute', start).isBefore(min)) { @@ -76,9 +76,9 @@ function getMinutes(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('minute', end).isAfter(max)) { end = max.minute(); } - return getArray(start, end, format.bind(this, 'minute')); + return getArray(start, end, format.bind(null, 'minute')); } -function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { +function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs,format) { let start = 0; let end = 59; if (currentPicker.clone().set('second', start).isBefore(min)) { @@ -87,7 +87,7 @@ function getSeconds(min: Dayjs, max: Dayjs, currentPicker: Dayjs, format) { if (currentPicker.clone().set('second', end).isAfter(max)) { end = max.second(); } - return getArray(start, end, format.bind(this, 'second')); + return getArray(start, end, format.bind(null, 'second')); } export function getRangeData( precision: keyof typeof precisionLengthRecord, @@ -155,7 +155,6 @@ export function getValueByDate( 'getSeconds', ]; const value = []; - if (!date) return value; for (let i = 0; i < precisionLengthRecord[precision]; i++) { value.push(date[fields[i]]()); if (i === 1) { diff --git a/src/Divider/index.json b/src/Divider/index.json index cf1e493a1..ac34bd704 100644 --- a/src/Divider/index.json +++ b/src/Divider/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { } } diff --git a/src/Empty/index.json b/src/Empty/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Empty/index.json +++ b/src/Empty/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Form/FormCascaderPicker/index.json b/src/Form/FormCascaderPicker/index.json index 83597fe6f..9cc26fa6a 100644 --- a/src/Form/FormCascaderPicker/index.json +++ b/src/Form/FormCascaderPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-cascader-picker": "../../Picker/CascaderPicker/index", diff --git a/src/Form/FormCascaderPicker/index.ts b/src/Form/FormCascaderPicker/index.ts index b3631c991..82fafb831 100644 --- a/src/Form/FormCascaderPicker/index.ts +++ b/src/Form/FormCascaderPicker/index.ts @@ -1,55 +1,56 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormCascaderPickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( FormCascaderPickerDefaultProps, - { - onOk(value, option, e) { - const v = resolveEventValues(value, option); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(value, option, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(value, option), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'cancel', e); - }, - onChange(value, options, e) { - triggerEventValues(this, 'change', resolveEventValues(value, options), e); - }, - handleFormat(value, option) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(value, option); + FormCascaderPickerProps, +} from './props'; + +const FormCascaderPicker = (props: FormCascaderPickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (value, option, e) => { + emit('onChange', value); + triggerEventValues('ok', [value, option], e); + }); + + useMultipleValueHandleCustomEvent('onPickerChange', (value, option, e) => { + triggerEventValues('pickerChange', [value, option], e); + }); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useEvent( + 'handleFormat', + (value, option) => { + if (props.onFormat) { + return props.onFormat(value, option); } }, - }, - {}, - [createForm()], - { - /// #if WECHAT - attached() { - this.setData({ - handleFormat: this.handleFormat.bind(this), - }); - }, - /// #endif - } -); + { handleResult: true } + ); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('cancel', e); + }); + + useMultipleValueHandleCustomEvent('onChange', (value, options, e) => { + triggerEventValues('change', [value, options], e); + }); + + return { + formData, + }; +}; + +mountComponent(FormCascaderPicker, FormCascaderPickerDefaultProps); diff --git a/src/Form/FormCascaderPicker/props.ts b/src/Form/FormCascaderPicker/props.ts index 924717f0d..e7de550b9 100644 --- a/src/Form/FormCascaderPicker/props.ts +++ b/src/Form/FormCascaderPicker/props.ts @@ -1,8 +1,8 @@ import { - CascaderDefaultProps, + CascaderFunctionalProps, ICascaderProps, } from '../../Picker/CascaderPicker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormCascaderPickerProps extends ICascaderProps, FormItemProps { /** @@ -13,7 +13,7 @@ export interface FormCascaderPickerProps extends ICascaderProps, FormItemProps { export const FormCascaderPickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...CascaderDefaultProps, + ...FormItemFunctionalProps, + ...CascaderFunctionalProps, arrow: false, }; diff --git a/src/Form/FormCheckboxGroup/index.json b/src/Form/FormCheckboxGroup/index.json index a257669cb..a7aba7f79 100644 --- a/src/Form/FormCheckboxGroup/index.json +++ b/src/Form/FormCheckboxGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "checkbox-group": "../../Checkbox/CheckboxGroup/index" diff --git a/src/Form/FormCheckboxGroup/index.ts b/src/Form/FormCheckboxGroup/index.ts index 703fd3539..92c773f20 100644 --- a/src/Form/FormCheckboxGroup/index.ts +++ b/src/Form/FormCheckboxGroup/index.ts @@ -1,16 +1,21 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { FormCheckboxGroupDefaultProps } from './props'; -import { resolveEventValue } from '../../_util/platform'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormCheckboxGroupDefaultProps, FormCheckboxGroupProps } from './props'; -Component( - FormCheckboxGroupDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormCheckboxGroup = (props: FormCheckboxGroupProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormCheckboxGroup, FormCheckboxGroupDefaultProps); diff --git a/src/Form/FormCheckboxGroup/props.ts b/src/Form/FormCheckboxGroup/props.ts index 3321bd084..fcc3d1168 100644 --- a/src/Form/FormCheckboxGroup/props.ts +++ b/src/Form/FormCheckboxGroup/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { CheckboxGroupDefaultProps, ICheckboxGroupProps, @@ -13,7 +13,7 @@ export interface FormCheckboxGroupProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { position, ...rest } = CheckboxGroupDefaultProps; export const FormCheckboxGroupDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, checkboxPosition: 'horizontal', }; diff --git a/src/Form/FormDatePicker/index.json b/src/Form/FormDatePicker/index.json index 190c929df..a99473a3c 100644 --- a/src/Form/FormDatePicker/index.json +++ b/src/Form/FormDatePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-date-picker": "../../DatePicker/index", diff --git a/src/Form/FormDatePicker/index.ts b/src/Form/FormDatePicker/index.ts index c9eae1721..a5308b49a 100644 --- a/src/Form/FormDatePicker/index.ts +++ b/src/Form/FormDatePicker/index.ts @@ -1,65 +1,67 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormDatePickerDefaultProps } from './props'; -import { createForm } from '../form'; + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormDatePickerDefaultProps, FormDatePickerProps } from './props'; +import { platform } from '../../_util/platform'; -Component( - FormDatePickerDefaultProps, - { - onOk(date, dateStr, e) { - const v = resolveEventValues(date, dateStr); - /// #if ALIPAY - this.emit('onChange', v[0]); - /// #endif - /// #if WECHAT - this.emit('onChange', v[1]); - /// #endif - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(date, dateStr, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(date, dateStr), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'dismissPicker', e); - }, +const FormDatePicker = (props: FormDatePickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (date, dateStr, e) => { + emit('onChange', platform() === 'wechat' ? date.getTime() : date); + triggerEventValues('ok', [date, dateStr], e); + }); + + useMultipleValueHandleCustomEvent('onPickerChange', (date, dateStr, e) => { + triggerEventValues('pickerChange', [date, dateStr], e); + }); - handleFormat(date, dateStr) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(date, dateStr); + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('dismissPicker', e); + }); + + useEvent( + 'handleFormat', + (date, dateStr) => { + if (props.onFormat) { + return props.onFormat(date, dateStr); } }, - handleFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - if (onFormatLabel) { - return onFormatLabel(type, value); + { + handleResult: true, + } + ); + + useEvent( + 'handleFormatLabel', + (type, value) => { + if (props.onFormatLabel) { + return props.onFormatLabel(type, value); } }, - }, - {}, - [createForm()], - { - /// #if WECHAT - attached() { - this.setData({ - handleFormat: this.handleFormat.bind(this), - handleFormatLabel: this.handleFormatLabel.bind(this), - }); - }, - /// #endif - } + { + handleResult: true, + } + ); + + return { + formData, + }; +}; + +mountComponent( + FormDatePicker, + FormDatePickerDefaultProps as FormDatePickerProps ); diff --git a/src/Form/FormDatePicker/props.ts b/src/Form/FormDatePicker/props.ts index 491125606..56d3c8be4 100644 --- a/src/Form/FormDatePicker/props.ts +++ b/src/Form/FormDatePicker/props.ts @@ -1,8 +1,8 @@ import { - DatePickerDefaultProps, + DatePickerFunctionalProps, IDatePickerProps, } from '../../DatePicker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormDatePickerProps extends IDatePickerProps, FormItemProps { /** @@ -12,7 +12,7 @@ export interface FormDatePickerProps extends IDatePickerProps, FormItemProps { } export const FormDatePickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...DatePickerDefaultProps, + ...FormItemFunctionalProps, + ...DatePickerFunctionalProps, arrow: false, }; diff --git a/src/Form/FormImageUpload/index.json b/src/Form/FormImageUpload/index.json index 5d38464c7..c3adc9767 100644 --- a/src/Form/FormImageUpload/index.json +++ b/src/Form/FormImageUpload/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "image-upload": "../../ImageUpload/index" } -} +} \ No newline at end of file diff --git a/src/Form/FormImageUpload/index.ts b/src/Form/FormImageUpload/index.ts index 8c918f75d..0d32fe42d 100644 --- a/src/Form/FormImageUpload/index.ts +++ b/src/Form/FormImageUpload/index.ts @@ -1,76 +1,83 @@ -import { Component, triggerEvent, getValueFromProps } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormImageUploadDefaultProps } from './props'; -import { createForm } from '../form'; +import { useEvent, useRef, useEffect } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormImageUploadDefaultProps, FormImageUploadProps } from './props'; -Component( - FormImageUploadDefaultProps, - { - handleRef(imageUpload) { - /// #if ALIPAY - this.imageUpload = imageUpload; - /// #endif - /// #if WECHAT - this.imageUpload = imageUpload.detail; - /// #endif - }, - onChange(value) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value)); - }, - onPreview(file) { - triggerEvent(this, 'preview', resolveEventValue(file)); - }, - onChooseImageError(err) { - triggerEvent(this, 'chooseImageError', resolveEventValue(err)); - }, +interface ImageUploadRef { + update(value: FormImageUploadProps['fileList']); +} + +const FormImageUpload = (props: FormImageUploadProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + const imageUploadRef = useRef(); + + useHandleCustomEvent('handleRef', (imageUpload: ImageUploadRef) => { + imageUploadRef.current = imageUpload; + }); + + useEffect(() => { + if (imageUploadRef.current) { + imageUploadRef.current.update(formData.value); + } + }, [formData.value]); - handleUpload(localFile) { - const onUpload = getValueFromProps(this, 'onUpload'); - if (!onUpload) { + useHandleCustomEvent('onChange', (value) => { + emit('onChange', value); + triggerEvent('change', value); + }); + + useEvent( + 'handleUpload', + (localFile) => { + if (!props.onUpload) { throw new Error('need props onUpload'); } - return onUpload(localFile); + return props.onUpload(localFile); }, - handleRemove(file) { - const onRemove = getValueFromProps(this, 'onRemove'); - if (onRemove) { - return onRemove(file); + { + handleResult: true, + } + ); + + useEvent( + 'handleRemove', + (file) => { + if (props.onRemove) { + return props.onRemove(file); } }, - handleBeforeUpload(localFileList) { - const onBeforeUpload = getValueFromProps(this, 'onBeforeUpload'); - if (onBeforeUpload) { - return onBeforeUpload(localFileList); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onPreview', (file, e) => { + triggerEvent('preview', file, e); + }); + + useEvent( + 'handleBeforeUpload', + (localFileList) => { + if (props.onBeforeUpload) { + return props.onBeforeUpload(localFileList); } }, - }, - {}, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.imageUpload && this.imageUpload.update(this.data.formData.value); - }, - }, - }), - ], - { - /// #if WECHAT - attached() { - this.setData({ - handleUpload: this.handleUpload.bind(this), - handleRemove: this.handleRemove.bind(this), - handleBeforeUpload: this.handleBeforeUpload.bind(this), - }); - }, - /// #endif - } -); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onChooseImageError', (err, e) => { + triggerEvent('chooseImageError', err, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormImageUpload, FormImageUploadDefaultProps); diff --git a/src/Form/FormImageUpload/props.ts b/src/Form/FormImageUpload/props.ts index fb3a2ad6d..44a2630fc 100644 --- a/src/Form/FormImageUpload/props.ts +++ b/src/Form/FormImageUpload/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IUploaderProps, UploaderDefaultProps, @@ -11,6 +11,6 @@ export interface FormImageUploadProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { defaultFileList, ...rest } = UploaderDefaultProps; export const FormImageUploadDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, }; diff --git a/src/Form/FormInput/index.json b/src/Form/FormInput/index.json index 4753b1bb0..c5ed09788 100644 --- a/src/Form/FormInput/index.json +++ b/src/Form/FormInput/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-input": "../../Input/index" diff --git a/src/Form/FormInput/index.ts b/src/Form/FormInput/index.ts index 544de12b2..4ed54950d 100644 --- a/src/Form/FormInput/index.ts +++ b/src/Form/FormInput/index.ts @@ -1,48 +1,49 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormInputDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormInputDefaultProps, - { - handleRef(input) { - /// #if ALIPAY - this.input = input; - /// #endif - /// #if WECHAT - this.input = input.detail; - /// #endif - }, - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(value, e) { - triggerEvent(this, 'blur', resolveEventValue(value), e); - }, - onFocus(value, e) { - triggerEvent(this, 'focus', resolveEventValue(value), e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - }, - null, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.input && this.input.update(this.data.formData.value); - }, - }, - }), - ] -); +import { useEffect, useRef } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormInputFunctionalProps, FormInputProps } from './props'; + +interface InputRef { + update(value: string); +} + +const FormInput = (props: FormInputProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + const inputRef = useRef(); + + useHandleCustomEvent('handleRef', (input: InputRef) => { + inputRef.current = input; + }); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.update(formData.value); + } + }, [formData]); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onBlur', (value, e) => { + triggerEvent('blur', value, e); + }); + + useHandleCustomEvent('onFocus', (value, e) => { + triggerEvent('focus', value, e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormInput, FormInputFunctionalProps); diff --git a/src/Form/FormInput/props.ts b/src/Form/FormInput/props.ts index 4b8293287..d367bf0de 100644 --- a/src/Form/FormInput/props.ts +++ b/src/Form/FormInput/props.ts @@ -1,5 +1,5 @@ -import { FormItemProps, FormItemDefaultProps } from '../FormItem/props'; -import { InputProps, InputDefaultProps } from '../../Input/props'; +import { FormItemProps, FormItemFunctionalProps } from '../FormItem/props'; +import { InputProps, InputFunctionalProps } from '../../Input/props'; export interface FormInputProps extends Omit, @@ -8,10 +8,12 @@ export interface FormInputProps inputClassStyle: string; } +export const FormInputDefaultProps: Partial = {}; + // eslint-disable-next-line @typescript-eslint/no-unused-vars -const { value, defaultValue, name, ...rest } = InputDefaultProps; -export const FormInputDefaultProps: FormInputProps = { - ...FormItemDefaultProps, +const { value, defaultValue, name, ...rest } = InputFunctionalProps; +export const FormInputFunctionalProps: FormInputProps = { + ...FormItemFunctionalProps, ...rest, inputClassName: '', inputClassStyle: ' ', diff --git a/src/Form/FormItem/index.json b/src/Form/FormItem/index.json index 7b25f207e..12ce40723 100644 --- a/src/Form/FormItem/index.json +++ b/src/Form/FormItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "popover": "../../Popover/index", "ant-icon": "../../Icon/index" diff --git a/src/Form/FormItem/index.ts b/src/Form/FormItem/index.ts index e7d56bb89..6948b6957 100644 --- a/src/Form/FormItem/index.ts +++ b/src/Form/FormItem/index.ts @@ -1,10 +1,6 @@ -import { Component } from '../../_util/simply'; -import { FormItemDefaultProps } from './props'; +import { mountComponent } from '../../_util/component'; +import { FormItemProps, FormItemFunctionalProps } from './props'; -Component(FormItemDefaultProps, null, null, null, { - /// #if WECHAT - attached() { - this.triggerEvent('ref', this); - }, - /// #endif -}); +const FormItem = () => {}; + +mountComponent(FormItem, FormItemFunctionalProps); diff --git a/src/Form/FormItem/props.ts b/src/Form/FormItem/props.ts index 10cf56ced..a556a58e3 100644 --- a/src/Form/FormItem/props.ts +++ b/src/Form/FormItem/props.ts @@ -19,7 +19,12 @@ export interface FormItemProps extends IBaseProps { dependencies?: string[]; } -export const FormItemDefaultProps: FormItemProps = { +export const FormItemDefaultProps: Partial = { + position: 'horizontal', + requiredMark: 'asterisk', +}; + +export const FormItemFunctionalProps: FormItemProps = { name: null, label: null, labelWidth: null, diff --git a/src/Form/FormPicker/index.json b/src/Form/FormPicker/index.json index c0b9103e0..dc690762e 100644 --- a/src/Form/FormPicker/index.json +++ b/src/Form/FormPicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-picker": "../../Picker/index", diff --git a/src/Form/FormPicker/index.ts b/src/Form/FormPicker/index.ts index fabeecd8e..fc759232a 100644 --- a/src/Form/FormPicker/index.ts +++ b/src/Form/FormPicker/index.ts @@ -1,48 +1,50 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormPickerDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormPickerDefaultProps, - { - onOk(value, column, e) { - const v = resolveEventValues(value, column); - this.emit('onChange', v[0]); - triggerEventValues(this, 'ok', v, e); - }, - onChange(value, column, e) { - triggerEventValues(this, 'change', resolveEventValues(value, column), e); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'cancel', e); - }, + useHandleCustomEvent, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormPickerDefaultProps, FormPickerProps } from './props'; + +const FormPicker = (props: FormPickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (value, column, e) => { + emit('onChange', value); + triggerEventValues('ok', [value, column], e); + }); - handleFormat(value, column) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(value, column); + useMultipleValueHandleCustomEvent('onChange', (value, column, e) => { + triggerEventValues('change', [value, column], e); + }); + + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useEvent( + 'handleFormat', + (value, column) => { + if (props.onFormat) { + return props.onFormat(value, column); } }, - }, - {}, - [createForm()], - { - /// #if WECHAT - attached() { - this.setData({ - handleFormat: this.handleFormat.bind(this), - }); - }, - /// #endif - } -); + { + handleResult: true, + } + ); + + useHandleCustomEvent('onDismissPicker', (e) => { + triggerEventOnly('cancel', e); + }); + + return { + formData, + }; +}; + +mountComponent(FormPicker, FormPickerDefaultProps as FormPickerProps); diff --git a/src/Form/FormPicker/props.ts b/src/Form/FormPicker/props.ts index 858ab1531..715176d77 100644 --- a/src/Form/FormPicker/props.ts +++ b/src/Form/FormPicker/props.ts @@ -1,5 +1,5 @@ -import { IPickerProps, PickerDefaultProps } from '../../Picker/props'; -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { IPickerProps, PickerFunctionalProps } from '../../Picker/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; export interface FormPickerProps extends IPickerProps, FormItemProps { /** @@ -9,7 +9,7 @@ export interface FormPickerProps extends IPickerProps, FormItemProps { } export const FormPickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...PickerDefaultProps, + ...FormItemFunctionalProps, + ...PickerFunctionalProps, arrow: false, }; diff --git a/src/Form/FormRadioGroup/index.json b/src/Form/FormRadioGroup/index.json index 3741e2c7b..266076e3f 100644 --- a/src/Form/FormRadioGroup/index.json +++ b/src/Form/FormRadioGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-radio-group": "../../Radio/RadioGroup/index" diff --git a/src/Form/FormRadioGroup/index.ts b/src/Form/FormRadioGroup/index.ts index cd7cb476b..bf301b68f 100644 --- a/src/Form/FormRadioGroup/index.ts +++ b/src/Form/FormRadioGroup/index.ts @@ -1,16 +1,25 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormRadioGroupDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormRadioGroupDefaultProps, FormRadioGroupProps } from './props'; -Component( - FormRadioGroupDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] +const FormRadioGroup = (props: FormRadioGroupProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent( + FormRadioGroup, + FormRadioGroupDefaultProps as FormRadioGroupProps ); diff --git a/src/Form/FormRadioGroup/props.ts b/src/Form/FormRadioGroup/props.ts index 97f22cc74..6f236366f 100644 --- a/src/Form/FormRadioGroup/props.ts +++ b/src/Form/FormRadioGroup/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IRadioGroupProps, RadioGroupDefaultProps, @@ -18,7 +18,7 @@ const { value, defaultValue, position, name, ...rest } = RadioGroupDefaultProps; export const FormRadioGroupDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, radioPosition: 'horizontal', }; diff --git a/src/Form/FormRangePicker/index.json b/src/Form/FormRangePicker/index.json index 24e7b435a..09d909562 100644 --- a/src/Form/FormRangePicker/index.json +++ b/src/Form/FormRangePicker/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-range-picker": "../../DatePicker/RangePicker/index", diff --git a/src/Form/FormRangePicker/index.ts b/src/Form/FormRangePicker/index.ts index 1b6d2f0bb..79cbadb2b 100644 --- a/src/Form/FormRangePicker/index.ts +++ b/src/Form/FormRangePicker/index.ts @@ -1,65 +1,78 @@ +import { useEvent } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; import { - Component, - triggerEvent, - triggerEventValues, - triggerEventOnly, - getValueFromProps, -} from '../../_util/simply'; -import { resolveEventValue, resolveEventValues } from '../../_util/platform'; -import { FormRangePickerDefaultProps } from './props'; -import { createForm } from '../form'; + useHandleCustomEvent, + useHandleCustomEventOnly, + useMultipleValueHandleCustomEvent, +} from '../../_util/hooks/useHandleCustomEvent'; +import { platform } from '../../_util/platform'; +import { useFormItem } from '../use-form-item'; +import { FormRangePickerDefaultProps, FormRangePickerProps } from './props'; -Component( - FormRangePickerDefaultProps, - { - onOk(date, dateStr, e) { - const v = resolveEventValues(date, dateStr); - /// #if ALIPAY - this.emit('onChange', v[0]); - /// #endif - /// #if WECHAT - this.emit('onChange', v[1]); - /// #endif - triggerEventValues(this, 'ok', v, e); - }, - onPickerChange(type, date, dateStr, e) { - triggerEventValues( - this, - 'pickerChange', - resolveEventValues(type, date, dateStr), - e - ); - }, - onVisibleChange(visible, e) { - triggerEvent(this, 'visibleChange', resolveEventValue(visible), e); - }, - onDismissPicker(e) { - triggerEventOnly(this, 'dismissPicker', e); - }, +const FormDatePicker = (props: FormRangePickerProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEventValues, triggerEventOnly, triggerEvent } = + useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onOk', (date, dateStr, e) => { + emit( + 'onChange', + date.map((o: Date) => { + if (platform() === 'wechat') { + return o.getTime(); + } + return o; + }) + ); + triggerEventValues('ok', [date, dateStr], e); + }); + + useMultipleValueHandleCustomEvent( + 'onPickerChange', + (type, date, dateStr, e) => { + triggerEventValues('pickerChange', [type, date, dateStr], e); + } + ); - handleFormat(date, dateStr) { - const onFormat = getValueFromProps(this, 'onFormat'); - if (onFormat) { - return onFormat(date, dateStr); + useHandleCustomEvent('onVisibleChange', (visible, e) => { + triggerEvent('visibleChange', visible, e); + }); + + useHandleCustomEventOnly('onDismissPicker', (e) => { + triggerEventOnly('dismissPicker', e); + }); + + useEvent( + 'handleFormat', + (date, dateStr) => { + if (props.onFormat) { + return props.onFormat(date, dateStr); } }, - handleFormatLabel(type, value) { - const onFormatLabel = getValueFromProps(this, 'onFormatLabel'); - if (onFormatLabel) { - return onFormatLabel(type, value); + { + handleResult: true, + } + ); + + useEvent( + 'handleFormatLabel', + (type, value) => { + if (props.onFormatLabel) { + return props.onFormatLabel(type, value); } }, - }, - {}, - [createForm()], - { - /// #if WECHAT - attached() { - this.setData({ - handleFormat: this.handleFormat.bind(this), - handleFormatLabel: this.handleFormatLabel.bind(this), - }); - }, - /// #endif - } + { + handleResult: true, + } + ); + + return { + formData, + }; +}; + +mountComponent( + FormDatePicker, + FormRangePickerDefaultProps as FormRangePickerProps ); diff --git a/src/Form/FormRangePicker/props.ts b/src/Form/FormRangePicker/props.ts index eba7a9cca..6a4d4779f 100644 --- a/src/Form/FormRangePicker/props.ts +++ b/src/Form/FormRangePicker/props.ts @@ -1,6 +1,6 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IDateRangePickerProps } from '../../DatePicker/RangePicker/props'; -import { DateRangePickerDefaultProps } from '../../DatePicker/RangePicker/props'; +import { DateRangePickerFunctionalProps } from '../../DatePicker/RangePicker/props'; export interface FormRangePickerProps extends IDateRangePickerProps, @@ -12,7 +12,7 @@ export interface FormRangePickerProps } export const FormRangePickerDefaultProps: Partial = { - ...FormItemDefaultProps, - ...DateRangePickerDefaultProps, + ...FormItemFunctionalProps, + ...DateRangePickerFunctionalProps, arrow: false, }; diff --git a/src/Form/FormRate/index.json b/src/Form/FormRate/index.json index a070eadf5..184e99870 100644 --- a/src/Form/FormRate/index.json +++ b/src/Form/FormRate/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "icon": "../../Icon/index", diff --git a/src/Form/FormRate/index.ts b/src/Form/FormRate/index.ts index c7cd8471d..01f7b5d3e 100644 --- a/src/Form/FormRate/index.ts +++ b/src/Form/FormRate/index.ts @@ -1,16 +1,22 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormRateDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormRateDefaultProps, FormRateProps } from './props'; -Component( - FormRateDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormRate = (props: FormRateProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormRate, FormRateDefaultProps); diff --git a/src/Form/FormRate/props.ts b/src/Form/FormRate/props.ts index 3a121e4d9..6e2baf5b4 100644 --- a/src/Form/FormRate/props.ts +++ b/src/Form/FormRate/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IRateProps, RateDefaultProps } from '../../Rate/props'; export interface FormRateProps @@ -12,7 +12,7 @@ export interface FormRateProps const { defaultValue, ...rest } = RateDefaultProps; export const FormRateDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, rateClassName: '', rateStyle: '', diff --git a/src/Form/FormSelector/index.json b/src/Form/FormSelector/index.json index 0216a4933..7e631fbaf 100644 --- a/src/Form/FormSelector/index.json +++ b/src/Form/FormSelector/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "selector": "../../Selector/index" diff --git a/src/Form/FormSelector/index.ts b/src/Form/FormSelector/index.ts index 05665a750..c21799f9c 100644 --- a/src/Form/FormSelector/index.ts +++ b/src/Form/FormSelector/index.ts @@ -1,23 +1,30 @@ -import { Component, triggerEventValues } from '../../_util/simply'; -import { resolveEventValues } from '../../_util/platform'; -import { FormSelectorDefaultProps } from './props'; -import { createForm } from '../form'; +import { useMultipleValueHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSelectorDefaultProps, FormSelectorProps } from './props'; -Component( - FormSelectorDefaultProps, - { - onChange(value, item, e) { - const v = resolveEventValues(value, item); - this.emit('onChange', v[0]); - triggerEventValues(this, 'change', v, e); - }, - onSelectMax(value, item, e) { - triggerEventValues(this, 'selectMax', resolveEventValues(value, item), e); - }, - onSelectMin(value, item, e) { - triggerEventValues(this, 'selectMin', resolveEventValues(value, item), e); - }, - }, - null, - [createForm()] -); +const FormSelector = (props: FormSelectorProps) => { + const { formData, emit } = useFormItem(props); + + const { triggerEventValues } = useComponentEvent(props); + + useMultipleValueHandleCustomEvent('onChange', (value, item, e) => { + emit('onChange', value); + triggerEventValues('change', [value, item], e); + }); + + useMultipleValueHandleCustomEvent('onSelectMax', (value, item, e) => { + triggerEventValues('selectMax', [value, item], e); + }); + + useMultipleValueHandleCustomEvent('onSelectMin', (value, item, e) => { + triggerEventValues('selectMin', [value, item], e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSelector, FormSelectorDefaultProps); diff --git a/src/Form/FormSelector/props.ts b/src/Form/FormSelector/props.ts index cb35bfff1..f6c753d6c 100644 --- a/src/Form/FormSelector/props.ts +++ b/src/Form/FormSelector/props.ts @@ -1,9 +1,9 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISelectorProps, SelectorDefaultProps } from '../../Selector/props'; export interface FormSelectorProps extends ISelectorProps, FormItemProps {} export const FormSelectorDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...SelectorDefaultProps, }; diff --git a/src/Form/FormSlider/index.json b/src/Form/FormSlider/index.json index fc1f84fb4..85b540714 100644 --- a/src/Form/FormSlider/index.json +++ b/src/Form/FormSlider/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "slider": "../../Slider/index" } -} +} \ No newline at end of file diff --git a/src/Form/FormSlider/index.ts b/src/Form/FormSlider/index.ts index faf1ee86a..3e19b209d 100644 --- a/src/Form/FormSlider/index.ts +++ b/src/Form/FormSlider/index.ts @@ -1,19 +1,26 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormSliderDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSliderDefaultProps, FormSliderProps } from './props'; -Component( - FormSliderDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onAfterChange(value, e) { - triggerEvent(this, 'afterChange', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormSlider = (props: FormSliderProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onAfterChange', (value, e) => { + emit('onChange', value); + triggerEvent('afterChange', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSlider, FormSliderDefaultProps); diff --git a/src/Form/FormSlider/props.ts b/src/Form/FormSlider/props.ts index 1936cfd9c..82063124f 100644 --- a/src/Form/FormSlider/props.ts +++ b/src/Form/FormSlider/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISliderProps, sliderDefaultProps } from '../../Slider/props'; export interface FormSliderProps @@ -12,7 +12,7 @@ export interface FormSliderProps const { value, defaultValue, ...rest } = sliderDefaultProps; export const FormSliderDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, sliderClassName: '', sliderStyle: '', diff --git a/src/Form/FormStepper/index.json b/src/Form/FormStepper/index.json index cd7f470ce..2dbd1e5d2 100644 --- a/src/Form/FormStepper/index.json +++ b/src/Form/FormStepper/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "stepper": "../../Stepper/index" } -} +} \ No newline at end of file diff --git a/src/Form/FormStepper/index.ts b/src/Form/FormStepper/index.ts index 5af8a241f..b9de5d6a7 100644 --- a/src/Form/FormStepper/index.ts +++ b/src/Form/FormStepper/index.ts @@ -1,25 +1,36 @@ -import { Component, triggerEvent, triggerEventOnly } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormStepperDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { + useHandleCustomEvent, + useHandleCustomEventOnly, +} from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormStepperDefaultProps, FormStepperProps } from './props'; -Component( - FormStepperDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(e) { - triggerEventOnly(this, 'blur', e); - }, - onFocus(e) { - triggerEventOnly(this, 'focus', e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormStepper = (props: FormStepperProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent, triggerEventOnly } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEventOnly('onBlur', (e) => { + triggerEventOnly('blur', e); + }); + + useHandleCustomEventOnly('onFocus', (e) => { + triggerEventOnly('focus', e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormStepper, FormStepperDefaultProps); diff --git a/src/Form/FormStepper/props.ts b/src/Form/FormStepper/props.ts index 70b6cbfac..c43b1a45d 100644 --- a/src/Form/FormStepper/props.ts +++ b/src/Form/FormStepper/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { IStepperProps, StepperDefaultProps } from '../../Stepper/props'; export interface FormStepperProps @@ -12,7 +12,7 @@ export interface FormStepperProps const { value, defaultValue, ...rest } = StepperDefaultProps; export const FormStepperDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, stepperClassName: '', stepperStyle: '', diff --git a/src/Form/FormSwitch/index.json b/src/Form/FormSwitch/index.json index d8e535a8d..8c5946e15 100644 --- a/src/Form/FormSwitch/index.json +++ b/src/Form/FormSwitch/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "switch": "../../Switch/index" } -} +} \ No newline at end of file diff --git a/src/Form/FormSwitch/index.ts b/src/Form/FormSwitch/index.ts index 7463dbcb7..ab1e58ff0 100644 --- a/src/Form/FormSwitch/index.ts +++ b/src/Form/FormSwitch/index.ts @@ -1,16 +1,21 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormSwitchDefaultProps } from './props'; -import { createForm } from '../form'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormSwitchDefaultProps, FormSwitchProps } from './props'; -Component( - FormSwitchDefaultProps, - { - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [createForm()] -); +const FormSwitch = (props: FormSwitchProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormSwitch, FormSwitchDefaultProps); diff --git a/src/Form/FormSwitch/props.ts b/src/Form/FormSwitch/props.ts index aace47688..c1cea32d1 100644 --- a/src/Form/FormSwitch/props.ts +++ b/src/Form/FormSwitch/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps, FormItemProps } from '../FormItem/props'; +import { FormItemFunctionalProps, FormItemProps } from '../FormItem/props'; import { ISwitchProps, SwitchDefaultProps } from '../../Switch/props'; export interface FormSwitchProps @@ -11,7 +11,7 @@ export interface FormSwitchProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { checked, defaultChecked, ...rest } = SwitchDefaultProps; export const FormSwitchDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, switchClassName: '', switchStyle: '', diff --git a/src/Form/FormTextarea/index.json b/src/Form/FormTextarea/index.json index 12bd9d977..11d1ec17a 100644 --- a/src/Form/FormTextarea/index.json +++ b/src/Form/FormTextarea/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "form-item": "../FormItem/index", "ant-textarea": "../../Input/Textarea/index" diff --git a/src/Form/FormTextarea/index.ts b/src/Form/FormTextarea/index.ts index 32415a046..25102baba 100644 --- a/src/Form/FormTextarea/index.ts +++ b/src/Form/FormTextarea/index.ts @@ -1,52 +1,49 @@ -import { Component, triggerEvent } from '../../_util/simply'; -import { resolveEventValue } from '../../_util/platform'; -import { FormTextareaDefaultProps } from './props'; -import { createForm } from '../form'; - -Component( - FormTextareaDefaultProps, - { - handleRef(input) { - /// #if ALIPAY - this.input = input; - /// #endif - /// #if WECHAT - this.input = input.detail; - /// #endif - }, - onChange(value, e) { - this.emit('onChange', resolveEventValue(value)); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - onBlur(value, e) { - triggerEvent(this, 'blur', resolveEventValue(value), e); - }, - onFocus(value, e) { - triggerEvent(this, 'focus', resolveEventValue(value), e); - }, - onConfirm(value, e) { - triggerEvent(this, 'confirm', resolveEventValue(value), e); - }, - onClear(value, e) { - this.emit('onChange', ''); - triggerEvent(this, 'change', resolveEventValue(value), e); - }, - }, - null, - [ - createForm({ - methods: { - setFormData(this: any, values) { - this.setData({ - ...this.data, - formData: { - ...this.data.formData, - ...values, - }, - }); - this.input && this.input.update(this.data.formData.value); - }, - }, - }), - ] -); +import { useEffect, useRef } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useHandleCustomEvent } from '../../_util/hooks/useHandleCustomEvent'; +import { useFormItem } from '../use-form-item'; +import { FormTextareaDefaultProps, FormTextareaProps } from './props'; + +type TextareaRef = { + update(value: string): void; +}; + +const FormTextarea = (props: FormTextareaProps) => { + const { formData, emit } = useFormItem(props); + const { triggerEvent } = useComponentEvent(props); + const inputRef = useRef(); + + useHandleCustomEvent('handleRef', (input: TextareaRef) => { + inputRef.current = input; + }); + + useEffect(() => { + if (inputRef.current) { + inputRef.current.update(formData.value); + } + }, [formData]); + + useHandleCustomEvent('onChange', (value, e) => { + emit('onChange', value); + triggerEvent('change', value, e); + }); + + useHandleCustomEvent('onBlur', (value, e) => { + triggerEvent('blur', value, e); + }); + + useHandleCustomEvent('onFocus', (value, e) => { + triggerEvent('focus', value, e); + }); + + useHandleCustomEvent('onConfirm', (value, e) => { + triggerEvent('confirm', value, e); + }); + + return { + formData, + }; +}; + +mountComponent(FormTextarea, FormTextareaDefaultProps as FormTextareaProps); diff --git a/src/Form/FormTextarea/props.ts b/src/Form/FormTextarea/props.ts index 4ee6f12b6..a444d1f64 100644 --- a/src/Form/FormTextarea/props.ts +++ b/src/Form/FormTextarea/props.ts @@ -1,4 +1,4 @@ -import { FormItemDefaultProps } from './../FormItem/props'; +import { FormItemFunctionalProps } from './../FormItem/props'; import { FormItemProps } from '../FormItem/props'; import { TextareaDefaultProps, @@ -12,6 +12,6 @@ export interface FormTextareaProps // eslint-disable-next-line @typescript-eslint/no-unused-vars const { value, defaultValue, name, ...rest } = TextareaDefaultProps; export const FormTextareaDefaultProps: Partial = { - ...FormItemDefaultProps, + ...FormItemFunctionalProps, ...rest, }; diff --git a/src/Form/createComponent.ts b/src/Form/createComponent.ts new file mode 100644 index 000000000..db9b000d4 --- /dev/null +++ b/src/Form/createComponent.ts @@ -0,0 +1,51 @@ +import { FromItemRef, EventTrigger, Value, Values } from './form'; + +function createComponent({ props = {}, data = {}, methods = {} as any }) { + Component({ + props, + data: { + ...data, + formData: { + value: undefined, + status: 'default', + required: false, + errors: [], + }, + }, + ref() { + const formItemRef: FromItemRef = { + setFormData: (values: Values) => { + this.setData({ + ...this.data, + formData: { + ...this.data.formData, + ...values, + }, + }); + }, + getFormData: () => { + return this.data.formData; + }, + on: (callback: (trigger: EventTrigger, value?: Value) => void) => { + this.emit = callback; + }, + getProps: () => { + return this.props; + }, + }; + return formItemRef; + }, + didUnmount() { + this.emit('didUnmount'); + }, + deriveDataFromProps(nextProps) { + this.emit('deriveDataFromProps', nextProps); + }, + methods: { + ...methods, + emit(trigger: EventTrigger, value?: Value) {}, + }, + }); +} + +export default createComponent; diff --git a/src/Form/form.ts b/src/Form/form.ts index e86118a01..da385baa3 100644 --- a/src/Form/form.ts +++ b/src/Form/form.ts @@ -9,7 +9,6 @@ import AsyncValidator, { ValidateMessages, } from 'async-validator'; import { IMixin4Legacy } from '@mini-types/alipay'; -import { getValueFromProps } from '../_util/simply'; export { Value, Values }; export type Validator = ( @@ -859,7 +858,7 @@ export class Form { } export function createForm({ methods = {} } = {}) { - let mixin = { + return { data: { formData: { value: undefined, @@ -867,28 +866,12 @@ export function createForm({ methods = {} } = {}) { errors: [], }, }, - - /// #if ALIPAY didUnmount() { this.emit('didUnmount'); }, deriveDataFromProps(nextProps) { this.emit('deriveDataFromProps', nextProps); }, - /// #endif - /// #if WECHAT - attached() { - this.triggerEvent('ref', this); - }, - detached() { - this.emit('didUnmount'); - }, - observers: { - '**': function (nextProps) { - this.emit('deriveDataFromProps', nextProps); - }, - }, - /// #endif methods: { emit(trigger: EventTrigger, value?: Value) {}, setFormData(values: Values) { @@ -907,7 +890,7 @@ export function createForm({ methods = {} } = {}) { this.emit = callback; }, getProps() { - return getValueFromProps(this); + return this.props; }, ...methods, }, @@ -928,10 +911,4 @@ export function createForm({ methods = {} } = {}) { getProps: Record; } >; - /// #if WECHAT - // @ts-ignore - mixin = Behavior(mixin); - /// #endif - - return mixin; } diff --git a/src/Form/use-form-item.ts b/src/Form/use-form-item.ts new file mode 100644 index 000000000..b65508720 --- /dev/null +++ b/src/Form/use-form-item.ts @@ -0,0 +1,76 @@ +import { Value, Values } from 'async-validator'; +import { + useState, + useEvent, + useRef, + useEffect, +} from 'functional-mini/component'; +import { triggerRefEvent } from '../_util/hooks/useReportRef'; +import { EventTrigger } from './form'; + +type EventCallback = ( + trigger: EventTrigger, + value?: Value, + extraInfo?: any +) => void; + +export const useFormItem = (props) => { + const [formData, setFormDate] = useState({ + value: undefined, + status: 'default', + required: false, + errors: [], + }); + + const formRef = useRef(formData); + const emitRef = useRef(null); + + useEvent('setFormData', (values: Values) => { + setFormDate((old) => { + const newValue = { + ...old, + ...values, + }; + formRef.current = newValue; + return newValue; + }); + }); + + useEvent('getFormData', () => { + return formRef.current; + }); + + useEvent('on', (callback: EventCallback) => { + emitRef.current = callback; + }); + + const originalProps = useRef(); + + useEvent('getProps', () => { + return props; + }); + + useEffect(() => { + return () => { + emit('didUnmount'); + }; + }, []); + + function emit(event: EventTrigger, value?: any, extraInfo?: any) { + if (emitRef.current) { + emitRef.current(event, value, extraInfo); + } + } + // 这个必须要放在后面。 + triggerRefEvent(); + + useEffect(() => { + emit('deriveDataFromProps', props, originalProps.current); + originalProps.current = props; + }, [props]); + + return { + formData, + emit, + }; +}; diff --git a/src/Grid/index.json b/src/Grid/index.json index e014257aa..bf001147d 100644 --- a/src/Grid/index.json +++ b/src/Grid/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "image-icon": "../ImageIcon/index", "ant-pagination": "../Pagination/index" diff --git a/src/GuideTour/index.json b/src/GuideTour/index.json index 953dedaa1..9c14b8442 100644 --- a/src/GuideTour/index.json +++ b/src/GuideTour/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "mask": "../Mask/index", "ant-button": "../Button/index", diff --git a/src/Icon/index.json b/src/Icon/index.json index dc5676ea5..32640e0dc 100644 --- a/src/Icon/index.json +++ b/src/Icon/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" -} + "component": true +} \ No newline at end of file diff --git a/src/ImageIcon/index.json b/src/ImageIcon/index.json index 6501ab9c0..07a8bdbc4 100644 --- a/src/ImageIcon/index.json +++ b/src/ImageIcon/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index" } diff --git a/src/ImageUpload/index.json b/src/ImageUpload/index.json index 4ca3a28c9..b0463b66e 100644 --- a/src/ImageUpload/index.json +++ b/src/ImageUpload/index.json @@ -1,8 +1,7 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "loading": "../Loading/index" } -} +} \ No newline at end of file diff --git a/src/ImageUpload/index.ts b/src/ImageUpload/index.ts index 3d6bd52ad..6aaeb6482 100644 --- a/src/ImageUpload/index.ts +++ b/src/ImageUpload/index.ts @@ -184,7 +184,7 @@ Component( transformValue(fileList = []) { return { needUpdate: true, - value: (fileList || []).map((item) => { + value: fileList.map((item) => { const file = { ...item, }; diff --git a/src/IndexBar/index.json b/src/IndexBar/index.json index dc5676ea5..467ce2945 100644 --- a/src/IndexBar/index.json +++ b/src/IndexBar/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Input/InputBlur/index.json b/src/Input/InputBlur/index.json index dc5676ea5..467ce2945 100644 --- a/src/Input/InputBlur/index.json +++ b/src/Input/InputBlur/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Input/Textarea/index.json b/src/Input/Textarea/index.json index ffa3220f6..3a037cbf8 100644 --- a/src/Input/Textarea/index.json +++ b/src/Input/Textarea/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index" } diff --git a/src/Input/index.json b/src/Input/index.json index 6501ab9c0..07a8bdbc4 100644 --- a/src/Input/index.json +++ b/src/Input/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index" } diff --git a/src/Input/index.ts b/src/Input/index.ts index c301803c2..d9e5c142d 100644 --- a/src/Input/index.ts +++ b/src/Input/index.ts @@ -1,9 +1,9 @@ import { Component, triggerEvent } from '../_util/simply'; -import { InputDefaultProps } from './props'; +import { InputFunctionalProps } from './props'; import mixinValue from '../mixins/value'; Component( - InputDefaultProps, + InputFunctionalProps, { onChange(e) { const value = e.detail.value; diff --git a/src/Input/props.ts b/src/Input/props.ts index f4d7307e3..247b7ac7a 100644 --- a/src/Input/props.ts +++ b/src/Input/props.ts @@ -91,7 +91,7 @@ export interface InputProps extends IBaseProps { onConfirm?: (value: string, e: any) => void; } -export const InputDefaultProps: InputProps = { +export const InputFunctionalProps: InputProps = { type: null, value: null, defaultValue: null, diff --git a/src/List/ListItem/index.json b/src/List/ListItem/index.json index 40bda8aea..7dc253d62 100644 --- a/src/List/ListItem/index.json +++ b/src/List/ListItem/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../../Icon/index", "image-icon": "../../ImageIcon/index" diff --git a/src/List/index.json b/src/List/index.json index dc5676ea5..467ce2945 100644 --- a/src/List/index.json +++ b/src/List/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Loading/index.json b/src/Loading/index.json index dc5676ea5..467ce2945 100644 --- a/src/Loading/index.json +++ b/src/Loading/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Mask/index.json b/src/Mask/index.json index dc5676ea5..467ce2945 100644 --- a/src/Mask/index.json +++ b/src/Mask/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Modal/index.json b/src/Modal/index.json index 5d1d91f50..6eaf614ee 100644 --- a/src/Modal/index.json +++ b/src/Modal/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-button": "../Button/index", "ant-icon": "../Icon/index", diff --git a/src/NoticeBar/index.axml.tsx b/src/NoticeBar/index.axml.tsx index b99203983..a45f0677d 100644 --- a/src/NoticeBar/index.axml.tsx +++ b/src/NoticeBar/index.axml.tsx @@ -11,7 +11,7 @@ export default ( icon, mode, enableMarquee, - slotIcon, + $id, }: TSXMLProps, @@ -27,22 +27,8 @@ export default ( > {/* #if ALIPAY */} - - {icon ? ( - - ) : type === 'error' ? ( - - ) : ( - - )} - - - {/* #endif */} + {/* #endif */} - {/* #if WECHAT */} - {slotIcon ? ( - - ) : ( {icon ? ( @@ -52,7 +38,8 @@ export default ( )} - )} + {/* #if ALIPAY */} + {/* #endif */} 展示一组消息通知。 @@ -18,21 +18,20 @@ toc: content 用于当前页面内信息的通知,是一种较醒目的页面内通知方式。 ## 代码示例 - ## API -| 属性 | 说明 | 类型 | 默认值 | -| ------------- | ---------------------------------------------------------------------------------------------- | ------------ | ------- | -| className | 类名 | string | - | -| enableMarquee | 是否开启滚动动画 | boolean | false | -| extra | 自定义右侧内容 | slot | - | -| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot (微信版本需要设置 slotIcon) | string | - | -| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | -| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | -| style | 样式 | string | - | -| title | 标题 | string\|slot | - | -| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | -| slotIcon | 微信版本需要通过此字段启用 icon 位置的插槽 | boolean | - | -| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | +| 属性 | 说明 | 类型 | 默认值 | +| ---------- | ---------------------- | ----------- | ------ | +| className | 类名 | string | - | +| enableMarquee | 是否开启滚动动画 | boolean | false | +| extra | 自定义右侧内容 | slot | - | +| icon | 左侧 icon,支持所有内置 iconType 和自定义链接,也支持自定义 slot | slot \| string | - | +| loop | 是否循环滚动,`enableMarquee` 为 true 时有效 | boolean | false | +| mode | 通告类型,`link` 表示连接,整行可点;`closeable` 表示点击 x 可以关闭;不填时表示右侧没有图标 | string | - | +| style | 样式 | string | - | +| title | 标题 | string\|slot | - | +| type | 类型,可选 `default`, `error`, `primary`, `info` | string | default | +| onTap | 点击通知栏右侧的图标(箭头或者叉),触发回调 | () => void | - | + diff --git a/src/NoticeBar/props.ts b/src/NoticeBar/props.ts index ca69033dc..6468108a4 100644 --- a/src/NoticeBar/props.ts +++ b/src/NoticeBar/props.ts @@ -25,17 +25,15 @@ export interface INoticeBarProps extends IBaseProps { * @description 是否开启滚动动画 * @default false */ + enableMarquee: boolean; /** * @description 是否循环滚动,enableMarquee 为 true 时有效 * @default false */ + loop: boolean; - /** - * @description 微信版本需要通过此字段启用 icon 位置的插槽 - * @default false - */ - slotIcon?: boolean; + /** * @description 点击图标(箭头或者叉,由mode属性决定)的事件回调 */ @@ -44,6 +42,7 @@ export interface INoticeBarProps extends IBaseProps { * @description 行动点点击回调 * @param 当前点击的行动点序号 */ + onActionTap: (index: number) => void; } @@ -53,5 +52,4 @@ export const NoticeBarDefaultProps: Partial = { mode: null, enableMarquee: false, loop: false, - slotIcon: false, }; diff --git a/src/NumberKeyboard/index.json b/src/NumberKeyboard/index.json index 6cf21ce24..090c137c7 100644 --- a/src/NumberKeyboard/index.json +++ b/src/NumberKeyboard/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Pagination/index.json b/src/Pagination/index.json index dc5676ea5..467ce2945 100644 --- a/src/Pagination/index.json +++ b/src/Pagination/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Picker/CascaderPicker/index.axml.tsx b/src/Picker/CascaderPicker/index.axml.tsx index 954620d8a..48c06b23c 100644 --- a/src/Picker/CascaderPicker/index.axml.tsx +++ b/src/Picker/CascaderPicker/index.axml.tsx @@ -20,7 +20,7 @@ export default ( indicatorClassName, maskClosable, }: TSXMLProps, - { visible, columns, currentValue, formattedValueText }: InternalData + { state, columns, currentValue, formattedValueText }: InternalData ) => ( { - columns.push(options.map((v) => ({ value: v.value, label: v.label }))); - const currentOption = - options.find((v) => v.value === value?.[columns.length - 1]) || - options[0]; - if (currentOption?.children?.length > 0) { - return getColumns(currentOption.children, value, columns); - } - return columns; - }; - return getColumns(options, value); - }, - // 获取有效value,若从x项开始在columns里找不到,则从此项开始都选第一条 - getValidValue(value, columns) { - const result = []; - for (let i = 0; i < columns.length; i++) { - if (!columns[i].some((v) => v?.value === value?.[i])) { - result.push(...columns.slice(i).map((v) => v?.[0]?.value)); - break; - } else { - result[i] = value[i]; - } - } - return result; - }, - getOptionByValue(value) { - const options = getValueFromProps(this, 'options'); - if (!(value?.length > 0)) return null; - const result = []; - let item = options.find((v) => v.value === value[0]); - for (let i = 0; i < value.length; i++) { - if (!item) { - return null; - } - result.push({ - value: item.value, - label: item.label, - }); - item = item.children?.find((v) => v.value === value[i + 1]); - } - return result; - }, - onChange(selectedVal) { - let [selectedValue] = resolveEventValues(selectedVal); - const options = getValueFromProps(this, 'options'); - const { columns } = this.data; - const newColumns = this.getterColumns(selectedValue, options); - // columns没变化说明selectedValue在范围内,无需重置 - const newData: any = {}; - if (!equal(columns, newColumns)) { - selectedValue = this.getValidValue(selectedValue, newColumns); - newData.columns = newColumns; - } - newData.currentValue = selectedValue; - this.setData(newData); - triggerEventValues(this, 'change', [ - selectedValue, - this.getOptionByValue(selectedValue), - ]); - }, - async onOk() { - const { currentValue } = this.data; - const options = getValueFromProps(this, 'options'); - const newColumns = this.getterColumns(currentValue, options); - const validValue = this.getValidValue(currentValue, newColumns); - if (!this.isControlled()) { - this.update(validValue); - } - triggerEventValues(this, 'ok', [ - validValue, - this.getOptionByValue(validValue), - ]); - }, - onVisibleChange(visible) { - const options = getValueFromProps(this, 'options'); - const { columns } = this.data; - const realValue = this.getValue(); - if (!this.isVisibleControlled() && visible) { - const newColumns = this.getterColumns(realValue, options); - - if (!equal(columns, newColumns)) { - this.setData({ columns: newColumns }, () => { - this.setData({ - currentValue: this.getValidValue(realValue, newColumns), - formattedValueText: this.onFormat(), - }); - }); - } - } - triggerEvent(this, 'visibleChange', resolveEventValue(visible)); - }, - defaultFormat(value, options) { - if (options) { - return options.map((v) => v.label).join(''); +import { useEvent, useMemo, useEffect, useState } from 'functional-mini/component'; +import { mountComponent } from '../../_util/component'; +import { useComponentEvent } from '../../_util/hooks/useComponentEvent'; +import { useComponentUpdateEffect } from '../../_util/hooks/useLayoutEffect'; +import { useMixState } from '../../_util/hooks/useMixState'; +import { resolveEventValues, resolveEventValue } from '../../_util/platform'; +import { CascaderFunctionalProps, ICascaderProps } from './props'; +import { defaultFormat, getterColumns, getValidValue } from './utils'; + +const CascaderPicker = (props: ICascaderProps) => { + const [ + realValue, + { isControlled: isRealValueControlled, update: updateRealValue }, + ] = useMixState(props.defaultValue, { + value: props.value, + }); + const [{ value, columns }, setState] = useState(() => { + const value = props.value || props.defaultValue || []; + const columns = getterColumns( + props.value || props.defaultValue, + props.options + ); + return { columns, value: value }; + }); + + const { triggerEventOnly, triggerEventValues, triggerEvent } = + useComponentEvent(props); + + useComponentUpdateEffect(() => { + const newColumns = getterColumns(props.value, props.options); + const value = getValidValue(props.value, newColumns); + setState({ value, columns: newColumns }); + }, [ + props.value, + props.options, + /** + * 这里不要删 + * + * 1. picker 触发 onOk + * 2. 更新 realValue + * 3. picker 触发 onFormat (此时 realValue 未更新) + * 4. 依赖里的 realValue 更新 + * 5. 触发组件再次渲染 + * 6. 此时 onFormat 读取到最新的realValue + */ + realValue, + ]); + + function getOptionByValue(value, options) { + if (!(value?.length > 0)) return null; + const result = []; + let item = options.find((v) => v.value === value[0]); + for (let i = 0; i < value.length; i++) { + if (!item) { + return null; } - return ''; - }, - onFormat() { - const realValue = this.getValue(); - const onFormat = getValueFromProps(this, 'onFormat'); - const formatValueByProps = - onFormat && onFormat(realValue, this.getOptionByValue(realValue)); - if (formatValueByProps !== undefined && formatValueByProps !== null) { + result.push({ + value: item.value, + label: item.label, + }); + item = item.children?.find((v) => v.value === value[i + 1]); + } + return result; + } + + useEvent('onCancel', (e) => { + triggerEventOnly('cancel', e); + }); + + const formattedValueText = useMemo(() => { + const { onFormat } = props; + + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat( + realValue, + getOptionByValue(realValue, props.options) + ); + + if (typeof formatValueByProps !== 'undefined') { return formatValueByProps; } - return this.defaultFormat(realValue, this.getOptionByValue(realValue)); - }, + } + return defaultFormat(realValue, getOptionByValue(realValue, props.options)); + }, [realValue]); - onCancel(e) { - triggerEventOnly(this, 'cancel', e); - }, - }, - { - currentValue: [], // 当前picker选中值,didmount、弹窗打开、picker变化时更新 - columns: [], // 可选项,didmound、弹窗打开、picker变化时更新 - formattedValueText: '', - visible: false, - }, - [mixinValue()], - { - /// #if ALIPAY - onInit() { - this.initColumns(); - }, - didUpdate(prevProps, prevData) { - const options = getValueFromProps(this, 'options'); - if (!equal(options, prevProps.options)) { - const { currentValue } = this.data; - const newColumns = this.getterColumns(currentValue, options); - this.setData({ - columns: newColumns, - }); - } - if (!this.isEqualValue(prevData)) { - const realValue = this.getValue(); - const newColumns = this.getterColumns(realValue, options); - const currentValue = this.getValidValue(realValue, newColumns); - this.setData({ currentValue, formattedValueText: this.onFormat() }); - } - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevProps.visible, visible)) { - this.setData({ visible }); + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); + useEffect(() => { + setTimeout(() => { + if (visible) { + const newColumns = getterColumns(realValue, props.options); + const currentValue = getValidValue(realValue, newColumns); + setState({ value: currentValue, columns: newColumns }); } + }) + }, [visible]); + + useEvent('onVisibleChange', (event) => { + const visible = resolveEventValue(event) + if (visible) { + updateVisible(true); + } else { + updateVisible(false); + } + triggerEvent('visibleChange', visible); + }); + + useEvent('onOk', () => { + // 完成时再次校验value,避免visible状态下props无效 + const validValue = getValidValue(value, columns); + + if (!isRealValueControlled) { + setTimeout(() => { + updateRealValue(validValue); + }) + } + + triggerEventValues('ok', [ + validValue, + getOptionByValue(validValue, props.options), + ]); + }); + + useEvent('onChange', (event) => { + const [selectedValue] = resolveEventValues(event); + const newColumns = getterColumns(selectedValue, props.options); + const value = getValidValue(selectedValue, newColumns); + setState({ value, columns: newColumns }); + triggerEventValues('change', [ + selectedValue, + getOptionByValue(selectedValue, props.options), + ]); + }); + + return { + state: { + visible }, - /// #endif - /// #if WECHAT - created() { - this.initColumns(); - }, - observers: { - '**': function (data) { - const prevData = this._prevData || this.data; - this._prevData = { ...data }; - const options = getValueFromProps(this, 'options'); - if (!equal(options, prevData.options)) { - const { currentValue } = this.data; - const newColumns = this.getterColumns(currentValue, options); - this.setData({ - columns: newColumns, - }); - } - if (!this.isEqualValue(prevData)) { - const realValue = this.getValue(); - const newColumns = this.getterColumns(realValue, options); - const currentValue = this.getValidValue(realValue, newColumns); - this.setData({ currentValue, formattedValueText: this.onFormat() }); - } - }, - 'visible': function (data) { - const prevVisible = this._prevVisible; - this._prevVisible = data; - const visible = getValueFromProps(this, 'visible'); - if (this.isVisibleControlled() && !equal(prevVisible, visible)) { - this.setData({ visible }); - } - }, - }, - /// #endif - } -); + formattedValueText, + currentValue: value, + columns, + }; +}; + +mountComponent(CascaderPicker, CascaderFunctionalProps); diff --git a/src/Picker/CascaderPicker/props.ts b/src/Picker/CascaderPicker/props.ts index 09b589ae9..2d2b2d38d 100644 --- a/src/Picker/CascaderPicker/props.ts +++ b/src/Picker/CascaderPicker/props.ts @@ -121,6 +121,14 @@ export interface ICascaderProps extends IBaseProps { } export const CascaderDefaultProps: Partial = { + placeholder: '请选择', + okText: '确定', + cancelText: '取消', + disabled: false, + maskClosable: false, +}; + +export const CascaderFunctionalProps: Partial = { visible: null, defaultVisible: null, animationType: 'transform', diff --git a/src/Picker/index.axml.tsx b/src/Picker/index.axml.tsx index fd5b435b2..3f2597bd2 100644 --- a/src/Picker/index.axml.tsx +++ b/src/Picker/index.axml.tsx @@ -30,9 +30,9 @@ export default ( indicatorStyle, indicatorClassName, options, - emptyText, + emptyText }: TSXMLProps, - { visible, formatValue, selectedIndex, columns }: InternalData + { state, formatValue, selectedIndex, columns }: InternalData ) => ( { - const formatValue = this.getterFormatText(); - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - formatValue, - selectedIndex, - visible: this.isVisibleControlled() ? visible : defaultVisible, - }); - } - ); - }, - getterColumns(options) { - let columns = []; - if (options.length > 0) { - if (options.every((item) => Array.isArray(item))) { - this.single = false; - columns = options.slice(); - } else { - this.single = true; - columns = [options]; - } - } - return columns; - }, - defaultFormat(value, column) { - if (Array.isArray(column)) { - return column - .filter((c) => c !== undefined) - .map(function (c) { - if (typeof c === 'object') { - return c.label; - } - return c; - }) - .join('-'); - } - return (column && column.label) || column || ''; - }, - getterFormatText() { - const [onFormat, formattedValueText] = getValueFromProps(this, [ - 'onFormat', - 'formattedValueText', - ]); - if (typeof formattedValueText === 'string') { - return formattedValueText; - } - const { columns } = this.data; - const realValue = this.getValue(); - const { matchedColumn } = getStrictMatchedItemByValue( - columns, - realValue, - this.single - ); - const formatValueByProps = onFormat && onFormat(realValue, matchedColumn); - if (formatValueByProps !== undefined && formatValueByProps !== null) { - return formatValueByProps; - } - return this.defaultFormat(realValue, matchedColumn); - }, - getterSelectedIndex() { - const selectedIndex = []; - const columns = this.data.columns; - const realValue = this.getValue(); - let value = realValue || []; - if (this.single) { - value = [realValue]; - } - for (let i = 0; i < columns.length; i++) { - const column = columns[i]; - const compareValue = value[i]; - if (compareValue === undefined || compareValue === null) { - selectedIndex[i] = 0; - } - let index = column.findIndex((c) => { - return c === compareValue || c.value === compareValue; - }); - if (index === -1) { - index = 0; - } - selectedIndex[i] = index; - } - return selectedIndex; - }, +const Picker = (props: IPickerProps) => { + const [value, { isControlled: isValueControlled, update: updateValue }] = + useMixState(props.defaultValue ?? [], { + value: props.value, + }); - onOpen() { - const disabled = getValueFromProps(this, 'disabled'); - if (!disabled) { - this.tempSelectedIndex = null; - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex, - }); - this.triggerPicker(true); - } - }, + const { triggerEvent, triggerEventOnly, triggerEventValues } = + useComponentEvent(props); - triggerPicker(visible) { - this.setData({ - visible, - }); - triggerEvent(this, 'visibleChange', visible); - }, + const [visible, { update: updateVisible }] = useMixState( + props.defaultVisible, + { + value: props.visible, + } + ); + const singleRef = useRef(false); + const selectIndexRef = useRef(null); - onMaskDismiss() { - const maskClosable = getValueFromProps(this, 'maskClosable'); - if (!maskClosable) { - return; - } - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'mask' } }); - }, + function triggerPicker(newVisibleValue: boolean) { + updateVisible(newVisibleValue); + triggerEvent('visibleChange', newVisibleValue); + } - onCancel() { - this.triggerPicker(false); - triggerEventOnly(this, 'cancel', { detail: { type: 'cancel' } }); - }, + const [selectedIndex, setSelectedIndex] = useState([]); + + const columns = useMemo(() => { + return getterColumns(props.options, singleRef); + }, [props.options]); - onChange(e) { - const { value: selectedIndex } = e.detail; - this.tempSelectedIndex = selectedIndex; - this.isChangingPickerView = true; - const { matchedColumn, matchedValues } = getMatchedItemByIndex( - this.data.columns, - this.tempSelectedIndex, - this.single + useEffect(() => { + selectIndexRef.current = null; + setSelectedIndex(getterSelectedIndex(columns, value, singleRef)); + }, [columns, value]); + + const formatValue = useMemo(() => { + if (typeof props.formattedValueText === 'string') { + return props.formattedValueText; + } + const formatValue = getterFormatText( + columns, + value, + props.onFormat, + singleRef + ); + return formatValue; + }, [props.formattedValueText, visible, columns, value, props.onFormat]); + + useEvent('onOpen', () => { + if (props.disabled) { + return; + } + selectIndexRef.current = null; + const selectedIndex = getterSelectedIndex(columns, value, singleRef); + setSelectedIndex(selectedIndex); + triggerPicker(true); + }); + + useEvent('onCancel', () => { + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'cancel' } }); + }); + + useEvent('onMaskDismiss', () => { + if (!props.maskClosable) { + return; + } + triggerPicker(false); + triggerEventOnly('cancel', { detail: { type: 'mask' } }); + }); + + useEvent('onChange', (e) => { + const { value: selectedIndex } = e.detail; + const { matchedColumn, matchedValues } = getMatchedItemByIndex( + columns, + selectedIndex, + singleRef + ); + selectIndexRef.current = selectedIndex; + setSelectedIndex(selectedIndex); + triggerEventValues('change', [matchedValues, matchedColumn], e); + }); + + useEvent('onOk', () => { + let result; + if (selectIndexRef.current) { + result = getMatchedItemByIndex( + columns, + selectIndexRef.current, + singleRef ); - this.setData({ - selectedIndex, - }); - triggerEventValues(this, 'change', [matchedValues, matchedColumn], e); - }, + } else { + result = getMatchedItemByValue(columns, value, singleRef); + } - async onOk() { - let result; - if (this.tempSelectedIndex) { - result = getMatchedItemByIndex( - this.data.columns, - this.tempSelectedIndex, - this.single - ); - } else { - result = getMatchedItemByValue( - this.data.columns, - this.getValue(), - this.single - ); - } - const { matchedColumn, matchedValues } = result; - this.triggerPicker(false); - if (!this.isControlled()) { - this.update(matchedValues); - } - triggerEventValues(this, 'ok', [matchedValues, matchedColumn]); - }, - }, - { - formatValue: '', - columns: [], - visible: false, - selectedIndex: [], - }, - [ - mixinValue({ - transformValue(value) { - return { - needUpdate: true, - value: value === undefined ? [] : value, - }; - }, - }), - ], - { - tempSelectedIndex: null, - single: false, - isChangingPickerView: false, - /// #if ALIPAY - onInit() { - this.initData(); - }, - didUpdate(prevProps) { - const options = getValueFromProps(this, 'options'); - if (!equal(options, prevProps.options)) { - const newColums = this.getterColumns(options); - this.setData( - { - columns: newColums, - }, - () => { - // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 - if (!this.isChangingPickerView) { - this.tempSelectedIndex = null; - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex, - }); - } - } - ); - } - const value = getValueFromProps(this, 'value'); - if (!equal(prevProps.value, value)) { - const selectedIndex = this.getterSelectedIndex(); - this.tempSelectedIndex = null; - this.setData({ - selectedIndex, - }); - } - const visible = getValueFromProps(this, 'visible'); - if (!equal(prevProps.visible, visible)) { - this.setData({ visible }); - } - const formatValue = this.getterFormatText(); - const formattedValueText = getValueFromProps(this, 'formattedValueText'); - if ( - formatValue !== this.data.formatValue || - prevProps.formattedValueText !== formattedValueText - ) { - this.setData({ - formatValue, - }); - } - this.isChangingPickerView = false; - }, - /// #endif - /// #if WECHAT - created() { - this.initData(); - }, - observers: { - 'options': function () { - const options = getValueFromProps(this, 'options'); - const newColums = this.getterColumns(options); - this.setData( - { - columns: newColums, - }, - () => { - // 如果是在滚动过程中columns发生变化,以onChange里抛出的selectedIndex为准 - if (!this.isChangingPickerView) { - this.tempSelectedIndex = null; - const selectedIndex = this.getterSelectedIndex(); - this.setData({ - selectedIndex, - }); - } - this.isChangingPickerView = false; - } - ); - }, - 'value': function () { - const selectedIndex = this.getterSelectedIndex(); - this.tempSelectedIndex = null; - this.setData({ - selectedIndex, - }); - }, - 'visible': function () { - const visible = getValueFromProps(this, 'visible'); - if (this.data.visible !== visible) { - this.setData({ - visible, - }); - } - }, - 'formattedValueText': function () { - const formattedValueText = getValueFromProps( - this, - 'formattedValueText' - ); - this.setData({ - formatValue: formattedValueText, - }); - }, - '**': function () { - const formatValue = this.getterFormatText(); - if (formatValue !== this.data.formatValue) { - this.setData({ - formatValue, - }); - } - }, - }, - /// #endif - } -); + const { matchedColumn, matchedValues } = result; + + triggerPicker(false); + if (!isValueControlled) { + updateValue(matchedValues); + } + triggerEventValues('ok', [matchedValues, matchedColumn]); + }); + + return { + formatValue, + selectedIndex, + columns, + state: { + visible, + }, + mixin: { + value, + }, + }; +}; + +mountComponent(Picker, PickerFunctionalProps); diff --git a/src/Picker/props.ts b/src/Picker/props.ts index 3d2eab5a1..e5c75a091 100644 --- a/src/Picker/props.ts +++ b/src/Picker/props.ts @@ -54,7 +54,7 @@ export interface IPickerProps extends IBaseProps { * @default '请选择' */ placeholder: string; - /** + /** * @description 空状态提示文案 * @default '暂无数据' */ @@ -131,6 +131,17 @@ export interface IPickerProps extends IBaseProps { } export const PickerDefaultProps: Partial = { + okText: '确定', + cancelText: '取消', + disabled: false, + maskClosable: false, + options: [], + placeholder: '请选择', + defaultValue: [], + emptyText: '暂无数据' +}; + +export const PickerFunctionalProps: Partial = { formattedValueText: null, visible: null, defaultVisible: null, @@ -147,5 +158,5 @@ export const PickerDefaultProps: Partial = { popStyle: '', maskClosable: true, onFormat: null, - emptyText: '暂无数据', + emptyText: '暂无数据' }; diff --git a/src/Picker/utils.ts b/src/Picker/utils.ts index e3a9a1eb0..9ec50878d 100644 --- a/src/Picker/utils.ts +++ b/src/Picker/utils.ts @@ -1,3 +1,5 @@ +import { PickerValue } from './props'; + function getColumnValue(columnItem) { if (typeof columnItem === 'object') return columnItem.value; return columnItem; @@ -12,7 +14,7 @@ export function getStrictMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = (value || [])[i]; + const compareValue = value[i]; index = column.findIndex((c) => { const columnValue = getColumnValue(c); return columnValue === compareValue; @@ -27,8 +29,8 @@ export function getStrictMatchedItemByValue(columns, value, single) { } // 如果找不到value对应的item项目,返回第一项 -export function getMatchedItemByValue(columns, value, single) { - if (single) { +export function getMatchedItemByValue(columns, value, singleRef) { + if (singleRef.current) { value = [value]; } const matchedValues = []; @@ -36,7 +38,7 @@ export function getMatchedItemByValue(columns, value, single) { let index = null; for (let i = 0; i < columns.length; i++) { const column = columns[i]; - const compareValue = (value || [])[i]; + const compareValue = value[i]; if (compareValue === undefined || compareValue === null) { index = 0; } else { @@ -52,8 +54,8 @@ export function getMatchedItemByValue(columns, value, single) { matchedValues[i] = getColumnValue(column[index]); } return { - matchedColumn: single ? matchedColumn[0] : matchedColumn, - matchedValues: single ? matchedValues[0] : matchedValues, + matchedColumn: singleRef.current ? matchedColumn[0] : matchedColumn, + matchedValues: singleRef.current ? matchedValues[0] : matchedValues, }; } @@ -82,7 +84,75 @@ export function getMatchedItemByIndex(columns, selectedIndex, single) { } return { - matchedColumn: single ? matchedColumn[0] : matchedColumn, - matchedValues: single ? matchedValues[0] : matchedValues, + matchedColumn: single.current ? matchedColumn[0] : matchedColumn, + matchedValues: single.current ? matchedValues[0] : matchedValues, }; } + +export function getterColumns(options: PickerValue[], singleRef) { + let columns = []; + if (options.length > 0) { + if (options.every((item) => Array.isArray(item))) { + singleRef.current = false; + columns = options.slice(); + } else { + singleRef.current = true; + columns = [options]; + } + } + return columns; +} + +export function defaultFormat(value, column) { + if (Array.isArray(column)) { + return column + .filter((c) => c !== undefined) + .map(function (c) { + if (typeof c === 'object') { + return c.label; + } + return c; + }) + .join('-'); + } + return (column && column.label) || column || ''; +} + +export function getterFormatText(columns, realValue, onFormat, singleRef) { + const { matchedColumn } = getStrictMatchedItemByValue( + columns, + realValue, + singleRef.current + ); + + if (typeof onFormat === 'function') { + const formatValueByProps = onFormat(realValue, matchedColumn); + if (formatValueByProps !== undefined) { + return formatValueByProps; + } + } + return defaultFormat(realValue, matchedColumn); +} + +export function getterSelectedIndex(columns, realValue, sinefileRef) { + const selectedIndex = []; + let value = realValue || []; + if (sinefileRef.current) { + value = [realValue]; + } + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + const compareValue = value[i]; + if (compareValue === undefined || compareValue === null) { + selectedIndex[i] = 0; + } + let index = column.findIndex((c) => { + return c === compareValue || c.value === compareValue; + }); + if (index === -1) { + index = 0; + } + selectedIndex[i] = index; + } + return selectedIndex; +} diff --git a/src/Popover/index.json b/src/Popover/index.json index 6083004a5..0c9094440 100644 --- a/src/Popover/index.json +++ b/src/Popover/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "mask": "../Mask/index" } diff --git a/src/Popup/index.json b/src/Popup/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Popup/index.json +++ b/src/Popup/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Progress/index.json b/src/Progress/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Progress/index.json +++ b/src/Progress/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Radio/RadioGroup/index.json b/src/Radio/RadioGroup/index.json index 857c3e722..787ac5732 100644 --- a/src/Radio/RadioGroup/index.json +++ b/src/Radio/RadioGroup/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "list": "../../List/index", "list-item": "../../List/ListItem/index", diff --git a/src/Radio/index.json b/src/Radio/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Radio/index.json +++ b/src/Radio/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/RareWordsKeyboard/index.json b/src/RareWordsKeyboard/index.json index 63e881845..6b2389527 100644 --- a/src/RareWordsKeyboard/index.json +++ b/src/RareWordsKeyboard/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "result": "../Result/index", diff --git a/src/RareWordsKeyboard/index.ts b/src/RareWordsKeyboard/index.ts index 32bc29244..2f8181793 100644 --- a/src/RareWordsKeyboard/index.ts +++ b/src/RareWordsKeyboard/index.ts @@ -1,149 +1,159 @@ -import { Component, triggerEvent, triggerEventOnly } from '../_util/simply'; import { PINYIN_MAP } from './constants'; -import { RareWordsKeyboardProps } from './props'; +import { RareWordsKeyboardProps, IRareWordsKeyboardProps } from './props'; import { formatZDatas, loadFontFace, matchWordsRecommend } from './utils'; import { ZDATAS } from './zdatas'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; +import '../_util/assert-component2'; +import { useEffect, useEvent, useState } from 'functional-mini/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { mountComponent } from '../_util/component'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; const wordsData = formatZDatas(ZDATAS.datas); -Component( - RareWordsKeyboardProps, - { - getInstance() { - if (this.$id) { - return my; - } - return this; - }, - async getBoundingClientRect(query: string) { - return await getInstanceBoundingClientRect(this.getInstance(), query); - }, - // 隐藏键盘,失去焦点 - handleHide() { - this.setData({ - inputValue: [], - matchWordsList: [], - displayStr: '', - showMoreWords: false, - }); - triggerEventOnly(this, 'close'); - }, - - // 点击键盘key值 - handleKeyClick(e) { - if (this.data.loading) return; - const { value = '' } = e.currentTarget.dataset; - if (!value) return; - const inputValue = [...this.data.inputValue, value]; - this.setData({ - inputValue: [...inputValue], - ...this.computeMatchWords(inputValue), - }); - }, - - // 点击删除 - handleDelete() { - const inputValue = [...this.data.inputValue]; - if (this.data.inputValue.length === 0) return; - inputValue.pop(); - this.setData({ - inputValue: [...inputValue], - ...this.computeMatchWords(inputValue), - }); - }, - - // 计算展示值和候选字列表 - computeMatchWords(inputValue) { - const displayStr = Array.isArray(inputValue) - ? inputValue.join('') - : inputValue; - const curMatchWords = matchWordsRecommend(wordsData, displayStr); - return { - displayStr, - matchWordsList: curMatchWords, - }; - }, - - // 点击查看更多 - hanleLookMore() { - if (this.data.matchWordsList.length <= this.data.maxDisplayNum) { - this.handleHide(); - return; - } - this.setData({ - showMoreWords: !this.data.showMoreWords, - }); - }, - - // 计算每行可以展示的最大字数 - async computeMaxDisplayNum() { - const [singleWords, wordsWrap] = await Promise.all([ - this.getBoundingClientRect( - '.ant-rare-words-keyboard-match_words_hidden' - ), - this.getBoundingClientRect( - '.ant-rare-words-keyboard-match_words_inner' - ), - ]); - if (!wordsWrap?.width || !singleWords?.width) return; - const maxDisplayNumInOneLine = parseInt( - (wordsWrap?.width / singleWords?.width).toString(), - 10 - ); - this.setData({ maxDisplayNum: maxDisplayNumInOneLine }); - }, - - // 加载字体 - loadFont() { - this.setData({ - loading: true, - }); - loadFontFace() - .then(() => { - this.setData({ showErrorPage: false, loading: false }); - }) - .catch((err) => { - this.setData({ showErrorPage: true, loading: false }); - triggerEvent(this, 'error', err); - }); - }, - - // 点击重试 - handleRetry() { - this.loadFont(); - }, - - handleWordClick(e) { - const { value = '' } = e.currentTarget.dataset; - if (!value) return; - triggerEvent(this, 'change', value); - this.handleHide(); - }, - }, - { +const RareWordsKeyboard = (props: IRareWordsKeyboardProps) => { + const [fontState, setFontState] = useState({ + showErrorPage: false, // 是否展示错误页 loading: false, + }); + const [maxDisplayNum, setMaxDisplayNum] = useState(0); + const [keyboardState, setKeyboardState] = useState({ inputValue: [], // 已输入的字符数组 displayStr: '', // 已输入的字符串 matchWordsList: [], // 候选字列表 showMoreWords: false, // 是否展示更多候选字 - pinyinMaps: PINYIN_MAP, // 拼音键盘 - maxDisplayNum: 0, // 一行最多展示的字数 - showErrorPage: false, // 是否展示错误页 - }, - null, - { - /// #if ALIPAY - didMount() { - this.loadFont(); - this.computeMaxDisplayNum(); - }, - /// #endif - /// #if WECHAT - attached() { - this.loadFont(); - this.computeMaxDisplayNum(); - }, - /// #endif + }); + + const { triggerEvent, triggerEventOnly } = useComponentEvent(props); + + const handleHide = useStableCallback(() => { + setKeyboardState({ + inputValue: [], + matchWordsList: [], + displayStr: '', + showMoreWords: false, + }); + triggerEventOnly('close'); + }); + + // 计算展示值和候选字列表 + function computeMatchWords(inputValue) { + const displayStr = Array.isArray(inputValue) + ? inputValue.join('') + : inputValue; + const curMatchWords = matchWordsRecommend(wordsData, displayStr); + return { + displayStr, + matchWordsList: curMatchWords, + }; + } + function loadFont() { + setFontState((pre) => { + return { + ...pre, + loading: true, + }; + }); + loadFontFace() + .then(() => { + setFontState({ showErrorPage: false, loading: false }); + }) + .catch((err) => { + setFontState({ showErrorPage: true, loading: false }); + triggerEvent('error', err); + }); + } + + const { getBoundingClientRect } = useInstanceBoundingClientRect(); + async function computeMaxDisplayNum() { + const [singleWords, wordsWrap] = await Promise.all([ + getBoundingClientRect('.ant-rare-words-keyboard-match_words_hidden'), + getBoundingClientRect('.ant-rare-words-keyboard-match_words_inner'), + ]); + if (!wordsWrap?.width || !singleWords?.width) return; + const maxDisplayNumInOneLine = parseInt( + (wordsWrap?.width / singleWords?.width).toString(), + 10 + ); + setMaxDisplayNum(maxDisplayNumInOneLine); } -); + + useEffect(() => { + loadFont(); + computeMaxDisplayNum(); + }, []); + + useEvent('handleRetry', () => { + loadFont(); + }); + + useEvent('handleWordClick', (e) => { + const { value = '' } = e.currentTarget.dataset; + if (!value) return; + triggerEvent('change', value); + handleHide(); + }); + + useEvent('hanleLookMore', () => { + if (keyboardState.matchWordsList.length <= maxDisplayNum) { + handleHide(); + return; + } + setKeyboardState((old) => { + return { + ...old, + showMoreWords: !old.showMoreWords, + }; + }); + }); + + // 隐藏键盘,失去焦点 + useEvent('handleHide', () => { + handleHide(); + }); + + // 点击键盘key值 + useEvent('handleKeyClick', (e) => { + if (fontState.loading) { + return; + } + const { value = '' } = e.target.dataset; + if (!value) { + return; + } + + setKeyboardState((old) => { + const inputValue = [...old.inputValue, value]; + return { + ...old, + inputValue, + ...computeMatchWords(inputValue), + }; + }); + }); + + // 点击删除 + useEvent('handleDelete', () => { + if (keyboardState.inputValue.length === 0) { + return; + } + setKeyboardState((old) => { + const inputValue = [...old.inputValue]; + inputValue.pop(); + return { + ...old, + inputValue: [...inputValue], + ...computeMatchWords(inputValue), + }; + }); + }); + + return { + ...fontState, + maxDisplayNum, + ...keyboardState, + pinyinMaps: PINYIN_MAP, // 拼音键盘 + }; +}; + +mountComponent(RareWordsKeyboard, RareWordsKeyboardProps); diff --git a/src/Rate/index.json b/src/Rate/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Rate/index.json +++ b/src/Rate/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Result/index.json b/src/Result/index.json index 5b3034c4a..188dcef68 100644 --- a/src/Result/index.json +++ b/src/Result/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "icon": "../Icon/index", "image-icon": "../ImageIcon/index" diff --git a/src/Selector/index.json b/src/Selector/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Selector/index.json +++ b/src/Selector/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/Avatar/index.json b/src/Skeleton/Avatar/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Skeleton/Avatar/index.json +++ b/src/Skeleton/Avatar/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/Button/index.json b/src/Skeleton/Button/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Skeleton/Button/index.json +++ b/src/Skeleton/Button/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/Input/index.json b/src/Skeleton/Input/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Skeleton/Input/index.json +++ b/src/Skeleton/Input/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/Paragraph/index.json b/src/Skeleton/Paragraph/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Skeleton/Paragraph/index.json +++ b/src/Skeleton/Paragraph/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/Title/index.json b/src/Skeleton/Title/index.json index d9c3ee8be..a89ef4dbe 100644 --- a/src/Skeleton/Title/index.json +++ b/src/Skeleton/Title/index.json @@ -1,5 +1,4 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": {} } diff --git a/src/Skeleton/index.json b/src/Skeleton/index.json index 85c588cb3..04b9328d7 100644 --- a/src/Skeleton/index.json +++ b/src/Skeleton/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "avatar": "./Avatar/index", "paragraph": "./Paragraph/index", diff --git a/src/Slider/index.json b/src/Slider/index.json index adb9f384f..66ee617da 100644 --- a/src/Slider/index.json +++ b/src/Slider/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "popover": "../Popover/index" } diff --git a/src/Slider/index.ts b/src/Slider/index.ts index 23355ecdd..2308c6312 100644 --- a/src/Slider/index.ts +++ b/src/Slider/index.ts @@ -261,7 +261,11 @@ Component( typeof this.onChangeValue === 'undefined' ? this.getValue() : this.onChangeValue; - if (emit && !this.isSliderValueEqual(this.onChangeValue, value)) { + if ( + emit && + getValueFromProps(this, 'onChange') && + !this.isSliderValueEqual(this.onChangeValue, value) + ) { this.onChangeValue = value; triggerEvent(this, 'change', value); } diff --git a/src/Stepper/index.json b/src/Stepper/index.json index 4ea7f8f97..12bdacc36 100644 --- a/src/Stepper/index.json +++ b/src/Stepper/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-button": "../Button/index", "ant-input": "../Input/InputBlur/index" diff --git a/src/Steps/index.json b/src/Steps/index.json index dc5676ea5..467ce2945 100644 --- a/src/Steps/index.json +++ b/src/Steps/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/SwipeAction/index.json b/src/SwipeAction/index.json index dc5676ea5..32640e0dc 100644 --- a/src/SwipeAction/index.json +++ b/src/SwipeAction/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" -} + "component": true +} \ No newline at end of file diff --git a/src/Switch/index.json b/src/Switch/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Switch/index.json +++ b/src/Switch/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/TabBar/index.json b/src/TabBar/index.json index 5b443dea3..a7c04bf5b 100644 --- a/src/TabBar/index.json +++ b/src/TabBar/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-badge": "../Badge/index", "image-icon": "../ImageIcon/index" diff --git a/src/Tabs/index.json b/src/Tabs/index.json index dc5676ea5..467ce2945 100644 --- a/src/Tabs/index.json +++ b/src/Tabs/index.json @@ -1,4 +1,3 @@ { - "component": true, - "lazyCodeLoading": "renderedComponents" + "component": true } diff --git a/src/Tabs/index.ts b/src/Tabs/index.ts index 559658aa0..c7d992588 100644 --- a/src/Tabs/index.ts +++ b/src/Tabs/index.ts @@ -1,192 +1,194 @@ -import { Component, triggerEvent, getValueFromProps } from '../_util/simply'; -import { TabsDefaultProps } from './props'; -import createValue from '../mixins/value'; -import { getInstanceBoundingClientRect } from '../_util/jsapi/get-instance-bounding-client-rect'; +import { useState } from 'functional-mini/compat'; +import { + useDidMount, + useEvent, + useReady, + useRef, +} from 'functional-mini/component'; +import '../_util/assert-component2'; +import { mountComponent } from '../_util/component'; +import { useComponentEvent } from '../_util/hooks/useComponentEvent'; +import { useEvent as useStableCallback } from '../_util/hooks/useEvent'; +import { useInstanceBoundingClientRect } from '../_util/hooks/useInstanceBoundingClientRect'; +import { useComponentUpdateEffect } from '../_util/hooks/useLayoutEffect'; +import { useMixState } from '../_util/hooks/useMixState'; +import { ITabsProps, TabsFunctionalProps } from './props'; -Component( - TabsDefaultProps, - { - getInstance() { - if (this.$id) { - return my; - } - return this; - }, - get$Id() { - return this.$id ? `-${this.$id}` : ''; - }, - async getBoundingClientRect(query: string) { - return await getInstanceBoundingClientRect(this.getInstance(), query); - }, - async updateFade() { - this.setData({ - leftFade: !!this.scrollLeft, - }); - const items = getValueFromProps(this, 'items'); - const [view, item] = await Promise.all([ - this.getBoundingClientRect(`#ant-tabs-bar-scroll-view${this.get$Id()}`), - this.getBoundingClientRect( - `#ant-tabs-bar-item${this.get$Id()}-${items.length - 1}` - ), - ]); - if (!item || !view) { - return; - } - this.setData({ - rightFade: item.left + item.width / 2 > view.width, - }); - }, - async updateScroll() { - const current = this.getValue(); - const [view, item] = await Promise.all([ - this.getBoundingClientRect(`#ant-tabs-bar-scroll-view${this.get$Id()}`), - this.getBoundingClientRect( - `#ant-tabs-bar-item${this.get$Id()}-${current}` - ), - ]); +const Tabs = (props: ITabsProps) => { + const [currentValue, { isControlled, update }] = useMixState( + props.defaultCurrent, + { + value: props.current, + } + ); - if (!view || !item) { - return; - } + const [state, updateState] = useState({ + scrollLeft: 0, + scrollTop: 0, + leftFade: false, + rightFade: false, + }); + const scrollRef = useRef({ scrollLeft: 0, scrollTop: 0 }); - const [direction, scrollMode] = getValueFromProps(this, [ - 'direction', - 'scrollMode', - ]); - if (direction === 'vertical') { - let scrollTop = this.scrollTop || 0; - let needScroll = false; - if (scrollMode === 'center') { - needScroll = true; - scrollTop += - item.top - view.top - Math.max((view.height - item.height) / 2, 0); - } else { - const distance = item.top - view.top; - if (distance < 0) { - scrollTop += distance; - needScroll = true; - } else if (distance + item.height > view.height) { - scrollTop += Math.min( - distance + item.height - view.height, - distance - ); - needScroll = true; - } - } - if (needScroll) { - if (scrollTop === this.data.scrollTop) { - scrollTop += Math.random(); - } - this.setData({ - scrollTop, - }); - } - return; - } - let scrollLeft = this.scrollLeft || 0; + const { triggerEvent } = useComponentEvent(props); + + const updatePartState = (part) => { + updateState((old) => { + return { + ...old, + ...part, + }; + }); + }; + + const { getBoundingClientRectWithBuilder, getBoundingClientRect } = + useInstanceBoundingClientRect(); + + const updateFade = useStableCallback(async () => { + updatePartState({ + leftFade: !!scrollRef.current.scrollLeft, + }); + const [view, item] = await Promise.all([ + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-scroll-view${id}` + ), + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-item${id}-${props.items.length - 1}` + ), + ]); + if (!item || !view) { + return; + } + updatePartState({ + rightFade: item.left + item.width / 2 > view.width, + }); + }); + + const updateScroll = useStableCallback(async () => { + const current = currentValue; + const [view, item] = await Promise.all([ + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-scroll-view${id}` + ), + getBoundingClientRectWithBuilder( + (id) => `#ant-tabs-bar-item${id}-${current}` + ), + ]); + if (!view || !item) { + return; + } + + if (props.direction === 'vertical') { + let scrollTop = scrollRef.current.scrollTop || 0; let needScroll = false; - if (scrollMode === 'center') { + if (props.scrollMode === 'center') { needScroll = true; - scrollLeft += - item.left - view.left - Math.max((view.width - item.width) / 2, 0); + scrollTop += + item.top - view.top - Math.max((view.height - item.height) / 2, 0); } else { - const distance = item.left - view.left; + const distance = item.top - view.top; if (distance < 0) { - scrollLeft += distance; + scrollTop += distance; needScroll = true; - } else if (distance + item.width > view.width) { - scrollLeft += Math.min(distance + item.width - view.width, distance); + } else if (distance + item.height > view.height) { + scrollTop += Math.min(distance + item.height - view.height, distance); needScroll = true; } } if (needScroll) { - if (scrollLeft === this.data.scrollLeft) { - scrollLeft += Math.random(); + if (scrollTop === state.scrollTop) { + scrollTop += Math.random(); } - this.setData({ - scrollLeft, + updatePartState({ + scrollTop, }); - this.updateFade(); } - }, - async onScroll(e) { - const direction = getValueFromProps(this, 'direction'); - if (direction === 'vertical') { - this.scrollTop = e.detail.scrollTop; - return; - } - this.scrollLeft = e.detail.scrollLeft; - this.updateFade(); - }, - onChange(e) { - const index = parseInt(e.currentTarget.dataset.index, 10); - const items = getValueFromProps(this, 'items'); - if (items[index].disabled) { - return; + return; + } + let scrollLeft = scrollRef.current.scrollLeft || 0; + let needScroll = false; + if (props.scrollMode === 'center') { + needScroll = true; + scrollLeft += + item.left - view.left - Math.max((view.width - item.width) / 2, 0); + } else { + const distance = item.left - view.left; + if (distance < 0) { + scrollLeft += distance; + needScroll = true; + } else if (distance + item.width > view.width) { + scrollLeft += Math.min(distance + item.width - view.width, distance); + needScroll = true; } - if (this.getValue() === index) { - return; + } + if (needScroll) { + if (scrollLeft === state.scrollLeft) { + scrollLeft += Math.random(); } - if (!this.isControlled()) { - this.update(index); + updatePartState({ + scrollLeft, + }); + updateFade(); + } + }); + + useEvent('onScroll', async (e) => { + if (props.direction === 'vertical') { + scrollRef.current.scrollTop = e.detail.scrollTop; + return; + } + scrollRef.current.scrollLeft = e.detail.scrollLeft; + updateFade(); + }); + + useEvent('onChange', async (e) => { + const index = parseInt(e.currentTarget.dataset.index, 10); + if (props.items[index].disabled) { + return; + } + if (currentValue === index) { + return; + } + if (!isControlled) { + update(index); + } + triggerEvent('change', index, e); + }); + + /// #if ALIPAY + useDidMount(() => { + updateScroll(); + }, []); + /// #endif + + useComponentUpdateEffect(() => { + updateScroll(); + }, [props.items, currentValue]); + + /// #if WECHAT + const [scrollHeight, setScrollHeight] = useState( + // vertical 模式下,不需要设置高度 + props.direction === 'vertical' ? 0 : 40 + ); + useReady(() => { + updateScroll(); + getBoundingClientRect('.ant-tabs-bar-item').then((res) => { + if (res && res.height > 0 && props.direction !== 'vertical') { + setScrollHeight(res.height); } + }); + }, []); + /// #endif - triggerEvent(this, 'change', index, e); - }, - }, - { + return { /// #if WECHAT - scrollHeight: 0, + scrollHeight, /// #endif - scrollLeft: 0, - scrollTop: 0, - leftFade: false, - rightFade: false, - }, - [ - createValue({ - valueKey: 'current', - defaultValueKey: 'defaultCurrent', - }), - ], - { - scrollLeft: 0, - scrollTop: 0, - /// #if ALIPAY - didMount() { - this.updateScroll(); - }, - didUpdate(prevProps, prevData) { - const items = getValueFromProps(this, 'items'); - if (prevProps.items !== items || !this.isEqualValue(prevData)) { - this.updateScroll(); - } - }, - /// #endif - /// #if WECHAT - ready() { - this.updateScroll(); - this.getBoundingClientRect('.ant-tabs-bar-item').then((res) => { - const direction = getValueFromProps(this, 'direction'); - if (res && res.height > 0 && direction !== 'vertical') { - this.setData({ - scrollHeight: res.height, - }); - } else { - this.setData({ - scrollHeight: direction === 'vertical' ? 0 : 40, - }); - } - }); + mixin: { + value: currentValue, }, - observers: { - 'items': function () { - this.updateScroll(); - }, - 'mixin.current': function () { - this.updateScroll(); - }, - }, - /// #endif - } -); + ...state, + }; +}; + +mountComponent(Tabs, TabsFunctionalProps); diff --git a/src/Tabs/props.ts b/src/Tabs/props.ts index 7bb52cd9b..1bd4707be 100644 --- a/src/Tabs/props.ts +++ b/src/Tabs/props.ts @@ -58,6 +58,13 @@ export interface ITabsProps extends IBaseProps { } export const TabsDefaultProps: Partial = { + type: 'basic', + defaultCurrent: 0, + items: [], + scrollMode: 'edge', +}; + +export const TabsFunctionalProps: Partial = { type: 'basic', direction: 'horizontal', current: null, diff --git a/src/Tag/index.json b/src/Tag/index.json index 6cf21ce24..090c137c7 100644 --- a/src/Tag/index.json +++ b/src/Tag/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "ant-icon": "../Icon/index" } diff --git a/src/Toast/index.json b/src/Toast/index.json index 1d101cb6b..0918a24ce 100644 --- a/src/Toast/index.json +++ b/src/Toast/index.json @@ -1,6 +1,5 @@ { "component": true, - "lazyCodeLoading": "renderedComponents", "usingComponents": { "am-icon": "../Icon/index", "mask": "../Mask/index", diff --git a/src/_util/component.ts b/src/_util/component.ts new file mode 100644 index 000000000..0983dce4c --- /dev/null +++ b/src/_util/component.ts @@ -0,0 +1,44 @@ +import { alipayComponent, wechatComponent } from 'functional-mini/component'; + +function removeNullProps(props) { + const newProps = {}; + for (const key in props) { + if (props[key] !== null) { + newProps[key] = props[key]; + } + } + return newProps; +} + +export function mountComponent( + Hooks: (props: T) => unknown, + defaultProps: T +) { + /// #if WECHAT + Component( + wechatComponent(Hooks, mergeDefaultProps(defaultProps) as unknown as T, { + options: { + styleIsolation: 'shared', + multipleSlots: true, + virtualHost: true, + }, + }) + ); + /// #endif + + /// #if ALIPAY + Component( + alipayComponent(Hooks, removeNullProps(mergeDefaultProps(defaultProps))) + ); + /// #endif +} + +function mergeDefaultProps(defaultProps: Record = {}) { + return { + /// #if WECHAT + className: '', + style: '', + /// #endif + ...defaultProps, + }; +} diff --git a/src/_util/hooks/useComponentEvent.ts b/src/_util/hooks/useComponentEvent.ts new file mode 100644 index 000000000..cdfb318fa --- /dev/null +++ b/src/_util/hooks/useComponentEvent.ts @@ -0,0 +1,96 @@ +import { useComponent } from 'functional-mini/component'; +import fmtEvent from '../fmtEvent'; +import { useEvent } from './useEvent'; + +export function useComponentEvent(props: T) { + const component = useComponent(); + const triggerEvent = useEvent( + (eventName: string, value: unknown, e?: any) => { + // 首字母大写,然后加上 on + + /// #if ALIPAY + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](value, fmtEvent(props, e)); + } + /// #endif + + /// #if WECHAT + component.triggerEvent(eventName.toLocaleLowerCase(), value); + /// #endif + } + ); + + const triggerEventValues = useEvent( + (eventName: string, values: any[], e?: any) => { + // 首字母大写,然后加上 on + + /// #if ALIPAY + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](...values, fmtEvent(props, e)); + } + /// #endif + + /// #if WECHAT + component.triggerEvent(eventName.toLocaleLowerCase(), values); + /// #endif + } + ); + const triggerEventOnly = useEvent((eventName: string, e?: any) => { + // 首字母大写,然后加上 on + + /// #if ALIPAY + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + /// #endif + + /// #if WECHAT + component.triggerEvent(eventName.toLocaleLowerCase()); + /// #endif + }); + + const alipayForwardCatchEvent = useEvent((eventName: string, e: any) => { + // 首字母大写,然后加上 catch + + /// #if ALIPAY + const alipayCallbackName = + 'catch' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + /// #endif + }); + + const alipayForwardEvent = useEvent((eventName: string, e: any) => { + // 首字母大写,然后加上 on + + /// #if ALIPAY + const alipayCallbackName = + 'on' + eventName.charAt(0).toUpperCase() + eventName.slice(1); + + if (props[alipayCallbackName]) { + props[alipayCallbackName](fmtEvent(props, e)); + } + /// #endif + }); + + return { + triggerEvent, + triggerEventValues, + triggerEventOnly, + // 转发 catch 事件 + alipayForwardCatchEvent, + // 转发事件 + alipayForwardEvent, + }; +} diff --git a/src/_util/hooks/useEvent.ts b/src/_util/hooks/useEvent.ts new file mode 100644 index 000000000..665c6e811 --- /dev/null +++ b/src/_util/hooks/useEvent.ts @@ -0,0 +1,18 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useEvent.ts + */ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import * as React from 'functional-mini/compat'; + +// eslint-disable-next-line @typescript-eslint/ban-types +export function useEvent(callback: T): T { + const fnRef = React.useRef(); + fnRef.current = callback; + + const memoFn = React.useCallback( + ((...args: any) => fnRef.current?.(...args)) as any, + [] + ); + + return memoFn; +} diff --git a/src/_util/hooks/useHandleCustomEvent.ts b/src/_util/hooks/useHandleCustomEvent.ts new file mode 100644 index 000000000..6a2319ba7 --- /dev/null +++ b/src/_util/hooks/useHandleCustomEvent.ts @@ -0,0 +1,77 @@ +import { useEvent } from 'functional-mini/component'; +import { platform } from '../platform'; + +export type EventHandler = (value: T, e: any) => void; + +export const useHandleCustomEvent = ( + eventName: string, + handler: EventHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (eventOrValue: any, alipayEvent?: any) => { + /// #if ALIPAY + if (platform() === 'alipay') { + return handler(eventOrValue, alipayEvent); + } + /// #endif + + /// #if WECHAT + return handler(eventOrValue.detail, eventOrValue); + /// #endif + } + ); +}; + +export type MultipleValueEventHandler = (...args: any[]) => void; + +export const useMultipleValueHandleCustomEvent = ( + eventName: string, + handler: MultipleValueEventHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (...args: any[]) => { + /// #if ALIPAY + if (platform() === 'alipay') { + return handler(...args); + } + /// #endif + + /// #if WECHAT + const firstArgs = args[0]; + if (Array.isArray(firstArgs.detail)) { + const wechatArgs = firstArgs.detail.concat(firstArgs); + return handler(...wechatArgs); + } else { + return handler([firstArgs.detail, firstArgs]); + } + /// #endif + } + ); +}; + +export type EventOnlyHandler = (e: any) => void; + +export const useHandleCustomEventOnly = ( + eventName: string, + handler: EventOnlyHandler +) => { + useEvent( + eventName, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (event) => { + /// #if ALIPAY + if (platform() === 'alipay') { + return handler(event); + } + /// #endif + + /// #if WECHAT + return handler(event); + /// #endif + } + ); +}; diff --git a/src/_util/hooks/useInstanceBoundingClientRect.ts b/src/_util/hooks/useInstanceBoundingClientRect.ts new file mode 100644 index 000000000..467a457bb --- /dev/null +++ b/src/_util/hooks/useInstanceBoundingClientRect.ts @@ -0,0 +1,37 @@ +import { useComponent } from 'functional-mini/component'; +import { getInstanceBoundingClientRect } from '../jsapi/get-instance-bounding-client-rect'; + +export const useInstanceBoundingClientRect = () => { + const instance = useComponent(); + function getInstance() { + if (instance.$id) { + return my; + } + return instance; + } + + async function getBoundingClientRectWithId(prefix: string) { + return await getInstanceBoundingClientRect( + getInstance(), + `${prefix}${instance.$id ? `-${instance.$id}` : ''}` + ); + } + async function getBoundingClientRect(query: string) { + return await getInstanceBoundingClientRect(getInstance(), query); + } + + async function getBoundingClientRectWithBuilder( + builder: (id: string) => string + ) { + return await getInstanceBoundingClientRect( + getInstance(), + builder(instance.$id ? `-${instance.$id}` : '') + ); + } + + return { + getBoundingClientRect, + getBoundingClientRectWithId, + getBoundingClientRectWithBuilder, + }; +}; diff --git a/src/_util/hooks/useLayoutEffect.ts b/src/_util/hooks/useLayoutEffect.ts new file mode 100644 index 000000000..896935268 --- /dev/null +++ b/src/_util/hooks/useLayoutEffect.ts @@ -0,0 +1,39 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useLayoutEffect.ts + */ + +import * as React from 'functional-mini/compat'; + +/** + * Wrap `React.useLayoutEffect` which will not throw warning message in test env + */ +const useInternalLayoutEffect = React.useEffect; + +const useLayoutEffect = (callback: (mount: boolean) => void, deps?: any) => { + const firstMountRef = React.useRef(true); + + useInternalLayoutEffect(() => { + return callback(firstMountRef.current); + }, deps); + + // We tell react that first mount has passed + useInternalLayoutEffect(() => { + firstMountRef.current = false; + return () => { + firstMountRef.current = true; + }; + }, []); +}; + +export const useComponentUpdateEffect: typeof React.useEffect = ( + callback, + deps +) => { + useLayoutEffect((firstMount) => { + if (!firstMount) { + return callback(); + } + }, deps); +}; + +export default useLayoutEffect; diff --git a/src/_util/hooks/useMergedState.ts b/src/_util/hooks/useMergedState.ts new file mode 100644 index 000000000..37148ac85 --- /dev/null +++ b/src/_util/hooks/useMergedState.ts @@ -0,0 +1,81 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useMergedState.ts + */ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { useSafeState as useState } from './useState'; +import { supportUndefinedProperty } from '../platform'; + +type Updater = ( + updater: T | ((origin: T) => T), + ignoreDestroy?: boolean +) => void; + +/** We only think `undefined` is empty */ +export function hasValue(value: any) { + if (supportUndefinedProperty()) { + return value !== undefined; + } + return value !== null && value !== undefined; +} + +/** + * Similar to `useState` but will use props value if provided. + * Note that internal use rc-util `useState` hook. + */ +export function useMergedState( + defaultStateValue: T | (() => T), + option?: { + defaultValue?: T | (() => T); + value?: T; + onChange?: (value: T, prevValue: T) => void; + postState?: (value: T) => T; + } +): [R, Updater] { + const { defaultValue, value, onChange, postState } = option || {}; + + // ======================= Init ======================= + const [innerValue, setInnerValue] = useState(() => { + if (hasValue(value)) { + return value; + } else if (hasValue(defaultValue)) { + return typeof defaultValue === 'function' + ? (defaultValue as any)() + : defaultValue; + } else { + return typeof defaultStateValue === 'function' + ? (defaultStateValue as any)() + : defaultStateValue; + } + }); + + const mergedValue = hasValue(value) ? value : innerValue; + const postMergedValue = postState ? postState(mergedValue) : mergedValue; + + // ====================== Change ====================== + const onChangeFn = useEvent(onChange); + + const [prevValue, setPrevValue] = useState<[T]>([mergedValue]); + + useComponentUpdateEffect(() => { + const prev = prevValue[0]; + if (innerValue !== prev) { + onChangeFn(innerValue, prev); + } + }, [prevValue]); + + // Sync value back to `undefined` when it from control to un-control + useComponentUpdateEffect(() => { + if (!hasValue(value)) { + setInnerValue(value); + } + }, [value]); + + // ====================== Update ====================== + const triggerChange: Updater = useEvent((updater, ignoreDestroy) => { + setInnerValue(updater, ignoreDestroy); + setPrevValue([mergedValue], ignoreDestroy); + }); + + return [postMergedValue as unknown as R, triggerChange]; +} diff --git a/src/_util/hooks/useMixState.ts b/src/_util/hooks/useMixState.ts new file mode 100644 index 000000000..d558a71fd --- /dev/null +++ b/src/_util/hooks/useMixState.ts @@ -0,0 +1,109 @@ +import { useEvent } from './useEvent'; +import { useComponentUpdateEffect } from './useLayoutEffect'; +import { hasValue } from './useMergedState'; +import { useSafeState as useState } from './useState'; + +type Updater = ( + updater: T | ((old: T) => T), + ignoreDestroy?: boolean +) => void; + +export function useMixState( + defaultStateValue: T | (() => T), + option?: { + defaultValue?: T | (() => T); + value?: T; + postState?: ( + value: T, + option?: O + ) => { valid: true; value: T } | { valid: false }; + } +): [ + R, + { + isControlled: boolean; + triggerUpdater: (value: (old: T) => T, option?: O) => void; + update( + value: T, + option?: O + ): { changed: true; newValue: T } | { changed: false }; + } +] { + const { + defaultValue, + value, + postState = (v) => ({ valid: true, value: v }), + } = option || {}; + + // ======================= Init ======================= + const [innerValue, setInnerValue] = useState(() => { + let v; + if (hasValue(value)) { + v = value; + } else if (hasValue(defaultValue)) { + v = + typeof defaultValue === 'function' + ? (defaultValue as any)() + : defaultValue; + } else { + v = + typeof defaultStateValue === 'function' + ? (defaultStateValue as any)() + : defaultStateValue; + } + const state = postState(v); + if (state.valid) { + return state.value; + } + }); + + const state = postState(value); + const merge = hasValue(value) && state.valid ? state.value : innerValue; + + useComponentUpdateEffect(() => { + const state = postState(value); + if (state.valid) { + setInnerValue(state.value); + } + }, [value]); + + const isControlled = hasValue(value); + const triggerChange: Updater = useEvent((newState, ignoreDestroy) => { + setInnerValue(newState, ignoreDestroy); + }); + + const triggerUpdate = useEvent((value, option) => { + const state = postState(value, option); + if (state.valid && state.value !== innerValue) { + triggerChange(state.value); + return { changed: true, newValue: state.value }; + } + return { changed: false }; + }); + + const triggerUpdater: (value: (old: T) => T, option?: O) => void = useEvent( + (getValue, option) => { + if (isControlled) { + getValue(merge); + } else { + triggerChange((old: T): T => { + const newValue = getValue(old); + const state = postState(newValue, option); + if (state.valid && state.value !== innerValue) { + return state.value; + } + return old; + }); + } + } + ); + + return [ + merge as unknown as R, + { + isControlled, + update: triggerUpdate as any, + triggerUpdater, + }, + ]; +} diff --git a/src/_util/hooks/useReportRef.ts b/src/_util/hooks/useReportRef.ts new file mode 100644 index 000000000..1cb16e980 --- /dev/null +++ b/src/_util/hooks/useReportRef.ts @@ -0,0 +1,10 @@ +import { useComponent, useEffect } from 'functional-mini/component'; + +export const triggerRefEvent = () => { + /// #if WECHAT + const component = useComponent(); + useEffect(() => { + component.triggerEvent('ref', component); + }, []); + /// #endif +}; diff --git a/src/_util/hooks/useState.ts b/src/_util/hooks/useState.ts new file mode 100644 index 000000000..2c80b46b7 --- /dev/null +++ b/src/_util/hooks/useState.ts @@ -0,0 +1,46 @@ +/** + * copy from https://github.com/react-component/util/blob/9d5cb8946da29e690bead78b2c251da6f7cbd0eb/src/hooks/useState.ts + */ + +import * as React from 'functional-mini/compat'; + +type Updater = T | ((prevValue: T) => T); + +export type SetState = ( + nextValue: Updater, + /** + * Will not update state when destroyed. + * Developer should make sure this is safe to ignore. + */ + ignoreDestroy?: boolean +) => void; + +/** + * Same as React.useState but `setState` accept `ignoreDestroy` param to not to setState after destroyed. + * We do not make this auto is to avoid real memory leak. + * Developer should confirm it's safe to ignore themselves. + */ +export function useSafeState( + defaultValue?: T | (() => T) +): [T, SetState] { + const destroyRef = React.useRef(false); + const [value, setValue] = React.useState(defaultValue); + + React.useEffect(() => { + destroyRef.current = false; + + return () => { + destroyRef.current = true; + }; + }, []); + + function safeSetState(updater: Updater, ignoreDestroy?: boolean) { + if (ignoreDestroy && destroyRef.current) { + return; + } + + setValue(updater); + } + + return [value, safeSetState]; +} diff --git a/src/_util/platform.ts b/src/_util/platform.ts index 8d9e43c48..c9f69528b 100644 --- a/src/_util/platform.ts +++ b/src/_util/platform.ts @@ -35,7 +35,7 @@ export function resolveEventValue(value) { return value; } -export function resolveEventValues(args1: any, args2?: any, ...rest) { +export function resolveEventValues(args1: any, args2?: any) { /// #if WECHAT if (platform() === 'wechat') { @@ -43,7 +43,7 @@ export function resolveEventValues(args1: any, args2?: any, ...rest) { } /// #endif - return [args1, args2, ...rest]; + return [args1, args2]; } export function isOldSDKVersion() { diff --git a/src/_util/triggerComonentEvent.ts b/src/_util/triggerComonentEvent.ts new file mode 100644 index 000000000..a2c169cbe --- /dev/null +++ b/src/_util/triggerComonentEvent.ts @@ -0,0 +1,11 @@ +export function triggerComponentEvent(instance, propsName, event) { + /// #if WECHAT + instance.triggerEvent(propsName, event.detail); + /// #endif + + /// #if ALIPAY + if (instance.props[propsName]) { + instance.props[propsName](event); + } + /// #endif +} diff --git a/src/mixins/computed.ts b/src/mixins/computed.ts index 3e1f5c242..2df987908 100644 --- a/src/mixins/computed.ts +++ b/src/mixins/computed.ts @@ -1,9 +1,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import deepEqual from 'fast-deep-equal'; -import { getValueFromProps } from '../_util/simply'; function computedData(this: any) { - const nextData = this.computed(getValueFromProps(this)); + const nextData = this.computed(this.props); // 浅比较就行了 const changedData = Object.keys(nextData).reduce((prev, item) => { // 移除 _ $ 开头的保留 props @@ -30,33 +29,11 @@ function computedData(this: any) { this.setData(changedData); } -export default function () { - let mixin = { - /// #if ALIPAY - didMount(): void { - computedData.call(this); - }, - didUpdate(): void { - computedData.call(this); - }, - /// #endif - - /// #if WECHAT - attached(): void { - computedData.call(this); - }, - observers: { - '**': function () { - computedData.call(this); - }, - }, - /// #endif - }; - - /// #if WECHAT - // @ts-ignore - mixin = Behavior(mixin); - /// #endif - - return mixin; -} +export default { + didMount(): void { + computedData.call(this); + }, + didUpdate(): void { + computedData.call(this); + }, +}; diff --git a/tests/alipay/DatePicker/RangePicker/index.test.ts b/tests/alipay/DatePicker/RangePicker/index.test.ts index 341093b43..0229ab36d 100644 --- a/tests/alipay/DatePicker/RangePicker/index.test.ts +++ b/tests/alipay/DatePicker/RangePicker/index.test.ts @@ -227,21 +227,21 @@ describe('visible 受控模式', () => { visible: false, defaultVisible: true, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); await callVisibleChange(true); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); expect(onVisibleChange).toBeCalledWith(true, fmtEvent({})); }); it('visible 受控', async () => { const { instance } = createDateRangePicker({ visible: false, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); instance.setProps({ visible: true, }); await sleep(100); - expect(instance.getData().visible).toEqual(true); + expect(instance.getData().state.visible).toEqual(true); }); }); diff --git a/tests/alipay/DatePicker/index.test.ts b/tests/alipay/DatePicker/index.test.ts index ee8fcd0ab..906f5d3dd 100644 --- a/tests/alipay/DatePicker/index.test.ts +++ b/tests/alipay/DatePicker/index.test.ts @@ -194,21 +194,21 @@ describe('visible 受控模式', () => { visible: false, defaultVisible: true, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); await callVisibleChange(true); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); expect(onVisibleChange).toBeCalledWith(true, fmtEvent({})); }); it('visible 受控', async () => { const { instance } = createDatePicker({ visible: false, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); instance.setProps({ visible: true, }); await sleep(100); - expect(instance.getData().visible).toEqual(true); + expect(instance.getData().state.visible).toEqual(true); }); }); diff --git a/tests/alipay/Picker/CascaderPicker/__tests__/index.test.ts b/tests/alipay/Picker/CascaderPicker/__tests__/index.test.ts index 6019d6ce4..73275b7e0 100644 --- a/tests/alipay/Picker/CascaderPicker/__tests__/index.test.ts +++ b/tests/alipay/Picker/CascaderPicker/__tests__/index.test.ts @@ -310,9 +310,9 @@ describe('visible 受控模式', () => { visible: false, defaultVisible: true, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); await callVisibleChange(true); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); expect(onVisibleChange).toBeCalledWith(true, fmtEvent({})); }); it('visible 受控', async () => { @@ -320,11 +320,11 @@ describe('visible 受控模式', () => { options: cityList, visible: false, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); instance.setProps({ visible: true, }); await sleep(100); - expect(instance.getData().visible).toEqual(true); + expect(instance.getData().state.visible).toEqual(true); }); -}); +}); \ No newline at end of file diff --git a/tests/alipay/Picker/__tests__/index.test.ts b/tests/alipay/Picker/__tests__/index.test.ts index 00de50d84..0af8acb06 100644 --- a/tests/alipay/Picker/__tests__/index.test.ts +++ b/tests/alipay/Picker/__tests__/index.test.ts @@ -19,11 +19,11 @@ describe('picker onVisibleChange', () => { instance.callMethod('onOpen'); await sleep(20); - expect(instance.getData().visible).toBeTruthy(); + expect(instance.getData().state.visible).toBeTruthy(); instance.setProps({ maskClosable: false }); instance.callMethod('onMaskDismiss'); await sleep(20); - expect(instance.getData().visible).toBeTruthy(); + expect(instance.getData().state.visible).toBeTruthy(); }); it('onCancel', () => { @@ -237,19 +237,19 @@ it('假设在滚动的时候, value 变化', async () => { it('多次开启关闭, visible 状态应该正确', async () => { const { instance, callMethod } = createPicker(); await callMethod('onOpen'); - expect(instance.getData().visible).toBe(true); + expect(instance.getData().state.visible).toBe(true); await callMethod('onOk'); - expect(instance.getData().visible).toBe(false); + expect(instance.getData().state.visible).toBe(false); await callMethod('onOpen'); - expect(instance.getData().visible).toBe(true); + expect(instance.getData().state.visible).toBe(true); await callMethod('onOk'); - expect(instance.getData().visible).toBe(false); + expect(instance.getData().state.visible).toBe(false); }); it('如果 disabled, 则无法打开', async () => { const { instance, callMethod } = createPicker({ disabled: true }); await callMethod('onOpen'); - expect(instance.getData().visible).toBe(undefined); + expect(instance.getData().state.visible).toBe(undefined); }); describe('非受控模式', () => { @@ -259,12 +259,12 @@ describe('非受控模式', () => { options, }); await callMethod('onOpen'); - expect(instance.getData().visible).toBe(true); + expect(instance.getData().state.visible).toBe(true); await callMethod('onChange', { detail: { value: [1] } }); expect(instance.getData().selectedIndex).toStrictEqual([1]); expect(instance.getData().mixin.value).toStrictEqual([]); await callMethod('onOk'); - expect(instance.getData().visible).toBe(false); + expect(instance.getData().state.visible).toBe(false); expect(instance.getData().mixin.value).toStrictEqual(['上海']); }); @@ -276,10 +276,10 @@ describe('非受控模式', () => { defaultVisible: true, 'data-1': 2, }); - expect(instance.getData().visible).toBe(true); + expect(instance.getData().state.visible).toBe(true); expect(instance.getData().selectedIndex).toEqual([1]); await callMethod('onOk'); - expect(instance.getData().visible).toBe(false); + expect(instance.getData().state.visible).toBe(false); expect(onOk).toBeCalledWith( ['上海'], ['上海'], @@ -298,9 +298,9 @@ describe('visible 受控模式', () => { visible: false, defaultVisible: true, }); - expect(instance.getData().visible).toEqual(false); + expect(instance.getData().state.visible).toEqual(false); await callMethod('onOpen'); - expect(instance.getData().visible).toEqual(true); + expect(instance.getData().state.visible).toEqual(false); expect(onVisibleChange).toBeCalledWith(true, fmtEvent({})); }); }); diff --git a/tests/alipay/_util/__tests__/useHandleCustomEvent.spec.ts b/tests/alipay/_util/__tests__/useHandleCustomEvent.spec.ts new file mode 100644 index 000000000..535d5e94c --- /dev/null +++ b/tests/alipay/_util/__tests__/useHandleCustomEvent.spec.ts @@ -0,0 +1,122 @@ +import { useEvent, useState, alipayComponent } from 'functional-mini/component'; +import { sleep, createInstance } from '../../../utils'; +import { expect, it } from 'vitest'; +import { + useHandleCustomEvent, + useMultipleValueHandleCustomEvent, + useHandleCustomEventOnly, +} from 'compiled-alipay/_util/hooks/useHandleCustomEvent'; +import fmtEvent from 'compiled-alipay/_util/fmtEvent'; + +const testMy = { + canIUse() { + return true; + }, +}; + +it('test useHandleCustomEvent', async () => { + const Test = () => { + const [count, setCount] = useState(1); + useHandleCustomEvent('handleEvent', (value, event) => { + return { + value, + event, + count, + }; + }); + useEvent('updateCount', function (v) { + setCount(v); + return 'ok'; + }); + return { + count, + }; + }; + + const componentOptions = alipayComponent(Test, {}); + const instance = createInstance(componentOptions as any, {}, testMy); + expect( + instance.callMethod('handleEvent', 2, fmtEvent({ 'data-a': 1 })).count + ).toBe(1); + expect(instance.callMethod('updateCount', 10)).toEqual('ok'); + await sleep(20); + expect(instance.getData().count).toEqual(10); + expect( + instance.callMethod('handleEvent', 2, fmtEvent({ 'data-a': 1 })) + ).toEqual({ + value: 2, + event: { + currentTarget: { dataset: { 'a': 1 } }, + target: { dataset: { 'a': 1 }, targetDataset: { 'a': 1 } }, + }, + count: 10, + }); + expect(instance.callMethod('updateCount', 30)).toEqual('ok'); + await sleep(20); + expect(instance.getData().count).toEqual(30); +}); + +it('test useMultipleValueHandleCustomEvent', async () => { + const Test = () => { + useMultipleValueHandleCustomEvent('handleEvent', (...args) => { + return { + args, + }; + }); + return {}; + }; + + const componentOptions = alipayComponent(Test, {}); + const instance = createInstance(componentOptions as any, {}, testMy); + expect( + instance.callMethod('handleEvent', 1, 2, fmtEvent({ 'data-a': 1 })) + ).toEqual({ + args: [ + 1, + 2, + { + currentTarget: { dataset: { 'a': 1 } }, + target: { dataset: { 'a': 1 }, targetDataset: { 'a': 1 } }, + }, + ], + }); + + expect(instance.callMethod('handleEvent')).toEqual({ + args: [], + }); + + expect(instance.callMethod('handleEvent', fmtEvent({ 'data-a': 1 }))).toEqual( + { + args: [ + { + currentTarget: { dataset: { 'a': 1 } }, + target: { dataset: { 'a': 1 }, targetDataset: { 'a': 1 } }, + }, + ], + } + ); +}); + +it('test useHandleCustomEventOnly', async () => { + const Test = () => { + useHandleCustomEventOnly('handleEvent', (...args) => { + return { + args, + }; + }); + return {}; + }; + + const componentOptions = alipayComponent(Test, {}) as any; + const instance = createInstance(componentOptions, {}, testMy); + expect(instance.callMethod('handleEvent', fmtEvent({ 'data-a': 1 }))).toEqual( + { + args: [ + { + currentTarget: { dataset: { 'a': 1 } }, + target: { dataset: { 'a': 1 }, targetDataset: { 'a': 1 } }, + }, + ], + } + ); +}); diff --git a/vite.config.ts b/vite.config.ts index 1174da00c..726f1078d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -10,6 +10,11 @@ export default defineConfig({ }, }, test: { + server: { + deps: { + inline: [/functional-mini/], + }, + }, watch: true, globals: true, setupFiles: ['./tests/setup.ts'],