소스 검색

Merge branch 'main' into release

pointhalo 3 년 전
부모
커밋
09e86c64c4

+ 0 - 41
.github/ISSUE_TEMPLATE/1.bug_report.md

@@ -1,41 +0,0 @@
----
-name: " 🐛 Bug report"
-about: Report a bug
-title: ''
-labels: 'bug'
-assignees: ''
-
----
-
-### Which Component 出现bug的组件
-  - Button
-
-### semi-ui version
-  - latest
-    
-### Expected result 期望的结果是什么
-  - 
-
-### Actual result 实际的结果是什么
-  - 
-
-### Steps to reproduce 复现步骤
-  - 1
-
-
-### Reproducible code 复现代码
-```
-class Demo extends React.component {
-
-    render() {
-        return (
-            <Button>bug</Button>
-        )
-    }
-
-}
-
-```
-
-### Additional information 补充说明
-- 遇到这个bug的业务场景、上下文、或者你的需求场景

+ 3 - 3
.github/ISSUE_TEMPLATE/2.feature_request.md

@@ -1,8 +1,8 @@
 ---
-name: "🎁 Feature request"
+name: "\U0001F381 Feature request"
 about: Suggest an idea to make the project better
-title: ''
-labels: ''
+title: "[Button] feature description for this component"
+labels: feature request
 assignees: ''
 
 ---

+ 83 - 0
.github/ISSUE_TEMPLATE/3.bug_report_form.yml

@@ -0,0 +1,83 @@
+name: 🐞 Bug
+description: File a bug/issue
+title: "[BUG] <title>"
+labels: [Bug, Needs Triage]
+body:
+- type: checkboxes
+  attributes:
+    label: Is there an existing issue for this?
+    description: Please search to see if an issue already exists for the bug you encountered.
+    options:
+    - label: I have searched the existing issues
+      required: true
+- type: input
+  attributes:
+    label: Which Component
+    description: Which component are you having trouble using.
+  validations:
+    required: false
+- type: input
+  attributes:
+    label: Semi Version
+    description: The version number of semi you are using.
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: Current Behavior
+    description: A concise description of what you're experiencing.
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: Expected Behavior
+    description: A concise description of what you expected to happen.
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: Steps To Reproduce
+    description: Steps to reproduce the behavior.
+    placeholder: |
+      1. In this environment...
+      2. With this config...
+      3. Run '...'
+      4. See error...
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: ReproducibleCode
+    placeholder: |
+      You can paste a minimal reproducible code, preferably runnable in the code editing area of Semi official website
+      Or you can also use Codesandbox to create a minimal reproduction code
+      import { Button } from '@douyinfe/semi-ui';
+      () => {
+        return (<Button>bug</Button>);
+      }
+    render: markdown
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: Environment
+    description: |
+      examples:
+        - **OS**: Ubuntu 20.04
+        - **Node**: 13.14.0
+        - **npm**: 7.6.3
+    value: |
+        - OS:
+        - browser:
+    render: markdown
+  validations:
+    required: false
+- type: textarea
+  attributes:
+    label: Anything else?
+    description: |
+      Links? References? Anything that will give us more context about the issue you are encountering!
+
+      Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
+  validations:
+    required: false

+ 58 - 4
content/navigation/tree/index-en-US.md

@@ -1227,8 +1227,38 @@ import { Tree } from '@douyinfe/semi-ui';
 
 ### Draggable Tree
 You could use `draggable` along with `onDrop` to achieve a draggable Tree.
