@cloud-ru/ds-list 1.1.4-preview-5ffe9ec9.0 → 1.1.4

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/CHANGELOG.md CHANGED
@@ -3,6 +3,10 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 1.1.4 (2026-08-25)
7
+
8
+ **Note:** Version bump only for package @ds/list
9
+
6
10
  ## 1.1.3 (2026-08-24)
7
11
 
8
12
  **Note:** Version bump only for package @ds/list
@@ -22,10 +22,16 @@ function AccordionItem({ id, disabled, allChildIds, items, ...option }) {
22
22
  const isOpen = Boolean(openCollapseItems.includes(id ?? ''));
23
23
  const checked = Boolean((indeterminate && !isOpen && isSelectionSingle && value && allChildIds.includes(value)) ||
24
24
  (isSelectionMultiple && checkedProp));
25
- // Раскрытие переключает вся строка целиком: клик/Enter по телу и ArrowRight с клавиатуры.
26
- const handleToggle = (0, react_1.useCallback)(() => {
25
+ const handleKeyDown = (0, react_1.useCallback)(() => {
27
26
  toggleOpenCollapseItem?.(id ?? '');
28
27
  }, [id, toggleOpenCollapseItem]);
29
28
  const itemsJSX = (0, hooks_1.useRenderItems)(items);
30
- return ((0, jsx_runtime_1.jsx)(helperComponents_1.CollapseBlockPrivate, { header: (0, jsx_runtime_1.jsx)(BaseItem_1.BaseItem, { ...option, id: id, disabled: disabled, open: isOpen, expandIcon: isOpen ? (0, jsx_runtime_1.jsx)(system_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.ChevronDownSVG, {}), onToggleExpand: handleToggle, isParentNode: true, onOpenNestedList: handleToggle, checked: checked, indeterminate: indeterminate, onSelect: !disabled ? handleOnSelect : undefined }), expanded: isOpen, "data-test-id": `${constants_1.TEST_IDS.accordionItem}-${id}`, children: (0, jsx_runtime_1.jsx)(contexts_1.CollapseLevelContext.Provider, { value: { level: level + 1 }, children: itemsJSX }) }));
29
+ // Раскрытие привязано к явной кнопке-триггеру `groupIndicator` (шеврон справа) и
30
+ // ТОЛЬКО переключает collapse — `option.onClick` сюда не зовём, иначе у потребителя,
31
+ // который вешает на onClick собственный toggle, выходит двойное переключение.
32
+ // Клик по телу строки (выбор/навигация) идёт через `option.onClick` в BaseItem.
33
+ const handleExpandIconClick = () => {
34
+ toggleOpenCollapseItem?.(id ?? '');
35
+ };
36
+ return ((0, jsx_runtime_1.jsx)(helperComponents_1.CollapseBlockPrivate, { header: (0, jsx_runtime_1.jsx)(BaseItem_1.BaseItem, { ...option, id: id, disabled: disabled, open: isOpen, expandIcon: isOpen ? (0, jsx_runtime_1.jsx)(system_1.ChevronUpSVG, {}) : (0, jsx_runtime_1.jsx)(system_1.ChevronDownSVG, {}), onExpandIconClick: handleExpandIconClick, isParentNode: true, onOpenNestedList: handleKeyDown, checked: checked, indeterminate: indeterminate, onSelect: !disabled ? handleOnSelect : undefined }), expanded: isOpen, "data-test-id": `${constants_1.TEST_IDS.accordionItem}-${id}`, children: (0, jsx_runtime_1.jsx)(contexts_1.CollapseLevelContext.Provider, { value: { level: level + 1 }, children: itemsJSX }) }));
31
37
  }
@@ -1,4 +1,4 @@
1
- import { KeyboardEvent, ReactNode } from 'react';
1
+ import { KeyboardEvent, MouseEvent, ReactNode } from 'react';
2
2
  import { FlattenBaseItem } from '../types';
3
3
  type AllBaseItemProps = FlattenBaseItem & {
4
4
  expandIcon?: ReactNode;
@@ -8,11 +8,11 @@ type AllBaseItemProps = FlattenBaseItem & {
8
8
  isParentNode?: boolean;
9
9
  onOpenNestedList?(e?: KeyboardEvent<HTMLElement>): void;
10
10
  /**
11
- * Переключение раскрытия вложенного списка. Триггер вся строка целиком (клик или
12
- * Enter/Space), шеврон `groupIndicator` при этом остаётся неинтерактивным индикатором
13
- * состояния.
11
+ * Клик по явной кнопке-триггеру `groupIndicator` (шеврон справа), открывающей/закрывающей
12
+ * вложенный список. Если передан — шеврон рендерится как отдельная интерактивная кнопка
13
+ * со своим state-layer'ом, а клик по телу строки больше не переключает раскрытие.
14
14
  */
15
- onToggleExpand?(): void;
15
+ onExpandIconClick?(e: MouseEvent<HTMLElement>): void;
16
16
  /**
17
17
  * Слот ручки drag&drop (Figma `centeredWrapper`) — рендерится первым в строке, перед
18
18
  * маркером/чекбоксом. Интерактивность (обработчики `@dnd-kit`) и содержимое (иконка)
@@ -20,5 +20,5 @@ type AllBaseItemProps = FlattenBaseItem & {
20
20
  */
21
21
  dragHandle?: ReactNode;
22
22
  };
23
- export declare function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onToggleExpand, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }: AllBaseItemProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
23
+ export declare function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onExpandIconClick, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }: AllBaseItemProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
24
24
  export {};
@@ -15,7 +15,7 @@ const styles_module_scss_1 = __importDefault(require('../styles.module.css'));
15
15
  const utils_2 = require("../utils");
16
16
  const constants_2 = require("./constants");
17
17
  const styles_module_scss_2 = __importDefault(require('./styles.module.css'));
18
- function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onToggleExpand, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }) {
18
+ function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onExpandIconClick, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }) {
19
19
  const interactive = !inactive;
20
20
  const { size = constants_1.DEFAULT_SIZE, marker, contentRender, firstItemId, focusFlattenItems } = (0, contexts_1.useNewListContext)();
21
21
  const { level = 0 } = (0, contexts_1.useCollapseLevelContext)();
@@ -50,12 +50,7 @@ function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown,
50
50
  // `onClick` в публичном API типизирован под `MouseEvent` (это семантически клик по
51
51
  // пункту меню), поэтому keyboard-событие пробрасывается под тем же типом.
52
52
  onClick?.(e);
53
- if (isParentNode) {
54
- // Раскрытие вложенного списка триггерит вся строка целиком: шеврон `groupIndicator` —
55
- // только индикатор состояния, собственной интерактивности у него нет.
56
- onToggleExpand?.();
57
- }
58
- else if (interactive) {
53
+ if (interactive && !isParentNode) {
59
54
  handleChange();
60
55
  }
61
56
  if (!isSelectionMultiple && closeDroplistOnItemClick) {
@@ -71,21 +66,13 @@ function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown,
71
66
  return;
72
67
  }
73
68
  if (e.key === 'Enter' || e.key === ' ') {
74
- if (isParentNode) {
75
- // В multiple-режиме Enter/Space на группе выбирает всю ветку, иначе — раскрывает её.
76
- if (isSelectionMultiple && onSelect) {
77
- onSelect();
78
- }
79
- else {
80
- onToggleExpand?.();
81
- }
82
- }
83
- else {
84
- // Повторяем клик по элементу: `handleItemClick` сам вызывает `handleChange` /
85
- // `closeDroplist`. Отдельный `handleChange` здесь не нужен — иначе в multiple-режиме
86
- // выбор переключался бы дважды (toggle + откат) и Enter не менял бы состояние.
87
- handleItemClick(e);
69
+ if (isSelectionMultiple && isParentNode && onSelect) {
70
+ onSelect();
88
71
  }
72
+ // Повторяем клик по элементу: `handleItemClick` сам вызывает `handleChange` /
73
+ // `closeDroplist`. Отдельный `handleChange` здесь не нужен — иначе в multiple-режиме
74
+ // выбор переключался бы дважды (toggle + откат) и Enter не менял бы состояние.
75
+ !isParentNode && handleItemClick(e);
89
76
  e.stopPropagation();
90
77
  e.preventDefault();
91
78
  }
@@ -95,6 +82,16 @@ function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown,
95
82
  e.stopPropagation();
96
83
  }
97
84
  };
85
+ const handleExpandIconClick = (e) => {
86
+ if (disabled) {
87
+ return;
88
+ }
89
+ // Триггер раскрытия изолирован от клика по строке: всплытие останавливаем,
90
+ // чтобы клик по шеврону не активировал выбор/навигацию пункта.
91
+ e.stopPropagation();
92
+ e.preventDefault();
93
+ onExpandIconClick?.(e);
94
+ };
98
95
  const props = (0, utils_1.extractSupportProps)(rest);
99
96
  let contentNode;
100
97
  if (content && (0, utils_2.isContentItem)(content)) {
@@ -111,7 +108,9 @@ function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown,
111
108
  const stateLayerState = isSelectionSingle && isChecked && !switchProp && !isParentNode
112
109
  ? 'activatedOnBackground'
113
110
  : 'emptyNeutralOnBackground';
114
- const itemJSX = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.itemWrapper, styles_module_scss_2.default.innerWrapper, className), "data-inactive": inactive || undefined, "data-disabled": disabled || undefined, "data-variant": mode || undefined, "data-checked": (isParentNode && isChecked) || (!isParentNode && isChecked && !switchProp) || undefined, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.stateLayer, "aria-hidden": true, "data-state": stateLayerState }), (0, jsx_runtime_1.jsxs)("li", { "data-type": 'outside', role: 'menuitem', "data-test-id": props['data-test-id'] || `${constants_1.TEST_IDS.baseItem}_${id}`, ref: itemRef, className: (0, classnames_1.default)(styles_module_scss_1.default.listItem, styles_module_scss_2.default.droplistItem), "data-size": size, onClick: handleItemClick, onMouseDown: handleItemMouseDown, tabIndex: firstItemId && id === focusFlattenItems[firstItemId]?.originalId ? 0 : -1, "data-non-pointer": (inactive && !onClick) || undefined, "data-variant": mode || undefined, "data-open": open || undefined, "aria-expanded": isParentNode ? Boolean(open) : undefined, onKeyDown: handleItemKeyDown, onFocus: handleItemFocus, style: { '--level': level }, "data-level-one": level === 1 || undefined, "data-level-more-one": level > 1 || undefined, "data-checked": (isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined, children: [dragHandle && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.dragHandle, children: dragHandle }), !switchProp && isSelectionSingle && marker && !isParentNode && interactive && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.markerContainer, "data-test-id": constants_1.TEST_IDS.baseItemMarker })), !switchProp && isSelectionMultiple && interactive && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.checkbox, children: (0, jsx_runtime_1.jsx)(toggles_1.Checkbox, { size: constants_2.TOGGLE_SIZE_MAP[size], disabled: disabled, tabIndex: -1, onChange: isParentNode ? handleCheckboxChange : undefined, checked: isChecked, "data-test-id": constants_1.TEST_IDS.baseItemCheckbox, onClick: handleCheckboxClick, indeterminate: indeterminate }) })), beforeContent && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.beforeContent, children: beforeContent }), contentNode, afterContent && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.afterContent, children: afterContent }), switchProp && interactive && ((0, jsx_runtime_1.jsx)(toggles_1.Switch, { size: constants_2.TOGGLE_SIZE_MAP[size], disabled: disabled, checked: isChecked, "data-test-id": constants_1.TEST_IDS.baseItemSwitch, showIcon: showSwitchIcon })), !switchProp && expandIcon && ((0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.groupIndicator, "data-open": open || undefined, "data-test-id": constants_1.TEST_IDS.groupIndicator, "aria-hidden": true, children: expandIcon }))] })] }));
111
+ const itemJSX = ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.itemWrapper, styles_module_scss_2.default.innerWrapper, className), "data-inactive": inactive || undefined, "data-disabled": disabled || undefined, "data-variant": mode || undefined, "data-checked": (isParentNode && isChecked) || (!isParentNode && isChecked && !switchProp) || undefined, children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_1.default.stateLayer, "aria-hidden": true, "data-state": stateLayerState }), (0, jsx_runtime_1.jsxs)("li", { "data-type": 'outside', role: 'menuitem', "data-test-id": props['data-test-id'] || `${constants_1.TEST_IDS.baseItem}_${id}`, ref: itemRef, className: (0, classnames_1.default)(styles_module_scss_1.default.listItem, styles_module_scss_2.default.droplistItem), "data-size": size, onClick: handleItemClick, onMouseDown: handleItemMouseDown, tabIndex: firstItemId && id === focusFlattenItems[firstItemId]?.originalId ? 0 : -1, "data-non-pointer": (inactive && !onClick) || undefined, "data-variant": mode || undefined, "data-open": open || undefined, onKeyDown: handleItemKeyDown, onFocus: handleItemFocus, style: { '--level': level }, "data-level-one": level === 1 || undefined, "data-level-more-one": level > 1 || undefined, "data-checked": (isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined, children: [dragHandle && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.dragHandle, children: dragHandle }), !switchProp && isSelectionSingle && marker && !isParentNode && interactive && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.markerContainer, "data-test-id": constants_1.TEST_IDS.baseItemMarker })), !switchProp && isSelectionMultiple && interactive && ((0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.checkbox, children: (0, jsx_runtime_1.jsx)(toggles_1.Checkbox, { size: constants_2.TOGGLE_SIZE_MAP[size], disabled: disabled, tabIndex: -1, onChange: isParentNode ? handleCheckboxChange : undefined, checked: isChecked, "data-test-id": constants_1.TEST_IDS.baseItemCheckbox, onClick: handleCheckboxClick, indeterminate: indeterminate }) })), beforeContent && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.beforeContent, children: beforeContent }), contentNode, afterContent && (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_2.default.afterContent, children: afterContent }), switchProp && interactive && ((0, jsx_runtime_1.jsx)(toggles_1.Switch, { size: constants_2.TOGGLE_SIZE_MAP[size], disabled: disabled, checked: isChecked, "data-test-id": constants_1.TEST_IDS.baseItemSwitch, showIcon: showSwitchIcon })), !switchProp &&
112
+ expandIcon &&
113
+ (onExpandIconClick ? ((0, jsx_runtime_1.jsxs)("button", { type: 'button', className: styles_module_scss_2.default.groupIndicator, "data-size": size, "data-open": open || undefined, "data-test-id": constants_1.TEST_IDS.groupIndicator, tabIndex: -1, disabled: disabled, onClick: handleExpandIconClick, onMouseDown: e => e.stopPropagation(), children: [(0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.groupIndicatorState, "aria-hidden": true }), expandIcon] })) : ((0, jsx_runtime_1.jsx)("span", { className: styles_module_scss_2.default.expandableIcon, children: expandIcon })))] })] }));
115
114
  if (!itemWrapRender) {
116
115
  return itemJSX;
117
116
  }
