@salt-ds/lab 1.0.0-alpha.86 → 1.0.0-alpha.88

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/css/salt-lab.css +145 -212
  3. package/dist-cjs/calendar/internal/CalendarDay.css.js +1 -1
  4. package/dist-cjs/common-hooks/useSelection.js +0 -2
  5. package/dist-cjs/common-hooks/useSelection.js.map +1 -1
  6. package/dist-cjs/contact-details/ContactDetails.css.js +1 -1
  7. package/dist-cjs/date-input/DateInput.css.js +1 -1
  8. package/dist-cjs/date-input/DateInputRange.js +2 -8
  9. package/dist-cjs/date-input/DateInputRange.js.map +1 -1
  10. package/dist-cjs/date-input/DateInputSingle.js +1 -1
  11. package/dist-cjs/date-input/DateInputSingle.js.map +1 -1
  12. package/dist-cjs/index.js +6 -2
  13. package/dist-cjs/index.js.map +1 -1
  14. package/dist-cjs/list-deprecated/ListItem.js.map +1 -1
  15. package/dist-cjs/rating/Rating.css.js +1 -1
  16. package/dist-cjs/rating/Rating.js +8 -7
  17. package/dist-cjs/rating/Rating.js.map +1 -1
  18. package/dist-cjs/tabs-next/TabListNext.js +1 -1
  19. package/dist-cjs/tabs-next/TabListNext.js.map +1 -1
  20. package/dist-cjs/tokenized-input-next/TokenizedInputNext.js +2 -2
  21. package/dist-cjs/tokenized-input-next/TokenizedInputNext.js.map +1 -1
  22. package/dist-cjs/tree/Tree.css.js +1 -1
  23. package/dist-cjs/tree/Tree.js +274 -207
  24. package/dist-cjs/tree/Tree.js.map +1 -1
  25. package/dist-cjs/tree/TreeContext.js +31 -0
  26. package/dist-cjs/tree/TreeContext.js.map +1 -0
  27. package/dist-cjs/tree/TreeNode.css.js +1 -1
  28. package/dist-cjs/tree/TreeNode.js +86 -42
  29. package/dist-cjs/tree/TreeNode.js.map +1 -1
  30. package/dist-cjs/tree/TreeNodeExpansionIcon.css.js +6 -0
  31. package/dist-cjs/tree/TreeNodeExpansionIcon.css.js.map +1 -0
  32. package/dist-cjs/tree/TreeNodeExpansionIcon.js +62 -0
  33. package/dist-cjs/tree/TreeNodeExpansionIcon.js.map +1 -0
  34. package/dist-cjs/tree/TreeNodeLabel.css.js +6 -0
  35. package/dist-cjs/tree/TreeNodeLabel.css.js.map +1 -0
  36. package/dist-cjs/tree/TreeNodeLabel.js +26 -0
  37. package/dist-cjs/tree/TreeNodeLabel.js.map +1 -0
  38. package/dist-cjs/tree/TreeNodeTrigger.css.js +6 -0
  39. package/dist-cjs/tree/TreeNodeTrigger.css.js.map +1 -0
  40. package/dist-cjs/tree/TreeNodeTrigger.js +152 -0
  41. package/dist-cjs/tree/TreeNodeTrigger.js.map +1 -0
  42. package/dist-cjs/tree/useTree.js +305 -133
  43. package/dist-cjs/tree/useTree.js.map +1 -1
  44. package/dist-es/calendar/internal/CalendarDay.css.js +1 -1
  45. package/dist-es/combo-box-deprecated/internal/DefaultComboBox.js +1 -1
  46. package/dist-es/combo-box-deprecated/internal/MultiSelectComboBox.js +1 -1
  47. package/dist-es/combo-box-deprecated/internal/useComboBox.js +1 -1
  48. package/dist-es/combo-box-deprecated/internal/useMultiSelectComboBox.js +1 -1
  49. package/dist-es/common-hooks/useCollectionItems.js +1 -1
  50. package/dist-es/common-hooks/useSelection.js +1 -2
  51. package/dist-es/common-hooks/useSelection.js.map +1 -1
  52. package/dist-es/contact-details/ContactDetails.css.js +1 -1
  53. package/dist-es/date-input/DateInput.css.js +1 -1
  54. package/dist-es/date-input/DateInputRange.js +2 -8
  55. package/dist-es/date-input/DateInputRange.js.map +1 -1
  56. package/dist-es/date-input/DateInputSingle.js +1 -1
  57. package/dist-es/date-input/DateInputSingle.js.map +1 -1
  58. package/dist-es/dropdown/DropdownBase.js +1 -1
  59. package/dist-es/index.js +3 -1
  60. package/dist-es/index.js.map +1 -1
  61. package/dist-es/list-deprecated/ListItem.js.map +1 -1
  62. package/dist-es/rating/Rating.css.js +1 -1
  63. package/dist-es/rating/Rating.js +8 -7
  64. package/dist-es/rating/Rating.js.map +1 -1
  65. package/dist-es/tabs/drag-drop/useDragDropNaturalMovement.js +1 -1
  66. package/dist-es/tabs-next/TabListNext.js +1 -1
  67. package/dist-es/tabs-next/TabListNext.js.map +1 -1
  68. package/dist-es/tokenized-input/TokenizedInputBase.js +1 -1
  69. package/dist-es/tokenized-input-next/TokenizedInputNext.js +2 -2
  70. package/dist-es/tokenized-input-next/TokenizedInputNext.js.map +1 -1
  71. package/dist-es/tree/Tree.css.js +1 -1
  72. package/dist-es/tree/Tree.js +275 -208
  73. package/dist-es/tree/Tree.js.map +1 -1
  74. package/dist-es/tree/TreeContext.js +26 -0
  75. package/dist-es/tree/TreeContext.js.map +1 -0
  76. package/dist-es/tree/TreeNode.css.js +1 -1
  77. package/dist-es/tree/TreeNode.js +87 -43
  78. package/dist-es/tree/TreeNode.js.map +1 -1
  79. package/dist-es/tree/TreeNodeExpansionIcon.css.js +4 -0
  80. package/dist-es/tree/TreeNodeExpansionIcon.css.js.map +1 -0
  81. package/dist-es/tree/TreeNodeExpansionIcon.js +60 -0
  82. package/dist-es/tree/TreeNodeExpansionIcon.js.map +1 -0
  83. package/dist-es/tree/TreeNodeLabel.css.js +4 -0
  84. package/dist-es/tree/TreeNodeLabel.css.js.map +1 -0
  85. package/dist-es/tree/TreeNodeLabel.js +24 -0
  86. package/dist-es/tree/TreeNodeLabel.js.map +1 -0
  87. package/dist-es/tree/TreeNodeTrigger.css.js +4 -0
  88. package/dist-es/tree/TreeNodeTrigger.css.js.map +1 -0
  89. package/dist-es/tree/TreeNodeTrigger.js +150 -0
  90. package/dist-es/tree/TreeNodeTrigger.js.map +1 -0
  91. package/dist-es/tree/useTree.js +306 -134
  92. package/dist-es/tree/useTree.js.map +1 -1
  93. package/dist-types/date-input/DateInputRange.d.ts +1 -1
  94. package/dist-types/date-input/DateInputSingle.d.ts +1 -1
  95. package/dist-types/index.d.ts +0 -1
  96. package/dist-types/list-deprecated/ListItem.d.ts +1 -0
  97. package/dist-types/rating/Rating.d.ts +5 -6
  98. package/dist-types/tokenized-input/internal/InputPill.d.ts +1 -1
  99. package/dist-types/tokenized-input-next/internal/InputPill.d.ts +1 -1
  100. package/dist-types/tree/Tree.d.ts +36 -3
  101. package/dist-types/tree/TreeContext.d.ts +71 -0
  102. package/dist-types/tree/TreeNode.d.ts +23 -10
  103. package/dist-types/tree/TreeNodeExpansionIcon.d.ts +4 -0
  104. package/dist-types/tree/TreeNodeLabel.d.ts +4 -0
  105. package/dist-types/tree/TreeNodeTrigger.d.ts +8 -0
  106. package/dist-types/tree/index.d.ts +3 -0
  107. package/dist-types/tree/useTree.d.ts +79 -3
  108. package/package.json +3 -3
  109. package/dist-cjs/common-hooks/calcPreferredHeight.js +0 -27
  110. package/dist-cjs/common-hooks/calcPreferredHeight.js.map +0 -1
  111. package/dist-cjs/common-hooks/useAutoSizer.js +0 -33
  112. package/dist-cjs/common-hooks/useAutoSizer.js.map +0 -1
  113. package/dist-cjs/kbd/Kbd.css.js +0 -6
  114. package/dist-cjs/kbd/Kbd.css.js.map +0 -1
  115. package/dist-cjs/kbd/Kbd.js +0 -34
  116. package/dist-cjs/kbd/Kbd.js.map +0 -1
  117. package/dist-cjs/tree/use-tree-keyboard-navigation.js +0 -51
  118. package/dist-cjs/tree/use-tree-keyboard-navigation.js.map +0 -1
  119. package/dist-es/common-hooks/calcPreferredHeight.js +0 -25
  120. package/dist-es/common-hooks/calcPreferredHeight.js.map +0 -1
  121. package/dist-es/common-hooks/useAutoSizer.js +0 -31
  122. package/dist-es/common-hooks/useAutoSizer.js.map +0 -1
  123. package/dist-es/kbd/Kbd.css.js +0 -4
  124. package/dist-es/kbd/Kbd.css.js.map +0 -1
  125. package/dist-es/kbd/Kbd.js +0 -32
  126. package/dist-es/kbd/Kbd.js.map +0 -1
  127. package/dist-es/tree/use-tree-keyboard-navigation.js +0 -48
  128. package/dist-es/tree/use-tree-keyboard-navigation.js.map +0 -1
  129. package/dist-types/kbd/Kbd.d.ts +0 -8
  130. package/dist-types/kbd/index.d.ts +0 -1
  131. package/dist-types/tree/treeTypes.d.ts +0 -42
  132. package/dist-types/tree/use-tree-keyboard-navigation.d.ts +0 -15