-**Virtualized not supported at this moment**
-**v>=1.8.0**
+
+<Notice title='Notice'>
+    Drag and drop is available since v 1.8.0. Simultaneous use with virtualization is currently not supported
+</Notice>
+
+The callback input parameters of the drag event are as follows:
+```
+- onDragEnd: function({ event, node:treeNode })
+- onDragEnter:function({ event, node:treeNode, expandedKeys:string[] })
+- onDragLeave:function({ event, node:treeNode })
+- onDragOver:function({ event, node:treeNode })
+- onDragStart: function({ event, node })
+- onDrop:function({ event, node, dragNode:treeNode, dragNodesKeys:string[], dropPosition:number, dropToGap:Boolean })
+```
+
+The node, in addition to the original data originalData, also contains:
+```
+treeNode {
+    expanded: Boolean,
+    pos: string
+    value?: string | number;
+    label?: React.ReactNode;
+    disabled?: boolean;
+    isLeaf?: boolean;
+    [key: string]: any;
+}
+```
+
+- `pos` refers to the positional relationship of the current node in the entire treeData, such as the 0th node of the 2nd node of the 1st node of the 0th layer: '0-1-2-0'
+- `dropPosition` refers to the position where the dragged node is dropped in the current hierarchy. If it is inserted before the 0th node of the same level, it will be -1, and after the 0th node, it will be 1, and it will fall on it. is 0, and so on. With dropToGap, a more complete judgment can be obtained.
+- `dropToGap` refers to whether the dragged node is dropped between nodes, if false, it is dropped above a node
+
 ```jsx live=true
 import React, { useState } from 'react';
 import { Tree } from '@douyinfe/semi-ui';
@@ -1363,14 +1393,38 @@ import { Tree } from '@douyinfe/semi-ui';
 
 You could use `renderFullLabel` for advanced rendering to render the entire option on you own.
 
+```
+{
+    onClick: Function, // Click the callback of the entire row to control the expansion behavior and selection
+    onContextMenu: Function, // Callback for right-clicking the entire row
+    onDoubleClick: Function,  // Callback for double-clicking the entire row
+    className: strings, // Class name, including built-in styles such as indent, expand button, filter, disable, check, etc.
+    onExpand: Function, // Expand callback
+    data: object, // The original data of the row
+    level: number, // The level where the line is located, which can be used to customize the indentation value
+    style: object, // The style required for virtualization, if virtualization is used, the style must be assigned to the DOM element
+    onCheck: Function, // Multiple selection click callback
+    expandIcon: ReactNode, // Expand button
+    checkStatus: {
+        checked: Boolean, // Whether it is selected in the multi-select state
+        halfChecked: Boolean, // Whether half-selected in multi-select state
+    },
+    expandStatus: {
+        expanded,
+        loading,
+    },
+}
+```
+
 <Notice type="primary" title="Important">
 <div>If virtualized is set to true, be sure to apply `style` to targeted ReactNode to correctly render virtualized list.</div>
 </Notice>
 
 Here are some demos.
 
-First is to render Parent node as separator and only allow leaf nodes to be selected.
-⚠️:renderFullLabel only takes care of the UI rendering and won't affect inside data logic. But you could choose info to your needs and use it with controlled mode for advanced usage.
+First is to render Parent node as separator and only allow leaf nodes to be selected.  
+renderFullLabel only takes care of the UI rendering and won't affect inside data logic. But you could choose info to your needs and use it with controlled mode for advanced usage.
+
 ```jsx live=true
 import React from 'react';
 import { Tree, Checkbox } from '@douyinfe/semi-ui';

+ 32 - 2
content/navigation/tree/index.md