@@ -56,22 +56,62 @@
56
56
  color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
57
57
  }
58
58
 
59
+ .expandableIcon{
60
+ display:flex;
61
+ align-items:center;
62
+ color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
63
+ fill:currentcolor;
64
+ }
65
+
59
66
  .groupIndicator{
60
- pointer-events:none;
67
+ cursor:pointer;
68
+ position:relative;
61
69
  display:flex;
62
70
  flex-shrink:0;
63
71
  align-items:center;
64
72
  justify-content:center;
73
+ padding:0;
74
+ border:none;
75
+ border-radius:var(--sn-primitive-dimension-8, 8px);
65
76
  color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
66
- fill:currentcolor;
77
+ -webkit-appearance:none;
78
+ -moz-appearance:none;
79
+ appearance:none;
80
+ background:transparent;
81
+ outline:none;
67
82
  }
68
83
  .groupIndicator svg{
69
- width:100%;
70
- height:100%;
84
+ position:relative;
85
+ z-index:1;
86
+ width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
87
+ height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
88
+ }
89
+ .groupIndicator:focus-visible{
90
+ outline:var(--sn-theme-color-available-complementary, #000000) solid var(--sn-primitive-strokeWeight-strokeSemiBold, 2px);
91
+ outline-offset:calc(0px - var(--sn-primitive-strokeWeight-strokeSemiBold, 2px));
71
92
  }
72
93
  .groupIndicator[data-open]{
73
94
  border-radius:var(--sn-primitive-dimension-2, 2px);
74
95
  color:var(--sn-theme-color-available-version-textMain, var(--sn-brand-color-text-version-main, #41424e));
96
+ }
97
+
98
+ .groupIndicatorState{
99
+ pointer-events:none;
100
+ position:absolute;
101
+ inset:0;
102
+ border-radius:inherit;
103
+ background:transparent;
104
+ }
105
+
106
+ .groupIndicator:hover > .groupIndicatorState{
107
+ background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-hovered-filled, var(--sn-brand-color-state-neutral-forLightMode-hovered-background, rgba(188, 195, 220, 0.1490196078)));
108
+ }
109
+
110
+ .groupIndicator:active > .groupIndicatorState{
111
+ background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-pressed-filled, var(--sn-brand-color-state-neutral-forLightMode-pressed-background, rgba(188, 195, 220, 0.3019607843)));
112
+ }
113
+
114
+ .groupIndicator[data-open] > .groupIndicatorState{
75
115
  background:var(--sn-theme-color-neutral-decorTransparent, var(--sn-brand-color-neutral-transparent-forLightMode, rgba(124, 131, 182, 0.0784313725)));
76
116
  }
77
117
 
@@ -117,6 +157,10 @@
117
157
  padding-top:var(--sn-list-anatomy-size-s-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-s, var(--sn-primitive-dimension-6, 6px)));