@@ -2,54 +2,98 @@
2
2
 
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var core = require('@salt-ds/core');
5
- var icons = require('@salt-ds/icons');
6
5
  var styles = require('@salt-ds/styles');
7
6
  var window = require('@salt-ds/window');
8
- var clsx = require('clsx');
7
+ var react = require('react');
8
+ var TreeContext = require('./TreeContext.js');
9
9
  var TreeNode$1 = require('./TreeNode.css.js');
10
+ var TreeNodeLabel = require('./TreeNodeLabel.js');
11
+ var TreeNodeTrigger = require('./TreeNodeTrigger.js');
10
12
 
11
13
  const withBaseName = core.makePrefixer("saltTreeNode");
12
- const TreeNode = ({
13
- "aria-level": ariaLevel,
14
- children,
15
- className: classNameProp,
16
- description,
17
- highlighted,
18
- idx,
19
- isLeaf = false,
20
- label,
21
- onMouseEnter,
22
- selected,
23
- ...props
24
- }) => {
25
- const targetWindow = window.useWindow();
26
- styles.useComponentCssInjection({
27
- testId: "salt-tree-node",
28
- css: TreeNode$1,
29
- window: targetWindow
14
+ function separateChildren(children) {
15
+ const contentChildren = [];
16
+ const nodeChildren = [];
17
+ react.Children.forEach(children, (child) => {
18
+ if (react.isValidElement(child) && typeof child.props.value === "string") {
19
+ nodeChildren.push(child);
20
+ } else if (child != null) {
21
+ contentChildren.push(child);
22
+ }
30
23
  });
31
- const className = clsx.clsx(withBaseName(), classNameProp, {
32
- [withBaseName("highlighted")]: highlighted
33
- });
34
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { ...props, className, role: "presentation", children: [
35
- /* @__PURE__ */ jsxRuntime.jsxs(
36
- "div",
37
- {
38
- "aria-level": ariaLevel,
39
- "aria-selected": selected || void 0,
40
- className: withBaseName("item"),
41
- onMouseEnter,
42
- role: "treeitem",
43
- children: [
44
- isLeaf === false ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: withBaseName("toggle"), "data-toggle": true, children: /* @__PURE__ */ jsxRuntime.jsx(icons.TriangleRightIcon, {}) }) : null,
45
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("label"), children: label }),
46
- description !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: withBaseName("description"), children: description }) : null
47
- ]
48
- }
49
- ),
50
- children
51
- ] });
52
- };
24
+ return { contentChildren, nodeChildren };
25
+ }
26
+ const TreeNode = react.forwardRef(
27
+ function TreeNode2(props, ref) {
28
+ const {
29
+ value,
30
+ label,
31
+ icon: Icon,
32
+ disabled: disabledProp,
33
+ children
34
+ } = props;
35
+ const targetWindow = window.useWindow();
36
+ styles.useComponentCssInjection({
37
+ testId: "salt-tree-node",
38
+ css: TreeNode$1,
39
+ window: targetWindow
40
+ });
41
+ const id = core.useId(value) ?? value;
42
+ const {
43
+ expandedState,
44
+ selectedSet,
45
+ disabled: treeDisabled,
46
+ disabledIdsSet,
47
+ indeterminateState,
48
+ getElement
49
+ } = TreeContext.useTreeContext();
50
+ const parentContext = TreeContext.useTreeNodeContext();
51
+ const level = ((parentContext == null ? void 0 : parentContext.level) ?? 0) + 1;
52
+ const disabled = treeDisabled || disabledProp || disabledIdsSet.has(value);
53
+ const expanded = expandedState.has(value);
54
+ const selected = selectedSet.has(value);
55
+ const indeterminate = indeterminateState.has(value);
56
+ const usesLabelProp = label !== void 0;
57
+ const { contentChildren, nodeChildren } = react.useMemo(
58
+ () => usesLabelProp ? { contentChildren: [], nodeChildren: react.Children.toArray(children) } : separateChildren(children),
59
+ [children, usesLabelProp]
60
+ );
61
+ const hasChildren = nodeChildren.length > 0;
62
+ react.useImperativeHandle(ref, () => getElement(value), [
63
+ getElement,
64
+ value
65
+ ]);
66
+ const nodeContext = react.useMemo(
67
+ () => ({
68
+ value,
69
+ level,
70
+ hasChildren,
71
+ expanded,
72
+ disabled,
73
+ id,
74
+ selected,
75
+ indeterminate,
76
+ nodeChildren
77
+ }),
78
+ [
79
+ value,
80
+ level,
81
+ hasChildren,
82
+ expanded,
83
+ disabled,
84
+ id,
85
+ selected,
86
+ indeterminate,
87
+ nodeChildren
88
+ ]
89
+ );
90
+ const defaultContent = usesLabelProp ? /* @__PURE__ */ jsxRuntime.jsxs(TreeNodeTrigger.TreeNodeTrigger, { children: [
91
+ Icon ? /* @__PURE__ */ jsxRuntime.jsx(Icon, { "aria-hidden": true, className: withBaseName("icon") }) : null,
92
+ /* @__PURE__ */ jsxRuntime.jsx(TreeNodeLabel.TreeNodeLabel, { children: label })
93
+ ] }) : null;
94
+ return /* @__PURE__ */ jsxRuntime.jsx(TreeContext.TreeNodeProvider, { value: nodeContext, children: usesLabelProp ? defaultContent : contentChildren });
95
+ }
96
+ );
53
97
 
