@pgcorp/ui-kit 0.1.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.
Files changed (251) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +157 -0
  3. package/docs/accessibility.md +27 -0
  4. package/docs/getting-started.md +80 -0
  5. package/docs/licensing.md +30 -0
  6. package/docs/public-api.md +39 -0
  7. package/docs/security.md +21 -0
  8. package/docs/theming.md +35 -0
  9. package/docs/versioning.md +23 -0
  10. package/index.ts +3 -0
  11. package/package.json +592 -0
  12. package/src/components/icons/_internal/generatedSputnigUiIconMarkup.ts +971 -0
  13. package/src/components/icons/sputnigUiIcons.ts +530 -0
  14. package/src/components/layout/SAppShell.vue +232 -0
  15. package/src/components/layout/SDockRegion.vue +200 -0
  16. package/src/components/layout/SResizeHandle.vue +251 -0
  17. package/src/components/layout/SSideMenuButton.vue +104 -0
  18. package/src/components/layout/SSideMenuRail.vue +47 -0
  19. package/src/components/layout/SStack.css +25 -0
  20. package/src/components/layout/SStack.vue +57 -0
  21. package/src/components/layout/SStatusBarShell.css +15 -0
  22. package/src/components/layout/SStatusBarShell.vue +26 -0
  23. package/src/components/layout/SWorkbenchLayout.vue +53 -0
  24. package/src/components/layout/SWorkbenchPanelShell.css +161 -0
  25. package/src/components/layout/SWorkbenchPanelShell.vue +286 -0
  26. package/src/components/layout/_internal/SAppBrand.css +45 -0
  27. package/src/components/layout/_internal/SAppBrand.vue +37 -0
  28. package/src/components/layout/_internal/SAppBrandContent.vue +30 -0
  29. package/src/components/layout/types.ts +28 -0
  30. package/src/components/shared/_internal/SDialogSurface.css +127 -0
  31. package/src/components/shared/_internal/SDialogSurface.vue +117 -0
  32. package/src/components/shared/_internal/SDisclosureSummary.css +92 -0
  33. package/src/components/shared/_internal/SDisclosureSummary.vue +121 -0
  34. package/src/components/shared/_internal/SListboxGroup.css +18 -0
  35. package/src/components/shared/_internal/SListboxGroup.vue +24 -0
  36. package/src/components/shared/_internal/SMenuItem.css +112 -0
  37. package/src/components/shared/_internal/SMenuItem.vue +213 -0
  38. package/src/components/shared/_internal/SMenuLayer.css +21 -0
  39. package/src/components/shared/_internal/SMenuLayer.vue +48 -0
  40. package/src/components/shared/_internal/SMenuSeparator.css +5 -0
  41. package/src/components/shared/_internal/SMenuSeparator.vue +13 -0
  42. package/src/components/shared/_internal/SToastItem.css +65 -0
  43. package/src/components/shared/_internal/SToastItem.vue +58 -0
  44. package/src/components/shared/_internal/STreeNode.vue +761 -0
  45. package/src/components/shared/_internal/dialogSurface.ts +105 -0
  46. package/src/components/shared/_internal/focusTrap.ts +40 -0
  47. package/src/components/shared/_internal/listboxContext.ts +16 -0
  48. package/src/components/shared/_internal/markerContract.ts +10 -0
  49. package/src/components/shared/_internal/menuContext.ts +23 -0
  50. package/src/components/shared/_internal/selectionContract.ts +239 -0
  51. package/src/components/shared/_internal/sidebarGroupContext.ts +31 -0
  52. package/src/components/shared/_internal/tabsContext.ts +57 -0
  53. package/src/components/shared/_internal/treeRuntime.ts +203 -0
  54. package/src/components/shared/_internal/useSelectionRoving.ts +162 -0
  55. package/src/components/shared/codeLanguages.ts +168 -0
  56. package/src/components/shared/complex/SKanbanCard.css +8 -0
  57. package/src/components/shared/complex/SKanbanCard.vue +76 -0
  58. package/src/components/shared/complex/SKanbanLane.vue +82 -0
  59. package/src/components/shared/complex/STree.css +24 -0
  60. package/src/components/shared/complex/STree.vue +288 -0
  61. package/src/components/shared/complex/treeAdapter.ts +210 -0
  62. package/src/components/shared/complex/types.ts +102 -0
  63. package/src/components/shared/containers/SCloudChrome.css +103 -0
  64. package/src/components/shared/containers/SCloudChrome.vue +87 -0
  65. package/src/components/shared/containers/SCloudChromeEmpty.css +10 -0
  66. package/src/components/shared/containers/SCloudChromeEmpty.vue +18 -0
  67. package/src/components/shared/containers/SCloudChromeRow.css +78 -0
  68. package/src/components/shared/containers/SCloudChromeRow.vue +108 -0
  69. package/src/components/shared/containers/SCollapsiblePanel.css +57 -0
  70. package/src/components/shared/containers/SCollapsiblePanel.vue +360 -0
  71. package/src/components/shared/containers/SDrawer.css +60 -0
  72. package/src/components/shared/containers/SDrawer.vue +86 -0
  73. package/src/components/shared/containers/SFormGrid.css +26 -0
  74. package/src/components/shared/containers/SFormGrid.vue +46 -0
  75. package/src/components/shared/containers/SFormGridItem.css +18 -0
  76. package/src/components/shared/containers/SFormGridItem.vue +29 -0
  77. package/src/components/shared/containers/SLeftSidebar.vue +74 -0
  78. package/src/components/shared/containers/SModal.css +27 -0
  79. package/src/components/shared/containers/SModal.vue +105 -0
  80. package/src/components/shared/containers/SPageHeader.css +66 -0
  81. package/src/components/shared/containers/SPageHeader.vue +45 -0
  82. package/src/components/shared/containers/SPanel.css +134 -0
  83. package/src/components/shared/containers/SPanel.vue +169 -0
  84. package/src/components/shared/containers/SPopover.css +35 -0
  85. package/src/components/shared/containers/SPopover.vue +551 -0
  86. package/src/components/shared/containers/SSidebarGroup.css +12 -0
  87. package/src/components/shared/containers/SSidebarGroup.vue +443 -0
  88. package/src/components/shared/containers/SSidebarSection.css +41 -0
  89. package/src/components/shared/containers/SSidebarSection.vue +268 -0
  90. package/src/components/shared/containers/disclosureSummary.ts +48 -0
  91. package/src/components/shared/containers/popover.ts +72 -0
  92. package/src/components/shared/containers/sidebar.ts +206 -0
  93. package/src/components/shared/controls/SButton.css +274 -0
  94. package/src/components/shared/controls/SButton.vue +211 -0
  95. package/src/components/shared/controls/SCheckbox.css +65 -0
  96. package/src/components/shared/controls/SCheckbox.vue +130 -0
  97. package/src/components/shared/controls/SCheckboxGroup.vue +134 -0
  98. package/src/components/shared/controls/SChoiceCards.css +29 -0
  99. package/src/components/shared/controls/SChoiceCards.vue +145 -0
  100. package/src/components/shared/controls/SColorSelect.vue +146 -0
  101. package/src/components/shared/controls/SComboboxTrigger.css +35 -0
  102. package/src/components/shared/controls/SComboboxTrigger.vue +122 -0
  103. package/src/components/shared/controls/SContextMenu.css +11 -0
  104. package/src/components/shared/controls/SContextMenu.vue +186 -0
  105. package/src/components/shared/controls/SContextToggleButton.vue +64 -0
  106. package/src/components/shared/controls/SDragHandle.vue +100 -0
  107. package/src/components/shared/controls/SDropdownMenu.css +5 -0
  108. package/src/components/shared/controls/SDropdownMenu.vue +188 -0
  109. package/src/components/shared/controls/SField.css +79 -0
  110. package/src/components/shared/controls/SField.vue +89 -0
  111. package/src/components/shared/controls/SFieldGroup.css +58 -0
  112. package/src/components/shared/controls/SFieldGroup.vue +117 -0
  113. package/src/components/shared/controls/SFieldLabel.css +12 -0
  114. package/src/components/shared/controls/SFieldLabel.vue +51 -0
  115. package/src/components/shared/controls/SInlineTokenEditor.css +61 -0
  116. package/src/components/shared/controls/SInlineTokenEditor.vue +1081 -0
  117. package/src/components/shared/controls/SInputText.css +66 -0
  118. package/src/components/shared/controls/SInputText.vue +321 -0
  119. package/src/components/shared/controls/SInteractiveSurface.css +72 -0
  120. package/src/components/shared/controls/SInteractiveSurface.vue +326 -0
  121. package/src/components/shared/controls/SLink.css +114 -0
  122. package/src/components/shared/controls/SLink.ts +85 -0
  123. package/src/components/shared/controls/SLink.vue +114 -0
  124. package/src/components/shared/controls/SListbox.css +31 -0
  125. package/src/components/shared/controls/SListbox.vue +388 -0
  126. package/src/components/shared/controls/SListboxOption.css +63 -0
  127. package/src/components/shared/controls/SListboxOption.vue +85 -0
  128. package/src/components/shared/controls/SMarker.css +19 -0
  129. package/src/components/shared/controls/SMarker.vue +33 -0
  130. package/src/components/shared/controls/SMenuSurface.css +20 -0
  131. package/src/components/shared/controls/SMenuSurface.vue +333 -0
  132. package/src/components/shared/controls/SSegmentedControl.css +38 -0
  133. package/src/components/shared/controls/SSegmentedControl.vue +134 -0
  134. package/src/components/shared/controls/SSelect.css +12 -0
  135. package/src/components/shared/controls/SSelect.vue +338 -0
  136. package/src/components/shared/controls/STextarea.css +31 -0
  137. package/src/components/shared/controls/STextarea.vue +316 -0
  138. package/src/components/shared/controls/_internal/SInlineTokenSurface.vue +224 -0
  139. package/src/components/shared/controls/menu.ts +178 -0
  140. package/src/components/shared/data-display/SActionCard.css +6 -0
  141. package/src/components/shared/data-display/SActionCard.vue +49 -0
  142. package/src/components/shared/data-display/SActionList.css +15 -0
  143. package/src/components/shared/data-display/SActionList.vue +34 -0
  144. package/src/components/shared/data-display/SActionListItem.css +114 -0
  145. package/src/components/shared/data-display/SActionListItem.vue +230 -0
  146. package/src/components/shared/data-display/SBadge.css +73 -0
  147. package/src/components/shared/data-display/SBadge.vue +52 -0
  148. package/src/components/shared/data-display/SCodeBlock.css +56 -0
  149. package/src/components/shared/data-display/SCodeBlock.vue +188 -0
  150. package/src/components/shared/data-display/SCodeEditor.css +178 -0
  151. package/src/components/shared/data-display/SCodeEditor.vue +274 -0
  152. package/src/components/shared/data-display/SCodeSearchPanel.vue +327 -0
  153. package/src/components/shared/data-display/SCopyField.vue +77 -0
  154. package/src/components/shared/data-display/SDocBlock.css +136 -0
  155. package/src/components/shared/data-display/SDocBlock.vue +358 -0
  156. package/src/components/shared/data-display/SEmptyState.css +42 -0
  157. package/src/components/shared/data-display/SEmptyState.vue +79 -0
  158. package/src/components/shared/data-display/SExpandableText.vue +314 -0
  159. package/src/components/shared/data-display/SJsonTree.css +6 -0
  160. package/src/components/shared/data-display/SJsonTree.vue +111 -0
  161. package/src/components/shared/data-display/SKeyValueGrid.css +37 -0
  162. package/src/components/shared/data-display/SKeyValueGrid.vue +277 -0
  163. package/src/components/shared/data-display/SLinkedSystemsList.vue +270 -0
  164. package/src/components/shared/data-display/SMessage.css +88 -0
  165. package/src/components/shared/data-display/SMessage.vue +152 -0
  166. package/src/components/shared/data-display/SMetricCard.css +32 -0
  167. package/src/components/shared/data-display/SMetricCard.vue +117 -0
  168. package/src/components/shared/data-display/SProgressBar.css +84 -0
  169. package/src/components/shared/data-display/SProgressBar.vue +114 -0
  170. package/src/components/shared/data-display/SProgressIndicator.css +59 -0
  171. package/src/components/shared/data-display/SProgressIndicator.vue +104 -0
  172. package/src/components/shared/data-display/SSectionHeader.css +84 -0
  173. package/src/components/shared/data-display/SSectionHeader.vue +58 -0
  174. package/src/components/shared/data-display/SStatus.css +90 -0
  175. package/src/components/shared/data-display/SStatus.vue +79 -0
  176. package/src/components/shared/data-display/STable.css +83 -0
  177. package/src/components/shared/data-display/STable.vue +339 -0
  178. package/src/components/shared/data-display/SToastContainer.css +53 -0
  179. package/src/components/shared/data-display/SToastContainer.vue +31 -0
  180. package/src/components/shared/data-display/STooltip.css +114 -0
  181. package/src/components/shared/data-display/STooltip.vue +550 -0
  182. package/src/components/shared/data-display/STooltipAnchor.css +21 -0
  183. package/src/components/shared/data-display/STooltipAnchor.vue +119 -0
  184. package/src/components/shared/data-display/SVirtualList.css +24 -0
  185. package/src/components/shared/data-display/SVirtualList.ts +19 -0
  186. package/src/components/shared/data-display/SVirtualList.vue +361 -0
  187. package/src/components/shared/data-display/json.ts +136 -0
  188. package/src/components/shared/data-display/table.ts +76 -0
  189. package/src/components/shared/database/SDataGrid.css +3 -0
  190. package/src/components/shared/database/SDataGrid.vue +464 -0
  191. package/src/components/shared/database/SSqlEditor.vue +363 -0
  192. package/src/components/shared/database/dataGrid.ts +61 -0
  193. package/src/components/shared/feedback/SAsyncState.css +26 -0
  194. package/src/components/shared/feedback/SAsyncState.vue +190 -0
  195. package/src/components/shared/graph/SGraphViewport.ts +1 -0
  196. package/src/components/shared/graph/SGraphViewport.vue +858 -0
  197. package/src/components/shared/graph/_internal/graphViewportContract.ts +362 -0
  198. package/src/components/shared/markdown.ts +169 -0
  199. package/src/components/shared/navigation/SBottomNav.vue +692 -0
  200. package/src/components/shared/navigation/SBreadcrumbs.css +26 -0
  201. package/src/components/shared/navigation/SBreadcrumbs.vue +155 -0
  202. package/src/components/shared/navigation/SCatalogNavigator.css +100 -0
  203. package/src/components/shared/navigation/SCatalogNavigator.vue +308 -0
  204. package/src/components/shared/navigation/STab.vue +363 -0
  205. package/src/components/shared/navigation/STabList.vue +442 -0
  206. package/src/components/shared/navigation/STabPanel.vue +165 -0
  207. package/src/components/shared/navigation/STabPanels.vue +33 -0
  208. package/src/components/shared/navigation/STabs.vue +617 -0
  209. package/src/components/shared/navigation/SWizardSteps.css +69 -0
  210. package/src/components/shared/navigation/SWizardSteps.vue +171 -0
  211. package/src/components/shared/navigation/_internal/SCatalogNavigatorGroup.vue +63 -0
  212. package/src/components/shared/persona/SPersonaProjectPicker.css +36 -0
  213. package/src/components/shared/persona/SPersonaProjectPicker.vue +361 -0
  214. package/src/components/shared/persona/SPersonaRunWorkbench.css +109 -0
  215. package/src/components/shared/persona/SPersonaRunWorkbench.vue +549 -0
  216. package/src/components/shared/persona/_internal/SPersonaRunConsole.css +40 -0
  217. package/src/components/shared/persona/_internal/SPersonaRunConsole.vue +298 -0
  218. package/src/components/shared/persona/_internal/inventory.ts +110 -0
  219. package/src/components/shared/persona/_internal/labels.ts +79 -0
  220. package/src/components/shared/persona/presentation.ts +371 -0
  221. package/src/components/shared/persona/types.ts +256 -0
  222. package/src/composables/uiPreferencesReset.ts +52 -0
  223. package/src/composables/useClipboard.ts +37 -0
  224. package/src/composables/useDialogOverlay.ts +85 -0
  225. package/src/composables/useDisclosure.ts +40 -0
  226. package/src/composables/useFloatingPosition.ts +245 -0
  227. package/src/composables/useNotifier.ts +26 -0
  228. package/src/composables/useSidebarPanelState.ts +610 -0
  229. package/src/internal/codeEditorContract.ts +110 -0
  230. package/src/internal/codeEditorExtensions.ts +27 -0
  231. package/src/internal/feedbackPresentation.ts +136 -0
  232. package/src/internal/fieldSurface.ts +59 -0
  233. package/src/internal/focusNavigation.ts +69 -0
  234. package/src/internal/inlineTokenEditorContract.ts +136 -0
  235. package/src/internal/interactiveElement.ts +33 -0
  236. package/src/internal/layerStack.ts +202 -0
  237. package/src/internal/linkTarget.ts +256 -0
  238. package/src/internal/ownedAttrs.ts +464 -0
  239. package/src/internal/passiveContentContract.ts +129 -0
  240. package/src/internal/pointerInteractionLease.ts +81 -0
  241. package/src/internal/runtimeContract.ts +194 -0
  242. package/src/internal/runtimeTheme.ts +159 -0
  243. package/src/internal/semanticSizing.ts +60 -0
  244. package/src/internal/useMenuLayer.ts +129 -0
  245. package/src/stores/useNotifierStore.ts +69 -0
  246. package/src/styles/reference.css +4 -0
  247. package/src/styles/style.css +151 -0
  248. package/src/styles/tokens.css +836 -0
  249. package/src/theme.ts +449 -0
  250. package/src/types/highlight-js-lib.d.ts +76 -0
  251. package/src/variants.ts +15 -0
