@para-ui/core 5.0.0-beta.12 → 5.0.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +315 -0
- package/AlignBox/component.json +89 -0
- package/Anchor/component.json +130 -0
- package/Argv/component.json +216 -0
- package/AutoBox/component.json +133 -0
- package/AutoButton/component.json +109 -0
- package/AutoTips/component.json +121 -0
- package/Badge/component.json +92 -0
- package/Breadcrumbs/component.json +142 -0
- package/Button/component.json +168 -0
- package/ButtonGroup/component.json +132 -0
- package/Card/component.json +162 -0
- package/Carousel/component.json +142 -0
- package/Cascader/component.json +196 -0
- package/Checkbox/component.json +138 -0
- package/CheckboxGroup/component.json +152 -0
- package/CodeEditor/component.json +189 -0
- package/Collapse/component.json +166 -0
- package/CollapseBox/component.json +84 -0
- package/CollapseLayout/component.json +155 -0
- package/ColorPicker/component.json +142 -0
- package/ComboSelect/component.json +181 -0
- package/Container/component.json +111 -0
- package/ContentBox/component.json +81 -0
- package/CopyText/component.json +118 -0
- package/CycleSelector/component.json +98 -0
- package/DatePicker/component.json +192 -0
- package/Descriptions/component.json +142 -0
- package/Desktop/component.json +171 -0
- package/DragVerify/component.json +114 -0
- package/Drawer/component.json +200 -0
- package/Dropdown/component.json +147 -0
- package/DynamicMultiBox/component.json +278 -0
- package/Empty/component.json +123 -0
- package/FieldForm/component.json +196 -0
- package/Form/component.json +161 -0
- package/FormItem/component.json +171 -0
- package/FunctionModal/component.json +197 -0
- package/Help/component.json +118 -0
- package/HelperText/component.json +126 -0
- package/Image/component.json +165 -0
- package/InputCode/component.json +191 -0
- package/InputLang/component.json +205 -0
- package/InputNumber/component.json +162 -0
- package/Label/component.json +126 -0
- package/Loading/component.json +91 -0
- package/Menu/component.json +180 -0
- package/Message/component.json +246 -0
- package/Modal/component.json +277 -0
- package/MultiBox/component.json +216 -0
- package/Notification/component.json +184 -0
- package/OperateBtn/component.json +134 -0
- package/PageHeader/component.json +112 -0
- package/Pagination/component.json +181 -0
- package/PasswordRules/component.json +105 -0
- package/PopConfirm/component.json +227 -0
- package/PopMenu/component.json +131 -0
- package/Popover/component.json +165 -0
- package/Progress/component.json +161 -0
- package/Prompt/component.json +144 -0
- package/Querying/component.json +96 -0
- package/QuickReply/component.json +129 -0
- package/Radio/component.json +136 -0
- package/RadioGroup/component.json +149 -0
- package/RangeInput/component.json +198 -0
- package/Result/component.json +104 -0
- package/ScrollBar/component.json +115 -0
- package/Search/component.json +177 -0
- package/Select/component.json +244 -0
- package/SelectInput/component.json +184 -0
- package/Selector/component.json +203 -0
- package/SelectorPicker/component.json +179 -0
- package/SingleBox/component.json +151 -0
- package/Slider/component.json +181 -0
- package/SortBox/component.json +108 -0
- package/Status/component.json +104 -0
- package/Stepper/component.json +129 -0
- package/Switch/component.json +207 -0
- package/Table/component.json +547 -0
- package/Tabs/component.json +227 -0
- package/Tag/component.json +221 -0
- package/TextEditor/component.json +186 -0
- package/TextField/component.json +290 -0
- package/TimePicker/component.json +176 -0
- package/Timeline/component.json +110 -0
- package/Title/component.json +156 -0
- package/ToggleButton/component.json +153 -0
- package/Tooltip/component.json +176 -0
- package/Transfer/component.json +157 -0
- package/Tree/component.json +512 -0
- package/Upload/component.json +450 -0
- package/ai-workflows/01-crud-list-multi-drawer.md +278 -0
- package/ai-workflows/02-rbac-operation-buttons.md +290 -0
- package/ai-workflows/03-complex-form-async-cascade.md +350 -0
- package/ai-workflows/04-array-field-form.md +281 -0
- package/ai-workflows/05-popconfirm-async-message-queue.md +333 -0
- package/ai-workflows/06-modal-drawer-form-workflow.md +385 -0
- package/ai-workflows/07-search-filter-table-trio.md +387 -0
- package/ai-workflows/08-table-advanced-features.md +365 -0
- package/ai-workflows/09-batch-operation-export-progress.md +367 -0
- package/ai-workflows/10-cross-component-state-coordination.md +412 -0
- package/codemods/modal-onCancel-to-onDismiss.js +69 -0
- package/es/AlignBox/component.json +89 -0
- package/es/AlignBox/index.css +1 -1
- package/es/AlignBox/index.d.ts +6 -2
- package/es/AlignBox/index.js +1 -1
- package/es/AlignBox/style/index.css +1 -1
- package/es/Anchor/anchorMenu/index.d.ts +2 -1
- package/es/Anchor/anchorMenu/index.js +36 -33
- package/es/Anchor/component.json +130 -0
- package/es/Anchor/index.js +50 -47
- package/es/Anchor/type.d.ts +8 -4
- package/es/Argv/component.json +216 -0
- package/es/Argv/index.d.ts +5 -6
- package/es/AutoBox/component.json +133 -0
- package/es/AutoBox/index.d.ts +3 -3
- package/es/AutoBox/index.js +1 -1
- package/es/AutoBox/protal.d.ts +2 -2
- package/es/AutoBox/protal.js +32 -29
- package/es/AutoButton/component.json +109 -0
- package/es/AutoButton/index.js +1 -1
- package/es/AutoTips/autoTipsMultiline/index.d.ts +1 -1
- package/es/AutoTips/autoTipsMultiline/index.js +1 -1
- package/es/AutoTips/component.json +121 -0
- package/es/Badge/component.json +92 -0
- package/es/Breadcrumbs/component.json +142 -0
- package/es/Breadcrumbs/index.js +1 -1
- package/es/Button/SplitButton.d.ts +2 -2
- package/es/Button/component.json +168 -0
- package/es/Button/index.js +44 -44
- package/es/ButtonGroup/component.json +132 -0
- package/es/ButtonGroup/index.d.ts +1 -1
- package/es/Card/component.json +162 -0
- package/es/Card/index.d.ts +2 -2
- package/es/Card/index.js +2 -2
- package/es/Carousel/component.json +142 -0
- package/es/Carousel/index.d.ts +1 -1
- package/es/Cascader/Cascader.js +188 -180
- package/es/Cascader/component.json +196 -0
- package/es/Cascader/hooks/useEntities.js +7 -7
- package/es/Cascader/interface.d.ts +1 -0
- package/es/Cascader/utils/commonUtil.d.ts +1 -1
- package/es/Cascader/utils/commonUtil.js +16 -16
- package/es/Cascader/utils/treeUtil.d.ts +14 -5
- package/es/Cascader/utils/treeUtil.js +1 -1
- package/es/Checkbox/component.json +138 -0
- package/es/CheckboxGroup/component.json +152 -0
- package/es/CodeEditor/component.json +189 -0
- package/es/CodeEditor/index.d.ts +10 -9
- package/es/Collapse/component.json +166 -0
- package/es/Collapse/index.d.ts +1 -1
- package/es/Collapse/index.js +41 -33
- package/es/CollapseBox/component.json +84 -0
- package/es/CollapseLayout/component.json +155 -0
- package/es/ColorPicker/component.json +142 -0
- package/es/ComboSelect/component.json +181 -0
- package/es/ComboSelect/index.js +299 -287
- package/es/ComboSelect/interface.d.ts +6 -3
- package/es/ComboSelect/utils.d.ts +3 -3
- package/es/ComboSelect/utils.js +1 -1
- package/es/Container/component.json +111 -0
- package/es/ContentBox/component.json +81 -0
- package/es/CopyText/component.json +118 -0
- package/es/CycleSelector/component.json +98 -0
- package/es/CycleSelector/index.js +14 -13
- package/es/DatePicker/component.json +192 -0
- package/es/DatePicker/generatePicker/generateRangePicker.d.ts +0 -8
- package/es/DatePicker/generatePicker/generateRangePicker.js +73 -65
- package/es/DatePicker/generatePicker/generateSinglePicker.js +1 -1
- package/es/DatePicker/generatePicker/index.d.ts +11 -4
- package/es/Descriptions/component.json +142 -0
- package/es/Descriptions/index.d.ts +1 -1
- package/es/Desktop/component.json +171 -0
- package/es/DragVerify/component.json +114 -0
- package/es/DragVerify/index.js +19 -19
- package/es/Drawer/component.json +200 -0
- package/es/Drawer/index.js +86 -86
- package/es/Drawer/interface.d.ts +1 -1
- package/es/Drawer/util.d.ts +1 -6
- package/es/Drawer/util.js +9 -6
- package/es/Dropdown/component.json +147 -0
- package/es/DynamicMultiBox/component.json +278 -0
- package/es/DynamicMultiBox/formItem.d.ts +1 -1
- package/es/DynamicMultiBox/rowForm.d.ts +2 -2
- package/es/Empty/component.json +123 -0
- package/es/Empty/index.css +1 -1
- package/es/Empty/index.d.ts +2 -2
- package/es/Empty/index.js +27 -26
- package/es/Empty/style/index.css +1 -1
- package/es/FieldForm/FieldFormItem/MemoInput.d.ts +2 -2
- package/es/FieldForm/FieldFormItem/index.d.ts +6 -6
- package/es/FieldForm/Form.d.ts +2 -2
- package/es/FieldForm/FormList.d.ts +2 -2
- package/es/FieldForm/component.json +196 -0
- package/es/FieldForm/context.d.ts +5 -1
- package/es/FieldForm/context.js +2 -2
- package/es/FieldForm/hooks/useForm.d.ts +4 -3
- package/es/FieldForm/hooks/useFormInstance.d.ts +1 -1
- package/es/FieldForm/hooks/useFormItemStatus.d.ts +9 -5
- package/es/FieldForm/hooks/useFormItemStatus.js +2 -2
- package/es/FieldForm/hooks/useItemRef.d.ts +1 -1
- package/es/FieldForm/hooks/useItemRef.js +6 -6
- package/es/Form/component.json +161 -0
- package/es/Form/index.d.ts +52 -49
- package/es/FormItem/compoments/defaultCompoments/index.d.ts +5 -5
- package/es/FormItem/compoments/defaultCompoments/index.js +12 -11
- package/es/FormItem/compoments/formCheckboxGroup/index.d.ts +2 -2
- package/es/FormItem/compoments/formFile/index.js +8 -8
- package/es/FormItem/compoments/formRadioGroup/index.d.ts +1 -1
- package/es/FormItem/compoments/formSelect/index.d.ts +1 -1
- package/es/FormItem/component.json +171 -0
- package/es/FormItem/index.d.ts +5 -5
- package/es/FormItem/index.js +23 -23
- package/es/FormItem/itemType.js +1 -1
- package/es/FunctionModal/component.json +197 -0
- package/es/FunctionModal/dialog.d.ts +1 -1
- package/es/FunctionModal/modalContext.d.ts +4 -1
- package/es/Help/component.json +118 -0
- package/es/HelperText/component.json +126 -0
- package/es/Image/component.json +165 -0
- package/es/InputCode/component.json +191 -0
- package/es/InputCode/index.d.ts +2 -2
- package/es/InputLang/component.json +205 -0
- package/es/InputLang/index.js +1 -1
- package/es/InputNumber/component.json +162 -0
- package/es/Label/component.json +126 -0
- package/es/Label/index.d.ts +2 -2
- package/es/Loading/component.json +91 -0
- package/es/Menu/component.json +180 -0
- package/es/Message/component.json +246 -0
- package/es/Message/index.d.ts +2 -2
- package/es/Message/index.js +2 -2
- package/es/Modal/Confirm/index.d.ts +1 -1
- package/es/Modal/Confirm/index.js +81 -75
- package/es/Modal/component.json +277 -0
- package/es/Modal/index.d.ts +97 -6
- package/es/Modal/index.js +174 -122
- package/es/Modal/interface.d.ts +1 -0
- package/es/MultiBox/component.json +216 -0
- package/es/MultiBox/index.js +19 -14
- package/es/Notification/component.json +184 -0
- package/es/OperateBtn/component.json +134 -0
- package/es/OperateBtn/index.d.ts +3 -3
- package/es/PageHeader/component.json +112 -0
- package/es/Pagination/component.json +181 -0
- package/es/Pagination/index.js +15 -15
- package/es/PasswordRules/component.json +105 -0
- package/es/PasswordRules/index.d.ts +4 -4
- package/es/PopConfirm/component.json +227 -0
- package/es/PopConfirm/index.d.ts +1 -1
- package/es/PopConfirm/index.js +1 -1
- package/es/PopMenu/component.json +131 -0
- package/es/PopMenu/hooks.d.ts +1 -1
- package/es/PopMenu/index.js +8 -8
- package/es/Popover/component.json +165 -0
- package/es/Popover/index.js +1 -1
- package/es/Progress/component.json +161 -0
- package/es/Prompt/component.json +144 -0
- package/es/Querying/component.json +96 -0
- package/es/Querying/index.css +1 -1
- package/es/Querying/index.d.ts +2 -2
- package/es/Querying/index.js +20 -19
- package/es/Querying/style/index.css +1 -1
- package/es/QuickReply/component.json +129 -0
- package/es/QuickReply/index.d.ts +1 -1
- package/es/Radio/component.json +136 -0
- package/es/RadioGroup/component.json +149 -0
- package/es/RangeInput/component.json +198 -0
- package/es/RangeInput/index.js +1 -1
- package/es/Result/component.json +104 -0
- package/es/ScrollBar/component.json +115 -0
- package/es/Search/component.json +177 -0
- package/es/Search/index.d.ts +1 -1
- package/es/Select/component.json +244 -0
- package/es/Select/index.js +113 -113
- package/es/SelectInput/component.json +184 -0
- package/es/Selector/component.json +203 -0
- package/es/Selector/index.js +28 -27
- package/es/Selector/interface.d.ts +1 -1
- package/es/Selector/selectorMain/index.js +2 -2
- package/es/Selector/selectorNode/index.js +1 -1
- package/es/Selector/util.d.ts +2 -2
- package/es/SelectorPicker/component.json +179 -0
- package/es/SelectorPicker/index.d.ts +5 -5
- package/es/SelectorPicker/index.js +15 -15
- package/es/SingleBox/component.json +151 -0
- package/es/SingleBox/index.d.ts +2 -2
- package/es/Slider/component.json +181 -0
- package/es/SortBox/component.json +108 -0
- package/es/Status/component.json +104 -0
- package/es/Stepper/component.json +129 -0
- package/es/Stepper/index.d.ts +2 -2
- package/es/Switch/component.json +207 -0
- package/es/Switch/index.css +1 -1
- package/es/Switch/index.d.ts +3 -2
- package/es/Switch/index.js +60 -59
- package/es/Switch/style/index.css +1 -1
- package/es/Table/component.json +547 -0
- package/es/Table/index.d.ts +2 -2
- package/es/Table/index.js +414 -414
- package/es/Table/interface.d.ts +6 -0
- package/es/Tabs/component.json +227 -0
- package/es/Tag/component.json +221 -0
- package/es/Tag/index.css +1 -1
- package/es/Tag/index.d.ts +1 -1
- package/es/Tag/index.js +20 -20
- package/es/Tag/style/index.css +1 -1
- package/es/TextEditor/component.json +186 -0
- package/es/TextEditor/index.d.ts +5 -5
- package/es/TextField/component.json +290 -0
- package/es/TextField/index.d.ts +2 -2
- package/es/TimePicker/component.json +176 -0
- package/es/Timeline/component.json +110 -0
- package/es/Title/component.json +156 -0
- package/es/ToggleButton/component.json +153 -0
- package/es/Tooltip/component.json +176 -0
- package/es/Tooltip/index.js +74 -63
- package/es/Tooltip/interface.d.ts +14 -1
- package/es/Tooltip/utils.js +6 -6
- package/es/Transfer/component.json +157 -0
- package/es/Tree/component.json +512 -0
- package/es/Upload/component.json +450 -0
- package/es/Utils/type.d.ts +0 -2
- package/es/index.d.ts +2 -0
- package/es/index.js +1 -1
- package/es/locale/en_US.d.ts +361 -0
- package/es/locale/en_US.js +364 -0
- package/es/locale/index.d.ts +1 -723
- package/es/locale/index2.js +10 -0
- package/es/locale/zh_CN.d.ts +361 -0
- package/es/locale/zh_CN.js +364 -0
- package/lib/AlignBox/component.json +89 -0
- package/lib/AlignBox/index.css +1 -1
- package/lib/AlignBox/index.d.ts +6 -2
- package/lib/AlignBox/index.js +1 -1
- package/lib/AlignBox/style/index.css +1 -1
- package/lib/Anchor/anchorMenu/index.d.ts +2 -1
- package/lib/Anchor/anchorMenu/index.js +1 -1
- package/lib/Anchor/component.json +130 -0
- package/lib/Anchor/index.js +1 -1
- package/lib/Anchor/type.d.ts +8 -4
- package/lib/Argv/component.json +216 -0
- package/lib/Argv/index.d.ts +5 -6
- package/lib/AutoBox/component.json +133 -0
- package/lib/AutoBox/index.d.ts +3 -3
- package/lib/AutoBox/index.js +1 -1
- package/lib/AutoBox/protal.d.ts +2 -2
- package/lib/AutoBox/protal.js +1 -1
- package/lib/AutoButton/component.json +109 -0
- package/lib/AutoButton/index.js +1 -1
- package/lib/AutoTips/autoTipsMultiline/index.d.ts +1 -1
- package/lib/AutoTips/autoTipsMultiline/index.js +1 -1
- package/lib/AutoTips/component.json +121 -0
- package/lib/Badge/component.json +92 -0
- package/lib/Breadcrumbs/component.json +142 -0
- package/lib/Breadcrumbs/index.js +1 -1
- package/lib/Button/SplitButton.d.ts +2 -2
- package/lib/Button/component.json +168 -0
- package/lib/Button/index.js +1 -1
- package/lib/ButtonGroup/component.json +132 -0
- package/lib/ButtonGroup/index.d.ts +1 -1
- package/lib/Card/component.json +162 -0
- package/lib/Card/index.d.ts +2 -2
- package/lib/Card/index.js +1 -1
- package/lib/Carousel/component.json +142 -0
- package/lib/Carousel/index.d.ts +1 -1
- package/lib/Cascader/Cascader.js +1 -1
- package/lib/Cascader/component.json +196 -0
- package/lib/Cascader/hooks/useEntities.js +1 -1
- package/lib/Cascader/interface.d.ts +1 -0
- package/lib/Cascader/utils/commonUtil.d.ts +1 -1
- package/lib/Cascader/utils/commonUtil.js +1 -1
- package/lib/Cascader/utils/treeUtil.d.ts +14 -5
- package/lib/Cascader/utils/treeUtil.js +1 -1
- package/lib/Checkbox/component.json +138 -0
- package/lib/CheckboxGroup/component.json +152 -0
- package/lib/CodeEditor/component.json +189 -0
- package/lib/CodeEditor/index.d.ts +10 -9
- package/lib/Collapse/component.json +166 -0
- package/lib/Collapse/index.d.ts +1 -1
- package/lib/Collapse/index.js +1 -1
- package/lib/CollapseBox/component.json +84 -0
- package/lib/CollapseLayout/component.json +155 -0
- package/lib/ColorPicker/component.json +142 -0
- package/lib/ComboSelect/component.json +181 -0
- package/lib/ComboSelect/index.js +1 -1
- package/lib/ComboSelect/interface.d.ts +6 -3
- package/lib/ComboSelect/utils.d.ts +3 -3
- package/lib/ComboSelect/utils.js +1 -1
- package/lib/Container/component.json +111 -0
- package/lib/ContentBox/component.json +81 -0
- package/lib/CopyText/component.json +118 -0
- package/lib/CycleSelector/component.json +98 -0
- package/lib/CycleSelector/index.js +1 -1
- package/lib/DatePicker/component.json +192 -0
- package/lib/DatePicker/generatePicker/generateRangePicker.d.ts +0 -8
- package/lib/DatePicker/generatePicker/generateRangePicker.js +1 -1
- package/lib/DatePicker/generatePicker/generateSinglePicker.js +1 -1
- package/lib/DatePicker/generatePicker/index.d.ts +11 -4
- package/lib/Descriptions/component.json +142 -0
- package/lib/Descriptions/index.d.ts +1 -1
- package/lib/Desktop/component.json +171 -0
- package/lib/DragVerify/component.json +114 -0
- package/lib/DragVerify/index.js +1 -1
- package/lib/Drawer/component.json +200 -0
- package/lib/Drawer/index.js +1 -1
- package/lib/Drawer/interface.d.ts +1 -1
- package/lib/Drawer/util.d.ts +1 -6
- package/lib/Drawer/util.js +1 -1
- package/lib/Dropdown/component.json +147 -0
- package/lib/DynamicMultiBox/component.json +278 -0
- package/lib/DynamicMultiBox/formItem.d.ts +1 -1
- package/lib/DynamicMultiBox/rowForm.d.ts +2 -2
- package/lib/Empty/component.json +123 -0
- package/lib/Empty/index.css +1 -1
- package/lib/Empty/index.d.ts +2 -2
- package/lib/Empty/index.js +1 -1
- package/lib/Empty/style/index.css +1 -1
- package/lib/FieldForm/FieldFormItem/MemoInput.d.ts +2 -2
- package/lib/FieldForm/FieldFormItem/index.d.ts +6 -6
- package/lib/FieldForm/Form.d.ts +2 -2
- package/lib/FieldForm/FormList.d.ts +2 -2
- package/lib/FieldForm/component.json +196 -0
- package/lib/FieldForm/context.d.ts +5 -1
- package/lib/FieldForm/context.js +1 -1
- package/lib/FieldForm/hooks/useForm.d.ts +4 -3
- package/lib/FieldForm/hooks/useFormInstance.d.ts +1 -1
- package/lib/FieldForm/hooks/useFormItemStatus.d.ts +9 -5
- package/lib/FieldForm/hooks/useFormItemStatus.js +1 -1
- package/lib/FieldForm/hooks/useItemRef.d.ts +1 -1
- package/lib/FieldForm/hooks/useItemRef.js +1 -1
- package/lib/Form/component.json +161 -0
- package/lib/Form/index.d.ts +52 -49
- package/lib/FormItem/compoments/defaultCompoments/index.d.ts +5 -5
- package/lib/FormItem/compoments/defaultCompoments/index.js +1 -1
- package/lib/FormItem/compoments/formCheckboxGroup/index.d.ts +2 -2
- package/lib/FormItem/compoments/formFile/index.js +1 -1
- package/lib/FormItem/compoments/formRadioGroup/index.d.ts +1 -1
- package/lib/FormItem/compoments/formSelect/index.d.ts +1 -1
- package/lib/FormItem/component.json +171 -0
- package/lib/FormItem/index.d.ts +5 -5
- package/lib/FormItem/index.js +1 -1
- package/lib/FormItem/itemType.js +1 -1
- package/lib/FunctionModal/component.json +197 -0
- package/lib/FunctionModal/dialog.d.ts +1 -1
- package/lib/FunctionModal/modalContext.d.ts +4 -1
- package/lib/Help/component.json +118 -0
- package/lib/HelperText/component.json +126 -0
- package/lib/Image/component.json +165 -0
- package/lib/InputCode/component.json +191 -0
- package/lib/InputCode/index.d.ts +2 -2
- package/lib/InputLang/component.json +205 -0
- package/lib/InputLang/index.js +1 -1
- package/lib/InputNumber/component.json +162 -0
- package/lib/Label/component.json +126 -0
- package/lib/Label/index.d.ts +2 -2
- package/lib/Loading/component.json +91 -0
- package/lib/Menu/component.json +180 -0
- package/lib/Message/component.json +246 -0
- package/lib/Message/index.d.ts +2 -2
- package/lib/Message/index.js +1 -1
- package/lib/Modal/Confirm/index.d.ts +1 -1
- package/lib/Modal/Confirm/index.js +1 -1
- package/lib/Modal/component.json +277 -0
- package/lib/Modal/index.d.ts +97 -6
- package/lib/Modal/index.js +1 -1
- package/lib/Modal/interface.d.ts +1 -0
- package/lib/MultiBox/component.json +216 -0
- package/lib/MultiBox/index.js +1 -1
- package/lib/Notification/component.json +184 -0
- package/lib/OperateBtn/component.json +134 -0
- package/lib/OperateBtn/index.d.ts +3 -3
- package/lib/PageHeader/component.json +112 -0
- package/lib/Pagination/component.json +181 -0
- package/lib/Pagination/index.js +1 -1
- package/lib/PasswordRules/component.json +105 -0
- package/lib/PasswordRules/index.d.ts +4 -4
- package/lib/PopConfirm/component.json +227 -0
- package/lib/PopConfirm/index.d.ts +1 -1
- package/lib/PopConfirm/index.js +1 -1
- package/lib/PopMenu/component.json +131 -0
- package/lib/PopMenu/hooks.d.ts +1 -1
- package/lib/PopMenu/index.js +1 -1
- package/lib/Popover/component.json +165 -0
- package/lib/Popover/index.js +1 -1
- package/lib/Progress/component.json +161 -0
- package/lib/Prompt/component.json +144 -0
- package/lib/Querying/component.json +96 -0
- package/lib/Querying/index.css +1 -1
- package/lib/Querying/index.d.ts +2 -2
- package/lib/Querying/index.js +1 -1
- package/lib/Querying/style/index.css +1 -1
- package/lib/QuickReply/component.json +129 -0
- package/lib/QuickReply/index.d.ts +1 -1
- package/lib/Radio/component.json +136 -0
- package/lib/RadioGroup/component.json +149 -0
- package/lib/RangeInput/component.json +198 -0
- package/lib/RangeInput/index.js +1 -1
- package/lib/Result/component.json +104 -0
- package/lib/ScrollBar/component.json +115 -0
- package/lib/Search/component.json +177 -0
- package/lib/Search/index.d.ts +1 -1
- package/lib/Select/component.json +244 -0
- package/lib/Select/index.js +1 -1
- package/lib/SelectInput/component.json +184 -0
- package/lib/Selector/component.json +203 -0
- package/lib/Selector/index.js +1 -1
- package/lib/Selector/interface.d.ts +1 -1
- package/lib/Selector/selectorMain/index.js +1 -1
- package/lib/Selector/selectorNode/index.js +1 -1
- package/lib/Selector/util.d.ts +2 -2
- package/lib/SelectorPicker/component.json +179 -0
- package/lib/SelectorPicker/index.d.ts +5 -5
- package/lib/SelectorPicker/index.js +1 -1
- package/lib/SingleBox/component.json +151 -0
- package/lib/SingleBox/index.d.ts +2 -2
- package/lib/Slider/component.json +181 -0
- package/lib/SortBox/component.json +108 -0
- package/lib/Status/component.json +104 -0
- package/lib/Stepper/component.json +129 -0
- package/lib/Stepper/index.d.ts +2 -2
- package/lib/Switch/component.json +207 -0
- package/lib/Switch/index.css +1 -1
- package/lib/Switch/index.d.ts +3 -2
- package/lib/Switch/index.js +1 -1
- package/lib/Switch/style/index.css +1 -1
- package/lib/Table/component.json +547 -0
- package/lib/Table/index.d.ts +2 -2
- package/lib/Table/index.js +1 -1
- package/lib/Table/interface.d.ts +6 -0
- package/lib/Tabs/component.json +227 -0
- package/lib/Tag/component.json +221 -0
- package/lib/Tag/index.css +1 -1
- package/lib/Tag/index.d.ts +1 -1
- package/lib/Tag/index.js +1 -1
- package/lib/Tag/style/index.css +1 -1
- package/lib/TextEditor/component.json +186 -0
- package/lib/TextEditor/index.d.ts +5 -5
- package/lib/TextField/component.json +290 -0
- package/lib/TextField/index.d.ts +2 -2
- package/lib/TimePicker/component.json +176 -0
- package/lib/Timeline/component.json +110 -0
- package/lib/Title/component.json +156 -0
- package/lib/ToggleButton/component.json +153 -0
- package/lib/Tooltip/component.json +176 -0
- package/lib/Tooltip/index.js +1 -1
- package/lib/Tooltip/interface.d.ts +14 -1
- package/lib/Tooltip/utils.js +1 -1
- package/lib/Transfer/component.json +157 -0
- package/lib/Tree/component.json +512 -0
- package/lib/Upload/component.json +450 -0
- package/lib/Utils/type.d.ts +0 -2
- package/lib/index.d.ts +2 -0
- package/lib/index.js +1 -1
- package/lib/locale/en_US.d.ts +361 -0
- package/lib/locale/en_US.js +2 -0
- package/lib/locale/index.d.ts +1 -723
- package/lib/locale/index2.js +2 -0
- package/lib/locale/zh_CN.d.ts +361 -0
- package/lib/locale/zh_CN.js +2 -0
- package/package.json +10 -3
- /package/es/{Utils/Hooks → Hooks}/useResizeObserver.d.ts +0 -0
- /package/es/{Utils/Hooks → Hooks}/useResizeObserver.js +0 -0
- /package/lib/{Utils/Hooks → Hooks}/useResizeObserver.d.ts +0 -0
- /package/lib/{Utils/Hooks → Hooks}/useResizeObserver.js +0 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
# Workflow 10: 跨组件状态联动(Dashboard / 撤销重做 / 状态切换)
|
|
2
|
+
|
|
3
|
+
> **基于**:console/src/package/Dashboard/src/content.tsx(多 Widget 状态同步)/ console/src/package/Cluster/src/content.tsx(Tabs 驱动状态切换 + 实时刷新)
|
|
4
|
+
> **覆盖 baseline 失败任务**:Task 25(Dashboard 多组件联动)/ Task 27(撤销重做)/ Task 32(Tabs 状态切换)
|
|
5
|
+
> **集成 typescriptPitfalls**:Form check() 返回 false|object / Switch loading loadingMap / Tree checkStrictly 类型(M3 修复同款)/ Tabs activeKey onChange / Form ref 类型必须 `useRef<FormRefObject>({} as FormRefObject)`
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 何时使用
|
|
10
|
+
|
|
11
|
+
单个页面中多个独立组件的状态需要协调联动,包括:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Tabs 切换驱动多组件刷新 + Form 提交状态控制 Switch/Button + Tree 勾选同步列表 + 撤销重做栈
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
**典型业务**:Dashboard 看板 / 角色权限配置(Tree + 表格联动)/ 工作流编辑器(撤销重做)/ 分组切换(Tabs + 列表联动)
|
|
18
|
+
|
|
19
|
+
**不要用此模板的场景**:
|
|
20
|
+
- 单组件内部状态(无跨组件依赖)→ 用各组件独立模板
|
|
21
|
+
- 全局状态(跨页面)→ 用 Context / Redux
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## 关键模式(与脑补的区别)
|
|
26
|
+
|
|
27
|
+
| 错误模式(AI 常犯) | 正确模式 |
|
|
28
|
+
|------------------|--------|
|
|
29
|
+
| ❌ `const formRef = useRef(null)` → `ref={formRef}` 两处都错 | ✅ **`useRef<FormRefObject>({} as FormRefObject)`** 且用 **`form={formRef}`**(form prop 而非 ref prop)|
|
|
30
|
+
| ❌ `if (!formRef.current.check()) throw new Error(...)` check() 当 boolean 用 | ✅ **`const values = formRef.current.check?.(); if (!values) return; submit(values)`** check() 返回 `false | object` |
|
|
31
|
+
| ❌ Switch loading 用单个 boolean state(多行并发互相覆盖) | ✅ **`loadingMap: Record<string, boolean>`** 每个 Switch 独立 loading 状态 |
|
|
32
|
+
| ❌ Tree `checkStrictly=true` 但 `checkedKeys={keys: Key[]}` 类型不匹配 | ✅ **`checkedKeys={{ checked: keys, halfChecked: halfKeys }}`** checkStrictly=true 时必须传对象形式 |
|
|
33
|
+
| ❌ Tabs `onChange={(value) => setTab(value)}` 混用参数名 | ✅ **`onChange={(activeKey) => setTab(activeKey)}`** 参数名与 API 签名一致 |
|
|
34
|
+
| ❌ Dashboard 多 Widget 用 useEffect 监听数据相互触发 | ✅ **`timer.current` ref + setInterval 独立驱动各 Widget**,停止时统一 clearInterval |
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 完整代码(自包含,可直接复制)
|
|
39
|
+
|
|
40
|
+
```tsx
|
|
41
|
+
import React, {
|
|
42
|
+
FunctionComponent, useState, useRef, useMemo, useCallback, useEffect
|
|
43
|
+
} from 'react';
|
|
44
|
+
import { Tabs, Form, Switch, Tree, Button, Card } from '@para-ui/core';
|
|
45
|
+
import { Message } from '@para-ui/core/Message';
|
|
46
|
+
import type { FormRefObject } from '@para-ui/core';
|
|
47
|
+
import type { TabProps } from '@para-ui/core';
|
|
48
|
+
|
|
49
|
+
// ============================================================
|
|
50
|
+
// 类型定义
|
|
51
|
+
// ============================================================
|
|
52
|
+
|
|
53
|
+
interface RoleItem {
|
|
54
|
+
id: string;
|
|
55
|
+
name: string;
|
|
56
|
+
permissionCount: number;
|
|
57
|
+
enabled: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface PermTreeNode {
|
|
61
|
+
key: string;
|
|
62
|
+
title: string;
|
|
63
|
+
children?: PermTreeNode[];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type GroupTab = 'all' | 'admin' | 'readonly';
|
|
67
|
+
|
|
68
|
+
// ============================================================
|
|
69
|
+
// 主组件:跨组件状态联动示例
|
|
70
|
+
// ============================================================
|
|
71
|
+
|
|
72
|
+
const RolePermissionPage: FunctionComponent = () => {
|
|
73
|
+
// ── 1. Tabs 状态(驱动下方 Tree 和列表联动)────────────────
|
|
74
|
+
const [activeGroup, setActiveGroup] = useState<GroupTab>('all');
|
|
75
|
+
|
|
76
|
+
// ── 2. Tree 多选状态(checkStrictly 类型陷阱)────────────────
|
|
77
|
+
const [checkedKeys, setCheckedKeys] = useState<React.Key[]>([]);
|
|
78
|
+
const [halfCheckedKeys, setHalfCheckedKeys] = useState<React.Key[]>([]);
|
|
79
|
+
// checkStrictly=true 时 checkedKeys 必须是对象形式,不能是数组
|
|
80
|
+
|
|
81
|
+
// ── 3. Form ref(必须显式类型,不能 useRef(null))────────────
|
|
82
|
+
// 错误:const formRef = useRef(null) → formRef.current.check() TS 报 unknown
|
|
83
|
+
// 正确:
|
|
84
|
+
const formRef = useRef<FormRefObject>({} as FormRefObject);
|
|
85
|
+
|
|
86
|
+
// ── 4. Switch loadingMap(多行独立 loading)────────────────
|
|
87
|
+
const [switchLoadingMap, setSwitchLoadingMap] = useState<Record<string, boolean>>({});
|
|
88
|
+
|
|
89
|
+
// ── 5. 撤销重做栈 ──────────────────────────────────────────
|
|
90
|
+
const [history, setHistory] = useState<React.Key[][]>([[]]);
|
|
91
|
+
const [historyIndex, setHistoryIndex] = useState<number>(0);
|
|
92
|
+
|
|
93
|
+
const pushHistory = (keys: React.Key[]): void => {
|
|
94
|
+
const newHistory = history.slice(0, historyIndex + 1);
|
|
95
|
+
newHistory.push([...keys]);
|
|
96
|
+
setHistory(newHistory);
|
|
97
|
+
setHistoryIndex(newHistory.length - 1);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const undo = (): void => {
|
|
101
|
+
if (historyIndex <= 0) return;
|
|
102
|
+
const newIndex = historyIndex - 1;
|
|
103
|
+
setHistoryIndex(newIndex);
|
|
104
|
+
setCheckedKeys(history[newIndex]);
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
const redo = (): void => {
|
|
108
|
+
if (historyIndex >= history.length - 1) return;
|
|
109
|
+
const newIndex = historyIndex + 1;
|
|
110
|
+
setHistoryIndex(newIndex);
|
|
111
|
+
setCheckedKeys(history[newIndex]);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
// ── 6. Tabs 切换 → 清空 Tree 选择 + 刷新列表 ─────────────────
|
|
115
|
+
// onChange 参数名用 activeKey 与 API 签名一致(不要用 value)
|
|
116
|
+
const handleTabChange = (activeKey: string): void => {
|
|
117
|
+
setActiveGroup(activeKey as GroupTab);
|
|
118
|
+
setCheckedKeys([]); // Tabs 切换时清空 Tree 选择
|
|
119
|
+
setHalfCheckedKeys([]);
|
|
120
|
+
pushHistory([]); // 记录初始空状态到历史栈
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// ── 7. Tree onCheck(checkStrictly 类型处理)─────────────────
|
|
124
|
+
const handleTreeCheck = (
|
|
125
|
+
keys: React.Key[] | { checked: React.Key[]; halfChecked: React.Key[] }
|
|
126
|
+
): void => {
|
|
127
|
+
// checkStrictly=false 时 keys 是 Key[];checkStrictly=true 时是对象
|
|
128
|
+
const checkedArr = Array.isArray(keys) ? keys : keys.checked;
|
|
129
|
+
const halfArr = Array.isArray(keys) ? [] : keys.halfChecked;
|
|
130
|
+
setCheckedKeys(checkedArr);
|
|
131
|
+
setHalfCheckedKeys(halfArr);
|
|
132
|
+
pushHistory(checkedArr); // 每次勾选变化压栈
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// ── 8. Switch 行内切换(loadingMap 避免并发干扰)─────────────
|
|
136
|
+
const handleToggleRole = async (role: RoleItem): Promise<void> => {
|
|
137
|
+
setSwitchLoadingMap(prev => ({ ...prev, [role.id]: true }));
|
|
138
|
+
try {
|
|
139
|
+
await mockApi.toggleRole(role.id, !role.enabled);
|
|
140
|
+
Message.success(`已${role.enabled ? '停用' : '启用'} ${role.name}`);
|
|
141
|
+
} finally {
|
|
142
|
+
setSwitchLoadingMap(prev => ({ ...prev, [role.id]: false }));
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
// ── 9. Form 提交(check() 返回 false | object,不是 boolean)─
|
|
147
|
+
const handleSavePermissions = async (): Promise<void> => {
|
|
148
|
+
// check() 返回 false(失败)或 values 对象(成功),不抛异常
|
|
149
|
+
const values = formRef.current.check?.();
|
|
150
|
+
if (!values) return; // false 表示验证失败,直接 return
|
|
151
|
+
// values 是包含表单字段的对象
|
|
152
|
+
await mockApi.savePermissions({
|
|
153
|
+
group: activeGroup,
|
|
154
|
+
permissions: checkedKeys,
|
|
155
|
+
remark: (values as Record<string, unknown>).remark as string
|
|
156
|
+
});
|
|
157
|
+
Message.success('权限保存成功');
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// ── 10. Tabs 数据 ──────────────────────────────────────────
|
|
161
|
+
const tabsData = useMemo<TabProps<GroupTab>[]>(() => [
|
|
162
|
+
{ value: 'all', label: '全部角色' },
|
|
163
|
+
{ value: 'admin', label: '管理员' },
|
|
164
|
+
{ value: 'readonly', label: '只读角色' }
|
|
165
|
+
], []);
|
|
166
|
+
|
|
167
|
+
// ── 11. Tabs 驱动的 Tree 数据(按 activeGroup 过滤)──────────
|
|
168
|
+
const treeData: PermTreeNode[] = useMemo(() => {
|
|
169
|
+
// 实际项目里按 activeGroup 过滤权限树
|
|
170
|
+
return mockPermTree.filter(node =>
|
|
171
|
+
activeGroup === 'all' || node.key.startsWith(activeGroup)
|
|
172
|
+
);
|
|
173
|
+
}, [activeGroup]);
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<div style={{ display: 'flex', gap: 24 }}>
|
|
177
|
+
{/* 左侧:Tabs + Tree */}
|
|
178
|
+
<div style={{ width: 280, flexShrink: 0 }}>
|
|
179
|
+
<Tabs<GroupTab>
|
|
180
|
+
data={tabsData}
|
|
181
|
+
activeKey={activeGroup}
|
|
182
|
+
// onChange 参数名 activeKey 与 API 一致
|
|
183
|
+
onChange={(activeKey) => handleTabChange(activeKey)}
|
|
184
|
+
/>
|
|
185
|
+
|
|
186
|
+
<div style={{ margin: '16px 0 8px', display: 'flex', gap: 8 }}>
|
|
187
|
+
<Button
|
|
188
|
+
size="small"
|
|
189
|
+
disabled={historyIndex <= 0}
|
|
190
|
+
onClick={undo}
|
|
191
|
+
>
|
|
192
|
+
撤销
|
|
193
|
+
</Button>
|
|
194
|
+
<Button
|
|
195
|
+
size="small"
|
|
196
|
+
disabled={historyIndex >= history.length - 1}
|
|
197
|
+
onClick={redo}
|
|
198
|
+
>
|
|
199
|
+
重做
|
|
200
|
+
</Button>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
{/* Tree checkStrictly=true 时 checkedKeys 必须是对象形式 */}
|
|
204
|
+
<Tree
|
|
205
|
+
treeData={treeData}
|
|
206
|
+
checkable={true}
|
|
207
|
+
checkStrictly={true}
|
|
208
|
+
checkedKeys={{ checked: checkedKeys, halfChecked: halfCheckedKeys }}
|
|
209
|
+
onCheck={handleTreeCheck}
|
|
210
|
+
/>
|
|
211
|
+
</div>
|
|
212
|
+
|
|
213
|
+
{/* 右侧:角色列表 + Form 保存 */}
|
|
214
|
+
<div style={{ flex: 1 }}>
|
|
215
|
+
{mockRoles
|
|
216
|
+
.filter(r => activeGroup === 'all' || r.id.startsWith(activeGroup))
|
|
217
|
+
.map(role => (
|
|
218
|
+
<Card key={role.id} style={{ marginBottom: 12 }}>
|
|
219
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
|
|
220
|
+
<span>{role.name}</span>
|
|
221
|
+
<span style={{ color: '#999', fontSize: 12 }}>
|
|
222
|
+
{role.permissionCount} 个权限
|
|
223
|
+
</span>
|
|
224
|
+
{/* Switch loading 用 loadingMap,每行独立互不干扰 */}
|
|
225
|
+
<Switch
|
|
226
|
+
checked={role.enabled}
|
|
227
|
+
loading={switchLoadingMap[role.id] ?? false}
|
|
228
|
+
onChange={() => handleToggleRole(role)}
|
|
229
|
+
/>
|
|
230
|
+
</div>
|
|
231
|
+
</Card>
|
|
232
|
+
))
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
{/* Form:命令式 API 通过 form prop 传 ref(不是 ref prop,Form 不是 forwardRef 组件)*/}
|
|
236
|
+
<Form
|
|
237
|
+
form={formRef}
|
|
238
|
+
configList={[
|
|
239
|
+
{
|
|
240
|
+
name: 'remark',
|
|
241
|
+
label: '备注',
|
|
242
|
+
InputType: 'text', // InputType 不是 type(type 是布局覆盖)
|
|
243
|
+
rules: { validate: { required: false } } // required 在 rules.validate 下
|
|
244
|
+
}
|
|
245
|
+
]}
|
|
246
|
+
/>
|
|
247
|
+
|
|
248
|
+
<div style={{ marginTop: 16, display: 'flex', gap: 8 }}>
|
|
249
|
+
<Button onClick={handleSavePermissions}>
|
|
250
|
+
保存权限(已选 {checkedKeys.length} 项)
|
|
251
|
+
</Button>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
export default RolePermissionPage;
|
|
259
|
+
|
|
260
|
+
// === 占位 Mock ===
|
|
261
|
+
const mockPermTree: PermTreeNode[] = [
|
|
262
|
+
{ key: 'admin-read', title: '管理员只读' },
|
|
263
|
+
{ key: 'admin-write', title: '管理员读写' },
|
|
264
|
+
{ key: 'readonly-view', title: '只读查看' }
|
|
265
|
+
];
|
|
266
|
+
const mockRoles: RoleItem[] = [
|
|
267
|
+
{ id: 'admin-1', name: '超级管理员', permissionCount: 24, enabled: true },
|
|
268
|
+
{ id: 'readonly-1', name: '审计员', permissionCount: 6, enabled: false }
|
|
269
|
+
];
|
|
270
|
+
const mockApi = {
|
|
271
|
+
toggleRole: async (id: string, enabled: boolean): Promise<void> => { void id; void enabled; },
|
|
272
|
+
savePermissions: async (data: {
|
|
273
|
+
group: string; permissions: React.Key[]; remark?: string
|
|
274
|
+
}): Promise<void> => { void data; }
|
|
275
|
+
};
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 5 个真实陷阱(来自 M2/M3 修复实证)
|
|
281
|
+
|
|
282
|
+
### ❌ 陷阱 1:Form ref 类型写错 + 用 ref prop 而非 form prop
|
|
283
|
+
|
|
284
|
+
```tsx
|
|
285
|
+
// 错(最高频 Form 陷阱,M3 Stage 修复实证)
|
|
286
|
+
const formRef = useRef(null);
|
|
287
|
+
formRef.current?.check();
|
|
288
|
+
// TS 报错:类型"null"上不存在属性"check"
|
|
289
|
+
|
|
290
|
+
// 错(错误的泛型)
|
|
291
|
+
const formRef = useRef<HTMLElement>(null);
|
|
292
|
+
formRef.current?.check();
|
|
293
|
+
// TS 报错:类型"HTMLElement"上不存在属性"check"
|
|
294
|
+
|
|
295
|
+
// 错(Form 不是 forwardRef 组件,不接受 ref prop)
|
|
296
|
+
<Form ref={formRef} configList={...} />
|
|
297
|
+
// TS 报错:Property 'ref' does not exist on type 'IntrinsicAttributes & FormProps'
|
|
298
|
+
|
|
299
|
+
// 对:用 FormRefObject + form prop(不是 ref prop)
|
|
300
|
+
import type { FormRefObject } from '@para-ui/core';
|
|
301
|
+
const formRef = useRef<FormRefObject>({} as FormRefObject);
|
|
302
|
+
<Form form={formRef} configList={...} /> // form prop 接收 ref,不是 ref prop
|
|
303
|
+
formRef.current?.check(); // 正确,有类型提示
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### ❌ 陷阱 2:check() 返回值当 boolean 用 → 丢失表单数据
|
|
307
|
+
|
|
308
|
+
```tsx
|
|
309
|
+
// 错(check() 不是 boolean,是 false | object)
|
|
310
|
+
const ok: boolean = formRef.current.check?.() as boolean;
|
|
311
|
+
if (!ok) return;
|
|
312
|
+
submit({ data: '硬编码' }); // 丢失了 check() 返回的表单值
|
|
313
|
+
|
|
314
|
+
// 错(当 boolean 判断 + 取值分离,两次调用)
|
|
315
|
+
if (!formRef.current.check?.()) return;
|
|
316
|
+
const values = formRef.current.getData?.(); // getData 不存在
|
|
317
|
+
|
|
318
|
+
// 对:check() 返回 false 表失败,返回 object 表成功并含字段值
|
|
319
|
+
const values = formRef.current.check?.();
|
|
320
|
+
if (!values) return; // false 或 undefined → 验证失败
|
|
321
|
+
submit(values as Record<string, unknown>); // values 就是表单字段对象
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
### ❌ 陷阱 3:Tree checkStrictly=true 但 checkedKeys 传数组(M3 修复同款)
|
|
325
|
+
|
|
326
|
+
```tsx
|
|
327
|
+
// 错(checkStrictly=true 时 checkedKeys 必须是 { checked, halfChecked } 对象)
|
|
328
|
+
<Tree
|
|
329
|
+
checkStrictly={true}
|
|
330
|
+
checkedKeys={selectedKeys} // TS: Key[] 不匹配 {checked: Key[]; halfChecked: Key[]}
|
|
331
|
+
onCheck={(keys) => setSelectedKeys(keys as React.Key[])}
|
|
332
|
+
// keys 实际是 {checked,halfChecked} 对象,强转为 Key[] 会出错
|
|
333
|
+
/>
|
|
334
|
+
|
|
335
|
+
// 对
|
|
336
|
+
<Tree
|
|
337
|
+
checkStrictly={true}
|
|
338
|
+
checkedKeys={{ checked: checkedKeys, halfChecked: halfCheckedKeys }}
|
|
339
|
+
onCheck={(keys) => {
|
|
340
|
+
// keys 类型随 checkStrictly 变化,必须判断
|
|
341
|
+
const arr = Array.isArray(keys) ? keys : keys.checked;
|
|
342
|
+
setCheckedKeys(arr);
|
|
343
|
+
}}
|
|
344
|
+
/>
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### ❌ 陷阱 4:Tabs onChange 参数名混用导致语义混乱
|
|
348
|
+
|
|
349
|
+
```tsx
|
|
350
|
+
// 错(参数名 value 与 API 签名 activeKey 不一致,运行正确但误导)
|
|
351
|
+
<Tabs
|
|
352
|
+
data={tabsData}
|
|
353
|
+
activeKey={currentTab}
|
|
354
|
+
onChange={(value) => {
|
|
355
|
+
setCurrentTab(value); // value 实际是 activeKey,命名混乱
|
|
356
|
+
}}
|
|
357
|
+
/>
|
|
358
|
+
|
|
359
|
+
// 对(参数名与 API 一致)
|
|
360
|
+
<Tabs
|
|
361
|
+
data={tabsData}
|
|
362
|
+
activeKey={currentTab}
|
|
363
|
+
onChange={(activeKey) => {
|
|
364
|
+
setCurrentTab(activeKey as GroupTab);
|
|
365
|
+
}}
|
|
366
|
+
/>
|
|
367
|
+
|
|
368
|
+
// 另一个 Tabs 陷阱:data 是 TabProps[] 不是 antd 的 items
|
|
369
|
+
// data={[{ value: 'home', label: '首页', content: <Home /> }]}
|
|
370
|
+
// 不是 items={[{ key: 'home', label: '首页', children: <Home /> }]}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### ❌ 陷阱 5:Dashboard 多 Widget 用 useEffect 监听相互触发死循环
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
// 错(多组件状态互相监听,容易触发死循环或闪烁)
|
|
377
|
+
useEffect(() => {
|
|
378
|
+
fetchWidgetA(activeGroup).then(setDataA);
|
|
379
|
+
}, [activeGroup, dataB]); // dataB 变化又触发 fetchWidgetA,形成环
|
|
380
|
+
|
|
381
|
+
// 对(Dashboard/content.tsx 实证):各 Widget 独立用 timer ref 驱动
|
|
382
|
+
const timer = useRef<Record<string, NodeJS.Timeout>>({});
|
|
383
|
+
|
|
384
|
+
const startPolling = () => {
|
|
385
|
+
timer.current.widgetA = setInterval(() => fetchWidgetA(), 5000);
|
|
386
|
+
timer.current.widgetB = setInterval(() => fetchWidgetB(), 10000);
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
const stopPolling = () => {
|
|
390
|
+
Object.keys(timer.current).forEach(key => clearInterval(timer.current[key]));
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
useEffect(() => {
|
|
394
|
+
startPolling();
|
|
395
|
+
return stopPolling; // 组件卸载时统一清理
|
|
396
|
+
}, [activeGroup]); // 只依赖 activeGroup,不依赖 data
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
---
|
|
400
|
+
|
|
401
|
+
## 真实参考
|
|
402
|
+
|
|
403
|
+
**Para 团队真实业务代码**
|
|
404
|
+
|
|
405
|
+
| 文件 | 关键模式 | 行号 |
|
|
406
|
+
|------|---------|------|
|
|
407
|
+
| `Dashboard/src/content.tsx` | `timer.current` ref + `setInterval` 独立驱动各 Widget | 36, 79-90 |
|
|
408
|
+
| `Dashboard/src/content.tsx` | `stopGetMonitor` 统一 clearInterval 所有 timer | 136-139 |
|
|
409
|
+
| `Dashboard/src/content.tsx` | `useEffect(() => { startGetMonitor(); return stopGetMonitor; }, [wsStatus])` | 151-154 |
|
|
410
|
+
| `Cluster/src/content.tsx` | `Tabs onChange={(val) => setGroupId(val)}` 驱动 useEffect 联动 | 73-78 |
|
|
411
|
+
| `Cluster/src/content.tsx` | `useEffect(() => { queryGroupNodes(groupId)... }, [groupId])` Tabs 切换触发数据刷新 | 81-87 |
|
|
412
|
+
| `Service/src/content.tsx` | `useAsync(updateDisabled, 'id')` + `updateDisabledLoadingMap[row.id]` loadingMap 模式 | 66, 452 |
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* jscodeshift codemod · modal-onCancel-to-onDismiss
|
|
3
|
+
*
|
|
4
|
+
* 为 v5.0.0-beta.14 提供:把 `<Modal onCancel={fn}>` v4 写法
|
|
5
|
+
* 自动改成 `<Modal onCancel={fn} onDismiss={fn}>`,解决 X/ESC/蒙层
|
|
6
|
+
* 在 v6.0(2026 Q3)起 silently 失效的迁移问题。
|
|
7
|
+
*
|
|
8
|
+
* 用法(业务方):
|
|
9
|
+
* npx jscodeshift -t node_modules/@para-ui/core/codemods/modal-onCancel-to-onDismiss.js \
|
|
10
|
+
* --parser=tsx --extensions=tsx,jsx src/
|
|
11
|
+
*
|
|
12
|
+
* 规则:
|
|
13
|
+
* - 仅处理 <Modal> JSX(不处理 <NS.Modal>;不处理命令式 Modal.Confirm)
|
|
14
|
+
* - 已有 onDismiss / onClose → skip(避免破坏 legacy 双触发或 γ 单触发)
|
|
15
|
+
* - 含 JSX spread `{...rest}` → skip(无法静态判定)
|
|
16
|
+
* - onCancel 表达式直接复用作 onDismiss 值(同回调,与 dev throw / ESLint rule 一致)
|
|
17
|
+
*
|
|
18
|
+
* 详见:
|
|
19
|
+
* - docs/UPGRADE_v4_to_v5.md §3.D.0
|
|
20
|
+
* - BREAKING-CHANGES §B-Modal-props-rework 子条 #5
|
|
21
|
+
*/
|
|
22
|
+
module.exports = function transformer(file, api) {
|
|
23
|
+
const j = api.jscodeshift;
|
|
24
|
+
const root = j(file.source);
|
|
25
|
+
let touched = 0;
|
|
26
|
+
|
|
27
|
+
root.find(j.JSXOpeningElement)
|
|
28
|
+
.filter(path => {
|
|
29
|
+
const name = path.node.name;
|
|
30
|
+
return name && name.type === 'JSXIdentifier' && name.name === 'Modal';
|
|
31
|
+
})
|
|
32
|
+
.forEach(path => {
|
|
33
|
+
const attrs = path.node.attributes || [];
|
|
34
|
+
let onCancelAttr = null;
|
|
35
|
+
let hasOnDismiss = false;
|
|
36
|
+
let hasOnClose = false;
|
|
37
|
+
let hasSpread = false;
|
|
38
|
+
|
|
39
|
+
for (const attr of attrs) {
|
|
40
|
+
if (attr.type === 'JSXSpreadAttribute') {
|
|
41
|
+
hasSpread = true;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (attr.type !== 'JSXAttribute') continue;
|
|
45
|
+
if (!attr.name || attr.name.type !== 'JSXIdentifier') continue;
|
|
46
|
+
if (attr.name.name === 'onCancel') onCancelAttr = attr;
|
|
47
|
+
else if (attr.name.name === 'onDismiss') hasOnDismiss = true;
|
|
48
|
+
else if (attr.name.name === 'onClose') hasOnClose = true;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (hasSpread || !onCancelAttr || hasOnDismiss || hasOnClose) return;
|
|
52
|
+
if (!onCancelAttr.value) return;
|
|
53
|
+
|
|
54
|
+
const dismissAttr = j.jsxAttribute(
|
|
55
|
+
j.jsxIdentifier('onDismiss'),
|
|
56
|
+
onCancelAttr.value
|
|
57
|
+
);
|
|
58
|
+
path.node.attributes.push(dismissAttr);
|
|
59
|
+
touched += 1;
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
if (touched > 0) {
|
|
63
|
+
// 仅在有改动时输出,避免 dirty toSource 触发空 diff
|
|
64
|
+
return root.toSource({ quote: 'single', reuseWhitespace: true });
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
module.exports.parser = 'tsx';
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "AlignBox",
|
|
3
|
+
"category": "Layout",
|
|
4
|
+
"description": "方向语义对齐容器:direction='horizontal'(默认)子元素水平排列+垂直居中;direction='vertical'子元素纵向堆叠+水平居中。根元素为 block 级 flex div,style/className 直接作用于该 flex 容器。",
|
|
5
|
+
"semantic": {
|
|
6
|
+
"intent": [
|
|
7
|
+
"方向对齐",
|
|
8
|
+
"水平排列容器",
|
|
9
|
+
"纵向堆叠容器"
|
|
10
|
+
],
|
|
11
|
+
"useCases": [
|
|
12
|
+
"图标 + 文字 + 标签 一行内水平对齐(direction='horizontal')",
|
|
13
|
+
"字段纵向堆叠每行一个(direction='vertical')",
|
|
14
|
+
"卡片内简单的横向元素对齐"
|
|
15
|
+
],
|
|
16
|
+
"riskLevel": "low"
|
|
17
|
+
},
|
|
18
|
+
"variants": {
|
|
19
|
+
"horizontal": {
|
|
20
|
+
"meaning": "**子元素水平排列 + 垂直居中** — `display:flex; align-items:center`;子元素按 row 排列,在交叉轴(垂直)居中。默认值。**主轴对齐默认 flex-start**(DEFECT-006):两端对齐 / 居中等需 className 或 style 追加 justify-content"
|
|
21
|
+
},
|
|
22
|
+
"vertical": {
|
|
23
|
+
"meaning": "**子元素纵向堆叠 + 水平居中** — `display:flex; flex-direction:column; align-items:center`;子元素从上到下堆叠,在交叉轴(水平)居中。**⚠️ DEFECT-007:子元素宽度 = 内容宽度**(align-items:center 收缩,非撑满容器);修复方案:① 给子元素自身加 `width:100%`(推荐):`<div style={{ width: '100%' }}>内容</div>`;② 或在 AlignBox 上加 `style={{ alignItems: 'stretch' }}` 覆盖。嵌套场景(vertical 包 horizontal):内层 AlignBox 必须加 `style={{ width: '100%' }}` 才能撑满父容器"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"states": [
|
|
27
|
+
"default"
|
|
28
|
+
],
|
|
29
|
+
"idealProps": {
|
|
30
|
+
"direction": {
|
|
31
|
+
"type": "enum",
|
|
32
|
+
"values": [
|
|
33
|
+
"horizontal",
|
|
34
|
+
"vertical"
|
|
35
|
+
],
|
|
36
|
+
"default": "horizontal",
|
|
37
|
+
"description": "子元素排列方向(字面 = 行为):`horizontal` = 水平排列 + 垂直居中(`display:flex; align-items:center`;主轴对齐默认 flex-start,需要两端对齐用 `style={{ justifyContent: 'space-between' }}`,需要右对齐用 `justifyContent: 'flex-end'`);`vertical` = 纵向堆叠 + 水平居中(`display:flex; flex-direction:column; align-items:center`)。**vertical 模式两个注意点**:① 子元素间**无默认 gap**——需要均匀间距时加 `style={{ gap: '8px' }}`(8px 紧凑 / 12px 标准 / 16px 宽松);② 子元素**宽度默认收缩至内容宽度**(DEFECT-007,align-items:center 副作用)——若子元素需要撑满父宽度,加 `style={{ alignItems: 'stretch' }}`(整体)或在每个子元素上加 `style={{ width: '100%' }}`(单独控制)。**2026-05-08 跨组件命名 epic §3.3 选项 I 重设计** — 替代旧 `alignType: 'vertical' | 'flex'`(BREAKING-CHANGES §A5)"
|
|
38
|
+
},
|
|
39
|
+
"children": {
|
|
40
|
+
"type": "ReactNode",
|
|
41
|
+
"description": "子元素;按 direction 控制的轴向排列"
|
|
42
|
+
},
|
|
43
|
+
"className": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "外层根 div 的类名(AlignBox-DEFECT-003:src/AlignBox/index.tsx 实证)。常用于追加自定义样式覆盖,如 `flex-wrap: wrap` / `gap` / `justify-content` 等 direction 未提供的属性"
|
|
46
|
+
},
|
|
47
|
+
"style": {
|
|
48
|
+
"type": "React.CSSProperties",
|
|
49
|
+
"description": "外层根 div 的内联样式(AlignBox-DEFECT-003:src/AlignBox/index.tsx 实证)。**根 div 同时也是 flex 容器**(不存在两层 div 分离),因此 style 可直接传 flexWrap / gap / justifyContent 等 flex 属性,与 className 追加等效。常用示例:`style={{ flexWrap: 'wrap', gap: '8px' }}`(换行 + 间距);`style={{ justifyContent: 'space-between' }}`(两端对齐);`style={{ width: '100%' }}`(vertical 模式下覆盖 DEFECT-007 宽度收缩)"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
"do": [
|
|
53
|
+
"需要『一行内水平排列 + 垂直居中』(图标 + 文字 + 标签)用 direction='horizontal'(默认值,可省略)",
|
|
54
|
+
"需要『子元素纵向堆叠 + 水平居中』(字段每行一个)用 direction='vertical'",
|
|
55
|
+
"vertical 模式需要子元素间均匀间距:加 `style={{ gap: '8px' }}`(8px 紧凑 / 12px 标准 / 16px 宽松)——vertical 本身无默认 gap",
|
|
56
|
+
"vertical 模式需要子元素撑满父宽度(卡片内容、表单字段):加 `style={{ alignItems: 'stretch' }}`——vertical 子元素默认宽度收缩至内容宽度(DEFECT-007)",
|
|
57
|
+
"horizontal 需要两端对齐:`style={{ justifyContent: 'space-between', width: '100%' }}`;需要右对齐:`style={{ justifyContent: 'flex-end' }}`——horizontal 默认 flex-start(左对齐)",
|
|
58
|
+
"需要 wrap / gap / justify-content 等 direction 未提供的 flex 属性,用 **className** 追加 *或* **style 内联**(两种方式等效,因为 style 直接作用于根 flex div):`style={{ flexWrap: 'wrap', gap: '8px', justifyContent: 'space-between' }}`",
|
|
59
|
+
"**业务方语义直觉 = direction 字面**:从 v6 开始 horizontal/vertical 即字面对齐 — 不再有命名错位"
|
|
60
|
+
],
|
|
61
|
+
"dont": [
|
|
62
|
+
"过度嵌套 AlignBox",
|
|
63
|
+
"替代 CSS Grid/Flexbox 进行复杂布局",
|
|
64
|
+
"**不要再传旧 prop `alignType`** — 已 BREAKING 移除(BREAKING-CHANGES §A5);从 v5.x 之前升级请按以下映射:旧 `alignType='vertical'`(实为 inline vertical-align middle)→ 新 `direction='horizontal'`(语义最接近);旧 `alignType='flex'`(实为 flex row 居中)→ 新 `direction='horizontal'`(行为完全一致)。要用真正的纵向堆叠请显式传 `direction='vertical'`",
|
|
65
|
+
"不要假设 `direction='horizontal'` 自动 flex-wrap — src 仅 `display:flex; align-items:center`,无 wrap;要换行请加 className"
|
|
66
|
+
],
|
|
67
|
+
"events": {},
|
|
68
|
+
"typescriptPitfalls": [
|
|
69
|
+
{
|
|
70
|
+
"issue": "direction 只接受 'horizontal' | 'vertical',不接受 antd flex 方向字符串",
|
|
71
|
+
"wrong": "<AlignBox direction='row'>...</AlignBox> // 'row' 不在联合类型中,TS 报错",
|
|
72
|
+
"right": "<AlignBox direction='horizontal'>...</AlignBox> // 水平排列用 'horizontal'"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"issue": "vertical 模式下子元素宽度默认收缩至内容宽度(align-items:center 副作用),需显式覆盖",
|
|
76
|
+
"wrong": "<AlignBox direction='vertical'><div className='full-row'>...</div></AlignBox> // 子 div 宽度收缩,不是撑满",
|
|
77
|
+
"right": "<AlignBox direction='vertical' style={{ alignItems: 'stretch' }}>...</AlignBox> // 或在子元素加 style={{ width: '100%' }}"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"issue": "style 和 className 直接作用于根 flex div,不存在两层 div 分离",
|
|
81
|
+
"wrong": "// 以为有内外两层 div,试图用 className 覆盖内层 flex 容器\n<AlignBox style={{ display: 'block' }}>...</AlignBox> // 覆盖 display 会破坏 flex 对齐",
|
|
82
|
+
"right": "// style 直接透传到根 flex div,追加 flex 属性即可\n<AlignBox style={{ gap: '8px', justifyContent: 'space-between' }}>...</AlignBox>"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"mapping": {
|
|
86
|
+
"realComponent": "AlignBox",
|
|
87
|
+
"adapter": null
|
|
88
|
+
}
|
|
89
|
+
}
|
package/es/AlignBox/index.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.paraui-v4-align-box.paraui-v4-align-box-
|
|
1
|
+
@charset "UTF-8";.paraui-v4-align-box.paraui-v4-align-box-horizontal{display:flex;align-items:center}.paraui-v4-align-box.paraui-v4-align-box-vertical{display:flex;flex-direction:column;align-items:center}
|
package/es/AlignBox/index.d.ts
CHANGED
|
@@ -4,8 +4,12 @@ export interface AlignBoxProps {
|
|
|
4
4
|
className?: string;
|
|
5
5
|
/** style */
|
|
6
6
|
style?: React.CSSProperties;
|
|
7
|
-
/**
|
|
8
|
-
|
|
7
|
+
/**
|
|
8
|
+
* 子元素排列方向(字面 = 行为,2026-05-08 跨组件命名 epic §3.3 选项 I 重设计)
|
|
9
|
+
* - 'horizontal'(默认): display:flex; align-items:center — 子元素水平排列、垂直居中
|
|
10
|
+
* - 'vertical': display:flex; flex-direction:column; align-items:center — 子元素纵向堆叠、水平居中
|
|
11
|
+
*/
|
|
12
|
+
direction?: 'horizontal' | 'vertical';
|
|
9
13
|
children?: ReactNode;
|
|
10
14
|
}
|
|
11
15
|
declare const AlignBox: FunctionComponent<AlignBoxProps>;
|
package/es/AlignBox/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import m from "clsx";
|
|
|
3
3
|
import { $prefixCls as o } from "../GlobalContext/constant.js";
|
|
4
4
|
import './index.css';/* empty css */
|
|
5
5
|
const f = (r) => {
|
|
6
|
-
const { className: s, style: t, children: i,
|
|
6
|
+
const { className: s, style: t, children: i, direction: e = "horizontal", ...l } = r;
|
|
7
7
|
return /* @__PURE__ */ a.jsx(
|
|
8
8
|
"div",
|
|
9
9
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.paraui-v4-align-box.paraui-v4-align-box-
|
|
1
|
+
.paraui-v4-align-box.paraui-v4-align-box-horizontal{display:flex;align-items:center}.paraui-v4-align-box.paraui-v4-align-box-vertical{display:flex;flex-direction:column;align-items:center}
|
|
@@ -8,7 +8,8 @@ interface IProps {
|
|
|
8
8
|
isTree?: boolean;
|
|
9
9
|
anchorMap?: AnchorMap;
|
|
10
10
|
setAnchorMap?: (map: AnchorMap) => void;
|
|
11
|
-
|
|
11
|
+
/** R6 §6 类型放宽:静态 ReactNode 或函数形式 (item, isActive) => ReactNode */
|
|
12
|
+
customPrefixIcon?: React.ReactNode | ((item: AnchorItem, isActive: boolean) => React.ReactNode);
|
|
12
13
|
onlyOneLevel?: boolean;
|
|
13
14
|
}
|
|
14
15
|
declare const AnchorMenu: (props: IProps) => import("react/jsx-runtime").JSX.Element;
|