118
158
  padding-bottom:var(--sn-list-anatomy-size-s-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-s, var(--sn-primitive-dimension-6, 6px)));
119
159
  }
160
+ .droplistItem[data-size=s] .expandableIcon{
161
+ width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
162
+ height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
163
+ }
120
164
  .droplistItem[data-size=s] .groupIndicator{
121
165
  width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
122
166
  height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
@@ -160,6 +204,10 @@
160
204
  padding-top:var(--sn-list-anatomy-size-m-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-m, var(--sn-primitive-dimension-8, 8px)));
161
205
  padding-bottom:var(--sn-list-anatomy-size-m-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-m, var(--sn-primitive-dimension-8, 8px)));
162
206
  }
207
+ .droplistItem[data-size=m] .expandableIcon{
208
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
209
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
210
+ }
163
211
  .droplistItem[data-size=m] .groupIndicator{
164
212
  width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
165
213
  height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
@@ -203,6 +251,10 @@
203
251
  padding-top:var(--sn-list-anatomy-size-l-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-l, var(--sn-primitive-dimension-10, 10px)));
204
252
  padding-bottom:var(--sn-list-anatomy-size-l-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-l, var(--sn-primitive-dimension-10, 10px)));
205
253
  }
254
+ .droplistItem[data-size=l] .expandableIcon{
255
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
256
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
257
+ }
206
258
  .droplistItem[data-size=l] .groupIndicator{
207
259
  width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
208
260
  height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
@@ -228,7 +280,11 @@
228
280
  cursor:inherit;
229
281
  }
