From 8090bca68e35f6151352369341e3413eecae5717 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 11 Feb 2022 15:48:17 +0800 Subject: [PATCH 01/59] =?UTF-8?q?fix(Form):=20=E4=BF=AE=E5=A4=8Dref?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E4=B8=8D=E5=88=B0=E8=A1=A8=E5=8D=95=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 25 ++++++++++++++++---- website/src/routes/components/form/index.tsx | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 7a6d1f5b4f..fb88b00771 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useEffect, useState } from 'react'; import { IProps } from '@uiw/utils'; import FormItem, { FormItemProps } from './FormItem'; import './style/form.less'; @@ -100,7 +100,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: ((instance: HTMLInputElement) => void) | React.RefObject | null, + ref: React.ForwardedRef, ) { const initData = newFormState(fields, ({ initialValue }) => { initialValue = newInitialValue(initialValue); @@ -109,6 +109,18 @@ function Form( const [data, setData] = useState(initData); + useEffect(() => { + if (ref) { + (ref as unknown as React.MutableRefObject< + Record<'onSubmit' | 'resetForm' | 'getFieldValues', Function> + >)!.current = { + onSubmit: handleSubmit, + resetForm: handleReset, + getFieldValues: getFieldValues, + }; + } + }, [data]); + const formUnits: FormChildrenProps['fields'] = {}; for (const name in fields) { const props = fields[name]; @@ -139,6 +151,10 @@ function Form( ); } + function getFieldValues() { + return data.current; + } + function handleChange( name: string, validator: FormFieldsProps['validator'], @@ -175,7 +191,7 @@ function Form( }; } - function handleSubmit(e: React.FormEvent) { + const handleSubmit = (e: React.FormEvent) => { e && e.preventDefault(); const { initial, current } = data; setData({ ...data, submitting: true }); @@ -203,7 +219,7 @@ function Form( } catch (evn) { onError(evn); } - } + }; function canSubmit() { const { submitting, current = {} } = data; @@ -265,6 +281,7 @@ function Form( props.onChange = handleChange(name, validator, element, element.props.onChange) as FormElementProps['onChange']; return React.cloneElement(element, props as FormElementProps); } + return (
{ const md = await import('uiw/node_modules/@uiw/react-form/README.md'); From ddf96b29650e2e1b020512e24c026c6fdbe35ffc Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 11 Feb 2022 16:51:13 +0800 Subject: [PATCH 02/59] =?UTF-8?q?fix(Form):=E4=BD=BF=E7=94=A8useLayoutEffe?= =?UTF-8?q?ct=E6=9B=BF=E6=8D=A2useEffect=E7=BB=91=E5=AE=9A=E7=BB=91?= =?UTF-8?q?=E5=AE=9AForwardedRef?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 34 ++++++++++++++------------------ 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index fb88b00771..b4a62bd7d8 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useImperativeHandle } from 'react'; import { IProps } from '@uiw/utils'; import FormItem, { FormItemProps } from './FormItem'; import './style/form.less'; @@ -58,6 +58,8 @@ export type FormElementProps = { onChange?: (env: React.BaseSyntheticEvent, list?: string[]) => void; }; +export type FormRefType = Record<'onSubmit' | 'resetForm' | 'getFieldValues', Function>; + function newFormState( fields: FormProps['fields'], cb: (porps: FormFieldsProps) => { @@ -100,7 +102,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: React.ForwardedRef, + ref: React.ForwardedRef | React.RefObject, ) { const initData = newFormState(fields, ({ initialValue }) => { initialValue = newInitialValue(initialValue); @@ -109,17 +111,15 @@ function Form( const [data, setData] = useState(initData); - useEffect(() => { - if (ref) { - (ref as unknown as React.MutableRefObject< - Record<'onSubmit' | 'resetForm' | 'getFieldValues', Function> - >)!.current = { - onSubmit: handleSubmit, - resetForm: handleReset, - getFieldValues: getFieldValues, - }; - } - }, [data]); + useImperativeHandle( + ref as React.RefObject, + () => ({ + onSubmit: handleSubmit, + resetForm: handleReset, + getFieldValues: () => data.current, + }), + [data], + ); const formUnits: FormChildrenProps['fields'] = {}; for (const name in fields) { @@ -151,10 +151,6 @@ function Form( ); } - function getFieldValues() { - return data.current; - } - function handleChange( name: string, validator: FormFieldsProps['validator'], @@ -191,7 +187,7 @@ function Form( }; } - const handleSubmit = (e: React.FormEvent) => { + function handleSubmit(e: React.FormEvent) { e && e.preventDefault(); const { initial, current } = data; setData({ ...data, submitting: true }); @@ -219,7 +215,7 @@ function Form( } catch (evn) { onError(evn); } - }; + } function canSubmit() { const { submitting, current = {} } = data; From 53880a5f36b719d7135c372d266f69735aee3636 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 11 Feb 2022 17:58:24 +0800 Subject: [PATCH 03/59] =?UTF-8?q?refactor:(Form)=20=E4=BF=AE=E6=94=B9Ref?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E5=AE=9A=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/README.md | 118 ++++++++++++++++++------------- packages/react-form/src/Form.tsx | 10 +-- 2 files changed, 74 insertions(+), 54 deletions(-) diff --git a/packages/react-form/README.md b/packages/react-form/README.md index dd532b000c..9ec48c66eb 100644 --- a/packages/react-form/README.md +++ b/packages/react-form/README.md @@ -13,57 +13,77 @@ import { Form, FormItem } from '@uiw/react-form'; ```jsx + +import React, { useState, useRef } from "react"; import ReactDOM from 'react-dom'; import { Form, Input, Row, Col, Slider, Button, Notify } from 'uiw'; -const Demo = () => ( -
- { - console.log('onChange', initial, current); - }} - onSubmit={({initial, current}) => { - if(current.name === initial.name) { - Notify.error({ - title: '提交失败!', - description: `表单提交内容为空!`, - }); - } else { - Notify.success({ - title: '提交成功!', - description: `姓名为:${current.name},提交完成,将自动填充初始化值!`, - }); - } - }} - fields={{ - name: { - label: '姓名', - children: - }, - }} - > - {({ fields, state, canSubmit }) => { - return ( -
- - {fields.name} - - - - - - - - - {JSON.stringify(state.current)} - - -
- ) - }} - -
-) +function Demo() { + const form = useRef() + + const onSubmit = () => { + form.current.onSubmit() + } + const resetForm = () => { + form.current.resetForm() + } + const getFieldValues = () => { + console.log('getFieldValues', form.current.getFieldValues()) + } + + return ( +
+
{ + console.log('onChange', initial, current); + }} + onSubmit={({ initial, current }) => { + if (current.name === initial.name) { + Notify.error({ + title: '提交失败!', + description: `表单提交内容为空!`, + }); + } else { + Notify.success({ + title: '提交成功!', + description: `姓名为:${current.name},提交完成,将自动填充初始化值!`, + }); + } + }} + fields={{ + name: { + label: '姓名', + children: + }, + }} + > + {({ fields, state, canSubmit }) => { + return ( +
+ + {fields.name} + + + + + + + + + {JSON.stringify(state.current)} + + +
+ ) + }} +
+ + + +
+ ) +} ReactDOM.render(, _mount_); ``` @@ -682,4 +702,4 @@ ReactDOM.render(, _mount_); | labelStyle | 表单标题样式 | object | - | | labelFor | 列的宽度相对于同一网格中其他列的比率 | number | - | | help | 提示信息 | ReactNode | - | -| hasError | 如果为true,则应用错误CSS。转动边框并帮助文字变红。 | number | - | \ No newline at end of file +| hasError | 如果为true,则应用错误CSS。转动边框并帮助文字变红。 | number | - | diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index b4a62bd7d8..758496af7d 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useImperativeHandle } from 'react'; +import React, { useState, useImperativeHandle } from 'react'; import { IProps } from '@uiw/utils'; import FormItem, { FormItemProps } from './FormItem'; import './style/form.less'; @@ -102,7 +102,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: React.ForwardedRef | React.RefObject, + ref: React.Ref>, //| React.RefObject, ) { const initData = newFormState(fields, ({ initialValue }) => { initialValue = newInitialValue(initialValue); @@ -111,8 +111,8 @@ function Form( const [data, setData] = useState(initData); - useImperativeHandle( - ref as React.RefObject, + useImperativeHandle, any>( + ref, () => ({ onSubmit: handleSubmit, resetForm: handleReset, @@ -300,4 +300,4 @@ function Form( ); } -export default React.forwardRef>(Form); +export default React.forwardRef, FormProps<{}>>(Form); From 0c4f0bcd38e358d9354c3428c5fc681d320aa36b Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 14 Feb 2022 11:20:33 +0800 Subject: [PATCH 04/59] =?UTF-8?q?fix(Form):=20=E4=BF=AE=E5=A4=8D=E6=97=A0?= =?UTF-8?q?=E6=B3=95=E9=87=8D=E7=BD=AE(initialValue)=E8=A1=A8=E5=8D=95?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 758496af7d..6331436fab 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -1,4 +1,4 @@ -import React, { useState, useImperativeHandle } from 'react'; +import React, { useState, useImperativeHandle, useMemo } from 'react'; import { IProps } from '@uiw/utils'; import FormItem, { FormItemProps } from './FormItem'; import './style/form.less'; @@ -53,7 +53,7 @@ export interface FormChildrenProps { export type FormElementProps = { id?: string; name?: string; - value?: string; + value?: string | boolean; checked?: boolean; onChange?: (env: React.BaseSyntheticEvent, list?: string[]) => void; }; @@ -104,12 +104,20 @@ function Form( }: FormProps, ref: React.Ref>, //| React.RefObject, ) { - const initData = newFormState(fields, ({ initialValue }) => { - initialValue = newInitialValue(initialValue); - return { initialValue, currentValue: initialValue }; - }); + const initData = useMemo( + () => + newFormState(fields, ({ initialValue }) => { + initialValue = newInitialValue(initialValue); + return { initialValue, currentValue: initialValue }; + }), + [], + ); - const [data, setData] = useState(initData); + const [data, setDatas] = useState(JSON.parse(JSON.stringify(initData))); + const setData = (values: any) => { + // 解决value为数组时不进行深拷贝,initvalue无法重置问题 + setDatas(JSON.parse(JSON.stringify(values))); + }; useImperativeHandle, any>( ref, @@ -270,8 +278,9 @@ function Form( // : element.props.value; const type = element.props.type; - if (type === 'checkbox' || type === 'switch') { - props.checked = !!props.checked; + // console.log('type', element) + if (type === 'checkbox' || type === 'switch' || typeof props.value === 'boolean') { + props.checked = !!props.value; delete props.value; } props.onChange = handleChange(name, validator, element, element.props.onChange) as FormElementProps['onChange']; From 9f8cdd9a505e0dd21c38784699387ea47573f2da Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 14 Feb 2022 14:16:14 +0800 Subject: [PATCH 05/59] =?UTF-8?q?fix(Form):=20=E7=B1=BB=E5=9E=8B=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 6331436fab..401057372b 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -102,7 +102,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: React.Ref>, //| React.RefObject, + ref: React.ForwardedRef, //| React.RefObject, ) { const initData = useMemo( () => @@ -119,7 +119,7 @@ function Form( setDatas(JSON.parse(JSON.stringify(values))); }; - useImperativeHandle, any>( + useImperativeHandle( ref, () => ({ onSubmit: handleSubmit, @@ -309,4 +309,4 @@ function Form( ); } -export default React.forwardRef, FormProps<{}>>(Form); +export default React.forwardRef>(Form); From 8639505df14f6a8b969cd8de23098e45ee380736 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 10:02:48 +0800 Subject: [PATCH 06/59] =?UTF-8?q?feat(search-select):=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=A4=9A=E9=80=89=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/README.md | 19 +- packages/react-search-select/package.json | 1 + packages/react-search-select/src/index.tsx | 164 +++++++++++++----- .../react-search-select/src/style/index.less | 8 + 4 files changed, 149 insertions(+), 43 deletions(-) create mode 100644 packages/react-search-select/src/style/index.less diff --git a/packages/react-search-select/README.md b/packages/react-search-select/README.md index e3f0784d7f..2c4e0bf1c2 100644 --- a/packages/react-search-select/README.md +++ b/packages/react-search-select/README.md @@ -21,28 +21,38 @@ const Demo = () => { const [loading, setLoading] = React.useState(false); const [value, setValue] = React.useState(undefined); function handleSearch(e) { + console.log('handleSearch',e) setLoading(true) setTimeout(() => { setOption([ { label: 'a', value: 2 }, { label: 'aa', value: 3 }, { label: 'aaa', value: 4 }, + { label: 'a5', value: 5 }, + { label: 'a6', value: 6 }, + { label: 'a7', value: 7 }, + { label: 'a8', value: 8 }, ]); setLoading(false); }, 2000); } return( console.log('onSelect',value)} loading={loading} option={option} - onChange={(value) => setValue(value)} + onChange={(value) => { + console.log('onChange',value) + setValue(value) + }} /> ); }; @@ -62,6 +72,7 @@ const Demo = () => { const [option, setOption] = React.useState([]); const [loading, setLoading] = React.useState(false); function handleSearch(e) { + console.log('handleSearch',e) setLoading(true) setTimeout(() => { setOption([ @@ -107,6 +118,9 @@ const Demo = () => { disabled={false} placeholder="请输入选择" onSearch={handleSearch} + onChange={(v)=>{ + console.log('onChange',v) + }} option={option} loading={loading} /> @@ -148,6 +162,7 @@ ReactDOM.render(, _mount_); |--------- |-------- |--------- |-------- | | allowClear | 支持清除 | Boolean | `false` | | disabled | 禁用选择器 | Boolean | `false` | +| mode | 是否可以多选; 'multiple','single' | String | 'single' | | defaultValue | 指定默认选中的条目 | String/Number | - | | value | 指定选中的条目的值 | String/Number | - | | placeholder | 选择框默认文字 | String | - | diff --git a/packages/react-search-select/package.json b/packages/react-search-select/package.json index 572436dc48..feed8de3ca 100644 --- a/packages/react-search-select/package.json +++ b/packages/react-search-select/package.json @@ -49,6 +49,7 @@ "@uiw/react-input": "^4.10.6", "@uiw/react-loader": "^4.10.6", "@uiw/react-menu": "^4.10.6", + "@uiw/react-tag": "^4.10.7", "@uiw/utils": "^4.10.6" }, "devDependencies": { diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 08003aca80..9057ca6b12 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -1,29 +1,28 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import Dropdown, { DropdownProps } from '@uiw/react-dropdown'; import Icon from '@uiw/react-icon'; import Menu from '@uiw/react-menu'; import Input from '@uiw/react-input'; +import Tag from '@uiw/react-tag'; import { IProps } from '@uiw/utils'; import { useState } from 'react'; import { useRef } from 'react'; import { useEffect } from 'react'; +import './style/index.less'; +type ValueType = string | number | undefined; export interface SearchSelectProps extends IProps, DropdownProps { + mode?: 'single' | 'multiple'; size?: 'large' | 'default' | 'small'; loading: boolean; showSearch?: boolean; allowClear: boolean; defaultValue?: string | number; - value?: string | number; - option: { - label: string; - value: string | number; - key: any; - [propName: string]: any; - }[]; - onSelect?: (value: string | number) => void; + value?: ValueType; + option: MenuItemData[]; + onSelect?: (value: ValueType | Array) => void; onSearch?: (value: string) => void; - onChange?: (value: string) => void; + onChange?: (value: ValueType | Array) => void; } export interface MenuItemData { @@ -41,6 +40,7 @@ export default function SearchSelect(props: SearchSelectProps) { loading = false, prefixCls, className, + mode = 'single', style, isOpen, value, @@ -53,33 +53,56 @@ export default function SearchSelect(props: SearchSelectProps) { ...others } = props; + const isMultiple = useMemo(() => mode === 'multiple', [mode]); const [innerIsOpen, setInnerIsOpen] = useState(false); - const [selectedValue, setSelectedValue] = useState(value); + const [selectedValue, setSelectedValue] = useState>( + option.filter((item) => item.value === value), + ); const [selectedLabel, setSelectedLabel] = useState(''); const [selectIconType, setSelectIconType] = useState(''); const divRef = useRef(null); + const valueRef = useRef>(); + valueRef.current = useMemo(() => selectedValue, [selectedValue]); + useEffect(() => { if (defaultValue) { - const defaultMenuItem = option.find((menuItem: MenuItemData) => defaultValue === menuItem.value); - setSelectedValue(defaultValue); - setSelectedLabel(defaultMenuItem ? defaultMenuItem.label : ''); + const defaultMenuItem = option.filter((opt) => opt.value === defaultValue); + setSelectedValue(defaultMenuItem); } }, []); - useEffect(() => { - if (value !== selectedValue) { - setSelectedValue(value); - } - }, [value]); + function removeSelectItem(index: number) { + const selectedValue = valueRef.current as MenuItemData[]; + selectedValue.splice(index, 1); + const values = [...selectedValue]; + return values; + } function handleItemClick(item: MenuItemData) { setInnerIsOpen(false); - setSelectedValue(item.value); + const values = [item]; + setSelectedValue(values); setSelectedLabel(item.label); - onSelect && onSelect(item.value); + const resultValue = item.value; + onSelect && onSelect(resultValue); // 支持form组件 - handleSelectChange(item.value); + handleSelectChange(resultValue); + } + + function handleItemsClick(item: MenuItemData) { + let values: MenuItemData[] = []; + const index = selectedValue.findIndex((finds) => finds.value === item.value); + if (index !== -1) { + values = removeSelectItem(index); + } else { + values = [...selectedValue, item]; + } + setSelectedValue(values); + const resultValue = values.map((item) => item.value); + onSelect && onSelect(resultValue); + // // 支持form组件 + handleSelectChange(resultValue); } // 渲染icon @@ -99,27 +122,37 @@ export default function SearchSelect(props: SearchSelectProps) { setSelectedLabel(value); setSelectIconType(showSearch && value ? 'loading' : ''); showSearch && onSearch && onSearch(value); - handleSelectChange(value); + // handleSelectChange(value); } // 清除选中的值 function resetSelectedValue() { setInnerIsOpen(false); - setSelectedValue(''); + setSelectedValue([]); setSelectedLabel(''); setSelectIconType(''); handleSelectChange(''); } - function handleSelectChange(value: any) { + function handleSelectChange(value: ValueType | Array) { onChange && onChange(value); } + function inputKeyDown(e: any) { + if (selectedValue.length > 0 && !!selectedLabel && e.keyCode === 8) { + const values = removeSelectItem(selectedValue.length - 1); + setSelectedValue(values); + } + } + return ( 0 ? false : true} {...others} - onVisibleChange={(open) => setInnerIsOpen(open)} + onVisibleChange={(open) => { + if (!open && isMultiple) setSelectedLabel(''); + setInnerIsOpen(open); + }} isOpen={innerIsOpen} menu={ {loading ? '正在加载数据...' : '没有数据'} ) : ( option.map((item, idx) => { - const active = selectedValue === item.value; - return handleItemClick(item)} />; + const active = !!selectedValue.find((finds) => finds.value === item.value); + return ( + (isMultiple ? handleItemsClick(item) : handleItemClick(item))} + /> + ); }) )} @@ -146,21 +186,63 @@ export default function SearchSelect(props: SearchSelectProps) { ref={divRef} onMouseOver={() => renderSelectIcon('enter')} onMouseLeave={() => renderSelectIcon('leave')} - style={style} + style={{ + ...style, + maxWidth: 'none', + width: 200, + // display: 'flex', + // flexWrap: 'wrap', + // flex: '1 1 auto', + }} > - - ) +
+ > + {isMultiple && + selectedValue.map((item, index) => { + return ( + setSelectedValue(removeSelectItem(index))} + color="#ccc" + > + {item.label} + + ); + })} + + ) + } + /> +
); diff --git a/packages/react-search-select/src/style/index.less b/packages/react-search-select/src/style/index.less new file mode 100644 index 0000000000..016dc592df --- /dev/null +++ b/packages/react-search-select/src/style/index.less @@ -0,0 +1,8 @@ +.inptContents { + input { + box-shadow: none; + &:hover:after { + box-shadow: 'none' !important; + } + } +} From bfefc277b28efd68d7f462613c1a83387e023201 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 10:41:27 +0800 Subject: [PATCH 07/59] =?UTF-8?q?fix(form):=E5=A2=9E=E5=8A=A0=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE=E8=A1=A8=E5=8D=95=E5=80=BC=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 6331436fab..18315b1151 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -125,6 +125,7 @@ function Form( onSubmit: handleSubmit, resetForm: handleReset, getFieldValues: () => data.current, + setFields: setFields, }), [data], ); @@ -159,6 +160,11 @@ function Form( ); } + function setFields(fields: FormState['current']) { + data.current = fields; + setData(data); + } + function handleChange( name: string, validator: FormFieldsProps['validator'], From 94cdab2ae603d228370734a75dce97a1cd8f2b81 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 11:02:33 +0800 Subject: [PATCH 08/59] =?UTF-8?q?feat(form):=E5=A2=9E=E5=8A=A0=E5=BF=85?= =?UTF-8?q?=E4=BC=A0=E8=A1=A8=E5=8D=95=E9=A1=B9=E6=A0=87=E6=B3=A8=20#534?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 1 + packages/react-form/src/FormItem.tsx | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 18315b1151..c0961ba91d 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -29,6 +29,7 @@ export interface FormFieldsProps extends FormItemProps { inline?: boolean; checked?: boolean; initialValue?: string | number | T; + required?: boolean; validator?: (currentValue: any) => any; } diff --git a/packages/react-form/src/FormItem.tsx b/packages/react-form/src/FormItem.tsx index f73917f6d8..c03707d35a 100644 --- a/packages/react-form/src/FormItem.tsx +++ b/packages/react-form/src/FormItem.tsx @@ -8,6 +8,7 @@ export interface FormItemProps extends IProps, HTMLDivProps { inline?: boolean; hasError?: boolean; label?: React.ReactNode; + required?: boolean; labelFor?: string; labelClassName?: string; help?: React.ReactNode; @@ -24,6 +25,7 @@ export default class FormItem extends React.PureComponent> { const { prefixCls, className, + required, style, label, labelFor, @@ -36,6 +38,7 @@ export default class FormItem extends React.PureComponent> { hasError, ...otherProps } = this.props; + console.log('required', required); const cls = [prefixCls, className, hasError ? `${prefixCls}-error` : null].filter(Boolean).join(' ').trim(); const labelCls = ['w-form-label', labelClassName].filter(Boolean).join(' ').trim(); if (inline) { @@ -43,6 +46,7 @@ export default class FormItem extends React.PureComponent> {
+ {required && } @@ -60,9 +64,12 @@ export default class FormItem extends React.PureComponent> { return (
{label && ( - + + {required && } + + )} {this.props.children} {help &&
{help}
} From 8fc1fec2cb3739c38f34340fa6f58fe11fd14de6 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 11:16:32 +0800 Subject: [PATCH 09/59] =?UTF-8?q?fix(search-select):=E5=A2=9E=E5=8A=A0Tag?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 14 ++++++++------ packages/react-search-select/package.json | 1 + 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index c0961ba91d..8d5db58663 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -59,7 +59,7 @@ export type FormElementProps = { onChange?: (env: React.BaseSyntheticEvent, list?: string[]) => void; }; -export type FormRefType = Record<'onSubmit' | 'resetForm' | 'getFieldValues', Function>; +export type FormRefType = Record<'onSubmit' | 'resetForm' | 'getFieldValues' | 'setFields', Function>; function newFormState( fields: FormProps['fields'], @@ -120,13 +120,15 @@ function Form( setDatas(JSON.parse(JSON.stringify(values))); }; - useImperativeHandle, any>( + useImperativeHandle, React.MutableRefObject>( ref, () => ({ - onSubmit: handleSubmit, - resetForm: handleReset, - getFieldValues: () => data.current, - setFields: setFields, + current: { + onSubmit: handleSubmit, + resetForm: handleReset, + getFieldValues: () => data.current, + setFields: setFields, + }, }), [data], ); diff --git a/packages/react-search-select/package.json b/packages/react-search-select/package.json index 2008759519..125c9f3bd9 100644 --- a/packages/react-search-select/package.json +++ b/packages/react-search-select/package.json @@ -49,6 +49,7 @@ "@uiw/react-input": "^4.11.0", "@uiw/react-loader": "^4.11.0", "@uiw/react-menu": "^4.11.0", + "@uiw/react-tag": "^4.11.0", "@uiw/utils": "^4.11.0" }, "devDependencies": { From f47944d291f880a03813d595b4e69620ddb1e8ba Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 13:46:14 +0800 Subject: [PATCH 10/59] =?UTF-8?q?fix(form):=E5=A2=9E=E5=8A=A0=E8=8E=B7?= =?UTF-8?q?=E5=8F=96=E5=BC=82=E5=B8=B8=E4=BF=A1=E6=81=AF=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 8d5db58663..2d1e864179 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -120,15 +120,14 @@ function Form( setDatas(JSON.parse(JSON.stringify(values))); }; - useImperativeHandle, React.MutableRefObject>( + useImperativeHandle, any>( ref, () => ({ - current: { - onSubmit: handleSubmit, - resetForm: handleReset, - getFieldValues: () => data.current, - setFields: setFields, - }, + onSubmit: handleSubmit, + resetForm: handleReset, + getFieldValues: () => data.current, + getError: () => data.errors, + setFields: setFields, }), [data], ); From 34cbebc3916a40ea12697843778d91b703a62d6b Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 13:57:38 +0800 Subject: [PATCH 11/59] =?UTF-8?q?fix(form):=E4=BF=AE=E5=A4=8DafterSubmit?= =?UTF-8?q?=E5=9B=9E=E8=B0=83=E5=A4=B1=E6=95=88=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 2 +- packages/react-form/src/FormItem.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 2d1e864179..607153ccba 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -219,7 +219,7 @@ function Form( nextState.current = initial; } setData({ ...data, ...nextState, errors: {} }); - return () => afterSubmit!({ state: data, response, reset: handleReset }); + afterSubmit && afterSubmit({ state: data, response, reset: handleReset }); }; try { const afterSubmitPromise = onSubmit ? onSubmit({ initial, current }, e) : undefined; diff --git a/packages/react-form/src/FormItem.tsx b/packages/react-form/src/FormItem.tsx index c03707d35a..58b3225c36 100644 --- a/packages/react-form/src/FormItem.tsx +++ b/packages/react-form/src/FormItem.tsx @@ -38,7 +38,7 @@ export default class FormItem extends React.PureComponent> { hasError, ...otherProps } = this.props; - console.log('required', required); + const cls = [prefixCls, className, hasError ? `${prefixCls}-error` : null].filter(Boolean).join(' ').trim(); const labelCls = ['w-form-label', labelClassName].filter(Boolean).join(' ').trim(); if (inline) { From e206d3490a7bb8b31564b52a91d4b3ecd1e4538c Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 14:32:29 +0800 Subject: [PATCH 12/59] =?UTF-8?q?fix(search-select):=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/package.json | 1 + packages/react-search-select/src/index.tsx | 9 +-------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/react-search-select/package.json b/packages/react-search-select/package.json index 6c4af1ba4b..8eba0f036a 100644 --- a/packages/react-search-select/package.json +++ b/packages/react-search-select/package.json @@ -48,6 +48,7 @@ "@uiw/react-icon": "^4.11.1", "@uiw/react-input": "^4.11.1", "@uiw/react-loader": "^4.11.1", + "@uiw/react-tag": "^4.11.1", "@uiw/react-menu": "^4.11.1", "@uiw/utils": "^4.11.1" }, diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 9057ca6b12..3902fb5224 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -186,14 +186,7 @@ export default function SearchSelect(props: SearchSelectProps) { ref={divRef} onMouseOver={() => renderSelectIcon('enter')} onMouseLeave={() => renderSelectIcon('leave')} - style={{ - ...style, - maxWidth: 'none', - width: 200, - // display: 'flex', - // flexWrap: 'wrap', - // flex: '1 1 auto', - }} + style={{ width: 'auto', maxWidth: 'none', ...style }} >
Date: Wed, 16 Feb 2022 15:03:44 +0800 Subject: [PATCH 13/59] =?UTF-8?q?refactor(search-select):=E9=87=8D?= =?UTF-8?q?=E5=91=BD=E5=90=8D=E7=B1=BB=E5=9E=8B=E5=90=8D=E7=A7=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 3902fb5224..d68114512f 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -19,13 +19,13 @@ export interface SearchSelectProps extends IProps, DropdownProps { allowClear: boolean; defaultValue?: string | number; value?: ValueType; - option: MenuItemData[]; + option: SearchSelectOptionData[]; onSelect?: (value: ValueType | Array) => void; onSearch?: (value: string) => void; onChange?: (value: ValueType | Array) => void; } -export interface MenuItemData { +export interface SearchSelectOptionData { label: string; value: string | number; [keyName: string]: any; @@ -55,14 +55,14 @@ export default function SearchSelect(props: SearchSelectProps) { const isMultiple = useMemo(() => mode === 'multiple', [mode]); const [innerIsOpen, setInnerIsOpen] = useState(false); - const [selectedValue, setSelectedValue] = useState>( + const [selectedValue, setSelectedValue] = useState>( option.filter((item) => item.value === value), ); const [selectedLabel, setSelectedLabel] = useState(''); const [selectIconType, setSelectIconType] = useState(''); const divRef = useRef(null); - const valueRef = useRef>(); + const valueRef = useRef>(); valueRef.current = useMemo(() => selectedValue, [selectedValue]); useEffect(() => { @@ -73,13 +73,13 @@ export default function SearchSelect(props: SearchSelectProps) { }, []); function removeSelectItem(index: number) { - const selectedValue = valueRef.current as MenuItemData[]; + const selectedValue = valueRef.current as SearchSelectOptionData[]; selectedValue.splice(index, 1); const values = [...selectedValue]; return values; } - function handleItemClick(item: MenuItemData) { + function handleItemClick(item: SearchSelectOptionData) { setInnerIsOpen(false); const values = [item]; setSelectedValue(values); @@ -90,8 +90,8 @@ export default function SearchSelect(props: SearchSelectProps) { handleSelectChange(resultValue); } - function handleItemsClick(item: MenuItemData) { - let values: MenuItemData[] = []; + function handleItemsClick(item: SearchSelectOptionData) { + let values: SearchSelectOptionData[] = []; const index = selectedValue.findIndex((finds) => finds.value === item.value); if (index !== -1) { values = removeSelectItem(index); From 72216645f1d8a02fc3bff70bf3c5274e74d46b0b Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 15:36:50 +0800 Subject: [PATCH 14/59] =?UTF-8?q?style(search-select):=20=E5=A4=9A?= =?UTF-8?q?=E9=80=89select=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 4 ++-- packages/react-search-select/src/style/index.less | 9 +++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index d68114512f..699b9722fe 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -186,7 +186,7 @@ export default function SearchSelect(props: SearchSelectProps) { ref={divRef} onMouseOver={() => renderSelectIcon('enter')} onMouseLeave={() => renderSelectIcon('leave')} - style={{ width: 'auto', maxWidth: 'none', ...style }} + style={style} >
{ return ( setSelectedValue(removeSelectItem(index))} diff --git a/packages/react-search-select/src/style/index.less b/packages/react-search-select/src/style/index.less index 016dc592df..ff481636e3 100644 --- a/packages/react-search-select/src/style/index.less +++ b/packages/react-search-select/src/style/index.less @@ -1,8 +1,13 @@ .inptContents { input { box-shadow: none; - &:hover:after { - box-shadow: 'none' !important; + } + .w-input-inner { + &:hover { + box-shadow: none !important; + } + &:focus { + box-shadow: none !important; } } } From d6efbbe89f2a20d7aac0c353d511a20759721fe0 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 15:46:19 +0800 Subject: [PATCH 15/59] =?UTF-8?q?style(search-select):=20=E5=A4=9A?= =?UTF-8?q?=E9=80=89select=E4=B8=8B=E6=8B=89=E5=BC=B9=E5=B1=82=E6=A0=B7?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 699b9722fe..0f80574418 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -160,6 +160,7 @@ export default function SearchSelect(props: SearchSelectProps) { style={{ minHeight: 25, maxHeight: 280, + minWidth: style?.minWidth || 200, overflowY: 'scroll', width: divRef.current ? divRef.current.offsetWidth : 'auto', }} From 0cb0a693d161e1151e36be5d51777044c9034c10 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 16:29:11 +0800 Subject: [PATCH 16/59] =?UTF-8?q?fix(Table):data=E4=B8=8D=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E5=AF=B9=E8=B1=A1=E5=86=85=E5=8C=85=E5=90=AB=E5=B8=83?= =?UTF-8?q?=E5=B0=94=E7=B1=BB=E5=9E=8B=20#517?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 3 ++- packages/react-table/src/index.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 82716e75cb..7cfad8a890 100644 --- a/.gitignore +++ b/.gitignore @@ -29,4 +29,5 @@ yarn.lock # IDEA *.iml *.ipr -*.iws \ No newline at end of file +*.iws +Tools diff --git a/packages/react-table/src/index.tsx b/packages/react-table/src/index.tsx index b4ed1ab97b..0ca040f16e 100644 --- a/packages/react-table/src/index.tsx +++ b/packages/react-table/src/index.tsx @@ -25,7 +25,7 @@ export type TableColumns = { export interface TableProps extends IProps, Omit { prefixCls?: string; columns?: TableColumns[]; - data?: Record[]; + data?: Record[]; title?: React.ReactNode; footer?: React.ReactNode; bordered?: boolean; From 0048c06803b3b3c375e6032ccdbeb7808fdeb240 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 16 Feb 2022 16:51:03 +0800 Subject: [PATCH 17/59] =?UTF-8?q?style(search-select):=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E6=A0=B7=E5=BC=8F=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 6 +++-- .../react-search-select/src/style/index.less | 24 ++++++++++++------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 0f80574418..d9205e61cb 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -38,7 +38,7 @@ export default function SearchSelect(props: SearchSelectProps) { size = 'default', option = [], loading = false, - prefixCls, + prefixCls = 'w-search-select', className, mode = 'single', style, @@ -53,6 +53,7 @@ export default function SearchSelect(props: SearchSelectProps) { ...others } = props; + const cls = [prefixCls, className].filter(Boolean).join(' ').trim(); const isMultiple = useMemo(() => mode === 'multiple', [mode]); const [innerIsOpen, setInnerIsOpen] = useState(false); const [selectedValue, setSelectedValue] = useState>( @@ -145,6 +146,7 @@ export default function SearchSelect(props: SearchSelectProps) { return ( 0 ? false : true} @@ -218,7 +220,7 @@ export default function SearchSelect(props: SearchSelectProps) { })} Date: Wed, 16 Feb 2022 17:21:08 +0800 Subject: [PATCH 18/59] =?UTF-8?q?style(SearchSelect):=20=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - packages/react-search-select/src/index.tsx | 2 +- packages/react-search-select/src/style/index.less | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7cfad8a890..cd51ab3286 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,3 @@ yarn.lock *.iml *.ipr *.iws -Tools diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 13ba91e4a3..9ff56eb83a 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -220,7 +220,7 @@ export default function SearchSelect(props: SearchSelectProps) { })} Date: Thu, 17 Feb 2022 11:41:16 +0800 Subject: [PATCH 19/59] =?UTF-8?q?ifx(SearchSelect):=20=E5=A2=9E=E5=8A=A0va?= =?UTF-8?q?lue=E5=8F=97=E6=8E=A7=E6=94=AF=E6=8C=81,=E5=A4=9A=E9=80=89?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B8=8B=E4=B8=BA=E6=95=B0=E7=BB=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/README.md | 36 ++++++++++---------- packages/react-search-select/src/index.tsx | 39 ++++++++++++++-------- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/packages/react-search-select/README.md b/packages/react-search-select/README.md index 2c4e0bf1c2..9d0caf4e70 100644 --- a/packages/react-search-select/README.md +++ b/packages/react-search-select/README.md @@ -17,22 +17,25 @@ import ReactDOM from 'react-dom'; import { SearchSelect } from 'uiw'; const Demo = () => { - const [option, setOption] = React.useState([]); - const [loading, setLoading] = React.useState(false); - const [value, setValue] = React.useState(undefined); - function handleSearch(e) { - console.log('handleSearch',e) - setLoading(true) - setTimeout(() => { - setOption([ - { label: 'a', value: 2 }, - { label: 'aa', value: 3 }, - { label: 'aaa', value: 4 }, + const selectOption=[ + { label: 'a1', value: 1 }, + { label: 'a2', value: 2 }, + { label: 'a3', value: 3 }, + { label: 'a4', value: 4 }, { label: 'a5', value: 5 }, { label: 'a6', value: 6 }, { label: 'a7', value: 7 }, { label: 'a8', value: 8 }, - ]); + ] + + const [option, setOption] = React.useState(selectOption); + const [loading, setLoading] = React.useState(false); + const [value, setValue] = React.useState([2,5]); + function handleSearch(e) { + setValue([3,4]) + setLoading(true) + setTimeout(() => { + setOption(); setLoading(false); }, 2000); } @@ -42,7 +45,7 @@ const Demo = () => { style={{ maxWidth: 200 }} showSearch={true} allowClear - value={[2,3]} + value={value} disabled={false} placeholder="请输入选择" onSearch={handleSearch} @@ -50,7 +53,6 @@ const Demo = () => { loading={loading} option={option} onChange={(value) => { - console.log('onChange',value) setValue(value) }} /> @@ -162,13 +164,13 @@ ReactDOM.render(, _mount_); |--------- |-------- |--------- |-------- | | allowClear | 支持清除 | Boolean | `false` | | disabled | 禁用选择器 | Boolean | `false` | -| mode | 是否可以多选; 'multiple','single' | String | 'single' | +| mode | 选择模式: `multiple` `single` | String | `single` | | defaultValue | 指定默认选中的条目 | String/Number | - | -| value | 指定选中的条目的值 | String/Number | - | +| value | 指定选中的条目的值 | String/Number 多选模式下`value`皆为`Array` | - | | placeholder | 选择框默认文字 | String | - | | showSearch | 使单选模式可搜索 | Boolean | - | | size | 选择框尺寸 | Enum{`large`, `default`, `small` } | `default` | -| onChange | 选中 option,或 input 的 value,调用此函数 | `function(value, option:Option/Array
}> */} + {/* e.preventDefault()}> + 点击我出现下拉菜单 + */} +
renderSelectIcon('enter')} + // onMouseLeave={() => renderSelectIcon('leave')} + style={{ width: 200, maxWidth: 'none', ...style }} + > +
+
+ {selectedOption.map((item, index) => { + return ( + setSelectedOption(removeSelectItem(index))} + color="#ccc" + > + {item} + + ); + })} + +
+ {(selectIconType === 'close' || (selectIconType === 'loading' && loading)) && ( + {}} /> + )} +
+
+ + ); +} + +export default SearchTagInput; diff --git a/packages/react-search-tree/src/style/index.less b/packages/react-search-tree/src/style/index.less new file mode 100644 index 0000000000..8cff585394 --- /dev/null +++ b/packages/react-search-tree/src/style/index.less @@ -0,0 +1,65 @@ +@w-search-tree: ~'w-search-tree'; + +.@{w-search-tree} { + &-input-contents { + input { + box-shadow: none; + padding: 0px; + height: 20px; + } + + .w-input-inner { + &:hover { + box-shadow: none !important; + } + + &:focus { + box-shadow: none !important; + } + } + } + + &-inner { + display: flex; + justify-content: space-between; + outline: none; + border: none; + align-items: center; + border-radius: 3px; + box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.15), + inset 0 1px 1px rgba(16, 22, 26, 0.2); + box-sizing: border-box; + background: #fff; + min-height: 30px; + margin: 0 !important; + padding: 3px 10px 3px 10px; + vertical-align: middle; + line-height: 30px; + color: #393e48; + font-weight: 400; + font-size: inherit; + transition: box-shadow 0.3s cubic-bezier(0.4, 1, 0.75, 0.9); + appearance: none; + + &:focus { + box-shadow: 0 0 0 1px #393e48, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:focus&:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:disabled { + box-shadow: none; + background: #dddddd; + opacity: 0.75; + color: #a5a5a5; + cursor: not-allowed; + resize: none; + } + } +} diff --git a/packages/react-search-tree/tsconfig.json b/packages/react-search-tree/tsconfig.json new file mode 100644 index 0000000000..41a3f0ac82 --- /dev/null +++ b/packages/react-search-tree/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig", + "include": ["src/**/*"], + "compilerOptions": { + "outDir": "./cjs", + "baseUrl": "." + } +} From b9363e4cfc1d95048195cf28f53971c628517268 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Tue, 22 Feb 2022 18:09:26 +0800 Subject: [PATCH 32/59] SearchTree --- packages/uiw/package.json | 1 + packages/uiw/src/index.ts | 2 ++ website/src/menu.json | 1 + website/src/routers.tsx | 2 ++ .../src/routes/components/search-tree/index.tsx | 14 ++++++++++++++ 5 files changed, 20 insertions(+) create mode 100644 website/src/routes/components/search-tree/index.tsx diff --git a/packages/uiw/package.json b/packages/uiw/package.json index e5077cf7a8..bd1875c0b6 100644 --- a/packages/uiw/package.json +++ b/packages/uiw/package.json @@ -110,6 +110,7 @@ "@uiw/react-time-picker": "^4.11.4", "@uiw/react-tooltip": "^4.11.4", "@uiw/react-tree": "^4.11.4", + "@uiw/react-search-tree": "^4.11.4", "@uiw/react-tree-checked": "^4.11.4" }, "devDependencies": { diff --git a/packages/uiw/src/index.ts b/packages/uiw/src/index.ts index 0ea20b0bbe..31f4b8acd1 100644 --- a/packages/uiw/src/index.ts +++ b/packages/uiw/src/index.ts @@ -55,6 +55,7 @@ export * from '@uiw/react-time-picker'; export * from '@uiw/react-tooltip'; export * from '@uiw/react-tree'; export * from '@uiw/react-tree-checked'; +export * from '@uiw/react-search-tree'; export { default as Affix } from '@uiw/react-affix'; export { default as Alert } from '@uiw/react-alert'; @@ -112,3 +113,4 @@ export { default as TimePicker } from '@uiw/react-time-picker'; export { default as Tooltip } from '@uiw/react-tooltip'; export { default as Tree } from '@uiw/react-tree'; export { default as TreeChecked } from '@uiw/react-tree-checked'; +export { default as SearchTree } from '@uiw/react-search-tree'; diff --git a/website/src/menu.json b/website/src/menu.json index 56257b5065..7be5c0bb33 100755 --- a/website/src/menu.json +++ b/website/src/menu.json @@ -72,6 +72,7 @@ { "name": "Tag 标签", "path": "tag" }, { "name": "Tree 树形控件", "path": "tree" }, { "name": "TreeChecked 树形选择控件", "path": "tree-checked" }, + { "name": "SearchTree 搜索树形控件", "path": "search-tree" }, { "name": "Table 表格", "path": "table" }, { "name": "Progress 进度条", "path": "progress" }, { "name": "List 列表", "path": "list" }, diff --git a/website/src/routers.tsx b/website/src/routers.tsx index 7e30e2b869..b65a05e2e0 100755 --- a/website/src/routers.tsx +++ b/website/src/routers.tsx @@ -63,6 +63,7 @@ const Layout = Loadable(lazy(() => import('./routes/components/layout'))); const Notify = Loadable(lazy(() => import('./routes/components/notify'))); const Tree = Loadable(lazy(() => import('./routes/components/tree'))); const TreeChecked = Loadable(lazy(() => import('./routes/components/tree-checked'))); +const SearchTree = Loadable(lazy(() => import('./routes/components/search-tree'))); const Tag = Loadable(lazy(() => import('./routes/components/tag'))); const Tabs = Loadable(lazy(() => import('./routes/components/tabs'))); const Tooltip = Loadable(lazy(() => import('./routes/components/tooltip'))); @@ -153,6 +154,7 @@ export const routes: RouteObject[] = [ { path: '/components/notify', element: }, { path: '/components/tree', element: }, { path: '/components/tree-checked', element: }, + { path: '/components/search-tree', element: }, { path: '/components/tag', element: }, { path: '/components/tabs', element: }, { path: '/components/tooltip', element: }, diff --git a/website/src/routes/components/search-tree/index.tsx b/website/src/routes/components/search-tree/index.tsx new file mode 100644 index 0000000000..f8ee3e89a4 --- /dev/null +++ b/website/src/routes/components/search-tree/index.tsx @@ -0,0 +1,14 @@ +import React, { useState } from 'react'; +import { TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw'; +import Markdown from '../../../components/Markdown'; + +export default () => ( + { + const md = await import('uiw/node_modules/@uiw/react-search-tree/README.md'); + return md.default || md; + }} + /> +); From 940fb072fdd49c0de7cf05ada496895781a8e802 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 23 Feb 2022 00:32:37 +0800 Subject: [PATCH 33/59] =?UTF-8?q?=E6=9A=82=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 12 +- packages/react-search-tree/README.md | 1 - packages/react-search-tree/package.json | 1 + packages/react-search-tree/src/index.tsx | 160 +++++++++++++++--- .../react-search-tree/src/searchTagInput.tsx | 55 +++--- 5 files changed, 170 insertions(+), 59 deletions(-) diff --git a/package.json b/package.json index a01c1d042d..d96694ab12 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,12 @@ "homepage": "https://uiwjs.github.io", "private": true, "scripts": { - "lib": "lerna exec --scope @uiw/react-file-input -- tsbb build --target react", - "lib:css": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o esm", - "lib:css:dist": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o lib --combine=dist.css", - "lib:css:watch": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o esm --watch", - "lib:watch": "lerna exec --scope @uiw/react-file-input -- tsbb watch & npm run lib:css:watch", - "lib:bootstrap": "lerna bootstrap --hoist --scope @uiw/react-file-input", + "lib": "lerna exec --scope @uiw/react-search-tree -- tsbb build --target react", + "lib:css": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o esm", + "lib:css:dist": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o lib --combine=dist.css", + "lib:css:watch": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o esm --watch", + "lib:watch": "lerna exec --scope @uiw/react-search-tree -- tsbb watch & npm run lib:css:watch", + "lib:bootstrap": "lerna bootstrap --hoist --scope @uiw/react-search-tree", "lib:build": "npm run lib && npm run lib:css && npm run lib:css:dist", "//>>>>>>>>>>>>": "<<<<<<<<<<", "watch:other:lib": "lerna exec --parallel --scope @uiw/* --ignore @uiw/doc -- tsbb watch", diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index f5414e2fa7..ca5456aba0 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -53,7 +53,6 @@ const data = [ }, { label: '澳门', key: '3' }, ]; -console.log('data',data) const Demo = () => ( ; +const TreeCheckeds = (props: DropContent & { reff: any }) => { + // const [selectOption, selectOptionSet] = useState({}) + // const [keys, keysSet] = useState>() + + const { + option: [selectOption, selectOptionSet], + keys: [keys, keysSet], + } = props.reff.current; + console.log(',,,,,,,', keys); + const onSelected = (_1: any, _2: any, isChecked: any, evn: any) => { + let curSelectOption: SelectOtpion = {}; + curSelectOption = getOptionsRecursion([evn], selectOption, isChecked); + selectOptionSet(curSelectOption); + // const option = Object.entries(curSelectOption).map(([value, label]) => ({ value, label })) + const keys: any = []; + const option = Object.entries(curSelectOption).map(([value, label]) => { + keys.push(value); + return { value, label }; + }); + keysSet(keys); + props.onSelected(option); + }; + + const getOptionsRecursion = (childrens: Array, selectOption: SelectOtpion, isAdd: boolean) => { + childrens.forEach((child: any) => { + if (child?.children?.length > 0) { + selectOption = getOptionsRecursion(child.children, selectOption, isAdd); + } else if (isAdd) { + selectOption[child.key] = child.label; + } else { + delete selectOption[child.key]; + } + }); + return selectOption; + }; + + const data = [ + { + label: '湖北省', + key: '0-0-0', + children: [ + { + label: '武汉市', + key: '0-1-0', + children: [ + { label: '新洲区', key: '0-1-1', disabled: true }, + { label: '武昌区', key: '0-1-2' }, + { + label: '汉南区', + key: '0-1-3', + children: [ + { label: '汉南区1', key: '0-1-3-1' }, + { label: '汉南区2', key: '0-1-3-2' }, + { label: '汉南区3', key: '0-1-3-3' }, + ], + }, + ], + }, + { label: '黄冈市', key: '0-2-0' }, + { + label: '黄石市', + key: '0-3-0', + children: [ + { label: '青山区', key: '0-3-1' }, + { label: '黄陂区', key: '0-3-2' }, + { label: '青山区', key: '0-3-3' }, + ], + }, + ], + }, + { + label: '上海市', + key: '1-0-0', + children: [ + { label: '黄浦区', key: '1-0-1' }, + { label: '卢湾区', key: '1-0-2' }, + { + label: '徐汇区', + key: '1-0-3', + children: [ + { label: '半淞园路街道', key: '1-1-0' }, + { label: '南京东路街道', key: '1-2-0' }, + { label: '外滩街道', key: '1-3-0' }, + ], + }, + ], + }, + { + label: '北京市', + key: '2-0-0', + children: [ + { label: '东城区', key: '2-1-0' }, + { label: '西城区', key: '2-2-0' }, + { + label: '崇文区', + key: '2-3-0', + children: [ + { label: '东花市街道', key: '2-3-1' }, + { label: '体育馆路街道', key: '2-3-2' }, + { label: '前门街道', key: '2-3-3' }, + ], + }, + ], + }, + { label: '澳门', key: '3' }, + ]; + + return ; +}; + +function SearchTreeChecked(props: any) { + const reff = useRef(); + reff.current = { + option: useState({}), + keys: useState>(), + }; + + const onChange = (resultValue: Array) => { + // console.log('resultVal--ue', resultValue) + // props.onChange(resultValue) + }; -const TreeCheckeds = (props: DropContent) => { - console.log('aa', props.value); return ( - { - // console.log(key, expanded, data, node); - // }} - // onSelected={(key, selected, item, evn) => { - // console.log('select:', key); - // console.log('select:', selected); - // console.log('select:', item); - // console.log('select:', evn); - // }} + { + console.log('------------------', option); + }} + /> + } /> ); -}; - -function TreeChecked() { - return {}} />} />; } -export default TreeChecked; +export default SearchTreeChecked; diff --git a/packages/react-search-tree/src/searchTagInput.tsx b/packages/react-search-tree/src/searchTagInput.tsx index c8f3711517..829f3fd373 100644 --- a/packages/react-search-tree/src/searchTagInput.tsx +++ b/packages/react-search-tree/src/searchTagInput.tsx @@ -1,17 +1,15 @@ -import React, { useMemo, useState, useRef, useEffect } from 'react'; -import Dropdown, { DropdownProps } from '@uiw/react-dropdown'; +import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react'; +import Dropdown from '@uiw/react-dropdown'; import Icon from '@uiw/react-icon'; import Input from '@uiw/react-input'; import Tag from '@uiw/react-tag'; +import Card from '@uiw/react-card'; import { IProps } from '@uiw/utils'; import './style/index.less'; -export interface DropContent extends React.ReactElement { - value: Array | undefined; - onSelected: () => void; - // key: any, - // type: any, - // props: any +export interface DropContent { + values: Array | undefined; + onSelected: (options: Array) => void; // data: Array, } @@ -21,7 +19,7 @@ export interface SearchTagInputOption { } export interface SearchTagInputProps extends IProps { - content: DropContent; + content: ReactElement; onChange?: (_: Array) => void; mode?: 'single' | 'multiple'; loading?: boolean; @@ -41,48 +39,45 @@ function SearchTagInput(props: SearchTagInputProps) { } = props; const cls = [prefixCls, className].filter(Boolean).join(' ').trim(); - const isMultiple = useMemo(() => mode === 'multiple', [mode]); - const [innerIsOpen, setInnerIsOpen] = useState(false); + // const isMultiple = useMemo(() => mode === 'multiple', [mode]); + // const [innerIsOpen, setInnerIsOpen] = useState(false); const [selectedOption, setSelectedOption] = useState>([]); + const optionRef = useRef>(); + optionRef.current = useMemo(() => selectedOption, [selectedOption]); const [selectIconType, setSelectIconType] = useState(''); const onSelected = (selectedOption: Array) => { - console.log('selectedOption', selectedOption); setSelectedOption(selectedOption); + + onChange && onChange(selectedOption); }; const removeSelectItem = (index: number) => { - const selectedValue = selectedOption; - selectedValue.splice(index, 1); - const values = [...selectedValue]; - return values; + const selectedOption = optionRef.current as Array; + selectedOption.splice(index, 1); + onSelected([...selectedOption]); }; - const handleChangeForProps = (changeValue: Array) => { - if (!onChange) return; - - onChange(changeValue); - }; + // const handleChangeForProps = (selectedOption: Array) => { + // if (!onChange) return; + // onChange(selectedOption); + // }; const newContent = useMemo(() => { const newProps = { ...content.props, onSelected }; - return React.cloneElement(content as any, newProps); + return React.cloneElement(content as JSX.Element, newProps); }, []); return ( - - {/* 123
}> */} - {/* e.preventDefault()}> - 点击我出现下拉菜单 - */} + {newContent}}>
renderSelectIcon('enter')} // onMouseLeave={() => renderSelectIcon('leave')} style={{ width: 200, maxWidth: 'none', ...style }} >
+ {/* {optionRef.current.map((item, index) => { */} {selectedOption.map((item, index) => { return ( setSelectedOption(removeSelectItem(index))} + onClose={() => removeSelectItem(index)} color="#ccc" > - {item} + {item.label} ); })} From 455485cbd896f1cc484481780d4ac86e4898df9e Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 23 Feb 2022 17:47:15 +0800 Subject: [PATCH 34/59] =?UTF-8?q?feat(SearhTree):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=B8=A6=E6=90=9C=E7=B4=A2=E7=9A=84=E6=A0=91=E5=BD=A2=E9=80=89?= =?UTF-8?q?=E6=8B=A9=E6=8E=A7=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 1 + packages/react-search-tree/README.md | 49 ++---- packages/react-search-tree/src/index.tsx | 164 +++++------------- .../react-search-tree/src/searchTagInput.tsx | 123 ++++++++----- .../react-search-tree/src/style/index.less | 1 + packages/react-tree/src/index.tsx | 4 + 6 files changed, 152 insertions(+), 190 deletions(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index f800499cec..7b24e62e11 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -146,6 +146,7 @@ export default function SearchSelect(props: SearchSelectProps) { function renderSelectIcon(type: string) { let selectIconType; if (type === 'enter' && allowClear && selectedValue) { + console.log(123); selectIconType = 'close'; } else { selectIconType = ''; diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index ca5456aba0..76d3925aaa 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -56,34 +56,12 @@ const data = [ const Demo = () => ( consoe.log('SearchTree-> SearchTreeOption',SearchTreeOption)} - onChange={()=>console.log('SearchTree-> onChange',onChange)} - content={ - { - // console.log(key, expanded, data, node); - // }} - // onSelected={(key, selected, item, evn) => { - // console.log('select:', key); - // console.log('select:', selected); - // console.log('select:', item); - // console.log('select:', evn); - // }} - /> - } - // data={data} - // selectedKeys={['0-1-1']} - // onExpand={(key, expanded, data, node) => { - // console.log(key, expanded, data, node); - // }} - // onSelected={(key, selected, item, evn) => { - // console.log('select:', key); - // console.log('select:', selected); - // console.log('select:', item); - // console.log('select:', evn); - // }} + allowClear={true} + onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)} + onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)} + value={[{ label: '东花市街道', value: '2-3-1' }]} + options={data} + placeholder="请输入选择" /> ) ReactDOM.render(, _mount_); @@ -91,10 +69,15 @@ ReactDOM.render(, _mount_); ## Props -完全继承 [Tree](#/components/Tree) 组件属性,默认初始值不一样,下面仅列出默认不一致的 Props。 - | 参数 | 说明 | 类型 | 默认值 | |--------- |-------- |--------- |-------- | -| checkStrictly | 子节点受父节点控制设置 `true`,需要配合 `multiple` 参数使用。 | Boolean | `true` | -| isSelected | 是否选中当前节点 | Boolean | `false` | -| multiple | 支持点选多个节点 | Boolean | `true` | +| allowClear | 支持清除 | Boolean | `false` | +| disabled | 禁用选择器 | Boolean | `false` | +| value | 指定当前选中的条目 | [{label:string, value:string}] | - | +| options | 下拉数据源 | [{label:string, value:string}] | - | +| placeholder | 选择框默认文字 | String | - | +| size | 选择框尺寸 | Enum{large, default, small } | `default` | +| onChange | 选中 option,或 input 的 value,调用此函数 | function(selectdAll, selectd, isChecked)=>void | - | +| onSearch | 文本框值变化时回调 | function(searchValue) | - | +| loading | 加载中状态 | Boolean | `false` | + diff --git a/packages/react-search-tree/src/index.tsx b/packages/react-search-tree/src/index.tsx index 3136319bf0..4af3a831ed 100644 --- a/packages/react-search-tree/src/index.tsx +++ b/packages/react-search-tree/src/index.tsx @@ -1,144 +1,74 @@ import React, { useState, useEffect, useRef } from 'react'; import SearchTagInput, { DropContent, SearchTagInputOption } from './searchTagInput'; -import TreeChecked from '@uiw/react-tree-checked'; +import { TreeData } from '@uiw/react-tree'; +import TreeChecked, { TreeCheckedProps } from '@uiw/react-tree-checked'; type SelectOtpion = Record; -const TreeCheckeds = (props: DropContent & { reff: any }) => { - // const [selectOption, selectOptionSet] = useState({}) - // const [keys, keysSet] = useState>() - const { - option: [selectOption, selectOptionSet], - keys: [keys, keysSet], - } = props.reff.current; - console.log(',,,,,,,', keys); - const onSelected = (_1: any, _2: any, isChecked: any, evn: any) => { - let curSelectOption: SelectOtpion = {}; - curSelectOption = getOptionsRecursion([evn], selectOption, isChecked); - selectOptionSet(curSelectOption); - // const option = Object.entries(curSelectOption).map(([value, label]) => ({ value, label })) - const keys: any = []; - const option = Object.entries(curSelectOption).map(([value, label]) => { - keys.push(value); - return { value, label }; +// type TreeCheckedsProps = TreeCheckedProps & Partial> +function TreeCheckeds( + props: Omit & Partial>, +) { + const [selectOption, selectOptionSet] = useState({}); + const [keys, keysSet] = useState>([]); + + useEffect(() => { + let selectOption: SelectOtpion = {}; + const keys = props.values?.map((opt) => { + selectOption[opt.value] = opt.label; + return opt.value; }); - keysSet(keys); - props.onSelected(option); + selectOptionSet(selectOption); + keysSet(keys || []); + }, [props.values]); + + const onSelected = (_1: any, _2: any, isChecked: boolean, evn: TreeData) => { + const curSelectOption: SelectOtpion = getOptionsRecursion([evn], selectOption, isChecked); + const option = Object.entries(curSelectOption).map(([value, label]) => ({ value, label } as V)); + props.onSelected?.(option, { value: evn.key, label: evn.label as string } as V, isChecked); }; - const getOptionsRecursion = (childrens: Array, selectOption: SelectOtpion, isAdd: boolean) => { - childrens.forEach((child: any) => { - if (child?.children?.length > 0) { + const getOptionsRecursion = (childrens: TreeData[], selectOption: SelectOtpion, isAdd: boolean) => { + childrens.forEach((child: TreeData) => { + if (!!child.children?.length) { selectOption = getOptionsRecursion(child.children, selectOption, isAdd); } else if (isAdd) { - selectOption[child.key] = child.label; + selectOption[child.key!] = child.label?.toString()!; } else { - delete selectOption[child.key]; + delete selectOption[child.key!]; } }); return selectOption; }; - const data = [ - { - label: '湖北省', - key: '0-0-0', - children: [ - { - label: '武汉市', - key: '0-1-0', - children: [ - { label: '新洲区', key: '0-1-1', disabled: true }, - { label: '武昌区', key: '0-1-2' }, - { - label: '汉南区', - key: '0-1-3', - children: [ - { label: '汉南区1', key: '0-1-3-1' }, - { label: '汉南区2', key: '0-1-3-2' }, - { label: '汉南区3', key: '0-1-3-3' }, - ], - }, - ], - }, - { label: '黄冈市', key: '0-2-0' }, - { - label: '黄石市', - key: '0-3-0', - children: [ - { label: '青山区', key: '0-3-1' }, - { label: '黄陂区', key: '0-3-2' }, - { label: '青山区', key: '0-3-3' }, - ], - }, - ], - }, - { - label: '上海市', - key: '1-0-0', - children: [ - { label: '黄浦区', key: '1-0-1' }, - { label: '卢湾区', key: '1-0-2' }, - { - label: '徐汇区', - key: '1-0-3', - children: [ - { label: '半淞园路街道', key: '1-1-0' }, - { label: '南京东路街道', key: '1-2-0' }, - { label: '外滩街道', key: '1-3-0' }, - ], - }, - ], - }, - { - label: '北京市', - key: '2-0-0', - children: [ - { label: '东城区', key: '2-1-0' }, - { label: '西城区', key: '2-2-0' }, - { - label: '崇文区', - key: '2-3-0', - children: [ - { label: '东花市街道', key: '2-3-1' }, - { label: '体育馆路街道', key: '2-3-2' }, - { label: '前门街道', key: '2-3-3' }, - ], - }, - ], - }, - { label: '澳门', key: '3' }, - ]; + return ; +} - return ; -}; +export interface SearchTreeProps { + onChange?: (selectedAll: Array, selectd: V, isChecked: boolean) => void; + onSearch?: (seachValue: string) => void; + value?: Array; + options?: TreeData[]; + treeProps?: Omit & Partial>; +} -function SearchTreeChecked(props: any) { - const reff = useRef(); - reff.current = { - option: useState({}), - keys: useState>(), - }; +function SearchTree(props: SearchTreeProps) { + const { onChange, onSearch, options = [], value = [], treeProps, ...other } = props; + const [selectedValues, selectedValuesSet] = useState>(value); - const onChange = (resultValue: Array) => { - // console.log('resultVal--ue', resultValue) - // props.onChange(resultValue) + const selectedChange = (resultValue: Array, cur: V, isChecked: boolean) => { + selectedValuesSet(resultValue); + onChange?.(resultValue, cur, isChecked); }; return ( { - console.log('------------------', option); - }} - /> - } + {...other} + onChange={selectedChange} + values={selectedValues} + content={} /> ); } -export default SearchTreeChecked; +export default SearchTree; diff --git a/packages/react-search-tree/src/searchTagInput.tsx b/packages/react-search-tree/src/searchTagInput.tsx index 829f3fd373..e1c475392e 100644 --- a/packages/react-search-tree/src/searchTagInput.tsx +++ b/packages/react-search-tree/src/searchTagInput.tsx @@ -1,5 +1,5 @@ import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react'; -import Dropdown from '@uiw/react-dropdown'; +import Dropdown, { DropdownProps } from '@uiw/react-dropdown'; import Icon from '@uiw/react-icon'; import Input from '@uiw/react-input'; import Tag from '@uiw/react-tag'; @@ -7,77 +7,116 @@ import Card from '@uiw/react-card'; import { IProps } from '@uiw/utils'; import './style/index.less'; -export interface DropContent { - values: Array | undefined; - onSelected: (options: Array) => void; - // data: Array, +export interface DropContent { + values: Array; + onSelected?: (selectedAll: Array, selectd: V, isChecked: boolean) => void; + options?: any; } export interface SearchTagInputOption { label: string; - value: any; + value: string | number; } -export interface SearchTagInputProps extends IProps { - content: ReactElement; - onChange?: (_: Array) => void; - mode?: 'single' | 'multiple'; +export interface SearchTagInputProps extends IProps, DropdownProps, DropContent { + allowClear?: boolean; + content: ReactElement>; + size?: 'large' | 'default' | 'small'; + onChange: (selectedAll: Array, selectd: V, isChecked: boolean) => void; + onSearch?: (seachValue: string) => void; + // mode?: 'single' | 'multiple'; loading?: boolean; + placeholder?: string; } -function SearchTagInput(props: SearchTagInputProps) { +function SearchTagInput(props: SearchTagInputProps) { const { prefixCls = 'w-search-tree', mode = 'single', + size = 'default', + disabled = false, + allowClear = false, + loading = false, className, + style, + placeholder, + content, + values, onChange, - - style, - loading = false, + onSearch, ...others } = props; const cls = [prefixCls, className].filter(Boolean).join(' ').trim(); // const isMultiple = useMemo(() => mode === 'multiple', [mode]); // const [innerIsOpen, setInnerIsOpen] = useState(false); - const [selectedOption, setSelectedOption] = useState>([]); - const optionRef = useRef>(); + const [selectedOption, setSelectedOption] = useState>(values); + const optionRef = useRef>(); + const [searchValue, searchValueSet] = useState(''); optionRef.current = useMemo(() => selectedOption, [selectedOption]); const [selectIconType, setSelectIconType] = useState(''); + const inputRef = useRef(null); + + function renderSelectIcon(type: string) { + const selectIconType = type === 'enter' && allowClear && (!!selectedOption.length || searchValue) ? 'close' : ''; + setSelectIconType(selectIconType); + } - const onSelected = (selectedOption: Array) => { - setSelectedOption(selectedOption); + const handleSelectChange = (selectedAll: Array, selectd?: V, isChecked: boolean = true) => { + setSelectedOption(selectedAll); - onChange && onChange(selectedOption); + onChange && onChange(selectedAll, selectd!, isChecked); }; const removeSelectItem = (index: number) => { - const selectedOption = optionRef.current as Array; + const selectedOption = optionRef.current as Array; + const curreentItem = selectedOption[index]; selectedOption.splice(index, 1); - onSelected([...selectedOption]); + handleSelectChange([...selectedOption], curreentItem, false); }; - // const handleChangeForProps = (selectedOption: Array) => { - // if (!onChange) return; - // onChange(selectedOption); - // }; + function handleInputChange(e: React.ChangeEvent) { + const value = e.target.value; + searchValueSet(value); + onSearch?.(value); + setSelectIconType(value ? 'loading' : ''); + } + + // 清除选中的值 + function resetSelectedValue() { + // setInnerIsOpen(false); + setSelectedOption([]); + searchValueSet(''); + setSelectIconType(''); + handleSelectChange([]); + } + + function inputKeyDown(e: any) { + if (selectedOption.length > 0 && !searchValue && e.keyCode === 8) { + removeSelectItem(selectedOption.length - 1); + } + } const newContent = useMemo(() => { - const newProps = { ...content.props, onSelected }; + const newProps = { + ...content.props, + onSelected: handleSelectChange, + values: selectedOption, + }; return React.cloneElement(content as JSX.Element, newProps); - }, []); + }, [selectedOption]); return ( - {newContent}}> + {newContent}}>
renderSelectIcon('enter')} - // onMouseLeave={() => renderSelectIcon('leave')} + onMouseOver={() => renderSelectIcon('enter')} + onMouseLeave={() => renderSelectIcon('leave')} + onClick={() => inputRef.current?.focus()} style={{ width: 200, maxWidth: 'none', ...style }} >
- {/* {optionRef.current.map((item, index) => { */} {selectedOption.map((item, index) => { return ( removeSelectItem(index)} + onClose={(e) => { + e.stopPropagation(); + removeSelectItem(index); + }} color="#ccc" > {item.label} @@ -93,19 +135,20 @@ function SearchTagInput(props: SearchTagInputProps) { ); })}
{(selectIconType === 'close' || (selectIconType === 'loading' && loading)) && ( - {}} /> + )}
diff --git a/packages/react-search-tree/src/style/index.less b/packages/react-search-tree/src/style/index.less index 8cff585394..9fd269a3cb 100644 --- a/packages/react-search-tree/src/style/index.less +++ b/packages/react-search-tree/src/style/index.less @@ -21,6 +21,7 @@ &-inner { display: flex; + overflow: hidden; justify-content: space-between; outline: none; border: none; diff --git a/packages/react-tree/src/index.tsx b/packages/react-tree/src/index.tsx index 8c777f5df6..fb0912b61f 100644 --- a/packages/react-tree/src/index.tsx +++ b/packages/react-tree/src/index.tsx @@ -142,6 +142,10 @@ export default function Tree(props: TreeProps) { const [curOpenKeys, setCurOpenKeys] = useState(openKeys); const [curSelectedKeys, setCurSelectedKeys] = useState(selectedKeys); + useEffect(() => { + setCurSelectedKeys(props.selectedKeys!); + }, [JSON.parse(JSON.stringify(props.selectedKeys))]); + // useEffect(() => setCurOpenKeys(openKeys), [openKeys]); // useEffect(() => setCurSelectedKeys(selectedKeys), [selectedKeys]); From d0151c12f37c94bcabfad3e4038fd1c815363415 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 23 Feb 2022 17:50:33 +0800 Subject: [PATCH 35/59] =?UTF-8?q?revert:=20=E6=92=A4=E9=94=80package.json?= =?UTF-8?q?=E6=9B=B4=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index d96694ab12..a01c1d042d 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,12 @@ "homepage": "https://uiwjs.github.io", "private": true, "scripts": { - "lib": "lerna exec --scope @uiw/react-search-tree -- tsbb build --target react", - "lib:css": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o esm", - "lib:css:dist": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o lib --combine=dist.css", - "lib:css:watch": "lerna exec --scope @uiw/react-search-tree -- compile-less -d src -o esm --watch", - "lib:watch": "lerna exec --scope @uiw/react-search-tree -- tsbb watch & npm run lib:css:watch", - "lib:bootstrap": "lerna bootstrap --hoist --scope @uiw/react-search-tree", + "lib": "lerna exec --scope @uiw/react-file-input -- tsbb build --target react", + "lib:css": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o esm", + "lib:css:dist": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o lib --combine=dist.css", + "lib:css:watch": "lerna exec --scope @uiw/react-file-input -- compile-less -d src -o esm --watch", + "lib:watch": "lerna exec --scope @uiw/react-file-input -- tsbb watch & npm run lib:css:watch", + "lib:bootstrap": "lerna bootstrap --hoist --scope @uiw/react-file-input", "lib:build": "npm run lib && npm run lib:css && npm run lib:css:dist", "//>>>>>>>>>>>>": "<<<<<<<<<<", "watch:other:lib": "lerna exec --parallel --scope @uiw/* --ignore @uiw/doc -- tsbb watch", From 755d7714bb2cfe2379fad0b6bbc27efc2f5d5b4c Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Wed, 23 Feb 2022 17:58:12 +0800 Subject: [PATCH 36/59] =?UTF-8?q?docs(SearchTree):=20=E5=8D=95=E8=AF=8D?= =?UTF-8?q?=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index 76d3925aaa..c1773b02e1 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -1,4 +1,4 @@ -SearhTree 带搜索的Tree选择控件 +SearchTree 带搜索的Tree选择控件 === 使用树选择控件可以完整展现其中的层级关系,并具有选中状态。 From 41ead8f6dd33a24971f32c4d4151641414745edd Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Thu, 24 Feb 2022 15:23:25 +0800 Subject: [PATCH 37/59] =?UTF-8?q?feat(SearchTree):=20=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=90=9C=E7=B4=A2=E5=8A=9F=E8=83=BD,=E9=9A=90=E8=97=8F?= =?UTF-8?q?=E4=B8=8D=E5=8C=B9=E9=85=8D=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/src/index.tsx | 39 ++++++++++++++++++- .../react-search-tree/src/searchTagInput.tsx | 10 +++-- .../react-search-tree/src/style/index.less | 2 +- packages/react-tree/src/TreeNode.tsx | 2 +- packages/react-tree/src/index.tsx | 1 + 5 files changed, 46 insertions(+), 8 deletions(-) diff --git a/packages/react-search-tree/src/index.tsx b/packages/react-search-tree/src/index.tsx index 4af3a831ed..525967d82f 100644 --- a/packages/react-search-tree/src/index.tsx +++ b/packages/react-search-tree/src/index.tsx @@ -41,7 +41,9 @@ function TreeCheckeds( return selectOption; }; - return ; + return ( + + ); } export interface SearchTreeProps { @@ -55,18 +57,51 @@ export interface SearchTreeProps { function SearchTree(props: SearchTreeProps) { const { onChange, onSearch, options = [], value = [], treeProps, ...other } = props; const [selectedValues, selectedValuesSet] = useState>(value); + const [selectedOptions, selectedOptionSet] = useState>(options); const selectedChange = (resultValue: Array, cur: V, isChecked: boolean) => { selectedValuesSet(resultValue); onChange?.(resultValue, cur, isChecked); }; + // 防抖 + const debounce = (fn: Function, ms: number) => { + let timeoutId: NodeJS.Timeout; + return (searchValue: string) => { + onSearch?.(searchValue); + clearTimeout(timeoutId); + timeoutId = setTimeout(() => { + fn(searchValue); + }, ms); + }; + }; + + const selectedSearch = (searchValue: string) => { + const hiddenNodeForSeach = (childrens: TreeData[]) => { + childrens.forEach((child: TreeData) => { + const isHide = !(child.label as string).includes(searchValue); + if (!!child.children?.length) { + hiddenNodeForSeach(child.children); + const find = child.children.find((item) => !item.hideNode); + child.hideNode = isHide && !find; + } else { + // const isHide = !(child.label as string).includes(searchValue) + child.hideNode = isHide; + } + }); + }; + hiddenNodeForSeach(options); + selectedOptionSet([...options]); + }; + return ( } + options={selectedOptions} + content={} /> ); } diff --git a/packages/react-search-tree/src/searchTagInput.tsx b/packages/react-search-tree/src/searchTagInput.tsx index e1c475392e..aa818cbd7b 100644 --- a/packages/react-search-tree/src/searchTagInput.tsx +++ b/packages/react-search-tree/src/searchTagInput.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react'; +import React, { useMemo, useState, useRef, ReactElement } from 'react'; import Dropdown, { DropdownProps } from '@uiw/react-dropdown'; import Icon from '@uiw/react-icon'; import Input from '@uiw/react-input'; @@ -10,7 +10,7 @@ import './style/index.less'; export interface DropContent { values: Array; onSelected?: (selectedAll: Array, selectd: V, isChecked: boolean) => void; - options?: any; + options?: Array; } export interface SearchTagInputOption { @@ -42,6 +42,7 @@ function SearchTagInput(props: SearchTagInputPro placeholder, content, + options, values, onChange, onSearch, @@ -103,9 +104,10 @@ function SearchTagInput(props: SearchTagInputPro ...content.props, onSelected: handleSelectChange, values: selectedOption, + options, }; return React.cloneElement(content as JSX.Element, newProps); - }, [selectedOption]); + }, [selectedOption, options]); return ( {newContent}}> @@ -136,7 +138,7 @@ function SearchTagInput(props: SearchTagInputPro })} (props: TreeNodeProps) { const checkedKeys = selectedKeys ? selectedKeys.filter((key) => childKeys.indexOf(key) > -1) : []; const isHalfChecked = checkedKeys.length > 0 && childKeys.length !== checkedKeys.length; return ( -
  • +
  • onItemClick(item, evn)}> Date: Thu, 24 Feb 2022 15:40:08 +0800 Subject: [PATCH 38/59] =?UTF-8?q?docs(Searchtree):=20=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/README.md | 2 +- packages/react-search-tree/package.json | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index c1773b02e1..b26782b7e5 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -1,7 +1,7 @@ SearchTree 带搜索的Tree选择控件 === -使用树选择控件可以完整展现其中的层级关系,并具有选中状态。 +使用树选择控件可以完整展现其中的层级关系,并具有选中状态。新组件 v4.11.7+ 支持。 ```jsx import { TreeChecked } from 'uiw'; diff --git a/packages/react-search-tree/package.json b/packages/react-search-tree/package.json index e0047ff21e..c147b5d248 100644 --- a/packages/react-search-tree/package.json +++ b/packages/react-search-tree/package.json @@ -2,7 +2,6 @@ "name": "@uiw/react-search-tree", "version": "4.11.4", "description": "TreeChecked component", - "author": "Kenny Wong ", "homepage": "https://uiwjs.github.io/#/components/search-tree", "repository": { "type": "git", @@ -21,8 +20,8 @@ "access": "public" }, "keywords": [ - "tree-checked", - "react-tree-checked", + "react-search-checked", + "search-checked", "design", "uiw", "uiw-react", From c8b6a3920481449c3b8ed9f9fb23b3fa7e12c09f Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Thu, 24 Feb 2022 15:46:27 +0800 Subject: [PATCH 39/59] =?UTF-8?q?fix(SerachTree):=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E5=86=97=E4=BD=99=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/src/index.tsx | 2 +- packages/react-tree/src/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-search-tree/src/index.tsx b/packages/react-search-tree/src/index.tsx index 525967d82f..56b32b49dd 100644 --- a/packages/react-search-tree/src/index.tsx +++ b/packages/react-search-tree/src/index.tsx @@ -1,5 +1,5 @@ import React, { useState, useEffect, useRef } from 'react'; -import SearchTagInput, { DropContent, SearchTagInputOption } from './searchTagInput'; +import SearchTagInput, { DropContent, SearchTagInputOption } from './SearchTagInput'; import { TreeData } from '@uiw/react-tree'; import TreeChecked, { TreeCheckedProps } from '@uiw/react-tree-checked'; diff --git a/packages/react-tree/src/index.tsx b/packages/react-tree/src/index.tsx index 8108b2ec38..95a54fcd35 100644 --- a/packages/react-tree/src/index.tsx +++ b/packages/react-tree/src/index.tsx @@ -145,7 +145,7 @@ export default function Tree(props: TreeProps) { useEffect(() => { setCurSelectedKeys(props.selectedKeys!); - }, [JSON.parse(JSON.stringify(props.selectedKeys))]); + }, [JSON.stringify(props.selectedKeys)]); // useEffect(() => setCurOpenKeys(openKeys), [openKeys]); // useEffect(() => setCurSelectedKeys(selectedKeys), [selectedKeys]); From 167ff03bec873aaeeeabd66c20b17fb2bfab2fd3 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Thu, 24 Feb 2022 16:11:46 +0800 Subject: [PATCH 40/59] =?UTF-8?q?fix(SearchTree):=20=E6=96=87=E4=BB=B6?= =?UTF-8?q?=E5=90=8D=E6=9B=B4=E5=8F=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/{searchTagInput.tsx => SearchTagInput.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/react-search-tree/src/{searchTagInput.tsx => SearchTagInput.tsx} (100%) diff --git a/packages/react-search-tree/src/searchTagInput.tsx b/packages/react-search-tree/src/SearchTagInput.tsx similarity index 100% rename from packages/react-search-tree/src/searchTagInput.tsx rename to packages/react-search-tree/src/SearchTagInput.tsx From 25e9e16338fd804ee026d3b38393f16a3f79075a Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Thu, 24 Feb 2022 18:03:40 +0800 Subject: [PATCH 41/59] =?UTF-8?q?fix(SearchTree):=20=E6=A0=B7=E5=BC=8F?= =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/src/SearchTagInput.tsx | 12 +++++++----- packages/react-search-tree/src/style/index.less | 6 ++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/react-search-tree/src/SearchTagInput.tsx b/packages/react-search-tree/src/SearchTagInput.tsx index aa818cbd7b..f4218bdeee 100644 --- a/packages/react-search-tree/src/SearchTagInput.tsx +++ b/packages/react-search-tree/src/SearchTagInput.tsx @@ -115,7 +115,7 @@ function SearchTagInput(props: SearchTagInputPro onMouseOver={() => renderSelectIcon('enter')} onMouseLeave={() => renderSelectIcon('leave')} onClick={() => inputRef.current?.focus()} - style={{ width: 200, maxWidth: 'none', ...style }} + style={{ minWidth: 200, maxWidth: 'none', ...style }} >
    @@ -126,11 +126,11 @@ function SearchTagInput(props: SearchTagInputPro className={`${prefixCls}-tag`} key={index} closable + color="#393E48" onClose={(e) => { e.stopPropagation(); removeSelectItem(index); }} - color="#ccc" > {item.label} @@ -149,9 +149,11 @@ function SearchTagInput(props: SearchTagInputPro // readOnly={false} />
    - {(selectIconType === 'close' || (selectIconType === 'loading' && loading)) && ( - - )} + + {(selectIconType === 'close' || (selectIconType === 'loading' && loading)) && ( + + )} +
    diff --git a/packages/react-search-tree/src/style/index.less b/packages/react-search-tree/src/style/index.less index 26a2ae580b..e056ac9eb1 100644 --- a/packages/react-search-tree/src/style/index.less +++ b/packages/react-search-tree/src/style/index.less @@ -62,5 +62,11 @@ cursor: not-allowed; resize: none; } + + &-close-tag-contents { + width: 14px; + display: flex; + align-content: center; + } } } From bc0d1ee65230e46078508a91cc91734bc923035d Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 25 Feb 2022 10:50:53 +0800 Subject: [PATCH 42/59] =?UTF-8?q?fix(SearchTree):=20=E5=AD=90=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E5=85=A8=E9=83=A8=E9=80=89=E4=B8=AD=E7=88=B6=E8=8A=82?= =?UTF-8?q?=E7=82=B9=E6=B2=A1=E6=9C=89=E8=87=AA=E5=8A=A8=E5=8B=BE=E9=80=89?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 2 +- .../react-search-tree/src/SearchTagInput.tsx | 2 +- packages/react-search-tree/src/index.tsx | 25 +++++++++++++------ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index 7b24e62e11..6d8650cb6a 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -241,7 +241,7 @@ export default function SearchSelect(props: SearchSelectProps) { key={index} closable onClose={() => handleItemsClick(index, item)} - color="#ccc" + color="#393E48" > {item.label} diff --git a/packages/react-search-tree/src/SearchTagInput.tsx b/packages/react-search-tree/src/SearchTagInput.tsx index f4218bdeee..e01569b5ec 100644 --- a/packages/react-search-tree/src/SearchTagInput.tsx +++ b/packages/react-search-tree/src/SearchTagInput.tsx @@ -15,7 +15,7 @@ export interface DropContent { export interface SearchTagInputOption { label: string; - value: string | number; + key: string | number; } export interface SearchTagInputProps extends IProps, DropdownProps, DropContent { diff --git a/packages/react-search-tree/src/index.tsx b/packages/react-search-tree/src/index.tsx index 56b32b49dd..d6756e0505 100644 --- a/packages/react-search-tree/src/index.tsx +++ b/packages/react-search-tree/src/index.tsx @@ -15,8 +15,8 @@ function TreeCheckeds( useEffect(() => { let selectOption: SelectOtpion = {}; const keys = props.values?.map((opt) => { - selectOption[opt.value] = opt.label; - return opt.value; + selectOption[opt.key] = opt.label; + return opt.key; }); selectOptionSet(selectOption); keysSet(keys || []); @@ -24,18 +24,27 @@ function TreeCheckeds( const onSelected = (_1: any, _2: any, isChecked: boolean, evn: TreeData) => { const curSelectOption: SelectOtpion = getOptionsRecursion([evn], selectOption, isChecked); - const option = Object.entries(curSelectOption).map(([value, label]) => ({ value, label } as V)); - props.onSelected?.(option, { value: evn.key, label: evn.label as string } as V, isChecked); + const option = Object.entries(curSelectOption).map(([key, label]) => ({ key, label } as V)); + props.onSelected?.(option, { key: evn.key, label: evn.label as string } as V, isChecked); }; const getOptionsRecursion = (childrens: TreeData[], selectOption: SelectOtpion, isAdd: boolean) => { + const addOrDel = (key: string | number, label: string, isAdd: boolean) => { + if (isAdd) { + selectOption[key] = label; + } else { + delete selectOption[key!]; + } + }; + childrens.forEach((child: TreeData) => { if (!!child.children?.length) { selectOption = getOptionsRecursion(child.children, selectOption, isAdd); - } else if (isAdd) { - selectOption[child.key!] = child.label?.toString()!; - } else { - delete selectOption[child.key!]; + } + addOrDel(child.key!, child.label?.toString()!, isAdd); + if (child.parent) { + const selectCount = child.parent.children.filter((child: TreeData) => !selectOption[child.key!]).length; + addOrDel(child.parent.key, child.parent.label, selectCount === 0); } }); return selectOption; From d59d150f8b368055df74d93ac3bfbd3c9d7847a9 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 25 Feb 2022 11:10:38 +0800 Subject: [PATCH 43/59] =?UTF-8?q?docs(SearchTree):=20=E5=A2=9E=E5=8A=A0For?= =?UTF-8?q?m=E4=B8=AD=E4=BD=BF=E7=94=A8=E5=AE=9E=E4=BE=8B=E6=96=87?= =?UTF-8?q?=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-tree/README.md | 124 +++++++++++++++++- .../routes/components/search-tree/index.tsx | 4 +- 2 files changed, 122 insertions(+), 6 deletions(-) diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index fb6c202ba2..a2bae067cf 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -18,7 +18,7 @@ import TreeChecked from '@uiw/react-tree-checked'; ```jsx import ReactDOM from 'react-dom'; -import { TreeChecked, SearchTree, Card, Row, Col } from 'uiw'; +import { SearchTree } from 'uiw'; const data = [ { @@ -63,7 +63,7 @@ const Demo = () => ( allowClear={true} onSearch={(searchValue)=>console.log('SearchTree-> SearchTreeOption',searchValue)} onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)} - value={[{ label: '东花市街道', value: '2-3-1' }]} + value={[{ label: '东花市街道', key: '2-3-1' }]} options={data} placeholder="请输入选择" /> @@ -71,14 +71,130 @@ const Demo = () => ( ReactDOM.render(, _mount_); ``` +## Form中使用 + + +```jsx +import ReactDOM from 'react-dom'; +import { Form, Button, SearchTree, Card, Row, Col } from 'uiw';; + +const Demo = () => { + + const data = [ + { + label: '上海市', + key: '1-0-0', + children:[ + { label: '黄浦区', key: '1-0-1' }, + { label: '卢湾区', key: '1-0-2' }, + { + label: '徐汇区', + key: '1-0-3', + children:[ + { label: '半淞园路街道', key: '1-1-0' }, + { label: '南京东路街道', key: '1-2-0' }, + { label: '外滩街道', key: '1-3-0' }, + ] + }, + ] + }, + { + label: '北京市', + key: '2-0-0', + children:[ + { label: '东城区', key: '2-1-0' }, + { label: '西城区', key: '2-2-0' }, + { + label: '崇文区', + key: '2-3-0', + children:[ + { label: '东花市街道', key: '2-3-1' }, + { label: '体育馆路街道', key: '2-3-2' }, + { label: '前门街道', key: '2-3-3' }, + ] + }, + ] + }, + { label: '澳门', key: '3' }, + ]; + + return ( +
    +
    { + if (error.filed) { + return { ...error.filed }; + } + return null; + }} + onSubmit={({initial, current}) => { + const errorObj = {}; + if (!current.selectField) { + errorObj.selectField = '默认需要选择内容,选择入内容'; + } + if(Object.keys(errorObj).length > 0) { + const err = new Error(); + err.filed = errorObj; + Notify.error({ title: '提交失败!', description: '请确认提交表单是否正确!' }); + throw err; + } + Notify.success({ + title: '提交成功!', + description: `表单提交成功,选择值为:${current.selectField},将自动填充初始化值!`, + }); + }} + fields={{ + searchTree: { + initialValue:[{ label: '东花市街道', key: '2-3-1' }], + children: ( + console.log('SearchTree-> SearchTreeOption',searchValue)} + onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)} + options={data} + placeholder="请输入选择" + /> + ) + }, + }} + > + {({ fields, state, canSubmit }) => { + return ( +
    + + {fields.searchTree} + + + + + + + + +
    +                  {console.log('state',state)}
    +                    {JSON.stringify(state.current, null, 2)}
    +                  
    + +
    +
    + ) + }} + +
    + ); +} +ReactDOM.render(, _mount_); +``` + ## Props | 参数 | 说明 | 类型 | 默认值 | |--------- |-------- |--------- |-------- | | allowClear | 支持清除 | Boolean | `false` | | disabled | 禁用选择器 | Boolean | `false` | -| value | 指定当前选中的条目 | [{label:string, value:string}] | - | -| options | 下拉数据源 | [{label:string, value:string}] | - | +| value | 指定当前选中的条目 | [{label:string, key:string}] | - | +| options | 下拉数据源,可参考Tree下拉数据源 | [{label:string, key:string, children: [{label:string, key:string}] }] | - | | placeholder | 选择框默认文字 | String | - | | size | 选择框尺寸 | Enum{large, default, small } | `default` | | onChange | 选中 option,或 input 的 value,调用此函数 | function(selectdAll, selectd, isChecked)=>void | - | diff --git a/website/src/routes/components/search-tree/index.tsx b/website/src/routes/components/search-tree/index.tsx index f8ee3e89a4..51270bbcb9 100644 --- a/website/src/routes/components/search-tree/index.tsx +++ b/website/src/routes/components/search-tree/index.tsx @@ -1,11 +1,11 @@ import React, { useState } from 'react'; -import { TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw'; +import { Form, Button, TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw'; import Markdown from '../../../components/Markdown'; export default () => ( { const md = await import('uiw/node_modules/@uiw/react-search-tree/README.md'); return md.default || md; From e80c0de284c7ed2ac050cdd6c5dd09a9ecb8623e Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 25 Feb 2022 15:21:10 +0800 Subject: [PATCH 44/59] =?UTF-8?q?fix(SerachTree):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=B8=8D=E5=8F=97Form=E6=8E=A7=E5=88=B6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 4 +- packages/react-search-tree/README.md | 42 ++++++++++++++----- .../react-search-tree/src/SearchTagInput.tsx | 6 ++- packages/react-search-tree/src/index.tsx | 24 +++++++---- .../routes/components/search-tree/index.tsx | 4 +- 5 files changed, 57 insertions(+), 23 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 7c0d604a83..5f049f8bfe 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -158,8 +158,8 @@ function Form( } function setFields(fields: FormState['current']) { - data.current = fields; - setData(data); + const tempData = { ...data, current: fields }; + setData(tempData); } function handleChange( diff --git a/packages/react-search-tree/README.md b/packages/react-search-tree/README.md index db8e81952a..cc12d4cbfe 100644 --- a/packages/react-search-tree/README.md +++ b/packages/react-search-tree/README.md @@ -17,6 +17,7 @@ import SearchTree from '@uiw/react-search-tree'; ```jsx +import React, { useState, useEffect, useRef } from 'react'; import ReactDOM from 'react-dom'; import { SearchTree } from 'uiw'; @@ -57,17 +58,24 @@ const data = [ }, { label: '澳门', key: '3' }, ]; +const Demo = () => { + +const [value,valueSet]=useState([{ label: '东花市街道', key: '2-3-1' }]) + +const onChange=(selectd, selectedAll, isChecked)=>{ + console.log('SearchTree-> onChange',selectedAll, selectd, isChecked) + valueSet(selectedAll) +} -const Demo = () => ( - console.log('SearchTree-> SearchTreeOption',searchValue)} - onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)} - value={[{ label: '东花市街道', key: '2-3-1' }]} + onChange={onChange} + value={value} options={data} placeholder="请输入选择" - /> -) + />) +} ReactDOM.render(, _mount_); ``` @@ -75,10 +83,13 @@ ReactDOM.render(, _mount_); ```jsx +import React, { useState, useEffect, useRef } from 'react'; import ReactDOM from 'react-dom'; import { Form, Button, SearchTree, Card, Row, Col } from 'uiw';; + const Demo = () => { +const form=useRef() const data = [ { @@ -118,9 +129,18 @@ const Demo = () => { { label: '澳门', key: '3' }, ]; + const setValue=()=>{ + form.current.setFields({ searchTree: [{ label: '东城区', key: '2-1-0' }, { label: '外滩街道', key: '1-3-0' }] }) + } + + const resetValue=()=>{ + form.current.resetForm() + } + return (
    { if (error.filed) { return { ...error.filed }; @@ -128,6 +148,7 @@ const Demo = () => { return null; }} onSubmit={({initial, current}) => { + console.log('current',current) const errorObj = {}; if (!current.selectField) { errorObj.selectField = '默认需要选择内容,选择入内容'; @@ -145,12 +166,12 @@ const Demo = () => { }} fields={{ searchTree: { - initialValue:[{ label: '东花市街道', key: '2-3-1' }], + initialValue:[{ label: '东花市街道', key: '2-3-1' },{ label: '前门街道', key: '2-3-3' }], children: ( console.log('SearchTree-> SearchTreeOption',searchValue)} - onChange={(selectedAll, selectd, isChecked)=>console.log('SearchTree-> onChange',selectedAll, selectd, isChecked)} + onChange={(selectd, selectedAll, isChecked)=>console.log('SearchTree-> onChange', selectd, selectedAll, isChecked)} options={data} placeholder="请输入选择" /> @@ -167,12 +188,13 @@ const Demo = () => { + +
    -                  {console.log('state',state)}
                         {JSON.stringify(state.current, null, 2)}
                       
    @@ -197,7 +219,7 @@ ReactDOM.render(, _mount_); | options | 下拉数据源,可参考Tree下拉数据源 | [{label:string, key:string, children: [{label:string, key:string}] }] | - | | placeholder | 选择框默认文字 | String | - | | size | 选择框尺寸 | Enum{large, default, small } | `default` | -| onChange | 选中 option,或 input 的 value,调用此函数 | function(selectdAll, selectd, isChecked)=>void | - | +| onChange | 选中 option,或 input 的 value,调用此函数 | function(selectd, selectdAll, isChecked)=>void | - | | onSearch | 文本框值变化时回调 | function(searchValue) | - | | loading | 加载中状态 | Boolean | `false` | diff --git a/packages/react-search-tree/src/SearchTagInput.tsx b/packages/react-search-tree/src/SearchTagInput.tsx index e01569b5ec..85af853f1e 100644 --- a/packages/react-search-tree/src/SearchTagInput.tsx +++ b/packages/react-search-tree/src/SearchTagInput.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useState, useRef, ReactElement } from 'react'; +import React, { useMemo, useState, useRef, useEffect, ReactElement } from 'react'; import Dropdown, { DropdownProps } from '@uiw/react-dropdown'; import Icon from '@uiw/react-icon'; import Input from '@uiw/react-input'; @@ -59,6 +59,10 @@ function SearchTagInput(props: SearchTagInputPro const [selectIconType, setSelectIconType] = useState(''); const inputRef = useRef(null); + useEffect(() => { + setSelectedOption(values); + }, [JSON.stringify(values)]); + function renderSelectIcon(type: string) { const selectIconType = type === 'enter' && allowClear && (!!selectedOption.length || searchValue) ? 'close' : ''; setSelectIconType(selectIconType); diff --git a/packages/react-search-tree/src/index.tsx b/packages/react-search-tree/src/index.tsx index d6756e0505..21f22fbb5a 100644 --- a/packages/react-search-tree/src/index.tsx +++ b/packages/react-search-tree/src/index.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useRef } from 'react'; +import React, { useState, useEffect } from 'react'; import SearchTagInput, { DropContent, SearchTagInputOption } from './SearchTagInput'; import { TreeData } from '@uiw/react-tree'; import TreeChecked, { TreeCheckedProps } from '@uiw/react-tree-checked'; @@ -36,16 +36,21 @@ function TreeCheckeds( delete selectOption[key!]; } }; + const iteratorParent = (child: TreeData) => { + // 向上迭代 + if (child.parent) { + const selectCount = child.parent.children.filter((child: TreeData) => !selectOption[child.key!]).length; + addOrDel(child.parent.key, child.parent.label, selectCount === 0); + iteratorParent(child.parent); + } + }; childrens.forEach((child: TreeData) => { if (!!child.children?.length) { selectOption = getOptionsRecursion(child.children, selectOption, isAdd); } addOrDel(child.key!, child.label?.toString()!, isAdd); - if (child.parent) { - const selectCount = child.parent.children.filter((child: TreeData) => !selectOption[child.key!]).length; - addOrDel(child.parent.key, child.parent.label, selectCount === 0); - } + iteratorParent(child); }); return selectOption; }; @@ -54,9 +59,8 @@ function TreeCheckeds( ); } - export interface SearchTreeProps { - onChange?: (selectedAll: Array, selectd: V, isChecked: boolean) => void; + onChange?: (selectd: V, selectedAll: Array, isChecked: boolean) => void; onSearch?: (seachValue: string) => void; value?: Array; options?: TreeData[]; @@ -68,9 +72,13 @@ function SearchTree(props: SearchTreeProps) { const [selectedValues, selectedValuesSet] = useState>(value); const [selectedOptions, selectedOptionSet] = useState>(options); + useEffect(() => { + selectedValuesSet(value); + }, [JSON.stringify(value)]); + const selectedChange = (resultValue: Array, cur: V, isChecked: boolean) => { selectedValuesSet(resultValue); - onChange?.(resultValue, cur, isChecked); + onChange?.(cur, resultValue, isChecked); }; // 防抖 diff --git a/website/src/routes/components/search-tree/index.tsx b/website/src/routes/components/search-tree/index.tsx index 51270bbcb9..d5823fb2e2 100644 --- a/website/src/routes/components/search-tree/index.tsx +++ b/website/src/routes/components/search-tree/index.tsx @@ -1,11 +1,11 @@ -import React, { useState } from 'react'; +import React, { useState, useRef } from 'react'; import { Form, Button, TreeChecked, SearchTree, Row, Col, Card, Icon } from 'uiw'; import Markdown from '../../../components/Markdown'; export default () => ( { const md = await import('uiw/node_modules/@uiw/react-search-tree/README.md'); return md.default || md; From 97b7f3804fac2a814f0502a0c98f532a6b78c18e Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Fri, 25 Feb 2022 15:30:33 +0800 Subject: [PATCH 45/59] chore: update workflows config. --- .github/workflows/deploy.yml | 2 ++ .github/workflows/npm.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2e1e2ab3be..51d1e3598b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,8 @@ jobs: - run: npm run build - run: npm run bundle + - run: cp -rp packages/uiw/dist/*js website/build + - run: cp -rp packages/uiw/dist/*css website/build - run: npm run coverage - run: npm run b:website - run: npm run b:doc diff --git a/.github/workflows/npm.yml b/.github/workflows/npm.yml index 8af7a3026c..b17e370ae5 100644 --- a/.github/workflows/npm.yml +++ b/.github/workflows/npm.yml @@ -67,6 +67,9 @@ jobs: - run: cp -rf website/build/* packages/doc/web - run: npm run bundle + - run: cp -rp packages/uiw/dist/*js website/build + - run: cp -rp packages/uiw/dist/*css website/build + - run: git checkout -f packages/uiw/tsconfig.json - run: git status From 6c5d448986dc7c3ab870c0e01c6fb914649ddc2e Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Fri, 25 Feb 2022 15:46:26 +0800 Subject: [PATCH 46/59] chore: update workflows config. --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 51d1e3598b..06b5ea10cb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,8 +25,6 @@ jobs: - run: npm run build - run: npm run bundle - - run: cp -rp packages/uiw/dist/*js website/build - - run: cp -rp packages/uiw/dist/*css website/build - run: npm run coverage - run: npm run b:website - run: npm run b:doc @@ -36,6 +34,8 @@ jobs: - run: rm -rf packages/doc/web - run: mkdir -p packages/doc/web + - run: cp -rp packages/uiw/dist/*js website/build + - run: cp -rp packages/uiw/dist/*css website/build - name: Generate Contributors Images uses: jaywcjlove/github-action-contributors@main From 88ef62859884da67fced5bde2b9f30f0591aaa67 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 14 Feb 2022 14:16:14 +0800 Subject: [PATCH 47/59] =?UTF-8?q?fix(Form):=20=E7=B1=BB=E5=9E=8B=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 5f049f8bfe..fb732ac4a5 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -103,7 +103,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: React.Ref>, //| React.RefObject, + ref: React.ForwardedRef, //| React.RefObject, ) { const initData = useMemo( () => @@ -115,7 +115,7 @@ function Form( ); const [data, setData] = useState(initData); - useImperativeHandle, any>( + useImperativeHandle( ref, () => ({ onSubmit: handleSubmit, @@ -318,4 +318,4 @@ function Form( ); } -export default React.forwardRef, FormProps<{}>>(Form); +export default React.forwardRef>(Form); From c0af739f0ebeacd7e4348eb223679bc50005057f Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 25 Feb 2022 17:24:26 +0800 Subject: [PATCH 48/59] =?UTF-8?q?docs(List):=20=E6=96=87=E6=A1=A3=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-list/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-list/README.md b/packages/react-list/README.md index e2e2384755..1c075ab164 100644 --- a/packages/react-list/README.md +++ b/packages/react-list/README.md @@ -45,7 +45,7 @@ const Demo = () => (

    小尺寸

    列表头部
    } + header={
    列表头部
    } footer={
    列表尾部
    } dataSource={data} renderItem={item => ({item})} @@ -53,7 +53,7 @@ const Demo = () => (

    大尺寸

    列表头部
  • } + header={
    列表头部
    } footer={
    列表尾部
    } dataSource={data} renderItem={item => ({item})} @@ -278,7 +278,7 @@ ReactDOM.render(, _mount_); | footer | 列表底部 | String/ReactNode | - | | header | 列表头部 | String/ReactNode | - | | dataSource | 是否展示边框 | Boolean | - | -| renderItem | 通过毁掉函数返回Dome,渲染列表每个行 | Function(item,index) | - | +| renderItem | 通过回调函数返回Dome,渲染列表每个行 | Function(item,index) | - | ## List.Item @@ -304,4 +304,4 @@ const Demo = () => { ) } -``` \ No newline at end of file +``` From d632684a64a91b5b9761e2711b26a556b2fd2c84 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 17:21:45 +0800 Subject: [PATCH 49/59] =?UTF-8?q?feat(DateInputRange):=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=8C=BA=E9=97=B4=E9=80=89=E6=8B=A9=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20#536?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-date-input/README.md | 121 ++++++++++++------ .../react-date-input/src/DateInputRange.tsx | 112 ++++++++++++++++ packages/react-date-input/src/index.tsx | 1 + .../react-date-input/src/style/dateRange.less | 68 ++++++++++ .../routes/components/date-input/index.tsx | 4 +- website/src/routes/components/menu/index.tsx | 4 +- 6 files changed, 267 insertions(+), 43 deletions(-) create mode 100644 packages/react-date-input/src/DateInputRange.tsx create mode 100644 packages/react-date-input/src/style/dateRange.less diff --git a/packages/react-date-input/README.md b/packages/react-date-input/README.md index f6cb56dc7b..f31c978d43 100644 --- a/packages/react-date-input/README.md +++ b/packages/react-date-input/README.md @@ -8,9 +8,9 @@ DateInput 日期输入框 显示一个月的日历,并允许用户选择单个日期。 ```jsx -import { DateInput } from 'uiw'; +import { DateInput, DateInputRange } from 'uiw'; // or -import DateInput from '@uiw/react-date-input'; +import DateInput,{ DateInputRange } from '@uiw/react-date-input'; ``` ## 基本使用 @@ -19,32 +19,46 @@ import DateInput from '@uiw/react-date-input'; ```jsx import React from 'react'; import ReactDOM from 'react-dom'; -import { DateInput, Row, Col } from 'uiw'; +import { DateInput, DateInputRange, Row, Col } from 'uiw'; -class Demo extends React.Component { - onChange(selectedDate) { - console.log('selectedDate:', selectedDate) +function Demo () { + + const [dataRange,dataRangeSet] =React.useState(['2022-02-25 15:06:24','2022-02-27 14:47:32']) + + function onChange(selectedDate,dataRange) { + console.log('selectedDate',selectedDate,dataRange) } - render() { return ( - - - - - - - - +
    + + + + + + + + + + + + + +
    ) - } } ReactDOM.render(, _mount_); ``` @@ -55,13 +69,26 @@ ReactDOM.render(, _mount_); ```jsx +import React from 'react'; import ReactDOM from 'react-dom'; -import { DateInput, Notify, Button, Form, Row, Col } from 'uiw'; +import { DateInput,DateInputRange, Notify, Button, Form, Row, Col } from 'uiw'; + +function Demo(){ + const form = React.useRef(null) -ReactDOM.render( - { - if(current.date) { + const resetDateRange = () => { + form.current.resetForm() + } + + const setDateRange = () => { + form.current.setFields({dateRange:[new Date(),new Date()]}) + } + + return ( + { + if (current.date) { Notify.success({ title: '提交成功!', description: `表单提交时间成功,时间为:${current.date}`, @@ -72,7 +99,6 @@ ReactDOM.render( description: `表单提交时间成功,时间为:${current.date},将自动填充初始化值!`, }); } - console.log('-->>', initial, current); }} fields={{ date: { @@ -81,21 +107,38 @@ ReactDOM.render( labelFor: 'date-inline', children: }, + dateRange: { + initialValue: ['2019/02/17', '2019/02/20'], + labelClassName: 'fieldLabel', + labelFor: 'date-inline', + children: + }, }} > {({ fields, state, canSubmit }) => { return ( - - {fields.date} - - - - +
    + + {fields.date} + + + {fields.dateRange} + + + + + + + + +
    ) }} - , - _mount_ -); + + ) +} + +ReactDOM.render(, _mount_); ``` ## 日期格式 diff --git a/packages/react-date-input/src/DateInputRange.tsx b/packages/react-date-input/src/DateInputRange.tsx new file mode 100644 index 0000000000..a4b6678e30 --- /dev/null +++ b/packages/react-date-input/src/DateInputRange.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useState } from 'react'; +import Input, { InputProps } from '@uiw/react-input'; +import Popover, { PopoverProps } from '@uiw/react-popover'; +import DatePicker, { DatePickerProps } from '@uiw/react-date-picker'; +import Icon from '@uiw/react-icon'; +import { IProps } from '@uiw/utils'; +import formatter from '@uiw/formatter'; +import './style/dateRange.less'; + +export interface DateInputRangeProps extends IProps, Omit { + popoverProps?: PopoverProps; + datePickerProps?: DatePickerProps; + value?: Array; + format?: string; + allowClear?: boolean; + bodyStyle?: object; + onChange?: (selectedDate?: Date, dateRange?: Array) => void; +} + +export function DateInputRange(props: DateInputRangeProps) { + const { + prefixCls = 'w-daterange', + bodyStyle = undefined, + className, + popoverProps, + datePickerProps, + allowClear = true, + format = 'YYYY/MM/DD', + onChange, + value, + ...inputProps + } = props; + + const [dateRange, setDateRange] = useState>([]); + useEffect(() => { + let valueTemp: Array = []; + const propsValue = value; + if (Array.isArray(propsValue) && !!propsValue?.length) { + propsValue.forEach((date, index) => { + valueTemp[index] = typeof propsValue[index] === 'string' ? new Date(date) : (date as Date); + }); + } + setDateRange(valueTemp); + }, [JSON.stringify(value)]); + + function handleChange(cdate: Date | undefined, idx?: number) { + const changeValue = [...dateRange]; + changeValue[idx!] = cdate; + setDateRange(changeValue); + onChange && onChange(cdate, changeValue); + } + + return ( +
    + handleChange(selectedDate, 0)} + /> + } + > + console.log('v', v)} + value={dateRange[0] ? formatter(format, dateRange[0]) : ''} + className={[prefixCls, className].filter(Boolean).join(' ').trim()} + /> + + + + + handleChange(selectedDate, 1)} + /> + } + > + console.log('v2', v)} + className={[prefixCls, className].filter(Boolean).join(' ').trim()} + /> + + {allowClear && dateRange.length > 0 && ( + setDateRange([])} type="close" /> + )} +
    + ); +} diff --git a/packages/react-date-input/src/index.tsx b/packages/react-date-input/src/index.tsx index 262737a3b4..75ae01dac8 100644 --- a/packages/react-date-input/src/index.tsx +++ b/packages/react-date-input/src/index.tsx @@ -5,6 +5,7 @@ import DatePicker, { DatePickerProps } from '@uiw/react-date-picker'; import Icon from '@uiw/react-icon'; import { IProps } from '@uiw/utils'; import formatter from '@uiw/formatter'; +export * from './DateInputRange'; import './style/index.less'; export interface DateInputProps extends IProps, Omit { diff --git a/packages/react-date-input/src/style/dateRange.less b/packages/react-date-input/src/style/dateRange.less new file mode 100644 index 0000000000..7e9971a5e7 --- /dev/null +++ b/packages/react-date-input/src/style/dateRange.less @@ -0,0 +1,68 @@ +@daterange-prefix: ~'w-daterange'; + +.@{daterange-prefix} { + &-contents { + display: flex; + justify-content: space-between; + input { + box-shadow: none; + padding: 0px; + height: 20px; + } + + .w-input-inner { + &:hover { + box-shadow: none !important; + } + + &:focus { + box-shadow: none !important; + } + } + } + + &-inner { + display: flex; + // overflow: hidden; + justify-content: space-between; + outline: none; + border: none; + align-items: center; + border-radius: 3px; + box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.15), + inset 0 1px 1px rgba(16, 22, 26, 0.2); + box-sizing: border-box; + background: #fff; + min-height: 30px; + margin: 0 !important; + padding: 3px 10px 3px 10px; + vertical-align: middle; + line-height: 30px; + color: #393e48; + font-weight: 400; + font-size: inherit; + transition: box-shadow 0.3s cubic-bezier(0.4, 1, 0.75, 0.9); + appearance: none; + + &:focus { + box-shadow: 0 0 0 1px #393e48, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:focus&:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:disabled { + box-shadow: none; + background: #dddddd; + opacity: 0.75; + color: #a5a5a5; + cursor: not-allowed; + resize: none; + } + } +} diff --git a/website/src/routes/components/date-input/index.tsx b/website/src/routes/components/date-input/index.tsx index 2ee041eacf..99b791f34f 100755 --- a/website/src/routes/components/date-input/index.tsx +++ b/website/src/routes/components/date-input/index.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { DateInput, Notify, Form, Row, Col, Button } from 'uiw'; +import { DateInput, DateInputRange, Notify, Form, Row, Col, Button } from 'uiw'; import Markdown from '../../../components/Markdown'; export default function Page() { return ( { const md = await import('uiw/node_modules/@uiw/react-date-input/README.md'); return md.default || md; diff --git a/website/src/routes/components/menu/index.tsx b/website/src/routes/components/menu/index.tsx index 38addb386a..4e3d8eecc0 100755 --- a/website/src/routes/components/menu/index.tsx +++ b/website/src/routes/components/menu/index.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { Menu, MenuItem, MenuDivider, SubMenu, Row, Col, Switch, Icon, Popover, Button } from 'uiw'; +import { Menu, Drawer, MenuItem, MenuDivider, SubMenu, Row, Col, Switch, Icon, Popover, Button } from 'uiw'; import Markdown from '../../../components/Markdown'; export default function Page() { return ( { const md = await import('uiw/node_modules/@uiw/react-menu/README.md'); return md.default || md; From e2e91fca2e6d22ea312083d58d8b4582ba3a2825 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 14 Feb 2022 14:16:14 +0800 Subject: [PATCH 50/59] =?UTF-8?q?fix(Form):=20=E7=B1=BB=E5=9E=8B=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-form/src/Form.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-form/src/Form.tsx b/packages/react-form/src/Form.tsx index 5f049f8bfe..fb732ac4a5 100644 --- a/packages/react-form/src/Form.tsx +++ b/packages/react-form/src/Form.tsx @@ -103,7 +103,7 @@ function Form( afterSubmit, ...others }: FormProps, - ref: React.Ref>, //| React.RefObject, + ref: React.ForwardedRef, //| React.RefObject, ) { const initData = useMemo( () => @@ -115,7 +115,7 @@ function Form( ); const [data, setData] = useState(initData); - useImperativeHandle, any>( + useImperativeHandle( ref, () => ({ onSubmit: handleSubmit, @@ -318,4 +318,4 @@ function Form( ); } -export default React.forwardRef, FormProps<{}>>(Form); +export default React.forwardRef>(Form); From d5302c280c2de295b9573822d9b668744ed7e574 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Fri, 25 Feb 2022 17:24:26 +0800 Subject: [PATCH 51/59] =?UTF-8?q?docs(List):=20=E6=96=87=E6=A1=A3=E6=8F=8F?= =?UTF-8?q?=E8=BF=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-list/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/react-list/README.md b/packages/react-list/README.md index e2e2384755..1c075ab164 100644 --- a/packages/react-list/README.md +++ b/packages/react-list/README.md @@ -45,7 +45,7 @@ const Demo = () => (

    小尺寸

    列表头部
    } + header={
    列表头部
    } footer={
    列表尾部
    } dataSource={data} renderItem={item => ({item})} @@ -53,7 +53,7 @@ const Demo = () => (

    大尺寸

    列表头部
    } + header={
    列表头部
    } footer={
    列表尾部
    } dataSource={data} renderItem={item => ({item})} @@ -278,7 +278,7 @@ ReactDOM.render(, _mount_); | footer | 列表底部 | String/ReactNode | - | | header | 列表头部 | String/ReactNode | - | | dataSource | 是否展示边框 | Boolean | - | -| renderItem | 通过毁掉函数返回Dome,渲染列表每个行 | Function(item,index) | - | +| renderItem | 通过回调函数返回Dome,渲染列表每个行 | Function(item,index) | - | ## List.Item @@ -304,4 +304,4 @@ const Demo = () => { ) } -``` \ No newline at end of file +``` From 40d587af1070c409c81de097fe97bc4157588a05 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 17:21:45 +0800 Subject: [PATCH 52/59] =?UTF-8?q?feat(DateInputRange):=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E5=8C=BA=E9=97=B4=E9=80=89=E6=8B=A9=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=20#536?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-date-input/README.md | 121 ++++++++++++------ .../react-date-input/src/DateInputRange.tsx | 112 ++++++++++++++++ packages/react-date-input/src/index.tsx | 1 + .../react-date-input/src/style/dateRange.less | 68 ++++++++++ .../routes/components/date-input/index.tsx | 4 +- website/src/routes/components/menu/index.tsx | 4 +- 6 files changed, 267 insertions(+), 43 deletions(-) create mode 100644 packages/react-date-input/src/DateInputRange.tsx create mode 100644 packages/react-date-input/src/style/dateRange.less diff --git a/packages/react-date-input/README.md b/packages/react-date-input/README.md index f6cb56dc7b..f31c978d43 100644 --- a/packages/react-date-input/README.md +++ b/packages/react-date-input/README.md @@ -8,9 +8,9 @@ DateInput 日期输入框 显示一个月的日历,并允许用户选择单个日期。 ```jsx -import { DateInput } from 'uiw'; +import { DateInput, DateInputRange } from 'uiw'; // or -import DateInput from '@uiw/react-date-input'; +import DateInput,{ DateInputRange } from '@uiw/react-date-input'; ``` ## 基本使用 @@ -19,32 +19,46 @@ import DateInput from '@uiw/react-date-input'; ```jsx import React from 'react'; import ReactDOM from 'react-dom'; -import { DateInput, Row, Col } from 'uiw'; +import { DateInput, DateInputRange, Row, Col } from 'uiw'; -class Demo extends React.Component { - onChange(selectedDate) { - console.log('selectedDate:', selectedDate) +function Demo () { + + const [dataRange,dataRangeSet] =React.useState(['2022-02-25 15:06:24','2022-02-27 14:47:32']) + + function onChange(selectedDate,dataRange) { + console.log('selectedDate',selectedDate,dataRange) } - render() { return ( - - - - - - - - +
    + + + + + + + + + + + + + +
    ) - } } ReactDOM.render(, _mount_); ``` @@ -55,13 +69,26 @@ ReactDOM.render(, _mount_); ```jsx +import React from 'react'; import ReactDOM from 'react-dom'; -import { DateInput, Notify, Button, Form, Row, Col } from 'uiw'; +import { DateInput,DateInputRange, Notify, Button, Form, Row, Col } from 'uiw'; + +function Demo(){ + const form = React.useRef(null) -ReactDOM.render( -
    { - if(current.date) { + const resetDateRange = () => { + form.current.resetForm() + } + + const setDateRange = () => { + form.current.setFields({dateRange:[new Date(),new Date()]}) + } + + return ( + { + if (current.date) { Notify.success({ title: '提交成功!', description: `表单提交时间成功,时间为:${current.date}`, @@ -72,7 +99,6 @@ ReactDOM.render( description: `表单提交时间成功,时间为:${current.date},将自动填充初始化值!`, }); } - console.log('-->>', initial, current); }} fields={{ date: { @@ -81,21 +107,38 @@ ReactDOM.render( labelFor: 'date-inline', children: }, + dateRange: { + initialValue: ['2019/02/17', '2019/02/20'], + labelClassName: 'fieldLabel', + labelFor: 'date-inline', + children: + }, }} > {({ fields, state, canSubmit }) => { return ( - - {fields.date} - - - - +
    + + {fields.date} + + + {fields.dateRange} + + + + + + + + +
    ) }} - , - _mount_ -); + + ) +} + +ReactDOM.render(, _mount_); ``` ## 日期格式 diff --git a/packages/react-date-input/src/DateInputRange.tsx b/packages/react-date-input/src/DateInputRange.tsx new file mode 100644 index 0000000000..a4b6678e30 --- /dev/null +++ b/packages/react-date-input/src/DateInputRange.tsx @@ -0,0 +1,112 @@ +import React, { useEffect, useState } from 'react'; +import Input, { InputProps } from '@uiw/react-input'; +import Popover, { PopoverProps } from '@uiw/react-popover'; +import DatePicker, { DatePickerProps } from '@uiw/react-date-picker'; +import Icon from '@uiw/react-icon'; +import { IProps } from '@uiw/utils'; +import formatter from '@uiw/formatter'; +import './style/dateRange.less'; + +export interface DateInputRangeProps extends IProps, Omit { + popoverProps?: PopoverProps; + datePickerProps?: DatePickerProps; + value?: Array; + format?: string; + allowClear?: boolean; + bodyStyle?: object; + onChange?: (selectedDate?: Date, dateRange?: Array) => void; +} + +export function DateInputRange(props: DateInputRangeProps) { + const { + prefixCls = 'w-daterange', + bodyStyle = undefined, + className, + popoverProps, + datePickerProps, + allowClear = true, + format = 'YYYY/MM/DD', + onChange, + value, + ...inputProps + } = props; + + const [dateRange, setDateRange] = useState>([]); + useEffect(() => { + let valueTemp: Array = []; + const propsValue = value; + if (Array.isArray(propsValue) && !!propsValue?.length) { + propsValue.forEach((date, index) => { + valueTemp[index] = typeof propsValue[index] === 'string' ? new Date(date) : (date as Date); + }); + } + setDateRange(valueTemp); + }, [JSON.stringify(value)]); + + function handleChange(cdate: Date | undefined, idx?: number) { + const changeValue = [...dateRange]; + changeValue[idx!] = cdate; + setDateRange(changeValue); + onChange && onChange(cdate, changeValue); + } + + return ( +
    + handleChange(selectedDate, 0)} + /> + } + > + console.log('v', v)} + value={dateRange[0] ? formatter(format, dateRange[0]) : ''} + className={[prefixCls, className].filter(Boolean).join(' ').trim()} + /> + + + + + handleChange(selectedDate, 1)} + /> + } + > + console.log('v2', v)} + className={[prefixCls, className].filter(Boolean).join(' ').trim()} + /> + + {allowClear && dateRange.length > 0 && ( + setDateRange([])} type="close" /> + )} +
    + ); +} diff --git a/packages/react-date-input/src/index.tsx b/packages/react-date-input/src/index.tsx index 262737a3b4..75ae01dac8 100644 --- a/packages/react-date-input/src/index.tsx +++ b/packages/react-date-input/src/index.tsx @@ -5,6 +5,7 @@ import DatePicker, { DatePickerProps } from '@uiw/react-date-picker'; import Icon from '@uiw/react-icon'; import { IProps } from '@uiw/utils'; import formatter from '@uiw/formatter'; +export * from './DateInputRange'; import './style/index.less'; export interface DateInputProps extends IProps, Omit { diff --git a/packages/react-date-input/src/style/dateRange.less b/packages/react-date-input/src/style/dateRange.less new file mode 100644 index 0000000000..7e9971a5e7 --- /dev/null +++ b/packages/react-date-input/src/style/dateRange.less @@ -0,0 +1,68 @@ +@daterange-prefix: ~'w-daterange'; + +.@{daterange-prefix} { + &-contents { + display: flex; + justify-content: space-between; + input { + box-shadow: none; + padding: 0px; + height: 20px; + } + + .w-input-inner { + &:hover { + box-shadow: none !important; + } + + &:focus { + box-shadow: none !important; + } + } + } + + &-inner { + display: flex; + // overflow: hidden; + justify-content: space-between; + outline: none; + border: none; + align-items: center; + border-radius: 3px; + box-shadow: 0 0 0 0 rgba(19, 124, 189, 0), 0 0 0 0 rgba(19, 124, 189, 0), inset 0 0 0 1px rgba(16, 22, 26, 0.15), + inset 0 1px 1px rgba(16, 22, 26, 0.2); + box-sizing: border-box; + background: #fff; + min-height: 30px; + margin: 0 !important; + padding: 3px 10px 3px 10px; + vertical-align: middle; + line-height: 30px; + color: #393e48; + font-weight: 400; + font-size: inherit; + transition: box-shadow 0.3s cubic-bezier(0.4, 1, 0.75, 0.9); + appearance: none; + + &:focus { + box-shadow: 0 0 0 1px #393e48, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:focus&:hover { + box-shadow: 0 0 0 1px #6e6e6e, 0 0 0 3px rgba(57, 62, 72, 0.17), inset 0 1px 1px rgba(16, 22, 26, 0.2); + } + + &:disabled { + box-shadow: none; + background: #dddddd; + opacity: 0.75; + color: #a5a5a5; + cursor: not-allowed; + resize: none; + } + } +} diff --git a/website/src/routes/components/date-input/index.tsx b/website/src/routes/components/date-input/index.tsx index 2ee041eacf..99b791f34f 100755 --- a/website/src/routes/components/date-input/index.tsx +++ b/website/src/routes/components/date-input/index.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { DateInput, Notify, Form, Row, Col, Button } from 'uiw'; +import { DateInput, DateInputRange, Notify, Form, Row, Col, Button } from 'uiw'; import Markdown from '../../../components/Markdown'; export default function Page() { return ( { const md = await import('uiw/node_modules/@uiw/react-date-input/README.md'); return md.default || md; diff --git a/website/src/routes/components/menu/index.tsx b/website/src/routes/components/menu/index.tsx index 38addb386a..4e3d8eecc0 100755 --- a/website/src/routes/components/menu/index.tsx +++ b/website/src/routes/components/menu/index.tsx @@ -1,12 +1,12 @@ import React from 'react'; -import { Menu, MenuItem, MenuDivider, SubMenu, Row, Col, Switch, Icon, Popover, Button } from 'uiw'; +import { Menu, Drawer, MenuItem, MenuDivider, SubMenu, Row, Col, Switch, Icon, Popover, Button } from 'uiw'; import Markdown from '../../../components/Markdown'; export default function Page() { return ( { const md = await import('uiw/node_modules/@uiw/react-menu/README.md'); return md.default || md; From 8719e72f6fa59b44438b90b7a98a4dea0cdd7335 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 17:55:56 +0800 Subject: [PATCH 53/59] =?UTF-8?q?fix(DateInputRange):=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=91=BD=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-date-input/src/DateInputRange.tsx | 4 ++-- .../src/style/{dateRange.less => date-input-range.less} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename packages/react-date-input/src/style/{dateRange.less => date-input-range.less} (95%) diff --git a/packages/react-date-input/src/DateInputRange.tsx b/packages/react-date-input/src/DateInputRange.tsx index a4b6678e30..3c59b6f050 100644 --- a/packages/react-date-input/src/DateInputRange.tsx +++ b/packages/react-date-input/src/DateInputRange.tsx @@ -5,7 +5,7 @@ import DatePicker, { DatePickerProps } from '@uiw/react-date-picker'; import Icon from '@uiw/react-icon'; import { IProps } from '@uiw/utils'; import formatter from '@uiw/formatter'; -import './style/dateRange.less'; +import './style/date-input-range.less'; export interface DateInputRangeProps extends IProps, Omit { popoverProps?: PopoverProps; @@ -19,7 +19,7 @@ export interface DateInputRangeProps extends IProps, Omit(props: DateInputRangeProps) { const { - prefixCls = 'w-daterange', + prefixCls = 'w-dateinputrange', bodyStyle = undefined, className, popoverProps, diff --git a/packages/react-date-input/src/style/dateRange.less b/packages/react-date-input/src/style/date-input-range.less similarity index 95% rename from packages/react-date-input/src/style/dateRange.less rename to packages/react-date-input/src/style/date-input-range.less index 7e9971a5e7..8cfd859e0a 100644 --- a/packages/react-date-input/src/style/dateRange.less +++ b/packages/react-date-input/src/style/date-input-range.less @@ -1,6 +1,6 @@ -@daterange-prefix: ~'w-daterange'; +@dateinputrange-prefix: ~'w-dateinputrange'; -.@{daterange-prefix} { +.@{dateinputrange-prefix} { &-contents { display: flex; justify-content: space-between; From 23259a0476e27d65cf0a15f046e577b08cbd9d25 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 18:18:50 +0800 Subject: [PATCH 54/59] =?UTF-8?q?docs(DateInputRange):=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-date-input/README.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/packages/react-date-input/README.md b/packages/react-date-input/README.md index f31c978d43..0ca546686d 100644 --- a/packages/react-date-input/README.md +++ b/packages/react-date-input/README.md @@ -6,6 +6,7 @@ DateInput 日期输入框 [![npm version](https://img.shields.io/npm/v/@uiw/react-date-input.svg?label=@uiw/react-date-input)](https://npmjs.com/@uiw/react-date-input) 显示一个月的日历,并允许用户选择单个日期。 +在v4.12.3版本中增加 DateInputRange组件 ```jsx import { DateInput, DateInputRange } from 'uiw'; @@ -209,3 +210,20 @@ ReactDOM.render(, _mount_); | disabled | 组件 [``](#/components/input) 的属性,禁用日历 | Boolean | - | 更多属性文档请参考 [``](#/components/input)。 + +## DateInputRange + +| 参数 | 说明 | 类型 | 默认值 | +|--------- |-------- |--------- |-------- | +| value | 初始时间值 | Array | - | +| placeholder | 输入框提示文字 | String | - | +| allowClear | 是否显示清除按钮 | Boolean | true | +| format | 格式化时间,规则查看 [``](#/components/formatter) 文档 | String | `YYYY/MM/DD` | +| onChange | 选择一天时调用。 | Function(selectedDate:Date, dateRange: Array) | - | +| popoverProps | 将参数传递给 [``](#/components/popover) 组件 | Object | - | +| datePickerProps | 将参数传递给 [``](#/components/date-picker) 组件 | Object | - | +| disabled | 组件 [``](#/components/input) 的属性,禁用日历 | Boolean | - | +| bodyStyle | 选择框样式 | Object | { width: 300 } | - | + +更多属性文档请参考 [``](#/components/input)。 + From 883f15dbca5b5dbf9e5ea43cccdcf58aab51f806 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 18:50:40 +0800 Subject: [PATCH 55/59] =?UTF-8?q?fix(SearchSelect):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20value=E4=B8=8D=E5=AD=98=E5=9C=A8=E4=B8=8B=E6=8B=89=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=B8=AD=E4=BC=9A=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20#565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index dcc932943e..21acb55145 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -104,7 +104,7 @@ export default function SearchSelect(props: SearchSelectProps) { } } else { if (Array.isArray(changeValue)) { - opts = changeValue.map((v) => getSelectOption(option, v as ValueType)!); + opts = changeValue.map((v) => getSelectOption(option, v as ValueType)!).filter((m) => !!m); } else { const findResult = getSelectOption(option, changeValue as ValueType); if (findResult) { From 68a6808908ab37cf00de81aca1068b824247b1cb Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Fri, 25 Feb 2022 15:30:33 +0800 Subject: [PATCH 56/59] chore: update workflows config. --- .github/workflows/deploy.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 06b5ea10cb..e9bafaf60f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,6 +25,8 @@ jobs: - run: npm run build - run: npm run bundle + - run: cp -rp packages/uiw/dist/*js website/build + - run: cp -rp packages/uiw/dist/*css website/build - run: npm run coverage - run: npm run b:website - run: npm run b:doc From da54b4f87f4943cffa27a466f72ab965fc6c8cc4 Mon Sep 17 00:00:00 2001 From: jaywcjlove <398188662@qq.com> Date: Fri, 25 Feb 2022 15:46:26 +0800 Subject: [PATCH 57/59] chore: update workflows config. --- .github/workflows/deploy.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index e9bafaf60f..06b5ea10cb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,8 +25,6 @@ jobs: - run: npm run build - run: npm run bundle - - run: cp -rp packages/uiw/dist/*js website/build - - run: cp -rp packages/uiw/dist/*css website/build - run: npm run coverage - run: npm run b:website - run: npm run b:doc From 77559f01d21049bf564949715bf18a7c1df433c5 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 18:50:40 +0800 Subject: [PATCH 58/59] =?UTF-8?q?fix(SearchSelect):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=20value=E4=B8=8D=E5=AD=98=E5=9C=A8=E4=B8=8B=E6=8B=89=E5=88=97?= =?UTF-8?q?=E8=A1=A8=E4=B8=AD=E4=BC=9A=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?= =?UTF-8?q?=20#565?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-search-select/src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-search-select/src/index.tsx b/packages/react-search-select/src/index.tsx index dcc932943e..21acb55145 100644 --- a/packages/react-search-select/src/index.tsx +++ b/packages/react-search-select/src/index.tsx @@ -104,7 +104,7 @@ export default function SearchSelect(props: SearchSelectProps) { } } else { if (Array.isArray(changeValue)) { - opts = changeValue.map((v) => getSelectOption(option, v as ValueType)!); + opts = changeValue.map((v) => getSelectOption(option, v as ValueType)!).filter((m) => !!m); } else { const findResult = getSelectOption(option, changeValue as ValueType); if (findResult) { From 2247bddf6f2745bffb21c76d0f6b87489dc0b816 Mon Sep 17 00:00:00 2001 From: zhouzheng Date: Mon, 28 Feb 2022 19:02:17 +0800 Subject: [PATCH 59/59] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=86=B2=E7=AA=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/react-date-input/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/react-date-input/README.md b/packages/react-date-input/README.md index 9849fc7148..2575f24030 100644 --- a/packages/react-date-input/README.md +++ b/packages/react-date-input/README.md @@ -6,7 +6,6 @@ DateInput 日期输入框 [![npm version](https://img.shields.io/npm/v/@uiw/react-date-input.svg?label=@uiw/react-date-input)](https://npmjs.com/@uiw/react-date-input) 显示一个月的日历,并允许用户选择单个日期。 -在v4.12.3版本中增加 DateInputRange组件 ```jsx import { DateInput, DateInputRange } from 'uiw';