@@ -1254,9 +1254,39 @@ import { Tree } from '@douyinfe/semi-ui';
 ```
 
 ### 可拖拽的Tree
-**v>=1.8.0**  
+
 通过设置 draggable 配合 onDrop 可以实现 Tree 节点的拖拽。
-**目前不支持虚拟化**
+
+<Notice title='注意'>
+    拖拽功能于 v 1.8.0 后开始提供。目前不支持与虚拟化同时使用
+</Notice>
+
+拖拽事件的回调入参如下:
+```
+- onDragEnd: function({ event, node: treeNode })
+- onDragEnter:function({ event, node: treeNode, expandedKeys: string[] })
+- onDragLeave:function({ event, node: treeNode })
+- onDragOver:function({ event, node :treeNode })
+- onDragStart: function({ event, node })
+- onDrop:function({ event, node, dragNode:treeNode, dragNodesKeys:string[], dropPosition:number, dropToGap:Boolean })
+```
+
+其中node,除了原有数据originalData外,还包含:
+```
+treeNode {
+    expanded: Boolean,
+    pos: string
+    value?: string | number;
+    label?: React.ReactNode;
+    disabled?: boolean;
+    isLeaf?: boolean;
+    [key: string]: any;
+}
+```
+- `pos` 指的是当前节点在整个 treeData 中的位置关系,如第0层第1个节点的第2个节点的第0个节点:'0-1-2-0'
+- `dropPosition` 指的是被拖拽节点在当前层级中被 drop 的位置,如插入在同级的第0个节点前则为 -1,在第0个节点后则为 1,落在其上则为 0,以此类推。配合 dropToGap 可以得到更完整的判断。
+- `dropToGap` 指的是被拖拽节点是否被 drop 在节点之间的位置,如果为 false 则是 drop 在某个节点上方
+
 
 ```jsx live=true hideInDSM
 import React, { useState } from 'react';

+ 5 - 0
content/start/changelog/index-en-US.md

@@ -16,6 +16,11 @@ Version:Major.Minor.Patch
 
 ---
 