230
282
 
283
+ .innerWrapper[data-disabled] .expandableIcon{
284
+ color:var(--sn-theme-color-available-version-textDisabled, var(--sn-brand-color-text-version-disabled, rgba(65, 66, 78, 0.3490196078)));
285
+ }
231
286
  .innerWrapper[data-disabled] .groupIndicator{
287
+ cursor:not-allowed;
232
288
  color:var(--sn-theme-color-available-version-textDisabled, var(--sn-brand-color-text-version-disabled, rgba(65, 66, 78, 0.3490196078)));
233
289
  }
234
290
  .innerWrapper[data-disabled] .beforeContent,
@@ -67,5 +67,5 @@ function NextListItem({ items, placement = 'right-start', id, scroll, scrollRef,
67
67
  }, scrollRef: scrollRef, limitedScrollHeight: true, untouchableScrollbars: untouchableScrollbars, loading: loading, dataError: dataError, dataFiltered: dataFiltered }), trigger: 'hover', open: isOpen || open, onOpenChange: value => {
68
68
  setOpen(value);
69
69
  onSublistOpenChanged?.(value, id);
70
- }, placement: placement, widthStrategy: 'auto', children: (0, jsx_runtime_1.jsx)(BaseItem_1.BaseItem, { ...option, disabled: disabled, open: isOpen || open, expandIcon: (0, jsx_runtime_1.jsx)(system_1.ChevronRightSVG, {}), id: id, isParentNode: true, indeterminate: indeterminate, checked: checked, onOpenNestedList: openSublist, onToggleExpand: openSublist, onSelect: handleOnSelect }) }));
70
+ }, placement: placement, widthStrategy: 'auto', children: (0, jsx_runtime_1.jsx)(BaseItem_1.BaseItem, { ...option, disabled: disabled, open: isOpen || open, expandIcon: (0, jsx_runtime_1.jsx)(system_1.ChevronRightSVG, {}), id: id, isParentNode: true, indeterminate: indeterminate, checked: checked, onOpenNestedList: openSublist, onExpandIconClick: openSublist, onSelect: handleOnSelect }) }));
71
71
  }