@@ -0,0 +1,761 @@
1
+ <template>
2
+ <li
3
+ :id="itemId"
4
+ ref="itemEl"
5
+ class="s-tree-node-wrapper"
6
+ role="treeitem"
7
+ :tabindex="isActive ? 0 : -1"
8
+ :aria-level="props.level + 1"
9
+ :aria-posinset="props.position"
10
+ :aria-setsize="props.setSize"
11
+ :aria-expanded="hasChildren ? isExpanded : undefined"
12
+ :aria-selected="selection.mode === 'single' ? isSelected : undefined"
13
+ :aria-checked="selection.mode === 'multiple' ? selectionCheckedState : undefined"
14
+ :aria-disabled="isTreeItemDisabled || undefined"
15
+ :class="{
16
+ 's-tree-node-wrapper--has-children': hasChildren,
17
+ 's-tree-node-wrapper--expanded': isExpanded,
18
+ 's-tree-node-wrapper--with-selection-rail': hasSelectionRail,
19
+ 's-tree-node-wrapper--compact': runtime.density.value === 'compact',
20
+ 's-tree-node-wrapper--overlay-actions': runtime.actionsLayout.value === 'overlay',
21
+ 's-tree-node-wrapper--row-table': runtime.rowVariant.value === 'table',
22
+ }"
23
+ @focus="runtime.activeKey.value = nodeKey"
24
+ @click="handleTreeItemClick"
25
+ @keydown="handleTreeItemKeydown"
26
+ >
27
+ <div
28
+ class="s-tree-node-hitbox py-0.5 transition-colors duration-[var(--s-motion-fast)] hover:bg-surface-100 dark:hover:bg-surface-800"
29
+ >
30
+ <div
31
+ class="s-tree-node-row px-4 flex items-center"
32
+ :class="{
33
+ 's-tree-node-row--with-selection-rail': hasSelectionRail,
34
+ 's-tree-node-row--rail-selected': hasSelectionRail && isSelected,
35
+ 's-tree-node-row--rail-partial': hasSelectionRail && isPartiallySelected,
36
+ }"
37
+ :style="{ paddingLeft: hasSelectionRail ? undefined : nodeIndent }"
38
+ >
39
+ <div v-if="hasSelectionRail" class="s-tree-node-selection-rail" aria-hidden="false">
40
+ <SButton
41
+ appearance="ghost"
42
+ size="sm"
43
+ icon-only
44
+ :leading-icon="isSelected ? Check : isPartiallySelected ? Minus : undefined"
45
+ data-tree-selection-control
46
+ :data-state="isSelected ? 'selected' : isPartiallySelected ? 'partial' : 'unselected'"
47
+ :aria-label="selectionLabel"
48
+ :pressed="selectionPressedState"
49
+ :disabled="isSelectionDisabled"
50
+ tabindex="-1"
51
+ @pointerdown.prevent
52
+ @click.stop="activateSelectionAffordance"
53
+ />
54
+ </div>
55
+
56
+ <div
57
+ class="s-tree-node-content-shell"
58
+ :class="{
59
+ 's-tree-node-content-shell--has-children': hasChildren,
60
+ 's-tree-node-content-shell--expanded': isExpanded,
61
+ }"
62
+ :style="{ paddingLeft: hasSelectionRail ? nodeIndent : undefined }"
63
+ >
64
+ <div
65
+ v-if="runtime.expandControl.value === 'button'"
66
+ class="s-tree-node-toggle-slot shrink-0"
67
+ :class="{
68
+ 's-tree-node-toggle-slot--has-children': hasChildren,
69
+ 's-tree-node-toggle-slot--expanded': isExpanded,
70
+ }"
71
+ >
72
+ <SButton
73
+ v-if="hasChildren"
74
+ appearance="ghost"
75
+ size="xs"
76
+ icon-only
77
+ :leading-icon="isExpanded ? ChevronDown : ChevronRight"
78
+ :aria-label="toggleLabel"
79
+ tabindex="-1"
80
+ @pointerdown.prevent
81
+ @click.stop="activateToggleAffordance"
82
+ />
83
+ </div>
84
+
85
+ <SCheckbox
86
+ v-if="selection.mode === 'multiple' && !hasSelectionRail"
87
+ :model-value="isSelected"
88
+ :indeterminate="isPartiallySelected"
89
+ :disabled="isSelectionDisabled"
90
+ :aria-label="selectionLabel"
91
+ tabindex="-1"
92
+ @pointerdown.prevent
93
+ @click.stop
94
+ @update:model-value="activateSelectionAffordance"
95
+ />
96
+
97
+ <template v-if="isRowInteractive">
98
+ <div
99
+ class="s-tree-node s-tree-node__layout w-full cursor-pointer flex-grow"
100
+ :class="{
101
+ 's-tree-node--selected': isSelected && selection.mode === 'single',
102
+ 's-tree-node--rail-selected': hasSelectionRail && isSelected,
103
+ 's-tree-node--rail-partial': hasSelectionRail && isPartiallySelected,
104
+ 's-tree-node--row-expand': runtime.expandControl.value === 'row' && hasChildren,
105
+ 's-tree-node--disabled': isTreeItemDisabled,
106
+ }"
107
+ role="presentation"
108
+ >
109
+ <div class="s-tree-node__primary">
110
+ <PassiveContentBoundary :contract="rowContentContract">
111
+ <slot name="col-left" v-bind="scope">
112
+ <div class="s-tree-node__header">
113
+ <component :is="nodeIcon" v-if="nodeIcon" class="s-tree-node__icon" />
114
+ <span
115
+ class="s-tree-node__title"
116
+ :class="{ 'text-primary-800 dark:text-primary-200': isSelected }"
117
+ >{{ nodeLabel }}</span>
118
+ </div>
119
+ </slot>
120
+ </PassiveContentBoundary>
121
+ </div>
122
+ <div class="s-tree-node__center">
123
+ <PassiveContentBoundary :contract="rowContentContract">
124
+ <slot name="col-center" v-bind="scope" />
125
+ </PassiveContentBoundary>
126
+ </div>
127
+ <div class="s-tree-node__trailing s-tree-node-right">
128
+ <div class="s-tree-node__meta">
129
+ <PassiveContentBoundary :contract="rowContentContract">
130
+ <slot name="meta" v-bind="scope" />
131
+ </PassiveContentBoundary>
132
+ </div>
133
+ </div>
134
+ </div>
135
+
136
+ <TreeActionRegion
137
+ v-if="hasActionSlots"
138
+ :context="actionRegistry"
139
+ :set-element="setActionsElement"
140
+ class="s-tree-node-actions s-tree-node-actions--standalone"
141
+ :class="{ 's-tree-node-actions--has-persistent': Boolean($slots['persistent-actions']) }"
142
+ role="group"
143
+ :aria-label="`Действия: ${nodeLabel}. F2 — войти, Escape — вернуться`"
144
+ >
145
+ <div v-if="$slots['persistent-actions']" class="s-tree-node-actions__persistent">
146
+ <slot name="persistent-actions" v-bind="scope" />
147
+ </div>
148
+ <div v-if="$slots.actions" class="s-tree-node-actions__transient">
149
+ <slot name="actions" v-bind="scope" />
150
+ </div>
151
+ </TreeActionRegion>
152
+ </template>
153
+
154
+ <div v-else class="s-tree-node s-tree-node__layout w-full flex-grow">
155
+ <div class="s-tree-node__primary">
156
+ <PassiveContentBoundary :contract="rowContentContract">
157
+ <slot name="col-left" v-bind="scope">
158
+ <div class="s-tree-node__header">
159
+ <component :is="nodeIcon" v-if="nodeIcon" class="s-tree-node__icon" />
160
+ <span class="s-tree-node__title">{{ nodeLabel }}</span>
161
+ </div>
162
+ </slot>
163
+ </PassiveContentBoundary>
164
+ </div>
165
+ <div class="s-tree-node__center">
166
+ <PassiveContentBoundary :contract="rowContentContract">
167
+ <slot name="col-center" v-bind="scope" />
168
+ </PassiveContentBoundary>
169
+ </div>
170
+ <div class="s-tree-node__trailing s-tree-node-right">
171
+ <div class="s-tree-node__meta">
172
+ <PassiveContentBoundary :contract="rowContentContract">
173
+ <slot name="meta" v-bind="scope" />
174
+ </PassiveContentBoundary>
175
+ </div>
176
+ <TreeActionRegion
177
+ v-if="hasActionSlots"
178
+ :context="actionRegistry"
179
+ :set-element="setActionsElement"
180
+ class="s-tree-node-actions"
181
+ :class="{ 's-tree-node-actions--has-persistent': Boolean($slots['persistent-actions']) }"
182
+ role="group"
183
+ :aria-label="`Действия: ${nodeLabel}. F2 — войти, Escape — вернуться`"
184
+ >
185
+ <div v-if="$slots['persistent-actions']" class="s-tree-node-actions__persistent">
186
+ <slot name="persistent-actions" v-bind="scope" />
187
+ </div>
188
+ <div v-if="$slots.actions" class="s-tree-node-actions__transient">
189
+ <slot name="actions" v-bind="scope" />
190
+ </div>
191
+ </TreeActionRegion>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+
198
+ <ul v-if="isExpanded && hasChildren" class="s-tree-node-children" role="group">
199
+ <STreeNode
200
+ v-for="(child, index) in nodeChildren"
201
+ :key="runtime.model.key(child)"
202
+ :node="child"
203
+ :level="props.level + 1"
204
+ :parent-key="nodeKey"
205
+ :position="index + 1"
206
+ :set-size="nodeChildren.length"
207
+ >
208
+ <template v-if="$slots['col-left']" #col-left="childScope"><slot name="col-left" v-bind="childScope" /></template>
209
+ <template v-if="$slots['col-center']" #col-center="childScope"><slot name="col-center" v-bind="childScope" /></template>
210
+ <template v-if="$slots.meta" #meta="childScope"><slot name="meta" v-bind="childScope" /></template>
211
+ <template v-if="$slots['persistent-actions']" #persistent-actions="childScope"><slot name="persistent-actions" v-bind="childScope" /></template>
212
+ <template v-if="$slots.actions" #actions="childScope"><slot name="actions" v-bind="childScope" /></template>
213
+ </STreeNode>
214
+ </ul>
215
+ </li>
216
+ </template>
217
+
218
+ <script setup lang="ts" generic="T extends object, K extends SelectionKey">
219
+ import { computed, defineComponent, h, inject, onBeforeUnmount, onMounted, provide, ref } from 'vue'
220
+ import type { PropType } from 'vue'
221
+ import { Check, ChevronDown, ChevronRight, Minus } from '../../icons/sputnigUiIcons'
222
+ import {
223
+ PassiveContentBoundary,
224
+ type PassiveContentContract,
225
+ useInteractiveLeafRegistration,
226
+ } from '../../../internal/passiveContentContract'
227
+ import SButton from '../controls/SButton.vue'
228
+ import SCheckbox from '../controls/SCheckbox.vue'
229
+ import type { SelectionKey, STreeNodeContentScope, TreeActivationOrigin } from '../complex/types'
230
+ import { selectionKeyToken } from './useSelectionRoving'
231
+ import {
232
+ TREE_RUNTIME_KEY,
233
+ TREE_ACTION_CONTEXT_KEY,
234
+ type RegisteredTreeItem,
235
+ TreeActionRegistrationStore,
236
+ type TreeActionContext,
237
+ type TreeRuntime,
238
+ } from './treeRuntime'
239
+
240
+ defineOptions({ name: 'STreeNode' })
241
+ useInteractiveLeafRegistration({ owner: 'STreeNode' })
242
+
243
+ const props = defineProps<{
244
+ node: T
245
+ level: number
246
+ parentKey?: K
247
+ position: number
248
+ setSize: number
249
+ }>()
250
+
251
+ const slots = defineSlots<{
252
+ 'col-left': (props: STreeNodeContentScope<T, K>) => unknown
253
+ 'col-center': (props: STreeNodeContentScope<T, K>) => unknown
254
+ 'meta': (props: STreeNodeContentScope<T, K>) => unknown
255
+ 'persistent-actions': (props: STreeNodeContentScope<T, K>) => unknown
256
+ 'actions': (props: STreeNodeContentScope<T, K>) => unknown
257
+ }>()
258
+
259
+ function requireTreeRuntime(value: TreeRuntime<T, K> | undefined): TreeRuntime<T, K> {
260
+ if (value) return value
261
+ throw new Error('STreeNode must be rendered inside STree')
262
+ }
263
+ const runtime = requireTreeRuntime(inject<TreeRuntime<T, K>>(TREE_RUNTIME_KEY))
264
+
265
+ const itemEl = ref<HTMLElement | null>(null)
266
+ const actionsEl = ref<HTMLElement | null>(null)
267
+ const actionRegistry = new TreeActionRegistrationStore(() => actionsEl.value)
268
+ const rowContentContract: PassiveContentContract = {
269
+ owner: 'STreeNode',
270
+ region: 'passive row content',
271
+ guidance: 'Передайте действия через persistent-actions или actions slot. / Put actions in the persistent-actions or actions slot.',
272
+ }
273
+
274
+ const TreeActionRegion = defineComponent({
275
+ name: 'STreeActionRegion',
276
+ inheritAttrs: false,
277
+ props: {
278
+ context: {
279
+ type: Object as PropType<TreeActionContext>,
280
+ required: true,
281
+ },
282
+ setElement: {
283
+ type: Function as PropType<(element: unknown) => void>,
284
+ required: true,
285
+ },
286
+ },
287
+ setup(regionProps, { attrs, slots }) {
288
+ provide(TREE_ACTION_CONTEXT_KEY, regionProps.context)
289
+ return () => h('div', { ...attrs, ref: regionProps.setElement }, slots.default?.())
290
+ },
291
+ })
292
+
293
+ function setActionsElement(element: unknown): void {
294
+ if (element === null || element instanceof HTMLElement) {
295
+ actionsEl.value = element
296
+ return
297
+ }
298
+ throw new Error('STree action region ref must resolve to an HTMLElement')
299
+ }
300
+
301
+ const nodeKey = computed(() => runtime.model.key(props.node))
302
+ const nodeLabel = computed(() => runtime.model.label(props.node))
303
+ const nodeChildren = computed(() => runtime.model.children(props.node))
304
+ const nodeIcon = computed(() => runtime.model.icon(props.node))
305
+ const selection = computed(() => runtime.selection.value)
306
+ const multipleKeys = computed(() => runtime.multipleKeys(props.node))
307
+ const hasChildren = computed(() => nodeChildren.value.length > 0)
308
+ const isExpanded = computed(() => runtime.expanded.value.has(nodeKey.value))
309
+ const isTreeItemDisabled = computed(() => runtime.model.disabled(props.node))
310
+ const isSelectionDisabled = computed(() =>
311
+ isTreeItemDisabled.value
312
+ || (selection.value.mode === 'multiple' && multipleKeys.value.length === 0),
313
+ )
314
+ const isSelected = computed(() => {
315
+ if (selection.value.mode === 'none') return false
316
+ if (selection.value.mode === 'single') return selection.value.key === nodeKey.value
317
+ return multipleKeys.value.length > 0
318
+ && multipleKeys.value.every((key) => selection.value.mode === 'multiple' && selection.value.keys.has(key))
319
+ })
320
+ const isPartiallySelected = computed(() => {
321
+ if (selection.value.mode !== 'multiple' || multipleKeys.value.length === 0 || isSelected.value) return false
322
+ return multipleKeys.value.some((key) => selection.value.mode === 'multiple' && selection.value.keys.has(key))
323
+ })
324
+ const hasSelectionRail = computed(() =>
325
+ runtime.selectionRail.value === 'visible' && selection.value.mode === 'multiple',
326
+ )
327
+ const hasActionSlots = computed(() => Boolean(slots['persistent-actions'] || slots.actions))
328
+ const isRowInteractive = computed(() =>
329
+ selection.value.mode === 'single'
330
+ || selection.value.mode === 'multiple'
331
+ || (hasChildren.value && runtime.expandControl.value === 'row'),
332
+ )
333
+ const isActive = computed(() => runtime.activeKey.value === nodeKey.value)
334
+ const itemId = computed(() => `s-tree-item-${selectionKeyToken('STree', nodeKey.value, 'rendered node key')}`)
335
+ const nodeIndent = computed(() => {
336
+ if (runtime.density.value === 'compact') return `${props.level * 0.85 + 0.25}rem`
337
+ return `${props.level === 0 ? 1 : props.level * 1.5}rem`
338
+ })
339
+ const toggleLabel = computed(() =>
340
+ `${isExpanded.value ? 'Свернуть' : 'Развернуть'} узел ${nodeLabel.value}`,
341
+ )
342
+ const selectionLabel = computed(() =>
343
+ `${isSelected.value || isPartiallySelected.value ? 'Снять выбор' : 'Выбрать'}: ${nodeLabel.value}`,
344
+ )
345
+ const selectionPressedState = computed(() => isPartiallySelected.value ? 'mixed' : isSelected.value)
346
+ const selectionCheckedState = computed(() => isPartiallySelected.value ? 'mixed' : isSelected.value)
347
+
348
+ function toggle(): void {
349
+ runtime.toggleNode(props.node)
350
+ }
351
+
352
+ function select(): void {
353
+ if (isSelectionDisabled.value) return
354
+ if (selection.value.mode === 'multiple') runtime.checkNode(props.node)
355
+ else if (selection.value.mode === 'single') runtime.selectNode(props.node)
356
+ }
357
+
358
+ function activateRow(origin: TreeActivationOrigin): void {
359
+ if (runtime.expandControl.value === 'row' && hasChildren.value) {
360
+ toggle()
361
+ return
362
+ }
363
+ if (selection.value.mode === 'multiple') {
364
+ if (hasChildren.value) {
365
+ toggle()
366
+ return
367
+ }
368
+ }
369
+ if (selection.value.mode === 'single') runtime.selectNode(props.node)
370
+ if (!hasChildren.value) runtime.activateNode(props.node, origin)
371
+ }
372
+
373
+ function handleRowClick(): void {
374
+ runtime.activeKey.value = nodeKey.value
375
+ itemEl.value?.focus({ preventScroll: true })
376
+ if (isTreeItemDisabled.value) return
377
+ activateRow('pointer')
378
+ }
379
+
380
+ function eventElement(event: Event): Element | null {
381
+ return event.target instanceof Element ? event.target : null
382
+ }
383
+
384
+ function belongsToActions(event: Event): boolean {
385
+ const target = eventElement(event)
386
+ return Boolean(target && actionsEl.value?.contains(target))
387
+ }
388
+
389
+ function handleTreeItemClick(event: MouseEvent): void {
390
+ const owningTreeItem = event.composedPath().find((target) => (
391
+ target instanceof HTMLElement && target.getAttribute('role') === 'treeitem'
392
+ ))
393
+ if (owningTreeItem !== itemEl.value) return
394
+ if (belongsToActions(event)) return
395
+ handleRowClick()
396
+ }
397
+
398
+ function returnToTreeItem(): void {
399
+ runtime.activeKey.value = nodeKey.value
400
+ itemEl.value?.focus({ preventScroll: true })
401
+ }
402
+
403
+ function activateToggleAffordance(): void {
404
+ returnToTreeItem()
405
+ toggle()
406
+ }
407
+
408
+ function activateSelectionAffordance(): void {
409
+ returnToTreeItem()
410
+ select()
411
+ }
412
+
413
+ const scope = computed<STreeNodeContentScope<T, K>>(() => ({
414
+ node: props.node,
415
+ key: nodeKey.value,
416
+ isSelected: isSelected.value,
417
+ isPartiallySelected: isPartiallySelected.value,
418
+ isExpanded: isExpanded.value,
419
+ hasChildren: hasChildren.value,
420
+ toggle,
421
+ select,
422
+ level: props.level,
423
+ density: runtime.density.value,
424
+ actionsLayout: runtime.actionsLayout.value,
425
+ expandControl: runtime.expandControl.value,
426
+ selectionRail: runtime.selectionRail.value,
427
+ rowVariant: runtime.rowVariant.value,
428
+ }))
429
+
430
+ function registration(): RegisteredTreeItem<T, K> {
431
+ const element = itemEl.value
432
+ if (!element) throw new Error('STreeNode registration requires a mounted treeitem element')
433
+ return {
434
+ key: nodeKey.value,
435
+ parentKey: props.parentKey,
436
+ node: props.node,
437
+ element,
438
+ activate: activateRow,
439
+ select,
440
+ toggle,
441
+ expanded: () => isExpanded.value,
442
+ hasChildren: () => hasChildren.value,
443
+ disabled: () => isTreeItemDisabled.value,
444
+ }
445
+ }
446
+
447
+ function enterActions(): void {
448
+ actionRegistry.orderedEnabled()[0]?.focus({ preventScroll: true })
449
+ }
450
+
451
+ function handleActionsKeydown(event: KeyboardEvent): void {
452
+ const actions = actionRegistry.orderedEnabled()
453
+ const currentAction = actionRegistry.actionForTarget(event.target)
454
+ const currentIndex = currentAction ? actions.indexOf(currentAction) : -1
455
+ if (event.key === 'Escape') {
456
+ event.preventDefault()
457
+ event.stopPropagation()
458
+ returnToTreeItem()
459
+ return
460
+ }
461
+ if (event.key === 'Tab') {
462
+ event.preventDefault()
463
+ event.stopPropagation()
464
+ const next = actions[currentIndex + (event.shiftKey ? -1 : 1)]
465
+ if (next) next.focus({ preventScroll: true })
466
+ else returnToTreeItem()
467
+ return
468
+ }
469
+ if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(event.key)) return
470
+ event.preventDefault()
471
+ event.stopPropagation()
472
+ const nextIndex = event.key === 'Home'
473
+ ? 0
474
+ : event.key === 'End'
475
+ ? actions.length - 1
476
+ : currentIndex + (event.key === 'ArrowLeft' || event.key === 'ArrowUp' ? -1 : 1)
477
+ actions[nextIndex]?.focus({ preventScroll: true })
478
+ }
479
+
480
+ function handleTreeItemKeydown(event: KeyboardEvent): void {
481
+ if (belongsToActions(event)) {
482
+ if (actionRegistry.actionForTarget(event.target)) handleActionsKeydown(event)
483
+ return
484
+ }
485
+ if (event.target !== itemEl.value) return
486
+ if (event.key === 'F2' && actionRegistry.orderedEnabled().length > 0) {
487
+ event.preventDefault()
488
+ enterActions()
489
+ return
490
+ }
491
+ runtime.handleItemKeydown(registration(), event)
492
+ }
493
+
494
+ onMounted(() => {
495
+ runtime.register(registration())
496
+ })
497
+ onBeforeUnmount(() => {
498
+ runtime.unregister(nodeKey.value)
499
+ })
500
+ </script>
501
+
502
+ <style lang="postcss">
503
+ @reference "../../../styles/reference.css";
504
+
505
+ .s-tree-node-wrapper {
506
+ --s-tree-node-rail-width: 4rem;
507
+ --s-tree-node-toggle-width: 1.9rem;
508
+ position: relative;
509
+ list-style: none;
510
+ }
511
+
512
+ .s-tree-node-wrapper--compact {
513
+ --s-tree-node-rail-width: 3.15rem;
514
+ --s-tree-node-toggle-width: 1.62rem;
515
+ }
516
+
517
+ .s-tree-node-hitbox {
518
+ padding-block: 0.08rem;
519
+ border-bottom: var(--s-tree-row-border-bottom);
520
+ background: var(--s-tree-row-background);
521
+ transition: background-color var(--s-motion-fast) ease;
522
+ }
523
+
524
+ .s-tree-node-hitbox:hover,
525
+ .s-tree-node-hitbox:focus-within {
526
+ background: var(--color-surface-100);
527
+ }
528
+
529
+ .s-tree-node-wrapper:focus-visible > .s-tree-node-hitbox {
530
+ outline: var(--s-focus-ring-width) solid var(--s-focus-ring-strong-color);
531
+ outline-offset: var(--s-focus-ring-inset-offset);
532
+ }
533
+
534
+ .s-tree-node-row {
535
+ display: flex;
536
+ min-width: 0;
537
+ align-items: flex-start;
538
+ padding-inline: 1rem;
539
+ }
540
+
541
+ .s-tree-node-row--with-selection-rail {
542
+ align-items: stretch;
543
+ padding-left: 0.25rem;
544
+ }
545
+
546
+ .s-tree-node-row--rail-selected,
547
+ .s-tree-node-row--rail-partial {
548
+ background: var(--s-tree-row-selected-bg);
549
+ }
550
+
551
+ .s-tree-node-content-shell {
552
+ display: flex;
553
+ min-width: 0;
554
+ flex: 1 1 auto;
555
+ align-items: stretch;
556
+ }
557
+
558
+ .s-tree-node-selection-rail {
559
+ display: flex;
560
+ width: var(--s-tree-node-rail-width);
561
+ flex: 0 0 var(--s-tree-node-rail-width);
562
+ align-items: center;
563
+ justify-content: center;
564
+ border-right: 1px solid color-mix(in srgb, var(--color-surface-200) 76%, transparent);
565
+ padding: 0.16rem 0.5rem 0.16rem 0;
566
+ }
567
+
568
+ .s-tree-node-toggle-slot {
569
+ position: relative;
570
+ display: flex;
571
+ width: var(--s-tree-node-toggle-width);
572
+ min-height: 100%;
573
+ flex: 0 0 var(--s-tree-node-toggle-width);
574
+ align-self: stretch;
575
+ align-items: flex-start;
576
+ justify-content: center;
577
+ margin-right: 0.42rem;
578
+ padding-top: 0.28rem;
579
+ color: var(--color-surface-500);
580
+ }
581
+
582
+ .s-tree-node-toggle-slot--expanded::before {
583
+ position: absolute;
584
+ top: 1.88rem;
585
+ bottom: -0.22rem;
586
+ left: 50%;
587
+ width: 1px;
588
+ content: "";
589
+ background: var(--s-tree-branch-active-color);
590
+ }
591
+
592
+ .s-tree-node {
593
+ display: flex;
594
+ min-width: 0;
595
+ min-height: 3rem;
596
+ align-items: center;
597
+ justify-content: space-between;
598
+ border-radius: var(--radius-xs);
599
+ padding: 0.42rem 0.5rem;
600
+ color: var(--color-surface-700);
601
+ }
602
+
603
+ .s-tree-node__layout {
604
+ @apply grid w-full items-center gap-x-6;
605
+ grid-template-columns: minmax(0, 1fr) auto;
606
+ }
607
+
608
+ .s-tree-node__primary {
609
+ @apply flex min-w-0 flex-col gap-1;
610
+ }
611
+
612
+ .s-tree-node__center {
613
+ @apply min-w-0;
614
+ }
615
+
616
+ .s-tree-node__trailing {
617
+ @apply flex min-w-0 items-center justify-end gap-4;
618
+ }
619
+
620
+ .s-tree-node__header {
621
+ @apply flex min-w-0 items-center gap-2;
622
+ }
623
+
624
+ .s-tree-node__icon {
625
+ @apply shrink-0 text-surface-400 dark:text-surface-500;
626
+ }
627
+
628
+ .s-tree-node__title {
629
+ @apply min-w-0 font-semibold text-surface-900 dark:text-surface-50;
630
+ overflow-wrap: anywhere;
631
+ word-break: break-word;
632
+ }
633
+
634
+ .s-tree-node__meta {
635
+ @apply flex flex-wrap items-center justify-end gap-3 whitespace-nowrap text-sm text-surface-600 dark:text-surface-400;
636
+ }
637
+
638
+ .s-tree-node--selected {
639
+ @apply bg-primary-100 font-semibold text-primary-800 dark:bg-primary-900/60 dark:text-primary-200;
640
+ }
641
+
642
+ .s-tree-node--disabled {
643
+ cursor: not-allowed;
644
+ opacity: 0.58;
645
+ }
646
+
647
+ .s-tree-node--rail-selected,
648
+ .s-tree-node--rail-partial {
649
+ background: transparent;
650
+ color: var(--color-surface-900);
651
+ }
652
+
653
+ .s-tree-node-right,
654
+ .s-tree-node-actions {
655
+ display: flex;
656
+ min-width: 0;
657
+ align-items: center;
658
+ }
659
+
660
+ .s-tree-node-actions {
661
+ @apply ml-auto flex shrink-0 items-center gap-1 pl-2;
662
+ }
663
+
664
+ .s-tree-node-actions__persistent,
665
+ .s-tree-node-actions__transient {
666
+ @apply flex items-center gap-1;
667
+ }
668
+
669
+ .s-tree-node-actions__transient {
670
+ opacity: 0;
671
+ transition: opacity var(--s-motion-fast) ease;
672
+ }
673
+
674
+ .s-tree-node:hover .s-tree-node-actions__transient,
675
+ .s-tree-node:focus-within .s-tree-node-actions__transient {
676
+ opacity: 1;
677
+ }
678
+
679
+ .s-tree-node-wrapper--compact .s-tree-node-hitbox {
680
+ padding-block: 0;
681
+ }
682
+
683
+ .s-tree-node-wrapper--compact .s-tree-node-row {
684
+ padding-right: 0.25rem;
685
+ }
686
+
687
+ .s-tree-node-wrapper--compact .s-tree-node-selection-rail {
688
+ padding: 0.04rem 0.38rem 0.04rem 0;
689
+ }
690
+
691
+ .s-tree-node-wrapper--compact .s-tree-node {
692
+ min-height: 1.75rem;
693
+ gap: 0.25rem;
694
+ padding: 0 0.25rem;
695
+ }
696
+
697
+ .s-tree-node-wrapper--overlay-actions .s-tree-node {
698
+ position: relative;
699
+ display: grid;
700
+ overflow: hidden;
701
+ grid-template-columns: minmax(0, 1fr) max-content;
702
+ gap: 1.25rem;
703
+ padding-right: 0.78rem;
704
+ }
705
+
706
+ .s-tree-node-wrapper--overlay-actions .s-tree-node-right {
707
+ position: relative;
708
+ z-index: var(--s-layer-sticky);
709
+ grid-column: 2;
710
+ justify-content: flex-end;
711
+ }
712
+
713
+ .s-tree-node-wrapper--overlay-actions .s-tree-node-actions {
714
+ position: absolute;
715
+ top: 50%;
716
+ right: 0.42rem;
717
+ z-index: calc(var(--s-layer-sticky) + 1);
718
+ width: max-content;
719
+ padding: 0.16rem;
720
+ border-radius: var(--radius-sm);
721
+ background: color-mix(in srgb, var(--color-surface-0) 98%, transparent);
722
+ box-shadow: -18px 0 24px color-mix(in srgb, var(--color-surface-0) 86%, transparent);
723
+ opacity: 0;
724
+ transform: translateY(-50%);
725
+ transition: opacity var(--s-motion-fast) ease, transform var(--s-motion-fast) ease;
726
+ }
727
+
728
+ .s-tree-node-wrapper--overlay-actions .s-tree-node-actions--has-persistent {
729
+ opacity: 1;
730
+ }
731
+
732
+ .s-tree-node-wrapper--overlay-actions .s-tree-node:hover .s-tree-node-actions,
733
+ .s-tree-node-wrapper--overlay-actions .s-tree-node:focus-within .s-tree-node-actions {
734
+ opacity: 1;
735
+ transform: translate(-0.04rem, -50%);
736
+ }
737
+
738
+ .s-tree-node-wrapper--row-table .s-tree-node-hitbox:hover,
739
+ .s-tree-node-wrapper--row-table .s-tree-node-hitbox:focus-within {
740
+ background:
741
+ linear-gradient(90deg, color-mix(in srgb, var(--color-success-50) 36%, transparent), transparent 62%),
742
+ var(--color-surface-50);
743
+ }
744
+
745
+ .s-tree-node-wrapper--row-table .s-tree-node {
746
+ border-radius: 0;
747
+ }
748
+
749
+ .s-tree-node-wrapper--row-table .s-tree-node--rail-selected,
750
+ .s-tree-node-wrapper--row-table .s-tree-node--rail-partial {
751
+ background: transparent;
752
+ }
753
+
754
+ .s-tree-node-wrapper--row-table .s-tree-node-right {
755
+ align-self: stretch;
756
+ }
757
+
758
+ .s-tree-node-wrapper--row-table .s-tree-node__meta {
759
+ height: 100%;
760
+ }
761
+ </style>