diff --git a/.gitignore b/.gitignore index 22062024..239c6dfb 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ lib/* coverage yarn.lock package-lock.json +.npmrc es/* # umi .umi diff --git a/README.md b/README.md index 71313b88..76aaee07 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ online example: https://tree-select-react-component.vercel.app/ |defaultValue | initial selected treeNode(s) | same as value type | - | |value | current selected treeNode(s). | normal: String/Array. labelInValue: {value:String,label:React.Node}/Array<{value,label}>. treeCheckStrictly(halfChecked default false): {value:String,label:React.Node, halfChecked}/Array<{value,label,halfChecked}>. | - | |labelInValue| whether to embed label in value, see above value type | Bool | false | +|labelInAriaLive| whether to use option label instead of value for screenreader | Bool | false | |onChange | called when select treeNode or input value change | function(value, label(null), extra) | - | |onSelect | called when select treeNode | function(value, node, extra) | - | |onSearch | called when input changed | function | - | diff --git a/package.json b/package.json index 9b70510b..4bb3818b 100644 --- a/package.json +++ b/package.json @@ -1,21 +1,25 @@ { - "name": "rc-tree-select", - "version": "5.4.0", - "description": "tree-select ui component for react", + "name": "@juhovalkonen/rc-tree-select", + "version": "5.5.2", + "description": "custom fork of tree-select ui component for react", "keywords": [ "react", "react-component", "react-tree-select", "tree-select" ], - "homepage": "https://github.com/react-component/tree-select", - "author": "smith3816@gmail.com", + "homepage": "https://github.com/juhoValkonen/tree-select", + "author": "valkonen.juho@gmail.com", "repository": { "type": "git", - "url": "https://github.com/react-component/tree-select.git" + "url": "https://github.com/juhoValkonen/tree-select.git" }, "bugs": { - "url": "https://github.com/react-component/tree-select/issues" + "url": "https://github.com/juhoValkonen/tree-select/issues" + }, + "publishConfig": { + "registry": "https://registry.npmjs.org/", + "access": "public" }, "files": [ "es", diff --git a/src/OptionList.tsx b/src/OptionList.tsx index f0cb4121..7c578f61 100644 --- a/src/OptionList.tsx +++ b/src/OptionList.tsx @@ -1,12 +1,12 @@ -import * as React from 'react'; -import KeyCode from 'rc-util/lib/KeyCode'; -import useMemo from 'rc-util/lib/hooks/useMemo'; -import type { RefOptionListProps } from 'rc-select/lib/OptionList'; import { useBaseProps } from 'rc-select'; -import type { TreeProps } from 'rc-tree'; +import type { RefOptionListProps } from 'rc-select/lib/OptionList'; import Tree from 'rc-tree'; +import type { TreeProps } from 'rc-tree'; import type { EventDataNode, ScrollTo } from 'rc-tree/lib/interface'; -import type { TreeDataNode, Key } from './interface'; +import useMemo from 'rc-util/lib/hooks/useMemo'; +import KeyCode from 'rc-util/lib/KeyCode'; +import * as React from 'react'; +import type { Key, TreeDataNode } from './interface'; import LegacyContext from './LegacyContext'; import TreeSelectContext from './TreeSelectContext'; import { getAllKeys, isCheckDisabled } from './utils/valueUtil'; @@ -42,6 +42,7 @@ const OptionList: React.RefForwardingComponent = (_, r onSelect, dropdownMatchSelectWidth, treeExpandAction, + labelInAriaLive, } = React.useContext(TreeSelectContext); const { @@ -211,7 +212,7 @@ const OptionList: React.RefForwardingComponent = (_, r
{activeEntity && open && ( - {activeEntity.node.value} + {!labelInAriaLive ? activeEntity.node.value : activeEntity.node.title} )} diff --git a/src/TreeSelect.tsx b/src/TreeSelect.tsx index 4600481d..03c99011 100644 --- a/src/TreeSelect.tsx +++ b/src/TreeSelect.tsx @@ -1,33 +1,33 @@ -import * as React from 'react'; import { BaseSelect } from 'rc-select'; -import type { IconType } from 'rc-tree/lib/interface'; -import type { ExpandAction } from 'rc-tree/lib/Tree'; import type { - BaseSelectRef, - BaseSelectPropsWithoutPrivate, BaseSelectProps, + BaseSelectPropsWithoutPrivate, + BaseSelectRef, SelectProps, } from 'rc-select'; -import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; import useId from 'rc-select/lib/hooks/useId'; +import type { IconType } from 'rc-tree/lib/interface'; +import type { ExpandAction } from 'rc-tree/lib/Tree'; +import { conductCheck } from 'rc-tree/lib/utils/conductUtil'; import useMergedState from 'rc-util/lib/hooks/useMergedState'; +import warning from 'rc-util/lib/warning'; +import * as React from 'react'; +import useCache from './hooks/useCache'; +import useCheckedKeys from './hooks/useCheckedKeys'; +import useDataEntities from './hooks/useDataEntities'; +import useFilterTreeData from './hooks/useFilterTreeData'; +import useRefFunc from './hooks/useRefFunc'; +import useTreeData from './hooks/useTreeData'; +import LegacyContext from './LegacyContext'; import OptionList from './OptionList'; import TreeNode from './TreeNode'; -import { formatStrategyValues, SHOW_ALL, SHOW_PARENT, SHOW_CHILD } from './utils/strategyUtil'; -import type { CheckedStrategy } from './utils/strategyUtil'; import TreeSelectContext from './TreeSelectContext'; import type { TreeSelectContextProps } from './TreeSelectContext'; -import LegacyContext from './LegacyContext'; -import useTreeData from './hooks/useTreeData'; -import { toArray, fillFieldNames, isNil } from './utils/valueUtil'; -import useCache from './hooks/useCache'; -import useRefFunc from './hooks/useRefFunc'; -import useDataEntities from './hooks/useDataEntities'; import { fillAdditionalInfo, fillLegacyProps } from './utils/legacyUtil'; -import useCheckedKeys from './hooks/useCheckedKeys'; -import useFilterTreeData from './hooks/useFilterTreeData'; +import { formatStrategyValues, SHOW_ALL, SHOW_CHILD, SHOW_PARENT } from './utils/strategyUtil'; +import type { CheckedStrategy } from './utils/strategyUtil'; +import { fillFieldNames, isNil, toArray } from './utils/valueUtil'; import warningProps from './utils/warningPropsUtil'; -import warning from 'rc-util/lib/warning'; export type OnInternalSelect = (value: RawValueType, info: { selected: boolean }) => void; @@ -140,6 +140,7 @@ export interface TreeSelectProps< treeCheckable?: boolean | React.ReactNode; treeCheckStrictly?: boolean; labelInValue?: boolean; + labelInAriaLive?: boolean; // >>> Data treeData?: OptionType[]; @@ -202,6 +203,7 @@ const TreeSelect = React.forwardRef((props, ref) treeCheckable, treeCheckStrictly, labelInValue, + labelInAriaLive, // FieldNames fieldNames, @@ -651,6 +653,7 @@ const TreeSelect = React.forwardRef((props, ref) fieldNames: mergedFieldNames, onSelect: onOptionSelect, treeExpandAction, + labelInAriaLive, }), [ virtual, @@ -661,6 +664,7 @@ const TreeSelect = React.forwardRef((props, ref) mergedFieldNames, onOptionSelect, treeExpandAction, + labelInAriaLive, ], ); diff --git a/src/TreeSelectContext.ts b/src/TreeSelectContext.ts index 0cb40e0f..cc76375b 100644 --- a/src/TreeSelectContext.ts +++ b/src/TreeSelectContext.ts @@ -1,5 +1,5 @@ -import * as React from 'react'; import type { ExpandAction } from 'rc-tree/lib/Tree'; +import * as React from 'react'; import type { DefaultOptionType, InternalFieldName, OnInternalSelect } from './TreeSelect'; export interface TreeSelectContextProps { @@ -11,6 +11,7 @@ export interface TreeSelectContextProps { fieldNames: InternalFieldName; onSelect: OnInternalSelect; treeExpandAction?: ExpandAction; + labelInAriaLive?: boolean; } const TreeSelectContext = React.createContext(null as any); diff --git a/tests/Select.props.spec.js b/tests/Select.props.spec.js index b1fff014..8258505e 100644 --- a/tests/Select.props.spec.js +++ b/tests/Select.props.spec.js @@ -1,7 +1,8 @@ /* eslint-disable no-undef, react/no-multi-comp, no-console */ -import React from 'react'; import { mount } from 'enzyme'; import Tree, { TreeNode } from 'rc-tree'; +import KeyCode from 'rc-util/lib/KeyCode'; +import React from 'react'; import TreeSelect, { SHOW_ALL, SHOW_CHILD, SHOW_PARENT, TreeNode as SelectNode } from '../src'; // Promisify timeout to let jest catch works @@ -155,6 +156,40 @@ describe('TreeSelect.props', () => { ); }); + it('labelInAriaLive', () => { + function keyDown(code) { + wrapper.find('input').first().simulate('keyDown', { which: code }); + wrapper.update(); + } + + function keyUp(code) { + wrapper.find('input').first().simulate('keyUp', { which: code }); + wrapper.update(); + } + + const wrapper = mount( + , + ); + + wrapper.openSelect(); + keyDown(KeyCode.DOWN); + keyUp(KeyCode.DOWN); + + const ariaLiveSpan = wrapper.find('[aria-live="assertive"]'); + expect(ariaLiveSpan.text()).toEqual('parent-label'); + }); + it('set illegal value', () => { const wrapper = mount( createSelect({