@@ -56,22 +56,62 @@
56
56
  color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
57
57
  }
58
58
 
59
+ .expandableIcon{
60
+ display:flex;
61
+ align-items:center;
62
+ color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
63
+ fill:currentcolor;
64
+ }
65
+
59
66
  .groupIndicator{
60
- pointer-events:none;
67
+ cursor:pointer;
68
+ position:relative;
61
69
  display:flex;
62
70
  flex-shrink:0;
63
71
  align-items:center;
64
72
  justify-content:center;
73
+ padding:0;
74
+ border:none;
75
+ border-radius:var(--sn-primitive-dimension-8, 8px);
65
76
  color:var(--sn-theme-color-available-version-textSecondary, var(--sn-brand-color-text-version-secondary, rgba(65, 66, 78, 0.8)));
66
- fill:currentcolor;
77
+ -webkit-appearance:none;
78
+ -moz-appearance:none;
79
+ appearance:none;
80
+ background:transparent;
81
+ outline:none;
67
82
  }
68
83
  .groupIndicator svg{
69
- width:100%;
70
- height:100%;
84
+ position:relative;
85
+ z-index:1;
86
+ width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
87
+ height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
88
+ }
89
+ .groupIndicator:focus-visible{
90
+ outline:var(--sn-theme-color-available-complementary, #000000) solid var(--sn-primitive-strokeWeight-strokeSemiBold, 2px);
91
+ outline-offset:calc(0px - var(--sn-primitive-strokeWeight-strokeSemiBold, 2px));
71
92
  }
72
93
  .groupIndicator[data-open]{
73
94
  border-radius:var(--sn-primitive-dimension-2, 2px);
74
95
  color:var(--sn-theme-color-available-version-textMain, var(--sn-brand-color-text-version-main, #41424e));
96
+ }
97
+
98
+ .groupIndicatorState{
99
+ pointer-events:none;
100
+ position:absolute;
101
+ inset:0;
102
+ border-radius:inherit;
103
+ background:transparent;
104
+ }
105
+
106
+ .groupIndicator:hover > .groupIndicatorState{
107
+ background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-hovered-filled, var(--sn-brand-color-state-neutral-forLightMode-hovered-background, rgba(188, 195, 220, 0.1490196078)));
108
+ }
109
+
110
+ .groupIndicator:active > .groupIndicatorState{
111
+ background:var(--sn-theme-color-material-stateLayer-neutral-onBackground-pressed-filled, var(--sn-brand-color-state-neutral-forLightMode-pressed-background, rgba(188, 195, 220, 0.3019607843)));
112
+ }
113
+
114
+ .groupIndicator[data-open] > .groupIndicatorState{
75
115
  background:var(--sn-theme-color-neutral-decorTransparent, var(--sn-brand-color-neutral-transparent-forLightMode, rgba(124, 131, 182, 0.0784313725)));
76
116
  }
77
117
 
@@ -117,6 +157,10 @@
117
157
  padding-top:var(--sn-list-anatomy-size-s-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-s, var(--sn-primitive-dimension-6, 6px)));
118
158
  padding-bottom:var(--sn-list-anatomy-size-s-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-s, var(--sn-primitive-dimension-6, 6px)));
119
159
  }
160
+ .droplistItem[data-size=s] .expandableIcon{
161
+ width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
162
+ height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
163
+ }
120
164
  .droplistItem[data-size=s] .groupIndicator{
121
165
  width:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
122
166
  height:var(--sn-density-size-icon-xs, var(--sn-primitive-dimension-24, 24px));
@@ -160,6 +204,10 @@
160
204
  padding-top:var(--sn-list-anatomy-size-m-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-m, var(--sn-primitive-dimension-8, 8px)));
161
205
  padding-bottom:var(--sn-list-anatomy-size-m-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-m, var(--sn-primitive-dimension-8, 8px)));
162
206
  }
207
+ .droplistItem[data-size=m] .expandableIcon{
208
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
209
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
210
+ }
163
211
  .droplistItem[data-size=m] .groupIndicator{
164
212
  width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
165
213
  height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
@@ -203,6 +251,10 @@
203
251
  padding-top:var(--sn-list-anatomy-size-l-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-l, var(--sn-primitive-dimension-10, 10px)));
204
252
  padding-bottom:var(--sn-list-anatomy-size-l-listItem-centeredWrapper-paddingVertical, var(--sn-density-spacing-control-container-vertical-l, var(--sn-primitive-dimension-10, 10px)));
205
253
  }