+#### 🎉 2.12.0 (2022-06-06)
+- 【Fix】
+    - Fix the issue that the last item style is abnormal when Timeline is nested [#865](https://github.com/DouyinFE/semi-design/issues/865)
+    - Fix the problem that the height of emptyContent is incorrect when Select is virtualized and there is no data [#839](https://github.com/DouyinFE/semi-design/pull/839) [@tianenpang](https://github.com/tianenpang)
+
 #### 🎉 2.12.0-beta.5 (2022-05-31)
 - 【Fix】
     - Fix the problem that Tooltip, Popover, Select and other components with floating layers will flicker when they are used under React 1 [#715](https://github.com/DouyinFE/semi-design/issues/715)

+ 5 - 0
content/start/changelog/index.md

@@ -15,6 +15,11 @@ Semi 版本号遵循**Semver**规范(主版本号-次版本号-修订版本号
 
 ---
 
+#### 🎉 2.12.0 (2022-06-06)
+- 【Fix】
+    - 修复 Timeline 嵌套使用时最后一项样式异常的问题 [#865](https://github.com/DouyinFE/semi-design/issues/865)
+    - 修复 Select 开启虚拟化且无数据时 emptyContent 高度不对的问题 [#839](https://github.com/DouyinFE/semi-design/pull/839) [@tianenpang](https://github.com/tianenpang)
+
 #### 🎉 2.12.0-beta.5 (2022-05-31)
 - 【Fix】
     - 修复 Tooltip、Popover、Select等带浮层组件,在 React 18 下使用,关闭时会闪烁的问题 [#715](https://github.com/DouyinFE/semi-design/issues/715)

+ 68 - 0
cypress/integration/select.spec.js

@@ -0,0 +1,68 @@
+// form.spec.js created with Cypress
+//
+// Start writing your Cypress tests below!
+// If you're unfamiliar with how Cypress works,
+// check out the link below and learn how to write your first test:
+// https://on.cypress.io/writing-first-test
+
+/**
+ * why use `.then`?
+ * @see https://docs.cypress.io/guides/core-concepts/variables-and-aliases#Return-Values
+ */
+describe('Select', () => {
+
+    it('option hover, change active', () => {
+        cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/select--select-filter-single');
+        cy.get('.semi-select').eq(0).click();
+        // hover can change active index
+        cy.get('.semi-select-option').eq(5).trigger('mouseover');
+        cy.get('.semi-select-option-focused .semi-select-option-text').eq(0).should('have.text', 'wym');
+        // press downArrow to test it
+        cy.get('input').eq(0).type('{downArrow}');
+        cy.get('.semi-select-option-focused .semi-select-option-text').eq(0).should('have.text', 'opts');
+    });
+
+    it('keyboard-enter, select choose option', { keystrokeDelay: 0 }, () => {
+        cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/select--select-filter-single');
+        cy.get('.semi-select').eq(0).click();
+        cy.get('input').eq(0).type('o');
+        cy.get('input').eq(0).type('{downArrow}');
+        cy.get('input').eq(0).type('{downArrow}');
+        cy.get('input').eq(0).type('{enter}');
+        cy.get('.semi-select-selection-text').eq(0).should('have.text', 'opts');
+    });
+
+    it('clickOutSide, should hide', () => {
+        cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/select--select-filter-single');
+        cy.get('.semi-select').eq(0).click();
+        // should show now
+        cy.get('.semi-select-option-list').should('exist');
+        // should hide after click empty area
+        cy.get('h5').eq(0).click();
+        cy.get('.semi-select-option-list').should('not.exist');
+    });
+
+    // it('should trigger onSearch when click x icon', () => {
+    //     cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/select--select-filter-single');
+    //     cy.get('.semi-select').eq(0).click();
+    //     cy.get('.semi-select-option').eq(0).click();
+    //     cy.get('.semi-select').eq(0).click();
+    //     cy.get('.semi-select-clear').eq(0).click();
+    //     cy.get('.semi-select-input .semi-input').should('have.value', '');
+    // });
+
+    // it('should trigger onBlur and onSearch', () => {
+    //     cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/form--use-form-api-set-value-update-array');
+    // });
+
+    // it('keyboard-skip disabled option when press up/down', () => {
+
+    // });
+
+    // it('optionList scroll, should trigger onListScroll', () => {
+    //     cy.visit('http://127.0.0.1:6006/iframe.html?path=/story/form--use-form-api-set-value-update-array');
+    // });
+
+
+
+});

+ 1 - 1
lerna.json

@@ -1,5 +1,5 @@
 {
     "useWorkspaces": true,
     "npmClient": "yarn",
-    "version": "2.12.0-beta.5"
+    "version": "2.12.0"
 }

+ 3 - 3
packages/semi-animation-react/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation-react",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "motion library for semi-ui-react",
   "keywords": [
     "motion",
@@ -26,8 +26,8 @@
   },
   "dependencies": {
     "@babel/runtime-corejs3": "^7.15.4",
-    "@douyinfe/semi-animation": "2.12.0-beta.5",
-    "@douyinfe/semi-animation-styled": "2.12.0-beta.5",
+    "@douyinfe/semi-animation": "2.12.0",
+    "@douyinfe/semi-animation-styled": "2.12.0",
     "classnames": "^2.2.6"
   },
   "peerDependencies": {

+ 1 - 1
packages/semi-animation-styled/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation-styled",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "semi styled animation",
   "keywords": [
     "semi",

+ 1 - 1
packages/semi-animation/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-animation",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "animation base library for semi-ui",
   "keywords": [
     "animation",

+ 2 - 2
packages/semi-foundation/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-foundation",
-    "version": "2.12.0-beta.5",
+    "version": "2.12.0",
     "description": "",
     "scripts": {
         "build:lib": "node ./scripts/compileLib.js",
@@ -8,7 +8,7 @@
     },
     "dependencies": {
         "@babel/runtime-corejs3": "^7.15.4",
-        "@douyinfe/semi-animation": "2.12.0-beta.5",
+        "@douyinfe/semi-animation": "2.12.0",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
         "date-fns": "^2.9.0",

+ 14 - 2
packages/semi-foundation/select/foundation.ts

@@ -505,6 +505,15 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
 
     clearInput() {
         this._adapter.updateInputValue('');
+        this._adapter.notifySearch('');
+        // reset options filter
+        const { options } = this.getStates();
+        const { remote } = this.getProps();
+        let optionsAfterFilter = options;
+        if (!remote) {
+            optionsAfterFilter = this._filterOption(options, '');
+        }
+        this._adapter.updateOptions(optionsAfterFilter);
     }
 
     focusInput() {
@@ -871,8 +880,10 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
     }
 
     handleClearClick(e: MouseEvent) {
-        this.clearInput();
-        // TODO
+        const { filter } = this.getProps();
+        if (filter) {
+            this.clearInput();
+        }
         this.clearSelected();
         // prevent this click open dropdown
         e.stopPropagation();
@@ -946,6 +957,7 @@ export default class SelectFoundation extends BaseFoundation<SelectAdapter> {
             const { defaultValue, value } = currentProps;
             const selectedValues = value || defaultValue;
             if (!isNullOrUndefined(selectedValues) && !Array.isArray(selectedValues)) {
+                /* istanbul ignore next */
                 warning(true, '[Semi Select] defaultValue/value should be array type in multiple mode');
             }
         }

+ 2 - 2
packages/semi-foundation/timeline/timeline.scss

@@ -105,7 +105,7 @@ $module: #{$prefix}-timeline;
         }
 
         &:last-child {
-            .#{$module}-item-tail {
+            & > .#{$module}-item-tail {
                 border-left: none;
             }
         }
@@ -176,4 +176,4 @@ $module: #{$prefix}-timeline;
     }
 }
 
-@import './rtl.scss';
+@import './rtl.scss';

+ 2 - 2
packages/semi-icons/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-icons",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "semi icons",
   "keywords": [
     "semi",
@@ -38,7 +38,7 @@
     "@babel/plugin-transform-runtime": "^7.15.8",
     "@babel/preset-env": "^7.15.8",
     "@babel/preset-react": "^7.14.5",
-    "@douyinfe/semi-webpack-plugin": "2.12.0-beta.5",
+    "@douyinfe/semi-webpack-plugin": "2.12.0",
     "babel-loader": "^8.2.2",
     "css-loader": "4.3.0",
     "del": "^6.0.0",

+ 1 - 1
packages/semi-illustrations/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-illustrations",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "semi illustrations",
   "keywords": [
     "semi",

+ 2 - 2
packages/semi-next/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-next",
-    "version": "2.12.0-beta.5",
+    "version": "2.12.0",
     "description": "Plugin that support Semi Design in Next.js",
     "author": "伍浩威 <[email protected]>",
     "homepage": "",
@@ -23,7 +23,7 @@
         "typescript": "^4"
     },
     "dependencies": {
-        "@douyinfe/semi-webpack-plugin": "2.12.0-beta.5"
+        "@douyinfe/semi-webpack-plugin": "2.12.0"
     },
     "gitHead": "eb34a4f25f002bb4cbcfa51f3df93bed868c831a"
 }

+ 1 - 1
packages/semi-scss-compile/package.json

@@ -1,6 +1,6 @@
 {
   "name": "@douyinfe/semi-scss-compile",
-  "version": "2.12.0-beta.5",
+  "version": "2.12.0",
   "description": "compile semi scss to css",
   "author": "[email protected]",
   "license": "MIT",

+ 1 - 1
packages/semi-theme-default/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-theme-default",
-    "version": "2.12.0-beta.5",
+    "version": "2.12.0",
     "description": "semi-theme-default",
     "keywords": [
         "semi-theme",

+ 8 - 8
packages/semi-ui/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-ui",
-    "version": "2.12.0-beta.5",
+    "version": "2.12.0",
     "description": "",
     "main": "lib/cjs/index.js",
     "module": "lib/es/index.js",
@@ -14,12 +14,12 @@
     },
     "dependencies": {
         "@babel/runtime-corejs3": "^7.15.4",
-        "@douyinfe/semi-animation": "2.12.0-beta.5",
-        "@douyinfe/semi-animation-react": "2.12.0-beta.5",
-        "@douyinfe/semi-foundation": "2.12.0-beta.5",
-        "@douyinfe/semi-icons": "2.12.0-beta.5",
-        "@douyinfe/semi-illustrations": "2.12.0-beta.5",
-        "@douyinfe/semi-theme-default": "2.12.0-beta.5",
+        "@douyinfe/semi-animation": "2.12.0",
+        "@douyinfe/semi-animation-react": "2.12.0",
+        "@douyinfe/semi-foundation": "2.12.0",
+        "@douyinfe/semi-icons": "2.12.0",
+        "@douyinfe/semi-illustrations": "2.12.0",
+        "@douyinfe/semi-theme-default": "2.12.0",
         "@types/react-window": "^1.8.2",
         "async-validator": "^3.5.0",
         "classnames": "^2.2.6",
@@ -75,7 +75,7 @@
         "@babel/plugin-transform-runtime": "^7.15.8",
         "@babel/preset-env": "^7.15.8",
         "@babel/preset-react": "^7.14.5",
-        "@douyinfe/semi-scss-compile": "2.12.0-beta.5",
+        "@douyinfe/semi-scss-compile": "2.12.0",
         "@storybook/addon-knobs": "^6.3.1",
         "@types/lodash": "^4.14.176",
         "babel-loader": "^8.2.2",

+ 11 - 0
packages/semi-ui/select/_story/select.stories.js

@@ -759,7 +759,9 @@ export const SelectFilterSingle = () => (
         width: '250px',
         margin: 10,
       }}
+      showClear
       autoFocus
+      onSearch={(val) => console.log(`onSearch:${val}`)}
       onFocus={() => console.log('onFocus')}
       onBlur={() => console.log('onBlur')}
     >
@@ -783,7 +785,9 @@ export const SelectFilterSingle = () => (
         margin: 10,
       }}
       filter={filter}
+      showClear
       onBlur={() => console.log('onBlur')}
+      onSearch={val => console.log(val)}
       onFocus={() => console.log('onFocus')}
     >
       <Option value={1}>opt1(value:1)</Option>
@@ -797,11 +801,13 @@ export const SelectFilterSingle = () => (
         width: '250px',
         margin: 10,
       }}
+      showClear
       filter={customFilter}
       onChange={v => console.log(v)}
       insetLabel="insetLabel"
       onFocus={() => console.log('onFocus')}
       onBlur={() => console.log('onBlur')}
+      onSearch={(val) => console.log(val)}
     >
       {colorOptions.map(option => (
         <Option value={option.value} key={option.value}>
@@ -1553,6 +1559,7 @@ const SearchDemo1 = () => {
         optionList={optionList}
         value={value}
         loading={loading}
+        showClear
         onChange={onChange}
       ></Select>
       非受控:
@@ -1561,6 +1568,7 @@ const SearchDemo1 = () => {
           width: '150px',
         }}
         filter
+        showClear
         onSearch={v => handleSearch(v)}
         optionList={optionList}
         loading={loading}
@@ -1571,6 +1579,7 @@ const SearchDemo1 = () => {
         style={{
           width: '150px',
         }}
+        showClear
         filter
         multiple
         onSearch={v => handleSearch(v)}
@@ -1662,6 +1671,7 @@ class SearchDemo2 extends React.Component {
           style={{
             width: 150,
           }}
+          showClear
           filter
           labelInValue
           onSearch={this.handleSearch}
@@ -1677,6 +1687,7 @@ class SearchDemo2 extends React.Component {
             width: 180,
           }}
           filter // labelInValue
+          showClear
           multiple
           value={value}
           renderSelectedItem={this.customRender}

+ 1 - 1
packages/semi-webpack/package.json

@@ -1,6 +1,6 @@
 {
     "name": "@douyinfe/semi-webpack-plugin",
-    "version": "2.12.0-beta.5",
+    "version": "2.12.0",
     "description": "",
     "author": "伍浩威 <[email protected]>",
     "homepage": "",