@hh.ru/magritte-ui-tree-selector 5.4.11 → 5.5.0

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/Action.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FC, KeyboardEventHandler } from 'react';
1
+ import { FC } from 'react';
2
2
  import { TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';
3
3
  interface ActionProps {
4
4
  singleChoice?: boolean;
@@ -7,7 +7,6 @@ interface ActionProps {
7
7
  name?: string;
8
8
  selected: boolean;
9
9
  indeterminate?: boolean;
10
- onKeyDown?: KeyboardEventHandler;
11
10
  }
12
11
  export declare const Action: FC<ActionProps>;
13
12
  export {};
package/Action.js CHANGED
@@ -3,7 +3,7 @@ import { jsx } from 'react/jsx-runtime';
3
3
  import { memo, useCallback } from 'react';
4
4
  import { Radio, Checkbox } from '@hh.ru/magritte-ui-checkbox-radio';
5
5
 
6
- const Action = memo(({ id, name, singleChoice, indeterminate, selected, onChange, onKeyDown }) => {
6
+ const Action = memo(({ id, name, singleChoice, indeterminate, selected, onChange }) => {
7
7
  const handleChange = useCallback((event) => {
8
8
  onChange(id, event.target.checked);
9
9
  }, [id, onChange]);
@@ -11,7 +11,7 @@ const Action = memo(({ id, name, singleChoice, indeterminate, selected, onChange
11
11
  checked: selected,
12
12
  onChange: handleChange,
13
13
  name,
14
- onKeyDown,
14
+ tabIndex: -1,
15
15
  'data-qa': `tree-selector-input tree-selector-input-${id}`,
16
16
  };
17
17
  return singleChoice ? jsx(Radio, { ...inputProps }) : jsx(Checkbox, { ...inputProps, indeterminate: indeterminate });
package/Action.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Action.js","sources":["../src/Action.tsx"],"sourcesContent":["import { ChangeEventHandler, FC, useCallback, memo, KeyboardEventHandler } from 'react';\n\nimport { Checkbox, Radio } from '@hh.ru/magritte-ui-checkbox-radio';\nimport { TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\ninterface ActionProps {\n singleChoice?: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n id: TreeModel['id'];\n name?: string;\n selected: boolean;\n indeterminate?: boolean;\n onKeyDown?: KeyboardEventHandler;\n}\n\nexport const Action: FC<ActionProps> = memo(\n ({ id, name, singleChoice, indeterminate, selected, onChange, onKeyDown }) => {\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n onChange(id, event.target.checked);\n },\n [id, onChange]\n );\n\n const inputProps = {\n checked: selected,\n onChange: handleChange,\n name,\n onKeyDown,\n 'data-qa': `tree-selector-input tree-selector-input-${id}`,\n };\n\n return singleChoice ? <Radio {...inputProps} /> : <Checkbox {...inputProps} indeterminate={indeterminate} />;\n }\n);\n\nAction.displayName = 'TreeSelectorAction';\n"],"names":["_jsx"],"mappings":";;;;MAea,MAAM,GAAoB,IAAI,CACvC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAI;AACzE,IAAA,MAAM,YAAY,GAAyC,WAAW,CAClE,CAAC,KAAK,KAAI;QACN,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACvC,KAAC,EACD,CAAC,EAAE,EAAE,QAAQ,CAAC,CACjB,CAAC;AAEF,IAAA,MAAM,UAAU,GAAG;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,YAAY;QACtB,IAAI;QACJ,SAAS;QACT,SAAS,EAAE,CAA2C,wCAAA,EAAA,EAAE,CAAE,CAAA;KAC7D,CAAC;IAEF,OAAO,YAAY,GAAGA,IAAC,KAAK,EAAA,EAAA,GAAK,UAAU,EAAI,CAAA,GAAGA,GAAA,CAAC,QAAQ,EAAK,EAAA,GAAA,UAAU,EAAE,aAAa,EAAE,aAAa,EAAA,CAAI,CAAC;AACjH,CAAC,EACH;AAEF,MAAM,CAAC,WAAW,GAAG,oBAAoB;;;;"}
1
+ {"version":3,"file":"Action.js","sources":["../src/Action.tsx"],"sourcesContent":["import { ChangeEventHandler, FC, useCallback, memo } from 'react';\n\nimport { Checkbox, Radio } from '@hh.ru/magritte-ui-checkbox-radio';\nimport { TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\ninterface ActionProps {\n singleChoice?: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n id: TreeModel['id'];\n name?: string;\n selected: boolean;\n indeterminate?: boolean;\n}\n\nexport const Action: FC<ActionProps> = memo(({ id, name, singleChoice, indeterminate, selected, onChange }) => {\n const handleChange: ChangeEventHandler<HTMLInputElement> = useCallback(\n (event) => {\n onChange(id, event.target.checked);\n },\n [id, onChange]\n );\n\n const inputProps = {\n checked: selected,\n onChange: handleChange,\n name,\n tabIndex: -1,\n 'data-qa': `tree-selector-input tree-selector-input-${id}`,\n };\n\n return singleChoice ? <Radio {...inputProps} /> : <Checkbox {...inputProps} indeterminate={indeterminate} />;\n});\n\nAction.displayName = 'TreeSelectorAction';\n"],"names":["_jsx"],"mappings":";;;;MAca,MAAM,GAAoB,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,aAAa,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAI;AAC1G,IAAA,MAAM,YAAY,GAAyC,WAAW,CAClE,CAAC,KAAK,KAAI;QACN,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AACvC,KAAC,EACD,CAAC,EAAE,EAAE,QAAQ,CAAC,CACjB,CAAC;AAEF,IAAA,MAAM,UAAU,GAAG;AACf,QAAA,OAAO,EAAE,QAAQ;AACjB,QAAA,QAAQ,EAAE,YAAY;QACtB,IAAI;QACJ,QAAQ,EAAE,CAAC,CAAC;QACZ,SAAS,EAAE,CAA2C,wCAAA,EAAA,EAAE,CAAE,CAAA;KAC7D,CAAC;IAEF,OAAO,YAAY,GAAGA,IAAC,KAAK,EAAA,EAAA,GAAK,UAAU,EAAI,CAAA,GAAGA,GAAA,CAAC,QAAQ,EAAK,EAAA,GAAA,UAAU,EAAE,aAAa,EAAE,aAAa,EAAA,CAAI,CAAC;AACjH,CAAC,EAAE;AAEH,MAAM,CAAC,WAAW,GAAG,oBAAoB;;;;"}
package/Item.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { PropsWithChildren, ReactElement } from 'react';
1
+ import { PropsWithChildren, ReactElement, KeyboardEventHandler, AriaAttributes } from 'react';
2
2
  import TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';
3
3
  import { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';
4
4
  import { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';
@@ -18,6 +18,9 @@ interface ItemProps<Additional extends AdditionalDefault> extends PropsWithChild
18
18
  onChange: (id: string, isSelected: boolean) => void;
19
19
  renderItemForDesktop?: RenderItem<Additional>;
20
20
  cache: Record<string, number>;
21
+ isTabbed: boolean;
22
+ focusedId?: string;
23
+ onKeyDown?: KeyboardEventHandler;
21
24
  }
22
- export declare const Item: <Additional extends AdditionalDefault>(props: ItemProps<Additional>) => ReactElement;
25
+ export declare const Item: <Additional extends AdditionalDefault>(props: ItemProps<Additional> & AriaAttributes) => ReactElement;
23
26
  export {};
package/Item.js CHANGED
@@ -3,14 +3,13 @@ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { memo, useMemo } from 'react';
4
4
  import classnames from 'classnames';
5
5
  import { ItemContent } from './ItemContent.js';
6
- import '@hh.ru/magritte-common-keyboard';
7
6
  import '@hh.ru/magritte-ui-icon/icon';
8
7
  import './Action.js';
9
8
  import '@hh.ru/magritte-ui-checkbox-radio';
10
9
  import './TreeSelectorItemBase.js';
11
10
  import '@hh.ru/magritte-ui-cell';
12
11
  import '@hh.ru/magritte-ui-typography';
13
- import './tree-selector-item-Ch4gUsnP.js';
12
+ import './tree-selector-item-xbLyWy2t.js';
14
13
 
15
14
  const ONE_BOX_MARGIN = 36;
16
15
  const getMargin = (allBoxesCount, hasShift, hasIndent) => {
@@ -32,7 +31,7 @@ const getMargin = (allBoxesCount, hasShift, hasIndent) => {
32
31
  }
33
32
  return margin;
34
33
  };
35
- const ItemComponent = ({ collection, item, parentId, isExpanded, isSelected, isIndeterminate, isDisabled, leavesOnly, singleChoice, isSearch, checkSelectable, onExpansion, onChange, renderItemForDesktop, cache, children, }) => {
34
+ const ItemComponent = ({ collection, item, parentId, isExpanded, isSelected, isIndeterminate, isDisabled, leavesOnly, singleChoice, isSearch, checkSelectable, onExpansion, onChange, renderItemForDesktop, cache, isTabbed, children, focusedId, ...ariaProps }) => {
36
35
  const modelsOnLevel = useMemo(() => (parentId ? collection.getChildren(parentId) : collection.getTopLevel()), [parentId, collection]);
37
36
  const hasLetterOnLevel = useMemo(() => {
38
37
  return !isSearch && modelsOnLevel.some((model) => model.additional?.char);
@@ -67,7 +66,7 @@ const ItemComponent = ({ collection, item, parentId, isExpanded, isSelected, isI
67
66
  return (jsxs("div", { style: { paddingLeft: margin }, "data-qa": classnames('tree-selector-item', `tree-selector-item-${item.id}`, {
68
67
  'tree-selector-item-expanded': isExpanded,
69
68
  [`tree-selector-child-${parentId}`]: parentId,
70
- }), children: [jsx(ItemContent, { item: item, parentId: parentId, hasChildren: hasChildren, hasAction: !!hasAction, letter: hasLetter ? item.additional?.char : undefined, isExpanded: isExpanded, onExpansion: onExpansion, isSelected: isSelected, onChange: onChange, singleChoice: singleChoice, isIndeterminate: isIndeterminate, isDisabled: isDisabled, hasLetterOnLevel: hasLetterOnLevel, hasDot: hasDot, maxControlsOnLevel: maxControlsOnLevel, isSearch: isSearch, renderItemForDesktop: renderItemForDesktop }), children] }));
69
+ }), children: [jsx(ItemContent, { item: item, parentId: parentId, hasChildren: hasChildren, hasAction: !!hasAction, letter: hasLetter ? item.additional?.char : undefined, isExpanded: isExpanded, onExpansion: onExpansion, isSelected: isSelected, onChange: onChange, singleChoice: singleChoice, isIndeterminate: isIndeterminate, isDisabled: isDisabled, hasLetterOnLevel: hasLetterOnLevel, hasDot: hasDot, maxControlsOnLevel: maxControlsOnLevel, isSearch: isSearch, renderItemForDesktop: renderItemForDesktop, "aria-expanded": hasChildren ? isExpanded : undefined, "aria-selected": hasAction ? isSelected : undefined, ...ariaProps, tabIndex: isTabbed ? 0 : -1, focusedId: focusedId }), children] }));
71
70
  };
72
71
  const Item = memo(ItemComponent);
73
72
 
package/Item.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Item.js","sources":["../src/Item.tsx"],"sourcesContent":["import { PropsWithChildren, ReactElement, useMemo, memo } from 'react';\nimport classnames from 'classnames';\n\nimport { ItemContent } from '@hh.ru/magritte-ui-tree-selector/ItemContent';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nconst ONE_BOX_MARGIN = 36;\n\nconst getMargin = (allBoxesCount: number, hasShift: boolean, hasIndent: boolean): number => {\n let margin = 0;\n if (allBoxesCount === 2) {\n margin = ONE_BOX_MARGIN * 2;\n } else if (allBoxesCount === 3) {\n margin = ONE_BOX_MARGIN * 3;\n } else {\n margin = ONE_BOX_MARGIN;\n }\n if (hasIndent) {\n return margin + ONE_BOX_MARGIN;\n }\n\n if (hasShift) {\n return margin - ONE_BOX_MARGIN;\n }\n\n return margin;\n};\n\ninterface ItemProps<Additional extends AdditionalDefault> extends PropsWithChildren {\n collection: TreeCollection<Additional>;\n parentId?: TreeModel<Additional>['id'];\n item: TreeModel<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n singleChoice?: boolean;\n isIndeterminate: boolean;\n isSearch: boolean;\n onExpansion: (id: string) => void;\n onChange: (id: string, isSelected: boolean) => void;\n renderItemForDesktop?: RenderItem<Additional>;\n cache: Record<string, number>;\n}\n\nconst ItemComponent = <Additional extends AdditionalDefault>({\n collection,\n item,\n parentId,\n isExpanded,\n isSelected,\n isIndeterminate,\n isDisabled,\n leavesOnly,\n singleChoice,\n isSearch,\n checkSelectable,\n onExpansion,\n onChange,\n renderItemForDesktop,\n cache,\n children,\n}: ItemProps<Additional>): ReactElement => {\n const modelsOnLevel = useMemo(\n () => (parentId ? collection.getChildren(parentId) : collection.getTopLevel()),\n [parentId, collection]\n );\n\n const hasLetterOnLevel = useMemo(() => {\n return !isSearch && modelsOnLevel.some((model) => model.additional?.char);\n }, [modelsOnLevel, isSearch]);\n\n // максимальное кол-во контролов на уровне, максимум может быть 2 - шеврон + чекбокс/радио\n const maxControlsOnLevel = useMemo(() => {\n return modelsOnLevel.reduce((currentMax, model) => {\n const hasChildren = collection.hasChildren(model.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(model.id, collection);\n const actionCount = +hasChildren + +!!hasAction;\n return Math.max(currentMax, actionCount);\n }, 0);\n }, [modelsOnLevel, checkSelectable, leavesOnly, collection]);\n\n const hasChildren = collection.hasChildren(item.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(item.id, collection);\n const hasLetter = item.additional?.char && !isSearch;\n const realControlsCount = +hasChildren + +!!hasAction;\n\n // точка заменяет недостающий контрол, если их суммарное кол-во на уровне больше суммарного значения на текущем уровне\n const hasDot = realControlsCount < maxControlsOnLevel && (hasAction || hasChildren);\n const hasParentAction = parentId ? !leavesOnly && checkSelectable?.(parentId, collection) : false;\n\n const allBoxesCount = +hasLetterOnLevel + maxControlsOnLevel;\n\n const hasShift =\n allBoxesCount > 1 &&\n parentId &&\n ((hasParentAction && (hasLetterOnLevel || hasChildren || hasDot)) || (!hasParentAction && hasLetterOnLevel));\n\n const hasIndent = allBoxesCount === 0;\n\n useMemo(() => {\n cache[item.id] = getMargin(allBoxesCount, !!hasShift, hasIndent) + (parentId ? cache[parentId] : 0);\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, [item.id, parentId]);\n\n let margin = parentId ? cache[parentId] : 0;\n\n margin = margin + (hasShift ? -ONE_BOX_MARGIN : 0) + (hasIndent ? ONE_BOX_MARGIN : 0);\n\n return (\n <div\n style={{ paddingLeft: margin }}\n data-qa={classnames('tree-selector-item', `tree-selector-item-${item.id}`, {\n 'tree-selector-item-expanded': isExpanded,\n [`tree-selector-child-${parentId}`]: parentId,\n })}\n >\n <ItemContent\n item={item}\n parentId={parentId}\n hasChildren={hasChildren}\n hasAction={!!hasAction}\n letter={hasLetter ? item.additional?.char : undefined}\n isExpanded={isExpanded}\n onExpansion={onExpansion}\n isSelected={isSelected}\n onChange={onChange}\n singleChoice={singleChoice}\n isIndeterminate={isIndeterminate}\n isDisabled={isDisabled}\n hasLetterOnLevel={hasLetterOnLevel}\n hasDot={hasDot}\n maxControlsOnLevel={maxControlsOnLevel}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n />\n\n {children}\n </div>\n );\n};\n\nexport const Item = memo(ItemComponent) as <Additional extends AdditionalDefault>(\n props: ItemProps<Additional>\n) => ReactElement;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"Item.js","sources":["../src/Item.tsx"],"sourcesContent":["import { PropsWithChildren, ReactElement, useMemo, memo, KeyboardEventHandler, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { ItemContent } from '@hh.ru/magritte-ui-tree-selector/ItemContent';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nconst ONE_BOX_MARGIN = 36;\n\nconst getMargin = (allBoxesCount: number, hasShift: boolean, hasIndent: boolean): number => {\n let margin = 0;\n if (allBoxesCount === 2) {\n margin = ONE_BOX_MARGIN * 2;\n } else if (allBoxesCount === 3) {\n margin = ONE_BOX_MARGIN * 3;\n } else {\n margin = ONE_BOX_MARGIN;\n }\n if (hasIndent) {\n return margin + ONE_BOX_MARGIN;\n }\n\n if (hasShift) {\n return margin - ONE_BOX_MARGIN;\n }\n\n return margin;\n};\n\ninterface ItemProps<Additional extends AdditionalDefault> extends PropsWithChildren {\n collection: TreeCollection<Additional>;\n parentId?: TreeModel<Additional>['id'];\n item: TreeModel<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n singleChoice?: boolean;\n isIndeterminate: boolean;\n isSearch: boolean;\n onExpansion: (id: string) => void;\n onChange: (id: string, isSelected: boolean) => void;\n renderItemForDesktop?: RenderItem<Additional>;\n cache: Record<string, number>;\n isTabbed: boolean;\n focusedId?: string;\n onKeyDown?: KeyboardEventHandler;\n}\n\nconst ItemComponent = <Additional extends AdditionalDefault>({\n collection,\n item,\n parentId,\n isExpanded,\n isSelected,\n isIndeterminate,\n isDisabled,\n leavesOnly,\n singleChoice,\n isSearch,\n checkSelectable,\n onExpansion,\n onChange,\n renderItemForDesktop,\n cache,\n isTabbed,\n children,\n focusedId,\n ...ariaProps\n}: ItemProps<Additional> & AriaAttributes): ReactElement => {\n const modelsOnLevel = useMemo(\n () => (parentId ? collection.getChildren(parentId) : collection.getTopLevel()),\n [parentId, collection]\n );\n\n const hasLetterOnLevel = useMemo(() => {\n return !isSearch && modelsOnLevel.some((model) => model.additional?.char);\n }, [modelsOnLevel, isSearch]);\n\n // максимальное кол-во контролов на уровне, максимум может быть 2 - шеврон + чекбокс/радио\n const maxControlsOnLevel = useMemo(() => {\n return modelsOnLevel.reduce((currentMax, model) => {\n const hasChildren = collection.hasChildren(model.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(model.id, collection);\n const actionCount = +hasChildren + +!!hasAction;\n return Math.max(currentMax, actionCount);\n }, 0);\n }, [modelsOnLevel, checkSelectable, leavesOnly, collection]);\n\n const hasChildren = collection.hasChildren(item.id);\n const hasAction = !(leavesOnly && hasChildren) && checkSelectable?.(item.id, collection);\n const hasLetter = item.additional?.char && !isSearch;\n const realControlsCount = +hasChildren + +!!hasAction;\n\n // точка заменяет недостающий контрол, если их суммарное кол-во на уровне больше суммарного значения на текущем уровне\n const hasDot = realControlsCount < maxControlsOnLevel && (hasAction || hasChildren);\n const hasParentAction = parentId ? !leavesOnly && checkSelectable?.(parentId, collection) : false;\n\n const allBoxesCount = +hasLetterOnLevel + maxControlsOnLevel;\n\n const hasShift =\n allBoxesCount > 1 &&\n parentId &&\n ((hasParentAction && (hasLetterOnLevel || hasChildren || hasDot)) || (!hasParentAction && hasLetterOnLevel));\n\n const hasIndent = allBoxesCount === 0;\n\n useMemo(() => {\n cache[item.id] = getMargin(allBoxesCount, !!hasShift, hasIndent) + (parentId ? cache[parentId] : 0);\n // eslint-disable-next-line disable-autofix/react-hooks/exhaustive-deps\n }, [item.id, parentId]);\n\n let margin = parentId ? cache[parentId] : 0;\n\n margin = margin + (hasShift ? -ONE_BOX_MARGIN : 0) + (hasIndent ? ONE_BOX_MARGIN : 0);\n\n return (\n <div\n style={{ paddingLeft: margin }}\n data-qa={classnames('tree-selector-item', `tree-selector-item-${item.id}`, {\n 'tree-selector-item-expanded': isExpanded,\n [`tree-selector-child-${parentId}`]: parentId,\n })}\n >\n <ItemContent\n item={item}\n parentId={parentId}\n hasChildren={hasChildren}\n hasAction={!!hasAction}\n letter={hasLetter ? item.additional?.char : undefined}\n isExpanded={isExpanded}\n onExpansion={onExpansion}\n isSelected={isSelected}\n onChange={onChange}\n singleChoice={singleChoice}\n isIndeterminate={isIndeterminate}\n isDisabled={isDisabled}\n hasLetterOnLevel={hasLetterOnLevel}\n hasDot={hasDot}\n maxControlsOnLevel={maxControlsOnLevel}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n aria-expanded={hasChildren ? isExpanded : undefined}\n aria-selected={hasAction ? isSelected : undefined}\n {...ariaProps}\n tabIndex={isTabbed ? 0 : -1}\n focusedId={focusedId}\n />\n\n {children}\n </div>\n );\n};\n\nexport const Item = memo(ItemComponent) as <Additional extends AdditionalDefault>(\n props: ItemProps<Additional> & AriaAttributes\n) => ReactElement;\n"],"names":["_jsxs","_jsx"],"mappings":"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"}
package/ItemContent.d.ts CHANGED
@@ -19,6 +19,8 @@ interface ItemContent<Additional extends AdditionalDefault> {
19
19
  maxControlsOnLevel: number;
20
20
  renderItemForDesktop?: RenderItem<Additional>;
21
21
  isSearch: boolean;
22
+ tabIndex?: number;
23
+ focusedId?: string;
22
24
  }
23
25
  export declare const ItemContent: <Additional extends AdditionalDefault>(props: ItemContent<Additional>) => ReactElement;
24
26
  export {};
package/ItemContent.js CHANGED
@@ -1,35 +1,27 @@
1
1
  import './index.css';
2
2
  import { jsx, jsxs } from 'react/jsx-runtime';
3
- import { memo, useCallback } from 'react';
3
+ import { memo, useCallback, useRef, useEffect } from 'react';
4
4
  import classnames from 'classnames';
5
- import { keyboardMatch, keyboardKeys } from '@hh.ru/magritte-common-keyboard';
6
5
  import { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';
7
6
  import { Action } from './Action.js';
8
7
  import { TreeSelectorItemBase } from './TreeSelectorItemBase.js';
9
8
  import { Text } from '@hh.ru/magritte-ui-typography';
10
- import { s as styles } from './tree-selector-item-Ch4gUsnP.js';
9
+ import { s as styles } from './tree-selector-item-xbLyWy2t.js';
11
10
  import '@hh.ru/magritte-ui-checkbox-radio';
12
11
  import '@hh.ru/magritte-ui-cell';
13
12
 
14
- const ItemContentComponent = ({ item, parentId, hasAction, hasChildren, letter, isExpanded, isDisabled, onExpansion, hasLetterOnLevel, isSelected, onChange, isIndeterminate, singleChoice, hasDot, maxControlsOnLevel, isSearch, renderItemForDesktop = TreeSelectorItemBase, }) => {
13
+ const ItemContentComponent = ({ item, parentId, hasAction, hasChildren, letter, isExpanded, isDisabled, onExpansion, hasLetterOnLevel, isSelected, onChange, isIndeterminate, singleChoice, hasDot, maxControlsOnLevel, isSearch, renderItemForDesktop = TreeSelectorItemBase, focusedId, ...ariaProps }) => {
15
14
  const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);
16
15
  const currentActionCount = +hasDot + +hasAction + +hasChildren;
17
16
  const neededSpacesCount = maxControlsOnLevel - currentActionCount;
18
- const handleExpandableKeyDown = useCallback((event) => {
19
- if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowLeft)) {
20
- isExpanded && onExpansion(item.id);
21
- event.preventDefault();
22
- return;
17
+ const ref = useRef(null);
18
+ useEffect(() => {
19
+ if (focusedId === item.id && ref.current) {
20
+ ref.current.focus();
23
21
  }
24
- if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowRight)) {
25
- !isExpanded && onExpansion(item.id);
26
- event.preventDefault();
27
- }
28
- }, [isExpanded, onExpansion, item.id]);
29
- const input = hasAction ? (jsx(Action, { selected: isSelected, onChange: onChange, id: item.id, onKeyDown: handleExpandableKeyDown, indeterminate: isIndeterminate, singleChoice: singleChoice, name: `tree-selector-item-${parentId || 'top'}-${item.id}` })) : undefined;
30
- return (jsxs("div", { className: classnames(styles.wrapper, {
31
- [styles.wrapperActive]: hasChildren || hasAction,
32
- }), onClick: hasChildren && !hasAction ? handleExpandableClick : undefined, children: [(letter || hasLetterOnLevel) && (jsx("div", { className: styles.letter, children: letter && (jsx(Text, { typography: "subtitle-1-semibold", style: "secondary", Element: "span", children: letter })) })), hasDot && (jsx("div", { className: styles.icon, children: jsx(DotFilledSize24, { initialColor: "tertiary" }) })), [...Array(neededSpacesCount).keys()].map((_, i) => (jsx("div", { className: styles.space }, i))), hasChildren && (jsx("div", { className: classnames(styles.icon, styles.iconActive, {
22
+ }, [focusedId, item.id]);
23
+ const input = hasAction ? (jsx(Action, { selected: isSelected, onChange: onChange, id: item.id, indeterminate: isIndeterminate, singleChoice: singleChoice, name: `tree-selector-item-${parentId || 'top'}-${item.id}` })) : undefined;
24
+ return (jsxs("div", { className: classnames(styles.wrapper, { [styles.wrapperActive]: hasChildren || hasAction }), onClick: hasChildren && !hasAction ? handleExpandableClick : undefined, role: "treeitem", ref: ref, ...ariaProps, children: [(letter || hasLetterOnLevel) && (jsx("div", { className: styles.letter, children: letter && (jsx(Text, { typography: "subtitle-1-semibold", style: "secondary", Element: "span", children: letter })) })), hasDot && (jsx("div", { className: styles.icon, children: jsx(DotFilledSize24, { initialColor: "tertiary" }) })), [...Array(neededSpacesCount).keys()].map((_, i) => (jsx("div", { className: styles.space }, i))), hasChildren && (jsx("div", { className: classnames(styles.icon, styles.iconActive, {
33
25
  [styles.iconUp]: isExpanded,
34
26
  }), "data-qa": `tree-selector-chevron tree-selector-chevron-${item.id}`, onClick: hasAction ? handleExpandableClick : undefined, children: jsx(ChevronRightOutlinedSize24, { initialColor: "tertiary" }) })), renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })] }));
35
27
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ItemContent.js","sources":["../src/ItemContent.tsx"],"sourcesContent":["import { ReactElement, useCallback, memo, KeyboardEventHandler } from 'react';\nimport classnames from 'classnames';\n\nimport { keyboardKeys, keyboardMatch } from '@hh.ru/magritte-common-keyboard';\nimport { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { Action } from '@hh.ru/magritte-ui-tree-selector/Action';\nimport { TreeSelectorItemBase } from '@hh.ru/magritte-ui-tree-selector/TreeSelectorItemBase';\nimport { AdditionalDefault, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemContent<Additional extends AdditionalDefault> {\n item: TreeModel<Additional>;\n parentId?: TreeModel<Additional>['id'];\n hasChildren: boolean;\n hasAction: boolean;\n letter?: string;\n onExpansion: (id: string) => void;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n isIndeterminate: boolean;\n singleChoice?: boolean;\n hasLetterOnLevel: boolean;\n hasDot: boolean;\n maxControlsOnLevel: number;\n renderItemForDesktop?: RenderItem<Additional>;\n isSearch: boolean;\n}\n\nconst ItemContentComponent = <Additional extends AdditionalDefault>({\n item,\n parentId,\n hasAction,\n hasChildren,\n letter,\n isExpanded,\n isDisabled,\n onExpansion,\n hasLetterOnLevel,\n isSelected,\n onChange,\n isIndeterminate,\n singleChoice,\n hasDot,\n maxControlsOnLevel,\n isSearch,\n renderItemForDesktop = TreeSelectorItemBase,\n}: ItemContent<Additional>): ReactElement => {\n const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);\n const currentActionCount = +hasDot + +hasAction + +hasChildren;\n const neededSpacesCount = maxControlsOnLevel - currentActionCount;\n\n const handleExpandableKeyDown = useCallback<KeyboardEventHandler>(\n (event) => {\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowLeft)) {\n isExpanded && onExpansion(item.id);\n event.preventDefault();\n return;\n }\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowRight)) {\n !isExpanded && onExpansion(item.id);\n event.preventDefault();\n }\n },\n [isExpanded, onExpansion, item.id]\n );\n\n const input = hasAction ? (\n <Action\n selected={isSelected}\n onChange={onChange}\n id={item.id}\n onKeyDown={handleExpandableKeyDown}\n indeterminate={isIndeterminate}\n singleChoice={singleChoice}\n name={`tree-selector-item-${parentId || 'top'}-${item.id}`}\n />\n ) : undefined;\n\n return (\n <div\n className={classnames(styles.wrapper, {\n [styles.wrapperActive]: hasChildren || hasAction,\n })}\n onClick={hasChildren && !hasAction ? handleExpandableClick : undefined}\n >\n {(letter || hasLetterOnLevel) && (\n <div className={styles.letter}>\n {letter && (\n <Text typography=\"subtitle-1-semibold\" style=\"secondary\" Element=\"span\">\n {letter}\n </Text>\n )}\n </div>\n )}\n {hasDot && (\n <div className={styles.icon}>\n <DotFilledSize24 initialColor=\"tertiary\" />\n </div>\n )}\n\n {[...Array(neededSpacesCount).keys()].map((_, i) => (\n <div key={i} className={styles.space} />\n ))}\n\n {hasChildren && (\n <div\n className={classnames(styles.icon, styles.iconActive, {\n [styles.iconUp]: isExpanded,\n })}\n data-qa={`tree-selector-chevron tree-selector-chevron-${item.id}`}\n onClick={hasAction ? handleExpandableClick : undefined}\n >\n <ChevronRightOutlinedSize24 initialColor=\"tertiary\" />\n </div>\n )}\n {renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })}\n </div>\n );\n};\n\nexport const ItemContent = memo(ItemContentComponent) as <Additional extends AdditionalDefault>(\n props: ItemContent<Additional>\n) => ReactElement;\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"ItemContent.js","sources":["../src/ItemContent.tsx"],"sourcesContent":["import { ReactElement, useCallback, memo, useRef, useEffect, AriaAttributes } from 'react';\nimport classnames from 'classnames';\n\nimport { DotFilledSize24, ChevronRightOutlinedSize24 } from '@hh.ru/magritte-ui-icon/icon';\nimport { Action } from '@hh.ru/magritte-ui-tree-selector/Action';\nimport { TreeSelectorItemBase } from '@hh.ru/magritte-ui-tree-selector/TreeSelectorItemBase';\nimport { AdditionalDefault, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\nimport { Text } from '@hh.ru/magritte-ui-typography';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemContent<Additional extends AdditionalDefault> {\n item: TreeModel<Additional>;\n parentId?: TreeModel<Additional>['id'];\n hasChildren: boolean;\n hasAction: boolean;\n letter?: string;\n onExpansion: (id: string) => void;\n isExpanded: boolean;\n isSelected: boolean;\n isDisabled: boolean;\n onChange: (id: string, isSelected: boolean) => void;\n isIndeterminate: boolean;\n singleChoice?: boolean;\n hasLetterOnLevel: boolean;\n hasDot: boolean;\n maxControlsOnLevel: number;\n renderItemForDesktop?: RenderItem<Additional>;\n isSearch: boolean;\n tabIndex?: number;\n focusedId?: string;\n}\n\nconst ItemContentComponent = <Additional extends AdditionalDefault>({\n item,\n parentId,\n hasAction,\n hasChildren,\n letter,\n isExpanded,\n isDisabled,\n onExpansion,\n hasLetterOnLevel,\n isSelected,\n onChange,\n isIndeterminate,\n singleChoice,\n hasDot,\n maxControlsOnLevel,\n isSearch,\n renderItemForDesktop = TreeSelectorItemBase,\n focusedId,\n ...ariaProps\n}: ItemContent<Additional> & AriaAttributes): ReactElement => {\n const handleExpandableClick = useCallback(() => onExpansion && onExpansion(item.id), [item.id, onExpansion]);\n const currentActionCount = +hasDot + +hasAction + +hasChildren;\n const neededSpacesCount = maxControlsOnLevel - currentActionCount;\n const ref = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (focusedId === item.id && ref.current) {\n ref.current.focus();\n }\n }, [focusedId, item.id]);\n\n const input = hasAction ? (\n <Action\n selected={isSelected}\n onChange={onChange}\n id={item.id}\n indeterminate={isIndeterminate}\n singleChoice={singleChoice}\n name={`tree-selector-item-${parentId || 'top'}-${item.id}`}\n />\n ) : undefined;\n\n return (\n <div\n className={classnames(styles.wrapper, { [styles.wrapperActive]: hasChildren || hasAction })}\n onClick={hasChildren && !hasAction ? handleExpandableClick : undefined}\n role=\"treeitem\"\n ref={ref}\n {...ariaProps}\n >\n {(letter || hasLetterOnLevel) && (\n <div className={styles.letter}>\n {letter && (\n <Text typography=\"subtitle-1-semibold\" style=\"secondary\" Element=\"span\">\n {letter}\n </Text>\n )}\n </div>\n )}\n {hasDot && (\n <div className={styles.icon}>\n <DotFilledSize24 initialColor=\"tertiary\" />\n </div>\n )}\n\n {[...Array(neededSpacesCount).keys()].map((_, i) => (\n <div key={i} className={styles.space} />\n ))}\n\n {hasChildren && (\n <div\n className={classnames(styles.icon, styles.iconActive, {\n [styles.iconUp]: isExpanded,\n })}\n data-qa={`tree-selector-chevron tree-selector-chevron-${item.id}`}\n onClick={hasAction ? handleExpandableClick : undefined}\n >\n <ChevronRightOutlinedSize24 initialColor=\"tertiary\" />\n </div>\n )}\n {renderItemForDesktop({ disabled: isDisabled, input, item, isSearch, isParent: hasChildren })}\n </div>\n );\n};\n\nexport const ItemContent = memo(ItemContentComponent) as <Additional extends AdditionalDefault>(\n props: ItemContent<Additional>\n) => ReactElement;\n"],"names":["_jsx","_jsxs"],"mappings":";;;;;;;;;;;AAkCA,MAAM,oBAAoB,GAAG,CAAuC,EAChE,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,WAAW,EACX,MAAM,EACN,UAAU,EACV,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,UAAU,EACV,QAAQ,EACR,eAAe,EACf,YAAY,EACZ,MAAM,EACN,kBAAkB,EAClB,QAAQ,EACR,oBAAoB,GAAG,oBAAoB,EAC3C,SAAS,EACT,GAAG,SAAS,EAC2B,KAAkB;IACzD,MAAM,qBAAqB,GAAG,WAAW,CAAC,MAAM,WAAW,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC,CAAC;IAC7G,MAAM,kBAAkB,GAAG,CAAC,MAAM,GAAG,CAAC,SAAS,GAAG,CAAC,WAAW,CAAC;AAC/D,IAAA,MAAM,iBAAiB,GAAG,kBAAkB,GAAG,kBAAkB,CAAC;AAClE,IAAA,MAAM,GAAG,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEzC,SAAS,CAAC,MAAK;QACX,IAAI,SAAS,KAAK,IAAI,CAAC,EAAE,IAAI,GAAG,CAAC,OAAO,EAAE;AACtC,YAAA,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;SACvB;KACJ,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;IAEzB,MAAM,KAAK,GAAG,SAAS,IACnBA,GAAC,CAAA,MAAM,EACH,EAAA,QAAQ,EAAE,UAAU,EACpB,QAAQ,EAAE,QAAQ,EAClB,EAAE,EAAE,IAAI,CAAC,EAAE,EACX,aAAa,EAAE,eAAe,EAC9B,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,CAAA,mBAAA,EAAsB,QAAQ,IAAI,KAAK,CAAI,CAAA,EAAA,IAAI,CAAC,EAAE,CAAE,CAAA,EAAA,CAC5D,IACF,SAAS,CAAC;AAEd,IAAA,QACIC,IAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,aAAa,GAAG,WAAW,IAAI,SAAS,EAAE,CAAC,EAC3F,OAAO,EAAE,WAAW,IAAI,CAAC,SAAS,GAAG,qBAAqB,GAAG,SAAS,EACtE,IAAI,EAAC,UAAU,EACf,GAAG,EAAE,GAAG,EACJ,GAAA,SAAS,EAEZ,QAAA,EAAA,CAAA,CAAC,MAAM,IAAI,gBAAgB,MACxBD,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,MAAM,EAAA,QAAA,EACxB,MAAM,KACHA,GAAC,CAAA,IAAI,EAAC,EAAA,UAAU,EAAC,qBAAqB,EAAC,KAAK,EAAC,WAAW,EAAC,OAAO,EAAC,MAAM,EAClE,QAAA,EAAA,MAAM,EACJ,CAAA,CACV,GACC,CACT,EACA,MAAM,KACHA,GAAK,CAAA,KAAA,EAAA,EAAA,SAAS,EAAE,MAAM,CAAC,IAAI,EAAA,QAAA,EACvBA,GAAC,CAAA,eAAe,IAAC,YAAY,EAAC,UAAU,EAAA,CAAG,GACzC,CACT,EAEA,CAAC,GAAG,KAAK,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAC3CA,GAAA,CAAA,KAAA,EAAA,EAAa,SAAS,EAAE,MAAM,CAAC,KAAK,IAA1B,CAAC,CAA6B,CAC3C,CAAC,EAED,WAAW,KACRA,GAAA,CAAA,KAAA,EAAA,EACI,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE;AAClD,oBAAA,CAAC,MAAM,CAAC,MAAM,GAAG,UAAU;iBAC9B,CAAC,EAAA,SAAA,EACO,+CAA+C,IAAI,CAAC,EAAE,CAAE,CAAA,EACjE,OAAO,EAAE,SAAS,GAAG,qBAAqB,GAAG,SAAS,EAEtD,QAAA,EAAAA,GAAA,CAAC,0BAA0B,EAAA,EAAC,YAAY,EAAC,UAAU,EAAG,CAAA,EAAA,CACpD,CACT,EACA,oBAAoB,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC,CAC3F,EAAA,CAAA,EACR;AACN,CAAC,CAAC;MAEW,WAAW,GAAG,IAAI,CAAC,oBAAoB;;;;"}
package/ItemsList.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import './index.css';
2
2
  import { jsx } from 'react/jsx-runtime';
3
- import { useRef, useMemo, useCallback, useEffect } from 'react';
3
+ import { useRef, useMemo, useState, useCallback, useEffect } from 'react';
4
4
  import { useVirtualizer } from '@tanstack/react-virtual';
5
+ import { keyboardMatch, keyboardKeys } from '@hh.ru/magritte-common-keyboard';
5
6
  import { Item } from './Item.js';
6
- import { s as styles } from './tree-selector-item-Ch4gUsnP.js';
7
+ import { s as styles } from './tree-selector-item-xbLyWy2t.js';
7
8
  import 'classnames';
8
9
  import './ItemContent.js';
9
- import '@hh.ru/magritte-common-keyboard';
10
10
  import '@hh.ru/magritte-ui-icon/icon';
11
11
  import './Action.js';
12
12
  import '@hh.ru/magritte-ui-checkbox-radio';
@@ -20,6 +20,57 @@ const getNewExpanded = (oldExpanded, newExpanded) => {
20
20
  }
21
21
  return newExpanded.filter((i) => !oldExpanded.includes(i));
22
22
  };
23
+ const getKeyDownHandler = ({ id, nextItemId, prevItemId, parentId, parentIndex, isExpanded, isSelected, onExpansion, setFocusedId, hasChildren, collection, virtualizer, onChange, firstId, lastId, height, }) => {
24
+ return (event) => {
25
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowLeft)) {
26
+ event.preventDefault();
27
+ if (isExpanded) {
28
+ onExpansion(id);
29
+ }
30
+ else if (parentId) {
31
+ virtualizer.scrollToIndex(parentIndex);
32
+ setFocusedId(parentId);
33
+ }
34
+ return;
35
+ }
36
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowRight)) {
37
+ event.preventDefault();
38
+ if (!isExpanded && hasChildren) {
39
+ onExpansion(id);
40
+ }
41
+ else if (hasChildren) {
42
+ const firstChild = collection.getChildren(id);
43
+ setFocusedId(firstChild[0].id);
44
+ }
45
+ return;
46
+ }
47
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowDown) && nextItemId) {
48
+ event.preventDefault();
49
+ setFocusedId(nextItemId);
50
+ return;
51
+ }
52
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowUp) && prevItemId) {
53
+ event.preventDefault();
54
+ setFocusedId(prevItemId);
55
+ return;
56
+ }
57
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.Space) ||
58
+ keyboardMatch(event.nativeEvent, keyboardKeys.Enter)) {
59
+ event.preventDefault();
60
+ onChange(id, !isSelected);
61
+ }
62
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.Home)) {
63
+ event.preventDefault();
64
+ virtualizer.scrollToOffset(0);
65
+ setFocusedId(firstId);
66
+ }
67
+ if (keyboardMatch(event.nativeEvent, keyboardKeys.End)) {
68
+ event.preventDefault();
69
+ virtualizer.scrollToOffset(height);
70
+ setFocusedId(lastId);
71
+ }
72
+ };
73
+ };
23
74
  const DELIMITER = ';';
24
75
  const ItemsList = (props) => {
25
76
  const { collection, leavesOnly, checkSelectable, selected, expanded, disabled, onExpansion, indeterminate, onChange, isSearch, singleChoice, renderItemForDesktop, renderContentBefore, renderContentAfter, itemListRef, } = props;
@@ -28,18 +79,31 @@ const ItemsList = (props) => {
28
79
  const treeItems = useMemo(() => {
29
80
  const newItems = [];
30
81
  expandedIds.current = getNewExpanded(prevExpanded.current, expanded);
31
- collection.walk((item, currentParents) => {
82
+ const indexById = {};
83
+ const modelsInLevel = {};
84
+ let index = 0;
85
+ collection.walk((item, currentParents, indexInParent) => {
32
86
  const parentId = currentParents.length ? currentParents[0].id : undefined;
33
87
  const isExpandedChild = currentParents.every((parent) => expanded.includes(parent.id));
34
88
  if (!parentId || isExpandedChild) {
89
+ indexById[item.id] = index;
90
+ index += 1;
91
+ const parentIds = currentParents.map((parent) => parent.id);
92
+ const modelLevel = collection.getModelLevel(item.id) + 1;
93
+ modelsInLevel[modelLevel] = modelsInLevel[modelLevel] || 0;
94
+ modelsInLevel[modelLevel] += 1;
35
95
  newItems.push({
36
96
  ...item,
37
- parentIds: currentParents.map((parent) => parent.id),
97
+ parentIds,
98
+ parentIndex: parentIds[0] ? indexById[parentIds[0]] : undefined,
99
+ ...(indexInParent ? { indexInParent } : {}),
100
+ level: modelLevel,
38
101
  });
39
102
  }
40
103
  });
41
- return newItems;
104
+ return newItems.map((item) => ({ ...item, modelsInLevel: modelsInLevel[item.level] }));
42
105
  }, [collection, expanded]);
106
+ const [focusedId, setFocusedId] = useState();
43
107
  const marginCache = useRef({});
44
108
  const parentRef = useRef(null);
45
109
  const withPromoTopContent = !!renderContentBefore;
@@ -81,7 +145,7 @@ const ItemsList = (props) => {
81
145
  };
82
146
  return (jsx("div", { ref: itemListRefCallback, className: styles.virtualizedList, style: {
83
147
  height: `${virtualizer.getTotalSize()}px`,
84
- }, children: jsx("div", { className: styles.virtualizedItem, style: {
148
+ }, role: "tree", "aria-multiselectable": !singleChoice, children: jsx("div", { className: styles.virtualizedItem, style: {
85
149
  transform: `translateY(${items[0]?.start}px)`,
86
150
  }, children: items.map((virtualItem) => {
87
151
  if (withPromoTopContent && virtualItem.index === 0) {
@@ -92,10 +156,30 @@ const ItemsList = (props) => {
92
156
  }
93
157
  const treeIndex = withPromoTopContent ? virtualItem.index - 1 : virtualItem.index;
94
158
  const treeItem = treeItems[treeIndex];
95
- const { parentIds, ...item } = treeItem;
159
+ const { parentIds, parentIndex, ...item } = treeItem;
96
160
  const parentId = parentIds[0];
97
161
  const wasExpanded = expandedIds.current.some((expandedId) => parentIds.includes(expandedId));
98
- return (jsx("div", { ref: virtualizer.measureElement, "data-index": virtualItem.index, onAnimationEnd: onAnimationEnd, className: wasExpanded ? styles.wasExpanded : undefined, children: jsx(Item, { collection: collection, checkSelectable: checkSelectable, isSelected: selected.includes(item.id), isExpanded: expanded.includes(item.id), isIndeterminate: indeterminate.includes(item.id), isDisabled: disabled.includes(item.id), parentId: parentId, item: item, leavesOnly: leavesOnly, singleChoice: singleChoice, onExpansion: onExpansion, onChange: onChange, isSearch: isSearch, renderItemForDesktop: renderItemForDesktop, cache: marginCache.current }) }, virtualItem.key));
162
+ const nextItemId = treeIndex !== treeItems.length - 1 ? treeItems[treeIndex + 1].id : undefined;
163
+ const prevItemId = treeIndex !== 0 ? treeItems[treeIndex - 1].id : undefined;
164
+ const onKeyDown = getKeyDownHandler({
165
+ id: item.id,
166
+ parentId,
167
+ parentIndex,
168
+ nextItemId,
169
+ prevItemId,
170
+ isExpanded: expanded.includes(item.id),
171
+ onExpansion,
172
+ isSelected: selected.includes(item.id),
173
+ setFocusedId,
174
+ hasChildren: collection.hasChildren(item.id),
175
+ collection,
176
+ virtualizer,
177
+ onChange,
178
+ firstId: treeItems[0].id,
179
+ lastId: treeItems[treeItems.length - 1].id,
180
+ height: virtualizer.getTotalSize(),
181
+ });
182
+ return (jsx("div", { ref: virtualizer.measureElement, "data-index": virtualItem.index, onAnimationEnd: onAnimationEnd, className: wasExpanded ? styles.wasExpanded : undefined, children: jsx(Item, { collection: collection, checkSelectable: checkSelectable, isSelected: selected.includes(item.id), isExpanded: expanded.includes(item.id), isIndeterminate: indeterminate.includes(item.id), isDisabled: disabled.includes(item.id), parentId: parentId, item: item, leavesOnly: leavesOnly, singleChoice: singleChoice, onExpansion: onExpansion, onChange: onChange, isSearch: isSearch, renderItemForDesktop: renderItemForDesktop, cache: marginCache.current, isTabbed: focusedId ? item.id === focusedId : treeIndex === 0, focusedId: focusedId, "aria-setsize": item.modelsInLevel, "aria-posinset": item.indexInParent ? item.indexInParent + 1 : undefined, "aria-level": item.level, onKeyDown: onKeyDown }) }, virtualItem.key));
99
183
  }) }) }));
100
184
  };
101
185
 
package/ItemsList.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ItemsList.js","sources":["../src/ItemsList.tsx"],"sourcesContent":["import { ReactElement, ReactNode, RefCallback, useCallback, useEffect, useMemo, useRef } from 'react';\nimport { useVirtualizer } from '@tanstack/react-virtual';\n\nimport { Item } from '@hh.ru/magritte-ui-tree-selector/Item';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemsListProps<Additional extends AdditionalDefault> {\n collection: TreeCollection<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n onExpansion: (id: string) => void;\n expanded: string[];\n selected: string[];\n disabled: string[];\n onChange: (id: string, isSelected: boolean) => void;\n indeterminate: string[];\n singleChoice?: boolean;\n isSearch: boolean;\n renderItemForDesktop?: RenderItem<Additional>;\n renderContentBefore?: (isSearch: boolean) => ReactNode;\n renderContentAfter?: (isSearch: boolean) => ReactNode;\n itemListRef?: React.MutableRefObject<HTMLDivElement | null>;\n}\n\ninterface TreeModelItem<Additional extends AdditionalDefault> extends TreeModel<Additional> {\n parentIds: string[];\n}\n\nconst getNewExpanded = (oldExpanded: string[], newExpanded: string[]): string[] => {\n if (oldExpanded.length >= newExpanded.length) {\n return [];\n }\n return newExpanded.filter((i) => !oldExpanded.includes(i));\n};\n\nconst DELIMITER = ';';\n\nexport const ItemsList = <Additional extends AdditionalDefault>(props: ItemsListProps<Additional>): ReactElement => {\n const {\n collection,\n leavesOnly,\n checkSelectable,\n selected,\n expanded,\n disabled,\n onExpansion,\n indeterminate,\n onChange,\n isSearch,\n singleChoice,\n renderItemForDesktop,\n renderContentBefore,\n renderContentAfter,\n itemListRef,\n } = props;\n const prevExpanded = useRef<string[]>(expanded);\n const expandedIds = useRef<string[]>(expanded);\n\n const treeItems = useMemo(() => {\n const newItems: TreeModelItem<Additional>[] = [];\n expandedIds.current = getNewExpanded(prevExpanded.current, expanded);\n collection.walk((item, currentParents) => {\n const parentId = currentParents.length ? currentParents[0].id : undefined;\n const isExpandedChild = currentParents.every((parent) => expanded.includes(parent.id));\n if (!parentId || isExpandedChild) {\n newItems.push({\n ...item,\n parentIds: currentParents.map((parent) => parent.id),\n });\n }\n });\n return newItems;\n }, [collection, expanded]);\n const marginCache = useRef<Record<string, number>>({});\n const parentRef = useRef<HTMLElement | null>(null);\n const withPromoTopContent = !!renderContentBefore;\n const withPromoBottomContent = !!renderContentAfter;\n const listItemsCount = treeItems.length + (withPromoTopContent ? 1 : 0) + (withPromoBottomContent ? 1 : 0);\n\n const getKey = (index: number) => {\n const treeIndex = withPromoTopContent ? index - 1 : index;\n const treeItem = treeItems[treeIndex];\n if (withPromoTopContent && index === 0) {\n return 'promoTop';\n }\n\n if (withPromoBottomContent && index === listItemsCount - 1) {\n return 'promoBottom';\n }\n // без разделителя конкатенация значений может указывать на другой элемент\n return treeItem.parentIds[0] ? `${treeItem.parentIds[0]}${DELIMITER}${treeItem.id}` : `${treeItem.id}`;\n };\n const virtualizer = useVirtualizer({\n count: listItemsCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 48,\n getItemKey: getKey,\n });\n\n const itemListRefCallback: RefCallback<HTMLDivElement> = useCallback(\n (node) => {\n if (itemListRef !== undefined) {\n itemListRef.current = node;\n }\n parentRef.current = node ? node.parentElement : null;\n },\n [itemListRef]\n );\n\n const items = virtualizer.getVirtualItems();\n\n useEffect(() => {\n virtualizer.scrollToOffset(0);\n }, [collection, virtualizer]);\n\n useEffect(() => {\n prevExpanded.current = expanded;\n }, [expanded]);\n\n const onAnimationEnd = () => {\n expandedIds.current = [];\n };\n\n return (\n <div\n ref={itemListRefCallback}\n className={styles.virtualizedList}\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n }}\n >\n <div\n className={styles.virtualizedItem}\n style={{\n transform: `translateY(${items[0]?.start}px)`,\n }}\n >\n {items.map((virtualItem) => {\n if (withPromoTopContent && virtualItem.index === 0) {\n return (\n <div key={virtualItem.key} ref={virtualizer.measureElement} data-index={virtualItem.index}>\n {renderContentBefore(isSearch)}\n </div>\n );\n }\n\n if (withPromoBottomContent && virtualItem.index === listItemsCount - 1) {\n return (\n <div key={virtualItem.key} ref={virtualizer.measureElement} data-index={virtualItem.index}>\n {renderContentAfter(isSearch)}\n </div>\n );\n }\n\n const treeIndex = withPromoTopContent ? virtualItem.index - 1 : virtualItem.index;\n const treeItem = treeItems[treeIndex];\n const { parentIds, ...item } = treeItem;\n const parentId = parentIds[0];\n const wasExpanded = expandedIds.current.some((expandedId) => parentIds.includes(expandedId));\n\n return (\n <div\n key={virtualItem.key}\n ref={virtualizer.measureElement}\n data-index={virtualItem.index}\n onAnimationEnd={onAnimationEnd}\n className={wasExpanded ? styles.wasExpanded : undefined}\n >\n <Item\n collection={collection}\n checkSelectable={checkSelectable}\n isSelected={selected.includes(item.id)}\n isExpanded={expanded.includes(item.id)}\n isIndeterminate={indeterminate.includes(item.id)}\n isDisabled={disabled.includes(item.id)}\n parentId={parentId}\n item={item}\n leavesOnly={leavesOnly}\n singleChoice={singleChoice}\n onExpansion={onExpansion}\n onChange={onChange}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n cache={marginCache.current}\n />\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
1
+ {"version":3,"file":"ItemsList.js","sources":["../src/ItemsList.tsx"],"sourcesContent":["import {\n KeyboardEventHandler,\n ReactElement,\n ReactNode,\n RefCallback,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { useVirtualizer, Virtualizer } from '@tanstack/react-virtual';\n\nimport { keyboardKeys, keyboardMatch } from '@hh.ru/magritte-common-keyboard';\nimport { Item } from '@hh.ru/magritte-ui-tree-selector/Item';\nimport TreeCollection from '@hh.ru/magritte-ui-tree-selector/collection/treeCollection';\nimport { AdditionalDefault, IdCollectionPredicate, TreeModel } from '@hh.ru/magritte-ui-tree-selector/collection/types';\nimport { RenderItem } from '@hh.ru/magritte-ui-tree-selector/types';\n\nimport styles from './tree-selector-item.less';\n\ninterface ItemsListProps<Additional extends AdditionalDefault> {\n collection: TreeCollection<Additional>;\n leavesOnly?: boolean;\n checkSelectable?: IdCollectionPredicate;\n onExpansion: (id: string) => void;\n expanded: string[];\n selected: string[];\n disabled: string[];\n onChange: (id: string, isSelected: boolean) => void;\n indeterminate: string[];\n singleChoice?: boolean;\n isSearch: boolean;\n renderItemForDesktop?: RenderItem<Additional>;\n renderContentBefore?: (isSearch: boolean) => ReactNode;\n renderContentAfter?: (isSearch: boolean) => ReactNode;\n itemListRef?: React.MutableRefObject<HTMLDivElement | null>;\n}\n\ninterface TreeModelItem<Additional extends AdditionalDefault> extends TreeModel<Additional> {\n parentIds: string[];\n parentIndex?: number;\n level: number;\n modelsInLevel?: number;\n indexInParent?: number;\n}\n\nconst getNewExpanded = (oldExpanded: string[], newExpanded: string[]): string[] => {\n if (oldExpanded.length >= newExpanded.length) {\n return [];\n }\n return newExpanded.filter((i) => !oldExpanded.includes(i));\n};\n\ninterface GetKeyDownHandlerProps<Additional extends AdditionalDefault> {\n isExpanded: boolean;\n isSelected: boolean;\n hasChildren: boolean;\n id: string;\n onExpansion: (id: string) => void;\n parentId?: string;\n parentIndex?: number;\n nextItemId?: string;\n prevItemId?: string;\n setFocusedId: (id: string) => void;\n collection: TreeCollection<Additional>;\n virtualizer: Virtualizer<HTMLElement, Element>;\n onChange: (id: string, isSelected: boolean) => void;\n firstId: string;\n height: number;\n lastId: string;\n}\n\nconst getKeyDownHandler = <Additional extends AdditionalDefault>({\n id,\n nextItemId,\n prevItemId,\n parentId,\n parentIndex,\n isExpanded,\n isSelected,\n onExpansion,\n setFocusedId,\n hasChildren,\n collection,\n virtualizer,\n onChange,\n firstId,\n lastId,\n height,\n}: GetKeyDownHandlerProps<Additional>): KeyboardEventHandler => {\n return (event) => {\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowLeft)) {\n event.preventDefault();\n if (isExpanded) {\n onExpansion(id);\n } else if (parentId) {\n virtualizer.scrollToIndex(parentIndex as number);\n setFocusedId(parentId);\n }\n return;\n }\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowRight)) {\n event.preventDefault();\n if (!isExpanded && hasChildren) {\n onExpansion(id);\n } else if (hasChildren) {\n const firstChild = collection.getChildren(id);\n setFocusedId(firstChild[0].id);\n }\n return;\n }\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowDown) && nextItemId) {\n event.preventDefault();\n setFocusedId(nextItemId);\n return;\n }\n if (keyboardMatch(event.nativeEvent, keyboardKeys.ArrowUp) && prevItemId) {\n event.preventDefault();\n setFocusedId(prevItemId);\n return;\n }\n if (\n keyboardMatch(event.nativeEvent, keyboardKeys.Space) ||\n keyboardMatch(event.nativeEvent, keyboardKeys.Enter)\n ) {\n event.preventDefault();\n onChange(id, !isSelected);\n }\n\n if (keyboardMatch(event.nativeEvent, keyboardKeys.Home)) {\n event.preventDefault();\n virtualizer.scrollToOffset(0);\n setFocusedId(firstId);\n }\n\n if (keyboardMatch(event.nativeEvent, keyboardKeys.End)) {\n event.preventDefault();\n virtualizer.scrollToOffset(height);\n setFocusedId(lastId);\n }\n };\n};\n\nconst DELIMITER = ';';\n\nexport const ItemsList = <Additional extends AdditionalDefault>(props: ItemsListProps<Additional>): ReactElement => {\n const {\n collection,\n leavesOnly,\n checkSelectable,\n selected,\n expanded,\n disabled,\n onExpansion,\n indeterminate,\n onChange,\n isSearch,\n singleChoice,\n renderItemForDesktop,\n renderContentBefore,\n renderContentAfter,\n itemListRef,\n } = props;\n const prevExpanded = useRef<string[]>(expanded);\n const expandedIds = useRef<string[]>(expanded);\n\n const treeItems = useMemo(() => {\n const newItems: TreeModelItem<Additional>[] = [];\n expandedIds.current = getNewExpanded(prevExpanded.current, expanded);\n const indexById: Record<string, number> = {};\n const modelsInLevel: Record<number, number> = {};\n let index = 0;\n collection.walk((item, currentParents, indexInParent) => {\n const parentId = currentParents.length ? currentParents[0].id : undefined;\n const isExpandedChild = currentParents.every((parent) => expanded.includes(parent.id));\n if (!parentId || isExpandedChild) {\n indexById[item.id] = index;\n index += 1;\n const parentIds = currentParents.map((parent) => parent.id);\n const modelLevel = collection.getModelLevel(item.id) + 1;\n modelsInLevel[modelLevel] = modelsInLevel[modelLevel] || 0;\n modelsInLevel[modelLevel] += 1;\n newItems.push({\n ...item,\n parentIds,\n parentIndex: parentIds[0] ? indexById[parentIds[0]] : undefined,\n ...(indexInParent ? { indexInParent } : {}),\n level: modelLevel,\n });\n }\n });\n return newItems.map((item) => ({ ...item, modelsInLevel: modelsInLevel[item.level] }));\n }, [collection, expanded]);\n const [focusedId, setFocusedId] = useState<string | undefined>();\n const marginCache = useRef<Record<string, number>>({});\n const parentRef = useRef<HTMLElement | null>(null);\n const withPromoTopContent = !!renderContentBefore;\n const withPromoBottomContent = !!renderContentAfter;\n const listItemsCount = treeItems.length + (withPromoTopContent ? 1 : 0) + (withPromoBottomContent ? 1 : 0);\n\n const getKey = (index: number) => {\n const treeIndex = withPromoTopContent ? index - 1 : index;\n const treeItem = treeItems[treeIndex];\n if (withPromoTopContent && index === 0) {\n return 'promoTop';\n }\n\n if (withPromoBottomContent && index === listItemsCount - 1) {\n return 'promoBottom';\n }\n // без разделителя конкатенация значений может указывать на другой элемент\n return treeItem.parentIds[0] ? `${treeItem.parentIds[0]}${DELIMITER}${treeItem.id}` : `${treeItem.id}`;\n };\n const virtualizer = useVirtualizer({\n count: listItemsCount,\n getScrollElement: () => parentRef.current,\n estimateSize: () => 48,\n getItemKey: getKey,\n });\n\n const itemListRefCallback: RefCallback<HTMLDivElement> = useCallback(\n (node) => {\n if (itemListRef !== undefined) {\n itemListRef.current = node;\n }\n parentRef.current = node ? node.parentElement : null;\n },\n [itemListRef]\n );\n\n const items = virtualizer.getVirtualItems();\n\n useEffect(() => {\n virtualizer.scrollToOffset(0);\n }, [collection, virtualizer]);\n\n useEffect(() => {\n prevExpanded.current = expanded;\n }, [expanded]);\n\n const onAnimationEnd = () => {\n expandedIds.current = [];\n };\n\n return (\n <div\n ref={itemListRefCallback}\n className={styles.virtualizedList}\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n }}\n role=\"tree\"\n aria-multiselectable={!singleChoice}\n >\n <div\n className={styles.virtualizedItem}\n style={{\n transform: `translateY(${items[0]?.start}px)`,\n }}\n >\n {items.map((virtualItem) => {\n if (withPromoTopContent && virtualItem.index === 0) {\n return (\n <div key={virtualItem.key} ref={virtualizer.measureElement} data-index={virtualItem.index}>\n {renderContentBefore(isSearch)}\n </div>\n );\n }\n\n if (withPromoBottomContent && virtualItem.index === listItemsCount - 1) {\n return (\n <div key={virtualItem.key} ref={virtualizer.measureElement} data-index={virtualItem.index}>\n {renderContentAfter(isSearch)}\n </div>\n );\n }\n\n const treeIndex = withPromoTopContent ? virtualItem.index - 1 : virtualItem.index;\n const treeItem = treeItems[treeIndex];\n const { parentIds, parentIndex, ...item } = treeItem;\n const parentId = parentIds[0];\n const wasExpanded = expandedIds.current.some((expandedId) => parentIds.includes(expandedId));\n const nextItemId = treeIndex !== treeItems.length - 1 ? treeItems[treeIndex + 1].id : undefined;\n const prevItemId = treeIndex !== 0 ? treeItems[treeIndex - 1].id : undefined;\n\n const onKeyDown = getKeyDownHandler({\n id: item.id,\n parentId,\n parentIndex,\n nextItemId,\n prevItemId,\n isExpanded: expanded.includes(item.id),\n onExpansion,\n isSelected: selected.includes(item.id),\n setFocusedId,\n hasChildren: collection.hasChildren(item.id),\n collection,\n virtualizer,\n onChange,\n firstId: treeItems[0].id,\n lastId: treeItems[treeItems.length - 1].id,\n height: virtualizer.getTotalSize(),\n });\n\n return (\n <div\n key={virtualItem.key}\n ref={virtualizer.measureElement}\n data-index={virtualItem.index}\n onAnimationEnd={onAnimationEnd}\n className={wasExpanded ? styles.wasExpanded : undefined}\n >\n <Item\n collection={collection}\n checkSelectable={checkSelectable}\n isSelected={selected.includes(item.id)}\n isExpanded={expanded.includes(item.id)}\n isIndeterminate={indeterminate.includes(item.id)}\n isDisabled={disabled.includes(item.id)}\n parentId={parentId}\n item={item}\n leavesOnly={leavesOnly}\n singleChoice={singleChoice}\n onExpansion={onExpansion}\n onChange={onChange}\n isSearch={isSearch}\n renderItemForDesktop={renderItemForDesktop}\n cache={marginCache.current}\n isTabbed={focusedId ? item.id === focusedId : treeIndex === 0}\n focusedId={focusedId}\n aria-setsize={item.modelsInLevel}\n aria-posinset={item.indexInParent ? item.indexInParent + 1 : undefined}\n aria-level={item.level}\n onKeyDown={onKeyDown}\n />\n </div>\n );\n })}\n </div>\n </div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
@@ -10,7 +10,7 @@ import { Action } from './Action.js';
10
10
  import { MobileDelimiter } from './MobileDelimiter.js';
11
11
  import { MobileItem } from './MobileItem.js';
12
12
  import { MobileParentItem } from './MobileParentItem.js';
13
- import { s as styles } from './tree-selector-item-Ch4gUsnP.js';
13
+ import { s as styles } from './tree-selector-item-xbLyWy2t.js';
14
14
  import '@hh.ru/magritte-ui-checkbox-radio';
15
15
  import '@hh.ru/magritte-ui-card';
16
16
  import '@hh.ru/magritte-ui-typography';
package/TreeSelector.js CHANGED
@@ -9,17 +9,17 @@ import '@hh.ru/magritte-common-fuzzy-search';
9
9
  import '@hh.ru/magritte-ui-breakpoint';
10
10
  import './ItemsList.js';
11
11
  import '@tanstack/react-virtual';
12
+ import '@hh.ru/magritte-common-keyboard';
12
13
  import './Item.js';
13
14
  import 'classnames';
14
15
  import './ItemContent.js';
15
- import '@hh.ru/magritte-common-keyboard';
16
16
  import '@hh.ru/magritte-ui-icon/icon';
17
17
  import './Action.js';
18
18
  import '@hh.ru/magritte-ui-checkbox-radio';
19
19
  import './TreeSelectorItemBase.js';
20
20
  import '@hh.ru/magritte-ui-cell';
21
21
  import '@hh.ru/magritte-ui-typography';
22
- import './tree-selector-item-Ch4gUsnP.js';
22
+ import './tree-selector-item-xbLyWy2t.js';
23
23
  import './MobileItemsList.js';
24
24
  import '@hh.ru/magritte-common-func-utils';
25
25
  import '@hh.ru/magritte-ui-checkable-card/CheckableCardElement';
@@ -11,17 +11,17 @@ import { useExpanded } from './useExpanded.js';
11
11
  import { useIndeterminate } from './useIndeterminate.js';
12
12
  import { useRenderInput } from './useRenderInput.js';
13
13
  import '@tanstack/react-virtual';
14
+ import '@hh.ru/magritte-common-keyboard';
14
15
  import './Item.js';
15
16
  import 'classnames';
16
17
  import './ItemContent.js';
17
- import '@hh.ru/magritte-common-keyboard';
18
18
  import '@hh.ru/magritte-ui-icon/icon';
19
19
  import './Action.js';
20
20
  import '@hh.ru/magritte-ui-checkbox-radio';
21
21
  import './TreeSelectorItemBase.js';
22
22
  import '@hh.ru/magritte-ui-cell';
23
23
  import '@hh.ru/magritte-ui-typography';
24
- import './tree-selector-item-Ch4gUsnP.js';
24
+ import './tree-selector-item-xbLyWy2t.js';
25
25
  import '@hh.ru/magritte-common-func-utils';
26
26
  import '@hh.ru/magritte-ui-checkable-card/CheckableCardElement';
27
27
  import './MobileDelimiter.js';
@@ -7,18 +7,18 @@ import { CustomScrollContext } from '@hh.ru/magritte-internal-custom-scroll';
7
7
  import { useScrollbar, Scrollbar } from '@hh.ru/magritte-ui-scrollbar';
8
8
  import { ItemsList } from './ItemsList.js';
9
9
  import '@tanstack/react-virtual';
10
+ import '@hh.ru/magritte-common-keyboard';
10
11
  import './Item.js';
11
12
  import './ItemContent.js';
12
- import '@hh.ru/magritte-common-keyboard';
13
13
  import '@hh.ru/magritte-ui-icon/icon';
14
14
  import './Action.js';
15
15
  import '@hh.ru/magritte-ui-checkbox-radio';
16
16
  import './TreeSelectorItemBase.js';
17
17
  import '@hh.ru/magritte-ui-cell';
18
18
  import '@hh.ru/magritte-ui-typography';
19
- import './tree-selector-item-Ch4gUsnP.js';
19
+ import './tree-selector-item-xbLyWy2t.js';
20
20
 
21
- var styles = {"wrapper":"magritte-wrapper___EzesX_5-4-11","scroll-container":"magritte-scroll-container___wGzfI_5-4-11","scrollContainer":"magritte-scroll-container___wGzfI_5-4-11"};
21
+ var styles = {"wrapper":"magritte-wrapper___EzesX_5-5-0","scroll-container":"magritte-scroll-container___wGzfI_5-5-0","scrollContainer":"magritte-scroll-container___wGzfI_5-5-0"};
22
22
 
23
23
  const TreeSelectorWrapper = ({ forwardRef, children, ...props }) => {
24
24
  const { hasVerticalScroll, verticalScrollbarProps, ...scrollbar } = useScrollbar({ axis: 'vertical' });
@@ -123,8 +123,8 @@ class TreeCollection {
123
123
  */
124
124
  _walk(items, callback, parents) {
125
125
  const currentParents = parents ? parents.slice() : [];
126
- items.forEach((item) => {
127
- callback(item, currentParents);
126
+ items.forEach((item, index) => {
127
+ callback(item, currentParents, index);
128
128
  const children = this.getChildren(item.id);
129
129
  if (children && children.length) {
130
130
  this._walk(children, callback, [item].concat(currentParents));
@@ -1 +1 @@
1
- {"version":3,"file":"treeCollection.js","sources":["../../src/collection/treeCollection.ts"],"sourcesContent":["import {\n AdditionalDefault,\n TreeModel,\n WalkCallback,\n ModelPredicate,\n ModelData,\n} from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\nconst createModel = <Additional extends AdditionalDefault>(attrs: TreeModel<Additional>): TreeModel<Additional> => {\n const id = attrs.id;\n if (typeof id !== 'string') {\n throw new Error(`Invalid ID: \"${JSON.stringify(id)}\"`);\n }\n const model: TreeModel<Additional> = {\n id: attrs.id,\n text: attrs.text,\n ...('additional' in attrs ? { additional: attrs.additional } : {}),\n };\n return model;\n};\n\n/**\n * Многоцелевая иерархическая коллекция,\n * свободная от специфического поведения компонентов\n */\nclass TreeCollection<Additional extends AdditionalDefault = never> {\n protected models: TreeModel<Additional>[] = [];\n protected topLevelModels: TreeModel<Additional>[] = [];\n\n protected modelsById: Record<string, TreeModel<Additional>> = {};\n protected childrenById: Record<string, string[]> = {};\n\n protected parentsById: Record<string, string[]> = {};\n\n /**\n * Создаёт из объекта модель и добавляет в коллекцию.\n * Не добавляет модель в коллекцию, если модель с таким id уже существует\n */\n addModel(attrs: TreeModel<Additional>, parentId?: string): void {\n const model = createModel(attrs);\n const id = model.id;\n if (typeof this.getModel(id) === 'undefined') {\n this.models.push(model);\n this.modelsById[id] = model;\n }\n if (parentId) {\n this.parentsById[id] = this.parentsById[id] || [];\n this.parentsById[id].push(parentId);\n this.childrenById[parentId] = this.childrenById[parentId] || [];\n this.childrenById[parentId].push(id);\n } else {\n this.topLevelModels.push(model);\n }\n }\n\n toList(): TreeModel<Additional>[] {\n return this.models.slice();\n }\n\n getTopLevel(): TreeModel<Additional>[] {\n return this.topLevelModels.slice();\n }\n\n /** Возвращает модель по ID или `undefined` */\n getModel(id: string): TreeModel<Additional> | undefined {\n return this.modelsById.hasOwnProperty(id) ? this.modelsById[id] : undefined;\n }\n\n _getModelLevel(id: string, level = 0): number {\n const parentId = this.getParentId(id);\n if (!parentId) {\n return level;\n }\n return this._getModelLevel(parentId, level + 1);\n }\n\n getModelLevel(id: string): number {\n return this._getModelLevel(id);\n }\n\n /** Возвращает существующие в коллекции модели по IDs */\n getExistModels(ids: string[]): TreeModel<Additional>[] {\n return ids.reduce((result: TreeModel<Additional>[], id) => {\n const model = this.getModel(id);\n if (model) {\n result.push(model);\n }\n return result;\n }, []);\n }\n\n /** Возвращает ID родителя по ID модели или `undefined` */\n getParentId(id: string): string | undefined {\n return this.parentsById.hasOwnProperty(id) ? this.parentsById[id][0] : undefined;\n }\n\n /**\n * Возвращает модель первого родителя по ID или `undefined`.\n */\n getParent(id: string): TreeModel<Additional> | undefined {\n const parentId = this.getParentId(id);\n return parentId ? this.getModel(parentId) : undefined;\n }\n\n /** Возвращает массив IDs ближайших родителей по ID модели */\n getParentIdsDuplicates(id: string): string[] {\n return this.parentsById.hasOwnProperty(id) ? this.parentsById[id] : [];\n }\n\n /** Возвращает массив ID родителей от ближних к дальним */\n getParentIds(id: string, resultIds: string[] = []): string[] {\n const parentId = this.getParentIdsDuplicates(id);\n if (parentId.length) {\n resultIds.push(...parentId);\n parentId.forEach((id) => this.getParentIds(id, resultIds));\n }\n return resultIds;\n }\n\n /** Возвращает массив моделей родителей от ближнего к дальнему */\n getParents(id: string): TreeModel<Additional>[] {\n const parendIds = this.getParentIds(id);\n return this.getExistModels(parendIds);\n }\n\n /** Возвращает наличие дочерних моделей по ID родителя */\n hasChildren(id: string): boolean {\n return this.childrenById.hasOwnProperty(id);\n }\n\n /** Возвращает список ID дочерних по ID родителя */\n getChildrenIds(id: string): string[] {\n return this.hasChildren(id) ? this.childrenById[id].slice() : [];\n }\n\n /** Возвращает список дочерних моделей по ID родителя */\n getChildren(id: string): TreeModel<Additional>[] {\n const childrenIds = this.getChildrenIds(id);\n return this.getExistModels(childrenIds);\n }\n\n /**\n * Рекурсивно проходит по списку моделей, применяет к каждой модели переданную функцию.\n * items Список моделей для обработки.\n * callback Вызываемая функция.\n * [parents] Массив моделей родителей от ближнего к дальнему.\n * Используется в случаях, когда на вход поступают модели из середины дерева, имеющие своих родителей.\n */\n _walk(items: TreeModel<Additional>[], callback: WalkCallback<Additional>, parents?: TreeModel<Additional>[]): void {\n const currentParents = parents ? parents.slice() : [];\n items.forEach((item) => {\n callback(item, currentParents);\n const children = this.getChildren(item.id);\n if (children && children.length) {\n this._walk(children, callback, [item].concat(currentParents));\n }\n });\n }\n\n /** Рекурсивно проходит по дереву, применяет к каждой модели переданную функцию */\n walk(callback: WalkCallback<Additional>): void {\n this._walk(this.getTopLevel(), callback);\n }\n\n /**\n * Рекурсивно проходит по дочерним элементам указанной модели, применяет к каждому переданную функцию.\n * id ID модели, с которой начинать обход.\n * callback Вызываемая функция.\n */\n walkChildren(id: string, callback: WalkCallback<Additional>): void {\n const children = this.getChildren(id);\n if (children.length) {\n const parents = this.getExistModels([id]).concat(this.getParents(id));\n this._walk(children, callback, parents);\n }\n }\n\n /**\n * Проходит по родителям модели до самого верха, применяет к каждому указанную функцию.\n * id ID текущей модели.\n * callback Вызываемая функция.\n */\n walkParents(id: string, callback: WalkCallback<Additional>): void {\n const parents = this.getParents(id);\n while (parents.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstParent = parents.shift()!;\n callback(firstParent, parents.slice());\n }\n }\n\n /**\n * Возвращает коллекцию в виде дерева.\n * filter Функция-фильтр.\n * Если указана, оставляет в дереве только те элементы, для которых вернулось `true`.\n */\n toTree(filter?: ModelPredicate): ModelData<Additional>[] {\n const filteredTree: ModelData<Additional>[] = [];\n const modelsById: Record<string, ModelData<Additional>> = {};\n this.walk((model, parents) => {\n if (!filter || filter(model)) {\n const treeItem = { ...model };\n modelsById[model.id] = treeItem;\n if (parents.length === 0) {\n filteredTree.push(treeItem);\n } else {\n const parent = modelsById[parents[0].id];\n if (!parent.items) {\n parent.items = [];\n }\n parent.items.push(treeItem);\n }\n }\n });\n return filteredTree;\n }\n}\n\nexport default TreeCollection;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"treeCollection.js","sources":["../../src/collection/treeCollection.ts"],"sourcesContent":["import {\n AdditionalDefault,\n TreeModel,\n WalkCallback,\n ModelPredicate,\n ModelData,\n} from '@hh.ru/magritte-ui-tree-selector/collection/types';\n\nconst createModel = <Additional extends AdditionalDefault>(attrs: TreeModel<Additional>): TreeModel<Additional> => {\n const id = attrs.id;\n if (typeof id !== 'string') {\n throw new Error(`Invalid ID: \"${JSON.stringify(id)}\"`);\n }\n const model: TreeModel<Additional> = {\n id: attrs.id,\n text: attrs.text,\n ...('additional' in attrs ? { additional: attrs.additional } : {}),\n };\n return model;\n};\n\n/**\n * Многоцелевая иерархическая коллекция,\n * свободная от специфического поведения компонентов\n */\nclass TreeCollection<Additional extends AdditionalDefault = never> {\n protected models: TreeModel<Additional>[] = [];\n protected topLevelModels: TreeModel<Additional>[] = [];\n\n protected modelsById: Record<string, TreeModel<Additional>> = {};\n protected childrenById: Record<string, string[]> = {};\n\n protected parentsById: Record<string, string[]> = {};\n\n /**\n * Создаёт из объекта модель и добавляет в коллекцию.\n * Не добавляет модель в коллекцию, если модель с таким id уже существует\n */\n addModel(attrs: TreeModel<Additional>, parentId?: string): void {\n const model = createModel(attrs);\n const id = model.id;\n if (typeof this.getModel(id) === 'undefined') {\n this.models.push(model);\n this.modelsById[id] = model;\n }\n if (parentId) {\n this.parentsById[id] = this.parentsById[id] || [];\n this.parentsById[id].push(parentId);\n this.childrenById[parentId] = this.childrenById[parentId] || [];\n this.childrenById[parentId].push(id);\n } else {\n this.topLevelModels.push(model);\n }\n }\n\n toList(): TreeModel<Additional>[] {\n return this.models.slice();\n }\n\n getTopLevel(): TreeModel<Additional>[] {\n return this.topLevelModels.slice();\n }\n\n /** Возвращает модель по ID или `undefined` */\n getModel(id: string): TreeModel<Additional> | undefined {\n return this.modelsById.hasOwnProperty(id) ? this.modelsById[id] : undefined;\n }\n\n _getModelLevel(id: string, level = 0): number {\n const parentId = this.getParentId(id);\n if (!parentId) {\n return level;\n }\n return this._getModelLevel(parentId, level + 1);\n }\n\n getModelLevel(id: string): number {\n return this._getModelLevel(id);\n }\n\n /** Возвращает существующие в коллекции модели по IDs */\n getExistModels(ids: string[]): TreeModel<Additional>[] {\n return ids.reduce((result: TreeModel<Additional>[], id) => {\n const model = this.getModel(id);\n if (model) {\n result.push(model);\n }\n return result;\n }, []);\n }\n\n /** Возвращает ID родителя по ID модели или `undefined` */\n getParentId(id: string): string | undefined {\n return this.parentsById.hasOwnProperty(id) ? this.parentsById[id][0] : undefined;\n }\n\n /**\n * Возвращает модель первого родителя по ID или `undefined`.\n */\n getParent(id: string): TreeModel<Additional> | undefined {\n const parentId = this.getParentId(id);\n return parentId ? this.getModel(parentId) : undefined;\n }\n\n /** Возвращает массив IDs ближайших родителей по ID модели */\n getParentIdsDuplicates(id: string): string[] {\n return this.parentsById.hasOwnProperty(id) ? this.parentsById[id] : [];\n }\n\n /** Возвращает массив ID родителей от ближних к дальним */\n getParentIds(id: string, resultIds: string[] = []): string[] {\n const parentId = this.getParentIdsDuplicates(id);\n if (parentId.length) {\n resultIds.push(...parentId);\n parentId.forEach((id) => this.getParentIds(id, resultIds));\n }\n return resultIds;\n }\n\n /** Возвращает массив моделей родителей от ближнего к дальнему */\n getParents(id: string): TreeModel<Additional>[] {\n const parendIds = this.getParentIds(id);\n return this.getExistModels(parendIds);\n }\n\n /** Возвращает наличие дочерних моделей по ID родителя */\n hasChildren(id: string): boolean {\n return this.childrenById.hasOwnProperty(id);\n }\n\n /** Возвращает список ID дочерних по ID родителя */\n getChildrenIds(id: string): string[] {\n return this.hasChildren(id) ? this.childrenById[id].slice() : [];\n }\n\n /** Возвращает список дочерних моделей по ID родителя */\n getChildren(id: string): TreeModel<Additional>[] {\n const childrenIds = this.getChildrenIds(id);\n return this.getExistModels(childrenIds);\n }\n\n /**\n * Рекурсивно проходит по списку моделей, применяет к каждой модели переданную функцию.\n * items Список моделей для обработки.\n * callback Вызываемая функция.\n * [parents] Массив моделей родителей от ближнего к дальнему.\n * Используется в случаях, когда на вход поступают модели из середины дерева, имеющие своих родителей.\n */\n _walk(items: TreeModel<Additional>[], callback: WalkCallback<Additional>, parents?: TreeModel<Additional>[]): void {\n const currentParents = parents ? parents.slice() : [];\n items.forEach((item, index) => {\n callback(item, currentParents, index);\n const children = this.getChildren(item.id);\n if (children && children.length) {\n this._walk(children, callback, [item].concat(currentParents));\n }\n });\n }\n\n /** Рекурсивно проходит по дереву, применяет к каждой модели переданную функцию */\n walk(callback: WalkCallback<Additional>): void {\n this._walk(this.getTopLevel(), callback);\n }\n\n /**\n * Рекурсивно проходит по дочерним элементам указанной модели, применяет к каждому переданную функцию.\n * id ID модели, с которой начинать обход.\n * callback Вызываемая функция.\n */\n walkChildren(id: string, callback: WalkCallback<Additional>): void {\n const children = this.getChildren(id);\n if (children.length) {\n const parents = this.getExistModels([id]).concat(this.getParents(id));\n this._walk(children, callback, parents);\n }\n }\n\n /**\n * Проходит по родителям модели до самого верха, применяет к каждому указанную функцию.\n * id ID текущей модели.\n * callback Вызываемая функция.\n */\n walkParents(id: string, callback: WalkCallback<Additional>): void {\n const parents = this.getParents(id);\n while (parents.length) {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const firstParent = parents.shift()!;\n callback(firstParent, parents.slice());\n }\n }\n\n /**\n * Возвращает коллекцию в виде дерева.\n * filter Функция-фильтр.\n * Если указана, оставляет в дереве только те элементы, для которых вернулось `true`.\n */\n toTree(filter?: ModelPredicate): ModelData<Additional>[] {\n const filteredTree: ModelData<Additional>[] = [];\n const modelsById: Record<string, ModelData<Additional>> = {};\n this.walk((model, parents) => {\n if (!filter || filter(model)) {\n const treeItem = { ...model };\n modelsById[model.id] = treeItem;\n if (parents.length === 0) {\n filteredTree.push(treeItem);\n } else {\n const parent = modelsById[parents[0].id];\n if (!parent.items) {\n parent.items = [];\n }\n parent.items.push(treeItem);\n }\n }\n });\n return filteredTree;\n }\n}\n\nexport default TreeCollection;\n"],"names":[],"mappings":"AAQA,MAAM,WAAW,GAAG,CAAuC,KAA4B,KAA2B;AAC9G,IAAA,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;AACpB,IAAA,IAAI,OAAO,EAAE,KAAK,QAAQ,EAAE;AACxB,QAAA,MAAM,IAAI,KAAK,CAAC,CAAA,aAAA,EAAgB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAG,CAAA,CAAA,CAAC,CAAC;KAC1D;AACD,IAAA,MAAM,KAAK,GAA0B;QACjC,EAAE,EAAE,KAAK,CAAC,EAAE;QACZ,IAAI,EAAE,KAAK,CAAC,IAAI;AAChB,QAAA,IAAI,YAAY,IAAI,KAAK,GAAG,EAAE,UAAU,EAAE,KAAK,CAAC,UAAU,EAAE,GAAG,EAAE;KACpE,CAAC;AACF,IAAA,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF;;;AAGG;AACH,MAAM,cAAc,CAAA;IACN,MAAM,GAA4B,EAAE,CAAC;IACrC,cAAc,GAA4B,EAAE,CAAC;IAE7C,UAAU,GAA0C,EAAE,CAAC;IACvD,YAAY,GAA6B,EAAE,CAAC;IAE5C,WAAW,GAA6B,EAAE,CAAC;AAErD;;;AAGG;IACH,QAAQ,CAAC,KAA4B,EAAE,QAAiB,EAAA;AACpD,QAAA,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;AACjC,QAAA,MAAM,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;QACpB,IAAI,OAAO,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,WAAW,EAAE;AAC1C,YAAA,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxB,YAAA,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC;SAC/B;QACD,IAAI,QAAQ,EAAE;AACV,YAAA,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;YAClD,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACpC,YAAA,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YAChE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;SACxC;aAAM;AACH,YAAA,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SACnC;KACJ;IAED,MAAM,GAAA;AACF,QAAA,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;KAC9B;IAED,WAAW,GAAA;AACP,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;KACtC;;AAGD,IAAA,QAAQ,CAAC,EAAU,EAAA;QACf,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC;KAC/E;AAED,IAAA,cAAc,CAAC,EAAU,EAAE,KAAK,GAAG,CAAC,EAAA;QAChC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,QAAQ,EAAE;AACX,YAAA,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;KACnD;AAED,IAAA,aAAa,CAAC,EAAU,EAAA;AACpB,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;KAClC;;AAGD,IAAA,cAAc,CAAC,GAAa,EAAA;QACxB,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,MAA+B,EAAE,EAAE,KAAI;YACtD,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAChC,IAAI,KAAK,EAAE;AACP,gBAAA,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aACtB;AACD,YAAA,OAAO,MAAM,CAAC;SACjB,EAAE,EAAE,CAAC,CAAC;KACV;;AAGD,IAAA,WAAW,CAAC,EAAU,EAAA;QAClB,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;KACpF;AAED;;AAEG;AACH,IAAA,SAAS,CAAC,EAAU,EAAA;QAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACtC,QAAA,OAAO,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;KACzD;;AAGD,IAAA,sBAAsB,CAAC,EAAU,EAAA;QAC7B,OAAO,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;KAC1E;;AAGD,IAAA,YAAY,CAAC,EAAU,EAAE,SAAA,GAAsB,EAAE,EAAA;QAC7C,MAAM,QAAQ,GAAG,IAAI,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;AACjD,QAAA,IAAI,QAAQ,CAAC,MAAM,EAAE;AACjB,YAAA,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;AAC5B,YAAA,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC,CAAC;SAC9D;AACD,QAAA,OAAO,SAAS,CAAC;KACpB;;AAGD,IAAA,UAAU,CAAC,EAAU,EAAA;QACjB,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;AACxC,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;KACzC;;AAGD,IAAA,WAAW,CAAC,EAAU,EAAA;QAClB,OAAO,IAAI,CAAC,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;KAC/C;;AAGD,IAAA,cAAc,CAAC,EAAU,EAAA;QACrB,OAAO,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;KACpE;;AAGD,IAAA,WAAW,CAAC,EAAU,EAAA;QAClB,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;AAC5C,QAAA,OAAO,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;KAC3C;AAED;;;;;;AAMG;AACH,IAAA,KAAK,CAAC,KAA8B,EAAE,QAAkC,EAAE,OAAiC,EAAA;AACvG,QAAA,MAAM,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC;QACtD,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,KAAI;AAC1B,YAAA,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,KAAK,CAAC,CAAC;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3C,YAAA,IAAI,QAAQ,IAAI,QAAQ,CAAC,MAAM,EAAE;AAC7B,gBAAA,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;aACjE;AACL,SAAC,CAAC,CAAC;KACN;;AAGD,IAAA,IAAI,CAAC,QAAkC,EAAA;QACnC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,CAAC,CAAC;KAC5C;AAED;;;;AAIG;IACH,YAAY,CAAC,EAAU,EAAE,QAAkC,EAAA;QACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACtC,QAAA,IAAI,QAAQ,CAAC,MAAM,EAAE;YACjB,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;YACtE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;SAC3C;KACJ;AAED;;;;AAIG;IACH,WAAW,CAAC,EAAU,EAAE,QAAkC,EAAA;QACtD,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;AACpC,QAAA,OAAO,OAAO,CAAC,MAAM,EAAE;;AAEnB,YAAA,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,EAAG,CAAC;YACrC,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;SAC1C;KACJ;AAED;;;;AAIG;AACH,IAAA,MAAM,CAAC,MAAuB,EAAA;QAC1B,MAAM,YAAY,GAA4B,EAAE,CAAC;QACjD,MAAM,UAAU,GAA0C,EAAE,CAAC;QAC7D,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,KAAI;YACzB,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE;AAC1B,gBAAA,MAAM,QAAQ,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;AAC9B,gBAAA,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC;AAChC,gBAAA,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE;AACtB,oBAAA,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;iBAC/B;qBAAM;oBACH,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AACzC,oBAAA,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;AACf,wBAAA,MAAM,CAAC,KAAK,GAAG,EAAE,CAAC;qBACrB;AACD,oBAAA,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;iBAC/B;aACJ;AACL,SAAC,CAAC,CAAC;AACH,QAAA,OAAO,YAAY,CAAC;KACvB;AACJ;;;;"}
@@ -19,7 +19,7 @@ export interface WalkCallback<Additional extends AdditionalDefault> {
19
19
  /** Модель текущего узла. */
20
20
  item: TreeModel<Additional>,
21
21
  /** Массив моделей родителей от ближнего к дальнему. */
22
- currentParents: TreeModel<Additional>[]): void;
22
+ currentParents: TreeModel<Additional>[], indexInParent?: number): void;
23
23
  }
24
24
  export interface ModelPredicate {
25
25
  <Additional extends AdditionalDefault>(item: TreeModel<Additional>): boolean;
package/index.css CHANGED
@@ -1,10 +1,14 @@
1
+ :root{
2
+ --magritte-color-stroke-state-focused-accessible-v24-3-0:#0070ff7a;
3
+ }
4
+
1
5
  :root{
2
6
  --magritte-semantic-animation-ease-in-out-100-timing-function-v24-3-0:cubic-bezier(0.25, 0.1, 0.25, 1);
3
7
  --magritte-semantic-animation-ease-in-out-100-duration-v24-3-0:100ms;
4
8
  --magritte-semantic-animation-ease-in-out-200-timing-function-v24-3-0:cubic-bezier(0.25, 0.1, 0.25, 1);
5
9
  --magritte-semantic-animation-ease-in-out-200-duration-v24-3-0:200ms;
6
10
  }
7
- @keyframes magritte-fade-in___yS4Ja_5-4-11{
11
+ @keyframes magritte-fade-in___yS4Ja_5-5-0{
8
12
  0%{
9
13
  opacity:0;
10
14
  }
@@ -12,24 +16,27 @@
12
16
  opacity:1;
13
17
  }
14
18
  }
15
- .magritte-item-animation-timeout___pbOyZ_5-4-11{
16
- animation-name:magritte-fade-in___yS4Ja_5-4-11;
19
+ .magritte-item-animation-timeout___pbOyZ_5-5-0{
20
+ animation-name:magritte-fade-in___yS4Ja_5-5-0;
17
21
  animation-timing-function:var(--magritte-semantic-animation-ease-in-out-200-timing-function-v24-3-0);
18
22
  --animation-duration:0ms;
19
23
  animation-duration:var(--animation-duration);
20
24
  }
21
25
  @media (prefers-reduced-motion: no-preference){
22
- .magritte-item-animation-timeout___pbOyZ_5-4-11{
26
+ .magritte-item-animation-timeout___pbOyZ_5-5-0{
23
27
  --animation-duration:var(--magritte-semantic-animation-ease-in-out-200-duration-v24-3-0);
24
28
  }
25
29
  }
26
- .magritte-wrapper___GHKV6_5-4-11{
30
+ .magritte-wrapper___GHKV6_5-5-0{
27
31
  display:flex;
28
32
  padding:12px 0;
29
33
  gap:12px;
30
34
  align-items:flex-start;
31
35
  }
32
- .magritte-letter___yZOCU_5-4-11{
36
+ .magritte-wrapper___GHKV6_5-5-0.focus-visible{
37
+ box-shadow:inset 0 0 0 4px var(--magritte-color-stroke-state-focused-accessible-v24-3-0);
38
+ }
39
+ .magritte-letter___yZOCU_5-5-0{
33
40
  width:24px;
34
41
  height:24px;
35
42
  display:flex;
@@ -37,74 +44,74 @@
37
44
  justify-content:center;
38
45
  flex-shrink:0;
39
46
  }
40
- .magritte-icon___kO3Fj_5-4-11,
41
- .magritte-space___xTO79_5-4-11{
47
+ .magritte-icon___kO3Fj_5-5-0,
48
+ .magritte-space___xTO79_5-5-0{
42
49
  flex-shrink:0;
43
50
  line-height:0;
44
51
  width:24px;
45
52
  }
46
- .magritte-icon___kO3Fj_5-4-11{
53
+ .magritte-icon___kO3Fj_5-5-0{
47
54
  transform:rotate(0);
48
55
  }
49
- .magritte-wrapperActive___Hwk8p_5-4-11,
50
- .magritte-iconActive___4yrG5_5-4-11{
56
+ .magritte-wrapperActive___Hwk8p_5-5-0,
57
+ .magritte-iconActive___4yrG5_5-5-0{
51
58
  cursor:pointer;
52
59
  }
53
- .magritte-iconUp___mpXV6_5-4-11{
60
+ .magritte-iconUp___mpXV6_5-5-0{
54
61
  transform:rotate(90deg);
55
62
  }
56
63
  @media (prefers-reduced-motion: no-preference){
57
- .magritte-icon___kO3Fj_5-4-11{
64
+ .magritte-icon___kO3Fj_5-5-0{
58
65
  transition-property:transform;
59
66
  transition-duration:var(--magritte-semantic-animation-ease-in-out-100-duration-v24-3-0);
60
67
  transition-timing-function:var(--magritte-semantic-animation-ease-in-out-100-timing-function-v24-3-0);
61
68
  }
62
69
  }
63
- .magritte-content___ZRc6R_5-4-11{
70
+ .magritte-content___ZRc6R_5-5-0{
64
71
  flex-grow:1;
65
72
  }
66
- .magritte-mobile-item___ynALC_5-4-11{
73
+ .magritte-mobile-item___ynALC_5-5-0{
67
74
  display:flex;
68
75
  gap:12px;
69
76
  flex-wrap:wrap;
70
77
  }
71
- .magritte-with-gap___gbvGO_5-4-11{
78
+ .magritte-with-gap___gbvGO_5-5-0{
72
79
  padding-top:12px;
73
80
  }
74
- .magritte-virtualized-list___qt2E6_5-4-11{
81
+ .magritte-virtualized-list___qt2E6_5-5-0{
75
82
  width:100%;
76
83
  position:relative;
77
84
  will-change:transform;
78
85
  }
79
- .magritte-virtualized-item___qAYVN_5-4-11{
86
+ .magritte-virtualized-item___qAYVN_5-5-0{
80
87
  position:absolute;
81
88
  top:0;
82
89
  left:0;
83
90
  width:100%;
84
91
  }
85
- .magritte-was-expanded___uCFbW_5-4-11{
86
- animation-name:magritte-fade-in___yS4Ja_5-4-11;
92
+ .magritte-was-expanded___uCFbW_5-5-0{
93
+ animation-name:magritte-fade-in___yS4Ja_5-5-0;
87
94
  animation-timing-function:var(--magritte-semantic-animation-ease-in-out-200-timing-function-v24-3-0);
88
95
  --animation-duration:0ms;
89
96
  animation-duration:var(--animation-duration);
90
97
  }
91
98
  @media (prefers-reduced-motion: no-preference){
92
- .magritte-was-expanded___uCFbW_5-4-11{
99
+ .magritte-was-expanded___uCFbW_5-5-0{
93
100
  --animation-duration:var(--magritte-semantic-animation-ease-in-out-200-duration-v24-3-0);
94
101
  }
95
102
  }
96
103
 
97
- .magritte-wrapper___EzesX_5-4-11{
104
+ .magritte-wrapper___EzesX_5-5-0{
98
105
  height:100%;
99
106
  position:relative;
100
107
  }
101
- .magritte-scroll-container___wGzfI_5-4-11{
108
+ .magritte-scroll-container___wGzfI_5-5-0{
102
109
  height:100%;
103
110
  overflow:auto;
104
111
  overscroll-behavior:none;
105
112
  scrollbar-width:none;
106
113
  }
107
- .magritte-scroll-container___wGzfI_5-4-11::-webkit-scrollbar{
114
+ .magritte-scroll-container___wGzfI_5-5-0::-webkit-scrollbar{
108
115
  display:none;
109
116
  }
110
117
 
@@ -112,7 +119,7 @@
112
119
  --magritte-semantic-animation-ease-in-out-200-timing-function-v24-3-0:cubic-bezier(0.25, 0.1, 0.25, 1);
113
120
  --magritte-semantic-animation-ease-in-out-200-duration-v24-3-0:200ms;
114
121
  }
115
- @keyframes magritte-fade-in___FDoho_5-4-11{
122
+ @keyframes magritte-fade-in___FDoho_5-5-0{
116
123
  0%{
117
124
  opacity:0;
118
125
  }
@@ -120,14 +127,14 @@
120
127
  opacity:1;
121
128
  }
122
129
  }
123
- .magritte-item-animation-timeout___Pdli9_5-4-11{
124
- animation-name:magritte-fade-in___FDoho_5-4-11;
130
+ .magritte-item-animation-timeout___Pdli9_5-5-0{
131
+ animation-name:magritte-fade-in___FDoho_5-5-0;
125
132
  animation-timing-function:var(--magritte-semantic-animation-ease-in-out-200-timing-function-v24-3-0);
126
133
  --animation-duration:0ms;
127
134
  animation-duration:var(--animation-duration);
128
135
  }
129
136
  @media (prefers-reduced-motion: no-preference){
130
- .magritte-item-animation-timeout___Pdli9_5-4-11{
137
+ .magritte-item-animation-timeout___Pdli9_5-5-0{
131
138
  --animation-duration:var(--magritte-semantic-animation-ease-in-out-200-duration-v24-3-0);
132
139
  }
133
140
  }
package/index.js CHANGED
@@ -18,15 +18,15 @@ import '@hh.ru/magritte-common-fuzzy-search';
18
18
  import '@hh.ru/magritte-ui-breakpoint';
19
19
  import './ItemsList.js';
20
20
  import '@tanstack/react-virtual';
21
+ import '@hh.ru/magritte-common-keyboard';
21
22
  import './Item.js';
22
23
  import 'classnames';
23
24
  import './ItemContent.js';
24
- import '@hh.ru/magritte-common-keyboard';
25
25
  import '@hh.ru/magritte-ui-icon/icon';
26
26
  import './Action.js';
27
27
  import '@hh.ru/magritte-ui-checkbox-radio';
28
28
  import '@hh.ru/magritte-ui-typography';
29
- import './tree-selector-item-Ch4gUsnP.js';
29
+ import './tree-selector-item-xbLyWy2t.js';
30
30
  import './MobileItemsList.js';
31
31
  import '@hh.ru/magritte-common-func-utils';
32
32
  import '@hh.ru/magritte-ui-cell';
package/index.mock.js CHANGED
@@ -16,16 +16,16 @@ import '@hh.ru/magritte-internal-custom-scroll';
16
16
  import '@hh.ru/magritte-ui-scrollbar';
17
17
  import './ItemsList.js';
18
18
  import '@tanstack/react-virtual';
19
+ import '@hh.ru/magritte-common-keyboard';
19
20
  import './Item.js';
20
21
  import './ItemContent.js';
21
- import '@hh.ru/magritte-common-keyboard';
22
22
  import '@hh.ru/magritte-ui-icon/icon';
23
23
  import './Action.js';
24
24
  import '@hh.ru/magritte-ui-checkbox-radio';
25
25
  import './TreeSelectorItemBase.js';
26
26
  import '@hh.ru/magritte-ui-cell';
27
27
  import '@hh.ru/magritte-ui-typography';
28
- import './tree-selector-item-Ch4gUsnP.js';
28
+ import './tree-selector-item-xbLyWy2t.js';
29
29
 
30
30
  const TreeSelector = mockComponent('TreeSelector', undefined, { withChildren: true });
31
31
  const TreeSelectorDummy = mockComponent('TreeSelectorDummy', undefined, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hh.ru/magritte-ui-tree-selector",
3
- "version": "5.4.11",
3
+ "version": "5.5.0",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "sideEffects": [
@@ -49,5 +49,5 @@
49
49
  "publishConfig": {
50
50
  "access": "public"
51
51
  },
52
- "gitHead": "ff56ef41163336bfa045c946826add31b2ddb851"
52
+ "gitHead": "f0450749e357a57429bbbdcba59c0b43623dd384"
53
53
  }
@@ -0,0 +1,5 @@
1
+ import './index.css';
2
+ var styles = {"item-animation-timeout":"magritte-item-animation-timeout___pbOyZ_5-5-0","itemAnimationTimeout":"magritte-item-animation-timeout___pbOyZ_5-5-0","fade-in":"magritte-fade-in___yS4Ja_5-5-0","fadeIn":"magritte-fade-in___yS4Ja_5-5-0","wrapper":"magritte-wrapper___GHKV6_5-5-0","letter":"magritte-letter___yZOCU_5-5-0","icon":"magritte-icon___kO3Fj_5-5-0","space":"magritte-space___xTO79_5-5-0","wrapperActive":"magritte-wrapperActive___Hwk8p_5-5-0","iconActive":"magritte-iconActive___4yrG5_5-5-0","iconUp":"magritte-iconUp___mpXV6_5-5-0","content":"magritte-content___ZRc6R_5-5-0","mobile-item":"magritte-mobile-item___ynALC_5-5-0","mobileItem":"magritte-mobile-item___ynALC_5-5-0","with-gap":"magritte-with-gap___gbvGO_5-5-0","withGap":"magritte-with-gap___gbvGO_5-5-0","virtualized-list":"magritte-virtualized-list___qt2E6_5-5-0","virtualizedList":"magritte-virtualized-list___qt2E6_5-5-0","virtualized-item":"magritte-virtualized-item___qAYVN_5-5-0","virtualizedItem":"magritte-virtualized-item___qAYVN_5-5-0","was-expanded":"magritte-was-expanded___uCFbW_5-5-0","wasExpanded":"magritte-was-expanded___uCFbW_5-5-0"};
3
+
4
+ export { styles as s };
5
+ //# sourceMappingURL=tree-selector-item-xbLyWy2t.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-selector-item-xbLyWy2t.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,7 +1,7 @@
1
1
  import './index.css';
2
2
  import { useState, useLayoutEffect } from 'react';
3
3
 
4
- var styles = {"item-animation-timeout":"magritte-item-animation-timeout___Pdli9_5-4-11","itemAnimationTimeout":"magritte-item-animation-timeout___Pdli9_5-4-11","fade-in":"magritte-fade-in___FDoho_5-4-11","fadeIn":"magritte-fade-in___FDoho_5-4-11"};
4
+ var styles = {"item-animation-timeout":"magritte-item-animation-timeout___Pdli9_5-5-0","itemAnimationTimeout":"magritte-item-animation-timeout___Pdli9_5-5-0","fade-in":"magritte-fade-in___FDoho_5-5-0","fadeIn":"magritte-fade-in___FDoho_5-5-0"};
5
5
 
6
6
  const useAnimationTimeout = () => {
7
7
  const [animationTimeout, setAnimationTimeout] = useState(0);
@@ -1,5 +0,0 @@
1
- import './index.css';
2
- var styles = {"item-animation-timeout":"magritte-item-animation-timeout___pbOyZ_5-4-11","itemAnimationTimeout":"magritte-item-animation-timeout___pbOyZ_5-4-11","fade-in":"magritte-fade-in___yS4Ja_5-4-11","fadeIn":"magritte-fade-in___yS4Ja_5-4-11","wrapper":"magritte-wrapper___GHKV6_5-4-11","letter":"magritte-letter___yZOCU_5-4-11","icon":"magritte-icon___kO3Fj_5-4-11","space":"magritte-space___xTO79_5-4-11","wrapperActive":"magritte-wrapperActive___Hwk8p_5-4-11","iconActive":"magritte-iconActive___4yrG5_5-4-11","iconUp":"magritte-iconUp___mpXV6_5-4-11","content":"magritte-content___ZRc6R_5-4-11","mobile-item":"magritte-mobile-item___ynALC_5-4-11","mobileItem":"magritte-mobile-item___ynALC_5-4-11","with-gap":"magritte-with-gap___gbvGO_5-4-11","withGap":"magritte-with-gap___gbvGO_5-4-11","virtualized-list":"magritte-virtualized-list___qt2E6_5-4-11","virtualizedList":"magritte-virtualized-list___qt2E6_5-4-11","virtualized-item":"magritte-virtualized-item___qAYVN_5-4-11","virtualizedItem":"magritte-virtualized-item___qAYVN_5-4-11","was-expanded":"magritte-was-expanded___uCFbW_5-4-11","wasExpanded":"magritte-was-expanded___uCFbW_5-4-11"};
3
-
4
- export { styles as s };
5
- //# sourceMappingURL=tree-selector-item-Ch4gUsnP.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"tree-selector-item-Ch4gUsnP.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}