254
+ .droplistItem[data-size=l] .expandableIcon{
255
+ width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
256
+ height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
257
+ }
206
258
  .droplistItem[data-size=l] .groupIndicator{
207
259
  width:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
208
260
  height:var(--sn-density-size-icon-s, var(--sn-primitive-dimension-24, 24px));
@@ -228,7 +280,11 @@
228
280
  cursor:inherit;
229
281
  }
230
282
 
283
+ .innerWrapper[data-disabled] .expandableIcon{
284
+ color:var(--sn-theme-color-available-version-textDisabled, var(--sn-brand-color-text-version-disabled, rgba(65, 66, 78, 0.3490196078)));
285
+ }
231
286
  .innerWrapper[data-disabled] .groupIndicator{
287
+ cursor:not-allowed;
232
288
  color:var(--sn-theme-color-available-version-textDisabled, var(--sn-brand-color-text-version-disabled, rgba(65, 66, 78, 0.3490196078)));
233
289
  }
234
290
  .innerWrapper[data-disabled] .beforeContent,
@@ -19,10 +19,16 @@ export function AccordionItem({ id, disabled, allChildIds, items, ...option }) {
19
19
  const isOpen = Boolean(openCollapseItems.includes(id ?? ''));
20
20
  const checked = Boolean((indeterminate && !isOpen && isSelectionSingle && value && allChildIds.includes(value)) ||
21
21
  (isSelectionMultiple && checkedProp));
22
- // Раскрытие переключает вся строка целиком: клик/Enter по телу и ArrowRight с клавиатуры.
23
- const handleToggle = useCallback(() => {
22
+ const handleKeyDown = useCallback(() => {
24
23
  toggleOpenCollapseItem?.(id ?? '');
25
24
  }, [id, toggleOpenCollapseItem]);
26
25
  const itemsJSX = useRenderItems(items);
27
- return (_jsx(CollapseBlockPrivate, { header: _jsx(BaseItem, { ...option, id: id, disabled: disabled, open: isOpen, expandIcon: isOpen ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}), onToggleExpand: handleToggle, isParentNode: true, onOpenNestedList: handleToggle, checked: checked, indeterminate: indeterminate, onSelect: !disabled ? handleOnSelect : undefined }), expanded: isOpen, "data-test-id": `${TEST_IDS.accordionItem}-${id}`, children: _jsx(CollapseLevelContext.Provider, { value: { level: level + 1 }, children: itemsJSX }) }));
26
+ // Раскрытие привязано к явной кнопке-триггеру `groupIndicator` (шеврон справа) и
27
+ // ТОЛЬКО переключает collapse — `option.onClick` сюда не зовём, иначе у потребителя,
28
+ // который вешает на onClick собственный toggle, выходит двойное переключение.
29
+ // Клик по телу строки (выбор/навигация) идёт через `option.onClick` в BaseItem.
30
+ const handleExpandIconClick = () => {
31
+ toggleOpenCollapseItem?.(id ?? '');
32
+ };
33
+ return (_jsx(CollapseBlockPrivate, { header: _jsx(BaseItem, { ...option, id: id, disabled: disabled, open: isOpen, expandIcon: isOpen ? _jsx(ChevronUpSVG, {}) : _jsx(ChevronDownSVG, {}), onExpandIconClick: handleExpandIconClick, isParentNode: true, onOpenNestedList: handleKeyDown, checked: checked, indeterminate: indeterminate, onSelect: !disabled ? handleOnSelect : undefined }), expanded: isOpen, "data-test-id": `${TEST_IDS.accordionItem}-${id}`, children: _jsx(CollapseLevelContext.Provider, { value: { level: level + 1 }, children: itemsJSX }) }));
28
34
  }
@@ -1,4 +1,4 @@
1
- import { KeyboardEvent, ReactNode } from 'react';
1
+ import { KeyboardEvent, MouseEvent, ReactNode } from 'react';
2
2
  import { FlattenBaseItem } from '../types.js';
3
3
  type AllBaseItemProps = FlattenBaseItem & {
4
4
  expandIcon?: ReactNode;
@@ -8,11 +8,11 @@ type AllBaseItemProps = FlattenBaseItem & {
8
8
  isParentNode?: boolean;
9
9
  onOpenNestedList?(e?: KeyboardEvent<HTMLElement>): void;
10
10
  /**
11
- * Переключение раскрытия вложенного списка. Триггер вся строка целиком (клик или
12
- * Enter/Space), шеврон `groupIndicator` при этом остаётся неинтерактивным индикатором
13
- * состояния.
11
+ * Клик по явной кнопке-триггеру `groupIndicator` (шеврон справа), открывающей/закрывающей
12
+ * вложенный список. Если передан — шеврон рендерится как отдельная интерактивная кнопка
13
+ * со своим state-layer'ом, а клик по телу строки больше не переключает раскрытие.
14
14
  */
15
- onToggleExpand?(): void;
15
+ onExpandIconClick?(e: MouseEvent<HTMLElement>): void;
16
16
  /**
17
17
  * Слот ручки drag&drop (Figma `centeredWrapper`) — рендерится первым в строке, перед
18
18
  * маркером/чекбоксом. Интерактивность (обработчики `@dnd-kit`) и содержимое (иконка)
@@ -20,5 +20,5 @@ type AllBaseItemProps = FlattenBaseItem & {
20
20
  */
21
21
  dragHandle?: ReactNode;
22
22
  };
23
- export declare function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onToggleExpand, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }: AllBaseItemProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
23
+ export declare function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onExpandIconClick, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }: AllBaseItemProps): string | number | boolean | Iterable<ReactNode> | import("react/jsx-runtime").JSX.Element | null | undefined;
24
24
  export {};