54
98
  exports.TreeNode = TreeNode;
55
99
  //# sourceMappingURL=TreeNode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TreeNode.js","sources":["../src/tree/TreeNode.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { TriangleRightIcon } from \"@salt-ds/icons\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport type { HTMLAttributes, MouseEventHandler, ReactNode } from \"react\";\n\nimport treeNodeCss from \"./TreeNode.css\";\n\nconst withBaseName = makePrefixer(\"saltTreeNode\");\nexport interface TreeNodeProps\n extends Omit<HTMLAttributes<HTMLLIElement>, \"onMouseEnter\"> {\n children?: ReactNode;\n description?: string;\n highlighted?: boolean;\n idx?: number;\n isLeaf?: boolean;\n label?: string;\n onMouseEnter?: MouseEventHandler;\n selected?: boolean;\n}\n\nexport const TreeNode = ({\n \"aria-level\": ariaLevel,\n children,\n className: classNameProp,\n description,\n highlighted,\n idx,\n isLeaf = false,\n label,\n onMouseEnter,\n selected,\n ...props\n}: TreeNodeProps) => {\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node\",\n css: treeNodeCss,\n window: targetWindow,\n });\n\n const className = clsx(withBaseName(), classNameProp, {\n [withBaseName(\"highlighted\")]: highlighted,\n });\n\n return (\n <li {...props} className={className} role=\"presentation\">\n <div\n aria-level={ariaLevel}\n aria-selected={selected || undefined}\n className={withBaseName(\"item\")}\n onMouseEnter={onMouseEnter}\n role=\"treeitem\"\n >\n {isLeaf === false ? (\n <span className={withBaseName(\"toggle\")} data-toggle={true}>\n <TriangleRightIcon />\n </span>\n ) : null}\n <div className={withBaseName(\"label\")}>\n {/* {child.icon ? <span className={`${classBase}Node-icon`} /> : null} */}\n {label}\n </div>\n {description !== undefined ? (\n <div className={withBaseName(\"description\")}>{description}</div>\n ) : null}\n </div>\n {children}\n </li>\n );\n};\n"],"names":["makePrefixer","useWindow","useComponentCssInjection","treeNodeCss","clsx","jsxs","jsx","TriangleRightIcon"],"mappings":";;;;;;;;;;AASA,MAAM,YAAA,GAAeA,kBAAa,cAAc,CAAA;AAazC,MAAM,WAAW,CAAC;AAAA,EACvB,YAAA,EAAc,SAAA;AAAA,EACd,QAAA;AAAA,EACA,SAAA,EAAW,aAAA;AAAA,EACX,WAAA;AAAA,EACA,WAAA;AAAA,EACA,GAAA;AAAA,EACA,MAAA,GAAS,KAAA;AAAA,EACT,KAAA;AAAA,EACA,YAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,KAAqB;AACnB,EAAA,MAAM,eAAeC,gBAAA,EAAU;AAC/B,EAAAC,+BAAA,CAAyB;AAAA,IACvB,MAAA,EAAQ,gBAAA;AAAA,IACR,GAAA,EAAKC,UAAA;AAAA,IACL,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,SAAA,GAAYC,SAAA,CAAK,YAAA,EAAa,EAAG,aAAA,EAAe;AAAA,IACpD,CAAC,YAAA,CAAa,aAAa,CAAC,GAAG;AAAA,GAChC,CAAA;AAED,EAAA,uCACG,IAAA,EAAA,EAAI,GAAG,KAAA,EAAO,SAAA,EAAsB,MAAK,cAAA,EACxC,QAAA,EAAA;AAAA,oBAAAC,eAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,YAAA,EAAY,SAAA;AAAA,QACZ,iBAAe,QAAA,IAAY,MAAA;AAAA,QAC3B,SAAA,EAAW,aAAa,MAAM,CAAA;AAAA,QAC9B,YAAA;AAAA,QACA,IAAA,EAAK,UAAA;AAAA,QAEJ,QAAA,EAAA;AAAA,UAAA,MAAA,KAAW,KAAA,mBACVC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,YAAA,CAAa,QAAQ,CAAA,EAAG,aAAA,EAAa,IAAA,EACpD,QAAA,kBAAAA,cAAA,CAACC,uBAAA,EAAA,EAAkB,CAAA,EACrB,CAAA,GACE,IAAA;AAAA,yCACH,KAAA,EAAA,EAAI,SAAA,EAAW,YAAA,CAAa,OAAO,GAEjC,QAAA,EAAA,KAAA,EACH,CAAA;AAAA,UACC,WAAA,KAAgB,yBACfD,cAAA,CAAC,KAAA,EAAA,EAAI,WAAW,YAAA,CAAa,aAAa,CAAA,EAAI,QAAA,EAAA,WAAA,EAAY,CAAA,GACxD;AAAA;AAAA;AAAA,KACN;AAAA,IACC;AAAA,GAAA,EACH,CAAA;AAEJ;;;;"}
1
+ {"version":3,"file":"TreeNode.js","sources":["../src/tree/TreeNode.tsx"],"sourcesContent":["import { makePrefixer, useId } from \"@salt-ds/core\";\nimport type { IconProps } from \"@salt-ds/icons\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport {\n Children,\n type ComponentType,\n forwardRef,\n isValidElement,\n type ReactNode,\n useImperativeHandle,\n useMemo,\n} from \"react\";\nimport {\n TreeNodeProvider,\n useTreeContext,\n useTreeNodeContext,\n} from \"./TreeContext\";\nimport treeNodeCss from \"./TreeNode.css\";\nimport { TreeNodeLabel } from \"./TreeNodeLabel\";\nimport { TreeNodeTrigger } from \"./TreeNodeTrigger\";\n\nexport interface TreeNodeProps {\n /**\n * Unique value representing this node within the tree\n */\n value: string;\n /**\n * Label for the node. When provided, TreeNode automatically renders a TreeNodeTrigger.\n */\n label?: ReactNode;\n /**\n * Optional icon to display before the label\n */\n icon?: ComponentType<IconProps>;\n /**\n * Whether the node is disabled.\n */\n disabled?: boolean;\n /**\n * Child nodes or content.\n */\n children?: ReactNode;\n}\n\nconst withBaseName = makePrefixer(\"saltTreeNode\");\n\n// Need to take another look at this because its slightly brittle - alternative could be:\n// TreeNode having a 'content' prop that takes <TreeNodeTrigger> etc. and then `children` is reserved for other <TreeNode>'s\n// or a 'render' prop if we want to pass any state down. Simplifies it massively because then its clear children is for sub trees.\nfunction separateChildren(children: ReactNode): {\n contentChildren: ReactNode[];\n nodeChildren: ReactNode[];\n} {\n const contentChildren: ReactNode[] = [];\n const nodeChildren: ReactNode[] = [];\n\n Children.forEach(children, (child) => {\n if (isValidElement(child) && typeof child.props.value === \"string\") {\n nodeChildren.push(child);\n } else if (child != null) {\n contentChildren.push(child);\n }\n });\n\n return { contentChildren, nodeChildren };\n}\n\nexport const TreeNode = forwardRef<HTMLLIElement, TreeNodeProps>(\n function TreeNode(props, ref) {\n const {\n value,\n label,\n icon: Icon,\n disabled: disabledProp,\n children,\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node\",\n css: treeNodeCss,\n window: targetWindow,\n });\n\n const id = useId(value) ?? value;\n\n const {\n expandedState,\n selectedSet,\n disabled: treeDisabled,\n disabledIdsSet,\n indeterminateState,\n getElement,\n } = useTreeContext();\n\n const parentContext = useTreeNodeContext();\n const level = (parentContext?.level ?? 0) + 1;\n\n const disabled = treeDisabled || disabledProp || disabledIdsSet.has(value);\n const expanded = expandedState.has(value);\n const selected = selectedSet.has(value);\n const indeterminate = indeterminateState.has(value);\n\n const usesLabelProp = label !== undefined;\n const { contentChildren, nodeChildren } = useMemo(\n () =>\n usesLabelProp\n ? { contentChildren: [], nodeChildren: Children.toArray(children) }\n : separateChildren(children),\n [children, usesLabelProp],\n );\n\n const hasChildren = nodeChildren.length > 0;\n\n // Forward ref to the <li> element rendered by TreeNodeTrigger\n useImperativeHandle(ref, () => getElement(value) as HTMLLIElement, [\n getElement,\n value,\n ]);\n\n const nodeContext = useMemo(\n () => ({\n value,\n level,\n hasChildren,\n expanded,\n disabled,\n id,\n selected,\n indeterminate,\n nodeChildren,\n }),\n [\n value,\n level,\n hasChildren,\n expanded,\n disabled,\n id,\n selected,\n indeterminate,\n nodeChildren,\n ],\n );\n\n const defaultContent = usesLabelProp ? (\n <TreeNodeTrigger>\n {Icon ? <Icon aria-hidden className={withBaseName(\"icon\")} /> : null}\n <TreeNodeLabel>{label}</TreeNodeLabel>\n </TreeNodeTrigger>\n ) : null;\n\n return (\n <TreeNodeProvider value={nodeContext}>\n {usesLabelProp ? defaultContent : contentChildren}\n </TreeNodeProvider>\n );\n },\n);\n"],"names":["makePrefixer","Children","isValidElement","forwardRef","TreeNode","useWindow","useComponentCssInjection","treeNodeCss","useId","useTreeContext","useTreeNodeContext","useMemo","useImperativeHandle","jsxs","TreeNodeTrigger","jsx","TreeNodeLabel","TreeNodeProvider"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltTreeNodeExpansionIcon {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--salt-size-selectable);\n min-width: var(--salt-size-selectable);\n height: var(--salt-size-selectable);\n flex-shrink: 0;\n position: relative;\n}\n\n.saltTreeNodeExpansionIcon-icon {\n color: var(--salt-content-primary-foreground);\n}\n\n.saltTreeNodeExpansionIcon::before {\n content: \"\";\n display: block;\n position: absolute;\n width: var(--salt-size-base);\n height: var(--salt-size-base);\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=TreeNodeExpansionIcon.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeExpansionIcon.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,62 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var styles = require('@salt-ds/styles');
6
+ var window = require('@salt-ds/window');
7
+ var clsx = require('clsx');
8
+ var react = require('react');
9
+ var TreeContext = require('./TreeContext.js');
10
+ var TreeNodeExpansionIcon$1 = require('./TreeNodeExpansionIcon.css.js');
11
+
12
+ const withBaseName = core.makePrefixer("saltTreeNodeExpansionIcon");
13
+ const TreeNodeExpansionIcon = react.forwardRef(function TreeNodeExpansionIcon2(props, ref) {
14
+ const { className, onClick, ...rest } = props;
15
+ const targetWindow = window.useWindow();
16
+ styles.useComponentCssInjection({
17
+ testId: "salt-tree-node-expansion-icon",
18
+ css: TreeNodeExpansionIcon$1,
19
+ window: targetWindow
20
+ });
21
+ const nodeContext = TreeContext.useTreeNodeContext();
22
+ if (!nodeContext) {
23
+ throw new Error("TreeNodeExpansionIcon must be used within a TreeNode");
24
+ }
25
+ const { value, hasChildren, expanded, disabled } = nodeContext;
26
+ const { toggleExpanded } = TreeContext.useTreeContext();
27
+ const { ExpandGroupIcon, CollapseGroupIcon } = core.useIcon();
28
+ const handleClick = (event) => {
29
+ onClick == null ? void 0 : onClick(event);
30
+ if (disabled || !hasChildren) return;
31
+ toggleExpanded(event, value);
32
+ };
33
+ if (!hasChildren) {
34
+ return /* @__PURE__ */ jsxRuntime.jsx(
35
+ "span",
36
+ {
37
+ ref,
38
+ className: clsx.clsx(withBaseName(), withBaseName("placeholder"), className),
39
+ "aria-hidden": true,
40
+ ...rest
41
+ }
42
+ );
43
+ }
44
+ const Icon = expanded ? CollapseGroupIcon : ExpandGroupIcon;
45
+ return (
46
+ // biome-ignore lint/a11y/useKeyWithClickEvents: keyboard handled at tree level, same as W3C
47
+ /* @__PURE__ */ jsxRuntime.jsx(
48
+ "span",
49
+ {
50
+ ref,
51
+ className: clsx.clsx(withBaseName(), className),
52
+ onClick: handleClick,
53
+ "aria-hidden": true,
54
+ ...rest,
55
+ children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { className: withBaseName("icon") })
56
+ }
57
+ )
58
+ );
59
+ });
60
+
61
+ exports.TreeNodeExpansionIcon = TreeNodeExpansionIcon;
62
+ //# sourceMappingURL=TreeNodeExpansionIcon.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeExpansionIcon.js","sources":["../src/tree/TreeNodeExpansionIcon.tsx"],"sourcesContent":["import { makePrefixer, useIcon } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n forwardRef,\n type MouseEvent,\n} from \"react\";\nimport { useTreeContext, useTreeNodeContext } from \"./TreeContext\";\nimport treeNodeExpansionIconCss from \"./TreeNodeExpansionIcon.css\";\n\nexport interface TreeNodeExpansionIconProps\n extends ComponentPropsWithoutRef<\"span\"> {}\n\nconst withBaseName = makePrefixer(\"saltTreeNodeExpansionIcon\");\n\nexport const TreeNodeExpansionIcon = forwardRef<\n HTMLSpanElement,\n TreeNodeExpansionIconProps\n>(function TreeNodeExpansionIcon(props, ref) {\n const { className, onClick, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node-expansion-icon\",\n css: treeNodeExpansionIconCss,\n window: targetWindow,\n });\n\n const nodeContext = useTreeNodeContext();\n if (!nodeContext) {\n throw new Error(\"TreeNodeExpansionIcon must be used within a TreeNode\");\n }\n\n const { value, hasChildren, expanded, disabled } = nodeContext;\n const { toggleExpanded } = useTreeContext();\n const { ExpandGroupIcon, CollapseGroupIcon } = useIcon();\n\n const handleClick = (event: MouseEvent<HTMLSpanElement>) => {\n onClick?.(event);\n if (disabled || !hasChildren) return;\n toggleExpanded(event, value);\n };\n\n if (!hasChildren) {\n return (\n <span\n ref={ref}\n className={clsx(withBaseName(), withBaseName(\"placeholder\"), className)}\n aria-hidden\n {...rest}\n />\n );\n }\n\n const Icon = expanded ? CollapseGroupIcon : ExpandGroupIcon;\n\n return (\n // biome-ignore lint/a11y/useKeyWithClickEvents: keyboard handled at tree level, same as W3C\n <span\n ref={ref}\n className={clsx(withBaseName(), className)}\n onClick={handleClick}\n aria-hidden\n {...rest}\n >\n <Icon className={withBaseName(\"icon\")} />\n </span>\n );\n});\n"],"names":["makePrefixer","forwardRef","TreeNodeExpansionIcon","useWindow","useComponentCssInjection","treeNodeExpansionIconCss","useTreeNodeContext","useTreeContext","useIcon","jsx","clsx"],"mappings":";;;;;;;;;;;AAeA,MAAM,YAAA,GAAeA,kBAAa,2BAA2B,CAAA;AAEtD,MAAM,qBAAA,GAAwBC,gBAAA,CAGnC,SAASC,sBAAAA,CAAsB,OAAO,GAAA,EAAK;AAC3C,EAAA,MAAM,EAAE,SAAA,EAAW,OAAA,EAAS,GAAG,MAAK,GAAI,KAAA;AAExC,EAAA,MAAM,eAAeC,gBAAA,EAAU;AAC/B,EAAAC,+BAAA,CAAyB;AAAA,IACvB,MAAA,EAAQ,+BAAA;AAAA,IACR,GAAA,EAAKC,uBAAA;AAAA,IACL,MAAA,EAAQ;AAAA,GACT,CAAA;AAED,EAAA,MAAM,cAAcC,8BAAA,EAAmB;AACvC,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,MAAM,IAAI,MAAM,sDAAsD,CAAA;AAAA,EACxE;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,WAAA,EAAa,QAAA,EAAU,UAAS,GAAI,WAAA;AACnD,EAAA,MAAM,EAAE,cAAA,EAAe,GAAIC,0BAAA,EAAe;AAC1C,EAAA,MAAM,EAAE,eAAA,EAAiB,iBAAA,EAAkB,GAAIC,YAAA,EAAQ;AAEvD,EAAA,MAAM,WAAA,GAAc,CAAC,KAAA,KAAuC;AAC1D,IAAA,OAAA,IAAA,IAAA,GAAA,MAAA,GAAA,OAAA,CAAU,KAAA,CAAA;AACV,IAAA,IAAI,QAAA,IAAY,CAAC,WAAA,EAAa;AAC9B,IAAA,cAAA,CAAe,OAAO,KAAK,CAAA;AAAA,EAC7B,CAAA;AAEA,EAAA,IAAI,CAAC,WAAA,EAAa;AAChB,IAAA,uBACEC,cAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,WAAWC,SAAA,CAAK,YAAA,IAAgB,YAAA,CAAa,aAAa,GAAG,SAAS,CAAA;AAAA,QACtE,aAAA,EAAW,IAAA;AAAA,QACV,GAAG;AAAA;AAAA,KACN;AAAA,EAEJ;AAEA,EAAA,MAAM,IAAA,GAAO,WAAW,iBAAA,GAAoB,eAAA;AAE5C,EAAA;AAAA;AAAA,oBAEED,cAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,GAAA;AAAA,QACA,SAAA,EAAWC,SAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA;AAAA,QACzC,OAAA,EAAS,WAAA;AAAA,QACT,aAAA,EAAW,IAAA;AAAA,QACV,GAAG,IAAA;AAAA,QAEJ,QAAA,kBAAAD,cAAA,CAAC,IAAA,EAAA,EAAK,SAAA,EAAW,YAAA,CAAa,MAAM,CAAA,EAAG;AAAA;AAAA;AACzC;AAEJ,CAAC;;;;"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltTreeNodeLabel {\n flex: 1;\n font-family: var(--salt-text-fontFamily);\n font-size: var(--salt-text-fontSize);\n font-weight: var(--salt-text-fontWeight);\n line-height: var(--salt-text-lineHeight);\n letter-spacing: var(--salt-text-letterSpacing);\n word-break: break-word;\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=TreeNodeLabel.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeLabel.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,26 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var styles = require('@salt-ds/styles');
6
+ var window = require('@salt-ds/window');
7
+ var clsx = require('clsx');
8
+ var react = require('react');
9
+ var TreeNodeLabel$1 = require('./TreeNodeLabel.css.js');
10
+
11
+ const withBaseName = core.makePrefixer("saltTreeNodeLabel");
12
+ const TreeNodeLabel = react.forwardRef(
13
+ function TreeNodeLabel2(props, ref) {
14
+ const { children, className, ...rest } = props;
15
+ const targetWindow = window.useWindow();
16
+ styles.useComponentCssInjection({
17
+ testId: "salt-tree-node-label",
18
+ css: TreeNodeLabel$1,
19
+ window: targetWindow
20
+ });
21
+ return /* @__PURE__ */ jsxRuntime.jsx("span", { ref, className: clsx.clsx(withBaseName(), className), ...rest, children });
22
+ }
23
+ );
24
+
25
+ exports.TreeNodeLabel = TreeNodeLabel;
26
+ //# sourceMappingURL=TreeNodeLabel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeLabel.js","sources":["../src/tree/TreeNodeLabel.tsx"],"sourcesContent":["import { makePrefixer } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport { type ComponentPropsWithoutRef, forwardRef } from \"react\";\nimport treeNodeLabelCss from \"./TreeNodeLabel.css\";\n\nexport interface TreeNodeLabelProps extends ComponentPropsWithoutRef<\"span\"> {}\n\nconst withBaseName = makePrefixer(\"saltTreeNodeLabel\");\n\nexport const TreeNodeLabel = forwardRef<HTMLSpanElement, TreeNodeLabelProps>(\n function TreeNodeLabel(props, ref) {\n const { children, className, ...rest } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node-label\",\n css: treeNodeLabelCss,\n window: targetWindow,\n });\n\n return (\n <span ref={ref} className={clsx(withBaseName(), className)} {...rest}>\n {children}\n </span>\n );\n },\n);\n"],"names":["makePrefixer","forwardRef","TreeNodeLabel","useWindow","useComponentCssInjection","treeNodeLabelCss","jsx","clsx"],"mappings":";;;;;;;;;;AASA,MAAM,YAAA,GAAeA,kBAAa,mBAAmB,CAAA;AAE9C,MAAM,aAAA,GAAgBC,gBAAA;AAAA,EAC3B,SAASC,cAAAA,CAAc,KAAA,EAAO,GAAA,EAAK;AACjC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,GAAG,MAAK,GAAI,KAAA;AAEzC,IAAA,MAAM,eAAeC,gBAAA,EAAU;AAC/B,IAAAC,+BAAA,CAAyB;AAAA,MACvB,MAAA,EAAQ,sBAAA;AAAA,MACR,GAAA,EAAKC,eAAA;AAAA,MACL,MAAA,EAAQ;AAAA,KACT,CAAA;AAED,IAAA,uBACEC,cAAA,CAAC,MAAA,EAAA,EAAK,GAAA,EAAU,SAAA,EAAWC,SAAA,CAAK,YAAA,EAAa,EAAG,SAAS,CAAA,EAAI,GAAG,IAAA,EAC7D,QAAA,EACH,CAAA;AAAA,EAEJ;AACF;;;;"}
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ var css_248z = ".saltTreeNodeTrigger {\n box-sizing: border-box;\n display: flex;\n align-items: flex-start;\n gap: var(--salt-spacing-100);\n width: 100%;\n min-height: var(--salt-size-base);\n\n padding-top: calc((var(--salt-size-base) - var(--salt-size-selectable)) / 2);\n padding-bottom: calc((var(--salt-size-base) - var(--salt-size-selectable)) / 2);\n padding-right: var(--salt-spacing-100);\n /* Base padding for level-1 nodes, plus one indent step per additional level.\n Each indent step = (selectable element width + gap).\n Level-1 nodes get no extra indent; level-2 gets 1 step, level-3 gets 2, etc.\n --saltTreeNodeTrigger-indentStep is overridden in multiselect to account\n for the wider spacing around the checkbox. */\n --saltTreeNodeTrigger-indentStep: calc(var(--salt-size-selectable) + var(--salt-spacing-100));\n padding-left: calc(var(--salt-spacing-100) + (var(--saltTreeNodeTrigger-indentStep) * (var(--saltTreeNode-level, 1) - 1)));\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n}\n\n[aria-multiselectable=\"true\"] .saltTreeNodeTrigger {\n --saltTreeNodeTrigger-indentStep: calc(var(--salt-size-selectable) + var(--salt-spacing-150));\n}\n\n.saltTreeNodeTrigger:hover {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltTreeNode:focus-visible > .saltTreeNodeTrigger,\n.saltTreeNode-focusVisible > .saltTreeNodeTrigger {\n background: var(--salt-selectable-background-hover);\n}\n\n.saltTreeNode-selected > .saltTreeNodeTrigger {\n background: var(--salt-selectable-background-selected);\n box-shadow:\n 0 calc(var(--salt-size-border) * -1) 0 0 var(--salt-selectable-borderColor-selected),\n 0 var(--salt-size-border) 0 0 var(--salt-selectable-borderColor-selected);\n position: relative;\n z-index: var(--salt-zIndex-default);\n}\n\n.saltTreeNode-selected:focus-visible > .saltTreeNodeTrigger,\n.saltTreeNode-selected.saltTreeNode-focusVisible > .saltTreeNodeTrigger {\n background: var(--salt-selectable-background-selected);\n}\n\n.saltTreeNode-disabled > .saltTreeNodeTrigger,\n.saltTreeNode-disabled:hover > .saltTreeNodeTrigger {\n opacity: 0.4;\n cursor: var(--salt-cursor-disabled);\n\n background: var(--salt-selectable-background);\n color: var(--salt-content-primary-foreground);\n}\n\n.saltTreeNodeTrigger > .saltIcon {\n width: var(--salt-size-selectable);\n height: var(--salt-size-selectable);\n min-width: var(--salt-size-selectable);\n flex-shrink: 0;\n color: var(--salt-content-primary-foreground);\n}\n\n.saltTreeNodeTrigger > .saltTreeNode-checkbox {\n margin-left: calc(var(--salt-spacing-150) - var(--salt-spacing-100));\n margin-right: calc(var(--salt-spacing-150) - var(--salt-spacing-100));\n}\n";
4
+
5
+ module.exports = css_248z;
6
+ //# sourceMappingURL=TreeNodeTrigger.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeTrigger.css.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -0,0 +1,152 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var core = require('@salt-ds/core');
5
+ var styles = require('@salt-ds/styles');
6
+ var window = require('@salt-ds/window');
7
+ var clsx = require('clsx');
8
+ var react = require('react');
9
+ var TreeContext = require('./TreeContext.js');
10
+ var TreeNodeExpansionIcon = require('./TreeNodeExpansionIcon.js');
11
+ var TreeNodeTrigger$1 = require('./TreeNodeTrigger.css.js');
12
+
13
+ const withBaseName = core.makePrefixer("saltTreeNodeTrigger");
14
+ const withNodeBaseName = core.makePrefixer("saltTreeNode");
15
+ const TreeNodeTrigger = react.forwardRef(function TreeNodeTrigger2(props, ref) {
16
+ const {
17
+ className,
18
+ children,
19
+ style,
20
+ onClick,
21
+ onFocus,
22
+ onBlur,
23
+ onMouseDown,
24
+ onKeyDown,
25
+ ...rest
26
+ } = props;
27
+ const targetWindow = window.useWindow();
28
+ styles.useComponentCssInjection({
29
+ testId: "salt-tree-node-trigger",
30
+ css: TreeNodeTrigger$1,
31
+ window: targetWindow
32
+ });
33
+ const nodeContext = TreeContext.useTreeNodeContext();
34
+ if (!nodeContext) {
35
+ throw new Error("TreeNodeTrigger must be used within a TreeNode");
36
+ }
37
+ const {
38
+ value,
39
+ level,
40
+ hasChildren,
41
+ expanded,
42
+ disabled,
43
+ id,
44
+ selected,
45
+ indeterminate,
46
+ nodeChildren
47
+ } = nodeContext;
48
+ const {
49
+ multiselect,
50
+ activeNode,
51
+ setActiveNode,
52
+ select,
53
+ tabbableNodeId,
54
+ registerElement
55
+ } = TreeContext.useTreeContext();
56
+ const nodeRef = react.useRef(null);
57
+ const triggerContentRef = core.useForkRef(react.useRef(null), ref);
58
+ const wasMouseDownRef = react.useRef(false);
59
+ const [focusVisible, setFocusVisible] = react.useState(false);
60
+ const isActive = activeNode === value;
61
+ const isTabbable = tabbableNodeId === value;
62
+ react.useEffect(() => {
63
+ if (nodeRef.current) {
64
+ return registerElement(value, nodeRef.current);
65
+ }
66
+ }, [value, registerElement]);
67
+ const handleClick = (event) => {
68
+ onClick == null ? void 0 : onClick(event);
69
+ if (disabled) return;
70
+ const target = event.target;
71
+ if (target.closest(".saltTreeNodeExpansionIcon")) return;
72
+ const nestedTreeItem = target.closest('[role="treeitem"]');
73
+ if (nestedTreeItem && nestedTreeItem !== nodeRef.current) {
74
+ return;
75
+ }
76
+ setActiveNode(value);
77
+ select(event, value);
78
+ };
79
+ const handleFocus = (event) => {
80
+ onFocus == null ? void 0 : onFocus(event);
81
+ if (event.target !== event.currentTarget) return;
82
+ if (!wasMouseDownRef.current) {
83
+ setFocusVisible(true);
84
+ }
85
+ wasMouseDownRef.current = false;
86
+ setActiveNode(value);
87
+ };
88
+ const handleBlur = (event) => {
89
+ onBlur == null ? void 0 : onBlur(event);
90
+ if (event.target !== event.currentTarget) return;
91
+ setFocusVisible(false);
92
+ };
93
+ const handleMouseDown = (event) => {
94
+ wasMouseDownRef.current = true;
95
+ onMouseDown == null ? void 0 : onMouseDown(event);
96
+ };
97
+ return /* @__PURE__ */ jsxRuntime.jsxs(
98
+ "li",
99
+ {
100
+ ref: nodeRef,
101
+ id,
102
+ role: "treeitem",
103
+ "aria-expanded": hasChildren ? expanded : void 0,
104
+ "aria-selected": multiselect ? void 0 : selected,
105
+ "aria-checked": multiselect ? indeterminate ? "mixed" : selected : void 0,
106
+ "aria-level": level,
107
+ "aria-disabled": disabled || void 0,
108
+ tabIndex: isTabbable ? 0 : -1,
109
+ className: clsx.clsx(
110
+ withNodeBaseName(),
111
+ {
112
+ [withNodeBaseName("expanded")]: expanded,
113
+ [withNodeBaseName("selected")]: selected && !multiselect,
114
+ [withNodeBaseName("active")]: isActive,
115
+ [withNodeBaseName("disabled")]: disabled,
116
+ [withNodeBaseName("hasChildren")]: hasChildren,
117
+ [withNodeBaseName("focusVisible")]: focusVisible
118
+ },
119
+ className
120
+ ),
121
+ style: {
122
+ "--saltTreeNode-level": level,
123
+ ...style
124
+ },
125
+ onClick: handleClick,
126
+ onFocus: handleFocus,
127
+ onBlur: handleBlur,
128
+ onMouseDown: handleMouseDown,
129
+ onKeyDown,
130
+ ...rest,
131
+ children: [
132
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { ref: triggerContentRef, className: withBaseName(), children: [
133
+ /* @__PURE__ */ jsxRuntime.jsx(TreeNodeExpansionIcon.TreeNodeExpansionIcon, {}),
134
+ multiselect && /* @__PURE__ */ jsxRuntime.jsx(
135
+ core.CheckboxIcon,
136
+ {
137
+ checked: selected,
138
+ indeterminate,
139
+ disabled,
140
+ className: withNodeBaseName("checkbox")
141
+ }
142
+ ),
143
+ children
144
+ ] }),
145
+ hasChildren && expanded && /* @__PURE__ */ jsxRuntime.jsx("ul", { role: "group", className: withNodeBaseName("group"), children: nodeChildren })
146
+ ]
147
+ }
148
+ );
149
+ });
150
+
151
+ exports.TreeNodeTrigger = TreeNodeTrigger;
152
+ //# sourceMappingURL=TreeNodeTrigger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeTrigger.js","sources":["../src/tree/TreeNodeTrigger.tsx"],"sourcesContent":["import { CheckboxIcon, makePrefixer, useForkRef } from \"@salt-ds/core\";\nimport { useComponentCssInjection } from \"@salt-ds/styles\";\nimport { useWindow } from \"@salt-ds/window\";\nimport { clsx } from \"clsx\";\nimport {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n type FocusEvent,\n forwardRef,\n type MouseEvent,\n useEffect,\n useRef,\n useState,\n} from \"react\";\nimport { useTreeContext, useTreeNodeContext } from \"./TreeContext\";\nimport { TreeNodeExpansionIcon } from \"./TreeNodeExpansionIcon\";\nimport treeNodeTriggerCss from \"./TreeNodeTrigger.css\";\n\nexport interface TreeNodeTriggerProps extends ComponentPropsWithoutRef<\"li\"> {}\n\nconst withBaseName = makePrefixer(\"saltTreeNodeTrigger\");\nconst withNodeBaseName = makePrefixer(\"saltTreeNode\");\n\n/**\n * The forwarded ref points to the inner trigger content span (for tooltip positioning),\n * while the <li> handles focus, ARIA, and event handling.\n */\nexport const TreeNodeTrigger = forwardRef<\n HTMLSpanElement,\n TreeNodeTriggerProps\n>(function TreeNodeTrigger(props, ref) {\n const {\n className,\n children,\n style,\n onClick,\n onFocus,\n onBlur,\n onMouseDown,\n onKeyDown,\n ...rest\n } = props;\n\n const targetWindow = useWindow();\n useComponentCssInjection({\n testId: \"salt-tree-node-trigger\",\n css: treeNodeTriggerCss,\n window: targetWindow,\n });\n\n const nodeContext = useTreeNodeContext();\n if (!nodeContext) {\n throw new Error(\"TreeNodeTrigger must be used within a TreeNode\");\n }\n\n const {\n value,\n level,\n hasChildren,\n expanded,\n disabled,\n id,\n selected,\n indeterminate,\n nodeChildren,\n } = nodeContext;\n\n const {\n multiselect,\n activeNode,\n setActiveNode,\n select,\n tabbableNodeId,\n registerElement,\n } = useTreeContext();\n\n const nodeRef = useRef<HTMLLIElement>(null);\n const triggerContentRef = useForkRef(useRef<HTMLSpanElement>(null), ref);\n const wasMouseDownRef = useRef(false);\n const [focusVisible, setFocusVisible] = useState(false);\n\n const isActive = activeNode === value;\n\n const isTabbable = tabbableNodeId === value;\n\n useEffect(() => {\n if (nodeRef.current) {\n return registerElement(value, nodeRef.current);\n }\n }, [value, registerElement]);\n\n const handleClick = (event: MouseEvent<HTMLLIElement>) => {\n onClick?.(event);\n if (disabled) return;\n const target = event.target as HTMLElement;\n if (target.closest(\".saltTreeNodeExpansionIcon\")) return;\n const nestedTreeItem = target.closest('[role=\"treeitem\"]');\n if (nestedTreeItem && nestedTreeItem !== nodeRef.current) {\n return;\n }\n setActiveNode(value);\n select(event, value);\n };\n\n const handleFocus = (event: FocusEvent<HTMLLIElement>) => {\n onFocus?.(event);\n if (event.target !== event.currentTarget) return;\n if (!wasMouseDownRef.current) {\n setFocusVisible(true);\n }\n wasMouseDownRef.current = false;\n setActiveNode(value);\n };\n\n const handleBlur = (event: FocusEvent<HTMLLIElement>) => {\n onBlur?.(event);\n if (event.target !== event.currentTarget) return;\n setFocusVisible(false);\n };\n\n const handleMouseDown = (event: MouseEvent<HTMLLIElement>) => {\n wasMouseDownRef.current = true;\n onMouseDown?.(event);\n };\n\n return (\n <li\n ref={nodeRef}\n id={id}\n role=\"treeitem\"\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={multiselect ? undefined : selected}\n aria-checked={\n multiselect ? (indeterminate ? \"mixed\" : selected) : undefined\n }\n aria-level={level}\n aria-disabled={disabled || undefined}\n tabIndex={isTabbable ? 0 : -1}\n className={clsx(\n withNodeBaseName(),\n {\n [withNodeBaseName(\"expanded\")]: expanded,\n [withNodeBaseName(\"selected\")]: selected && !multiselect,\n [withNodeBaseName(\"active\")]: isActive,\n [withNodeBaseName(\"disabled\")]: disabled,\n [withNodeBaseName(\"hasChildren\")]: hasChildren,\n [withNodeBaseName(\"focusVisible\")]: focusVisible,\n },\n className,\n )}\n style={\n {\n \"--saltTreeNode-level\": level,\n ...style,\n } as CSSProperties\n }\n onClick={handleClick}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onMouseDown={handleMouseDown}\n onKeyDown={onKeyDown}\n {...rest}\n >\n <span ref={triggerContentRef} className={withBaseName()}>\n <TreeNodeExpansionIcon />\n {multiselect && (\n <CheckboxIcon\n checked={selected}\n indeterminate={indeterminate}\n disabled={disabled}\n className={withNodeBaseName(\"checkbox\")}\n />\n )}\n {children}\n </span>\n\n {hasChildren && expanded && (\n <ul role=\"group\" className={withNodeBaseName(\"group\")}>\n {nodeChildren}\n </ul>\n )}\n </li>\n );\n});\n"],"names":["makePrefixer","forwardRef","TreeNodeTrigger","useWindow","useComponentCssInjection","treeNodeTriggerCss","useTreeNodeContext","useTreeContext","useRef","useForkRef","useState","useEffect","jsxs","clsx","jsx","TreeNodeExpansionIcon","CheckboxIcon"],"mappings":"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"}