@@ -9,7 +9,7 @@ import commonStyles from '../styles.module.css';
9
9
  import { isContentItem, isPrimitiveContent } from '../utils.js';
10
10
  import { TOGGLE_SIZE_MAP } from './constants.js';
11
11
  import styles from './styles.module.css';
12
- export function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onToggleExpand, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }) {
12
+ export function BaseItem({ beforeContent, afterContent, content, onClick, onMouseDown, id, expandIcon, disabled, open, itemRef, switch: switchProp, showSwitchIcon, onKeyDown, onFocus, indeterminate, checked: checkedProp, onSelect, onOpenNestedList, onExpandIconClick, isParentNode, className, inactive, itemWrapRender, dragHandle, ...rest }) {
13
13
  const interactive = !inactive;
14
14
  const { size = DEFAULT_SIZE, marker, contentRender, firstItemId, focusFlattenItems } = useNewListContext();
15
15
  const { level = 0 } = useCollapseLevelContext();
@@ -44,12 +44,7 @@ export function BaseItem({ beforeContent, afterContent, content, onClick, onMous
44
44
  // `onClick` в публичном API типизирован под `MouseEvent` (это семантически клик по
45
45
  // пункту меню), поэтому keyboard-событие пробрасывается под тем же типом.
46
46
  onClick?.(e);
47
- if (isParentNode) {
48
- // Раскрытие вложенного списка триггерит вся строка целиком: шеврон `groupIndicator` —
49
- // только индикатор состояния, собственной интерактивности у него нет.
50
- onToggleExpand?.();
51
- }
52
- else if (interactive) {
47
+ if (interactive && !isParentNode) {
53
48
  handleChange();
54
49
  }
55
50
  if (!isSelectionMultiple && closeDroplistOnItemClick) {
@@ -65,21 +60,13 @@ export function BaseItem({ beforeContent, afterContent, content, onClick, onMous
65
60
  return;
66
61
  }
67
62
  if (e.key === 'Enter' || e.key === ' ') {
68
- if (isParentNode) {
69
- // В multiple-режиме Enter/Space на группе выбирает всю ветку, иначе — раскрывает её.
70
- if (isSelectionMultiple && onSelect) {
71
- onSelect();
72
- }
73
- else {
74
- onToggleExpand?.();
75
- }
76
- }
77
- else {
78
- // Повторяем клик по элементу: `handleItemClick` сам вызывает `handleChange` /
79
- // `closeDroplist`. Отдельный `handleChange` здесь не нужен — иначе в multiple-режиме
80
- // выбор переключался бы дважды (toggle + откат) и Enter не менял бы состояние.
81
- handleItemClick(e);
63
+ if (isSelectionMultiple && isParentNode && onSelect) {
64
+ onSelect();
82
65
  }
66
+ // Повторяем клик по элементу: `handleItemClick` сам вызывает `handleChange` /
67
+ // `closeDroplist`. Отдельный `handleChange` здесь не нужен — иначе в multiple-режиме
68
+ // выбор переключался бы дважды (toggle + откат) и Enter не менял бы состояние.
69
+ !isParentNode && handleItemClick(e);
83
70
  e.stopPropagation();
84
71
  e.preventDefault();
85
72
  }
@@ -89,6 +76,16 @@ export function BaseItem({ beforeContent, afterContent, content, onClick, onMous
89
76
  e.stopPropagation();
90
77
  }
91
78
  };
79
+ const handleExpandIconClick = (e) => {
80
+ if (disabled) {
81
+ return;
82
+ }
83
+ // Триггер раскрытия изолирован от клика по строке: всплытие останавливаем,
84
+ // чтобы клик по шеврону не активировал выбор/навигацию пункта.
85
+ e.stopPropagation();
86
+ e.preventDefault();
87
+ onExpandIconClick?.(e);
88
+ };
92
89
  const props = extractSupportProps(rest);
93
90
  let contentNode;
94
91
  if (content && isContentItem(content)) {
@@ -105,7 +102,9 @@ export function BaseItem({ beforeContent, afterContent, content, onClick, onMous
105
102
  const stateLayerState = isSelectionSingle && isChecked && !switchProp && !isParentNode
106
103
  ? 'activatedOnBackground'
107
104
  : 'emptyNeutralOnBackground';
108
- const itemJSX = (_jsxs("div", { className: cn(commonStyles.itemWrapper, styles.innerWrapper, className), "data-inactive": inactive || undefined, "data-disabled": disabled || undefined, "data-variant": mode || undefined, "data-checked": (isParentNode && isChecked) || (!isParentNode && isChecked && !switchProp) || undefined, children: [_jsx("span", { className: commonStyles.stateLayer, "aria-hidden": true, "data-state": stateLayerState }), _jsxs("li", { "data-type": 'outside', role: 'menuitem', "data-test-id": props['data-test-id'] || `${TEST_IDS.baseItem}_${id}`, ref: itemRef, className: cn(commonStyles.listItem, styles.droplistItem), "data-size": size, onClick: handleItemClick, onMouseDown: handleItemMouseDown, tabIndex: firstItemId && id === focusFlattenItems[firstItemId]?.originalId ? 0 : -1, "data-non-pointer": (inactive && !onClick) || undefined, "data-variant": mode || undefined, "data-open": open || undefined, "aria-expanded": isParentNode ? Boolean(open) : undefined, onKeyDown: handleItemKeyDown, onFocus: handleItemFocus, style: { '--level': level }, "data-level-one": level === 1 || undefined, "data-level-more-one": level > 1 || undefined, "data-checked": (isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined, children: [dragHandle && _jsx("div", { className: styles.dragHandle, children: dragHandle }), !switchProp && isSelectionSingle && marker && !isParentNode && interactive && (_jsx("div", { className: styles.markerContainer, "data-test-id": TEST_IDS.baseItemMarker })), !switchProp && isSelectionMultiple && interactive && (_jsx("div", { className: styles.checkbox, children: _jsx(Checkbox, { size: TOGGLE_SIZE_MAP[size], disabled: disabled, tabIndex: -1, onChange: isParentNode ? handleCheckboxChange : undefined, checked: isChecked, "data-test-id": TEST_IDS.baseItemCheckbox, onClick: handleCheckboxClick, indeterminate: indeterminate }) })), beforeContent && _jsx("div", { className: styles.beforeContent, children: beforeContent }), contentNode, afterContent && _jsx("div", { className: styles.afterContent, children: afterContent }), switchProp && interactive && (_jsx(Switch, { size: TOGGLE_SIZE_MAP[size], disabled: disabled, checked: isChecked, "data-test-id": TEST_IDS.baseItemSwitch, showIcon: showSwitchIcon })), !switchProp && expandIcon && (_jsx("span", { className: styles.groupIndicator, "data-open": open || undefined, "data-test-id": TEST_IDS.groupIndicator, "aria-hidden": true, children: expandIcon }))] })] }));
105
+ const itemJSX = (_jsxs("div", { className: cn(commonStyles.itemWrapper, styles.innerWrapper, className), "data-inactive": inactive || undefined, "data-disabled": disabled || undefined, "data-variant": mode || undefined, "data-checked": (isParentNode && isChecked) || (!isParentNode && isChecked && !switchProp) || undefined, children: [_jsx("span", { className: commonStyles.stateLayer, "aria-hidden": true, "data-state": stateLayerState }), _jsxs("li", { "data-type": 'outside', role: 'menuitem', "data-test-id": props['data-test-id'] || `${TEST_IDS.baseItem}_${id}`, ref: itemRef, className: cn(commonStyles.listItem, styles.droplistItem), "data-size": size, onClick: handleItemClick, onMouseDown: handleItemMouseDown, tabIndex: firstItemId && id === focusFlattenItems[firstItemId]?.originalId ? 0 : -1, "data-non-pointer": (inactive && !onClick) || undefined, "data-variant": mode || undefined, "data-open": open || undefined, onKeyDown: handleItemKeyDown, onFocus: handleItemFocus, style: { '--level': level }, "data-level-one": level === 1 || undefined, "data-level-more-one": level > 1 || undefined, "data-checked": (isParentNode && (indeterminate || isChecked)) || (isChecked && !switchProp) || undefined, children: [dragHandle && _jsx("div", { className: styles.dragHandle, children: dragHandle }), !switchProp && isSelectionSingle && marker && !isParentNode && interactive && (_jsx("div", { className: styles.markerContainer, "data-test-id": TEST_IDS.baseItemMarker })), !switchProp && isSelectionMultiple && interactive && (_jsx("div", { className: styles.checkbox, children: _jsx(Checkbox, { size: TOGGLE_SIZE_MAP[size], disabled: disabled, tabIndex: -1, onChange: isParentNode ? handleCheckboxChange : undefined, checked: isChecked, "data-test-id": TEST_IDS.baseItemCheckbox, onClick: handleCheckboxClick, indeterminate: indeterminate }) })), beforeContent && _jsx("div", { className: styles.beforeContent, children: beforeContent }), contentNode, afterContent && _jsx("div", { className: styles.afterContent, children: afterContent }), switchProp && interactive && (_jsx(Switch, { size: TOGGLE_SIZE_MAP[size], disabled: disabled, checked: isChecked, "data-test-id": TEST_IDS.baseItemSwitch, showIcon: showSwitchIcon })), !switchProp &&
106
+ expandIcon &&
107
+ (onExpandIconClick ? (_jsxs("button", { type: 'button', className: styles.groupIndicator, "data-size": size, "data-open": open || undefined, "data-test-id": TEST_IDS.groupIndicator, tabIndex: -1, disabled: disabled, onClick: handleExpandIconClick, onMouseDown: e => e.stopPropagation(), children: [_jsx("span", { className: styles.groupIndicatorState, "aria-hidden": true }), expandIcon] })) : (_jsx("span", { className: styles.expandableIcon, children: expandIcon })))] })] }));
109
108
  if (!itemWrapRender) {
110
109
  return itemJSX;
111
110
  }