@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,102 @@
1
+ import type { Component } from 'vue'
2
+ import type { SelectionKey } from '../_internal/useSelectionRoving'
3
+
4
+ export type { SelectionKey } from '../_internal/useSelectionRoving'
5
+
6
+ /**
7
+ * Стратегия множественного выбора узла. / Multiple-selection behavior for an item.
8
+ *
9
+ * `descendants` выбирает только явно выбираемые дочерние узлы и не добавляет
10
+ * контейнер в пользовательский selection set. `self-and-descendants` нужен
11
+ * доменным деревьям, где родитель одновременно является самостоятельной
12
+ * сущностью и контейнером.
13
+ */
14
+ export type TreeMultipleSelection =
15
+ | 'self'
16
+ | 'descendants'
17
+ | 'self-and-descendants'
18
+ | 'disabled'
19
+
20
+ export type TreeIcon = Component
21
+
22
+ /**
23
+ * Точная модель доменного дерева. / Exact domain-tree model.
24
+ *
25
+ * STree не читает поля доменного объекта по строковым именам. Каждый источник
26
+ * данных обязан один раз объявить identity, label, hierarchy и behavior.
27
+ */
28
+ export interface TreeModel<T extends object, K extends SelectionKey = SelectionKey> {
29
+ key(node: T): K
30
+ label(node: T): string
31
+ children(node: T): readonly T[]
32
+ disabled(node: T): boolean
33
+ icon(node: T): TreeIcon | undefined
34
+ multipleSelection(node: T): TreeMultipleSelection
35
+ }
36
+
37
+ /**
38
+ * Единое состояние выбора. / Single canonical selection state.
39
+ *
40
+ * Checkbox является presentation множественного режима, а не отдельной
41
+ * identity model.
42
+ */
43
+ export type TreeSelection<K extends SelectionKey = SelectionKey> =
44
+ | Readonly<{ mode: 'none' }>
45
+ | Readonly<{ mode: 'single'; key: K | null }>
46
+ | Readonly<{ mode: 'multiple'; keys: ReadonlySet<K> }>
47
+
48
+ export type TreeDensity = 'regular' | 'compact'
49
+ export type TreeActionsLayout = 'reserved' | 'overlay'
50
+ export type TreeExpandControl = 'button' | 'row'
51
+ export type TreeSelectionRail = 'hidden' | 'visible'
52
+ export type TreeRowVariant = 'default' | 'table'
53
+
54
+ export interface STreeProps<T extends object, K extends SelectionKey = SelectionKey> {
55
+ nodes: readonly T[]
56
+ model: TreeModel<T, K>
57
+ label: string
58
+ selection: TreeSelection<K>
59
+ expanded?: ReadonlySet<K>
60
+ density?: TreeDensity
61
+ actionsLayout?: TreeActionsLayout
62
+ expandControl?: TreeExpandControl
63
+ selectionRail?: TreeSelectionRail
64
+ rowVariant?: TreeRowVariant
65
+ }
66
+
67
+ export interface TreeNodeEvent<T extends object, K extends SelectionKey = SelectionKey> {
68
+ node: T
69
+ key: K
70
+ }
71
+
72
+ export type TreeActivationOrigin = 'pointer' | 'keyboard'
73
+
74
+ /**
75
+ * Активация конечного узла независимо от модели выбора. / Leaf activation independent of selection mode.
76
+ */
77
+ export interface TreeNodeActivationEvent<T extends object, K extends SelectionKey = SelectionKey>
78
+ extends TreeNodeEvent<T, K> {
79
+ origin: TreeActivationOrigin
80
+ }
81
+
82
+ export interface STreeNodeContentScope<T extends object, K extends SelectionKey = SelectionKey> {
83
+ node: T
84
+ key: K
85
+ isSelected: boolean
86
+ isPartiallySelected: boolean
87
+ isExpanded: boolean
88
+ hasChildren: boolean
89
+ toggle: () => void
90
+ select: () => void
91
+ level: number
92
+ density: TreeDensity
93
+ actionsLayout: TreeActionsLayout
94
+ expandControl: TreeExpandControl
95
+ selectionRail: TreeSelectionRail
96
+ rowVariant: TreeRowVariant
97
+ }
98
+
99
+ export interface STreeNodeActionsScope<T extends object, K extends SelectionKey = SelectionKey> {
100
+ node: T
101
+ key: K
102
+ }
@@ -0,0 +1,103 @@
1
+ @reference "../../../styles/reference.css";
2
+
3
+ .s-cloud-chrome {
4
+ --s-cloud-chrome-row-height: var(--s-density-row-default);
5
+ --s-cloud-chrome-row-edge-divider: transparent;
6
+ width: 100%;
7
+ min-width: 0;
8
+ color: var(--s-cloud-chrome-foreground);
9
+ background: var(--s-cloud-chrome-surface);
10
+ border: 1px solid var(--s-cloud-chrome-border);
11
+ box-shadow: var(--s-cloud-chrome-shadow);
12
+ -webkit-backdrop-filter: var(--s-cloud-chrome-backdrop-filter);
13
+ backdrop-filter: var(--s-cloud-chrome-backdrop-filter);
14
+ border-radius: var(--s-cloud-chrome-radius);
15
+ }
16
+
17
+ .s-cloud-chrome[data-density='compact'] {
18
+ --s-cloud-chrome-row-height: var(--s-density-row-compact);
19
+ }
20
+
21
+ .s-cloud-chrome[data-density='comfortable'] {
22
+ --s-cloud-chrome-row-height: var(--s-density-row-comfortable);
23
+ }
24
+
25
+ .s-cloud-chrome--flat,
26
+ .s-cloud-chrome--embedded {
27
+ border-color: transparent;
28
+ box-shadow: none;
29
+ background: transparent;
30
+ -webkit-backdrop-filter: none;
31
+ backdrop-filter: none;
32
+ }
33
+
34
+ .s-cloud-chrome--embedded {
35
+ --s-cloud-chrome-empty-border-radius: 0;
36
+ --s-cloud-chrome-empty-border-width: 1px 0;
37
+ --s-cloud-chrome-empty-background: transparent;
38
+ border-radius: 0;
39
+ }
40
+
41
+ .s-cloud-chrome--editing {
42
+ border-style: dashed;
43
+ }
44
+
45
+ .s-cloud-chrome--drop-active {
46
+ background: var(--s-cloud-chrome-drop-surface);
47
+ border-color: var(--s-cloud-chrome-drop-border);
48
+ }
49
+
50
+ .s-cloud-chrome--hidden-zone {
51
+ --s-cloud-chrome-surface: var(--s-cloud-chrome-hidden-surface);
52
+ --s-cloud-chrome-border: var(--s-cloud-chrome-hidden-border);
53
+ }
54
+
55
+ .s-cloud-chrome--edge-divider {
56
+ --s-cloud-chrome-row-edge-divider: var(--s-cloud-chrome-row-divider);
57
+ }
58
+
59
+ .s-cloud-chrome__header {
60
+ display: grid;
61
+ grid-template-columns: minmax(0, 1fr) auto;
62
+ min-height: var(--s-cloud-chrome-row-height);
63
+ @apply items-center gap-2 px-3 py-0;
64
+ }
65
+
66
+ .s-cloud-chrome__title {
67
+ color: var(--s-cloud-chrome-title-foreground);
68
+ @apply min-w-0 truncate text-xs font-semibold;
69
+ }
70
+
71
+ .s-cloud-chrome__description {
72
+ color: var(--s-cloud-chrome-description-foreground);
73
+ @apply min-w-0 truncate text-[11px];
74
+ }
75
+
76
+ .s-cloud-chrome__actions {
77
+ @apply flex shrink-0 items-center gap-1;
78
+ }
79
+
80
+ .s-cloud-chrome__body {
81
+ min-height: var(--s-cloud-chrome-row-height);
82
+ @apply flex min-w-0 flex-col;
83
+ }
84
+
85
+ .s-cloud-chrome__body[data-padding='default'] {
86
+ @apply p-1;
87
+ }
88
+
89
+ .s-cloud-chrome__body[data-padding='none'] {
90
+ @apply p-0;
91
+ }
92
+
93
+ .s-cloud-chrome__body[data-gap='default'] {
94
+ @apply gap-1;
95
+ }
96
+
97
+ .s-cloud-chrome__body[data-gap='none'] {
98
+ @apply gap-0;
99
+ }
100
+
101
+ .s-cloud-chrome__body--empty {
102
+ min-height: calc(var(--s-cloud-chrome-row-height) + 0.5rem);
103
+ }
@@ -0,0 +1,87 @@
1
+ <template>
2
+ <section
3
+ v-bind="ownedAttrs.bindings()"
4
+ class="s-cloud-chrome"
5
+ :data-density="density"
6
+ :class="{
7
+ 's-cloud-chrome--editing': editing,
8
+ 's-cloud-chrome--drop-active': dropActive,
9
+ 's-cloud-chrome--hidden-zone': zone === 'hidden',
10
+ 's-cloud-chrome--flat': surface === 'flat',
11
+ 's-cloud-chrome--embedded': surface === 'embedded',
12
+ 's-cloud-chrome--edge-divider': edgeDivider,
13
+ }"
14
+ >
15
+ <div v-if="title || description || $slots.actions" class="s-cloud-chrome__header">
16
+ <div class="min-w-0">
17
+ <div v-if="title" class="s-cloud-chrome__title">{{ title }}</div>
18
+ <div v-if="description" class="s-cloud-chrome__description">{{ description }}</div>
19
+ </div>
20
+ <div v-if="$slots.actions" class="s-cloud-chrome__actions">
21
+ <slot name="actions" />
22
+ </div>
23
+ </div>
24
+ <div
25
+ class="s-cloud-chrome__body"
26
+ :class="{ 's-cloud-chrome__body--empty': empty }"
27
+ :data-zone="zone"
28
+ :data-padding="resolvedBodyPadding"
29
+ :data-gap="resolvedBodyGap"
30
+ >
31
+ <slot />
32
+ <SCloudChromeEmpty v-if="empty && emptyText">{{ emptyText }}</SCloudChromeEmpty>
33
+ </div>
34
+ </section>
35
+ </template>
36
+
37
+ <script setup lang="ts">
38
+ import { computed } from 'vue'
39
+ import { useOwnedAttrs } from '../../../internal/ownedAttrs'
40
+ import SCloudChromeEmpty from './SCloudChromeEmpty.vue'
41
+
42
+ defineOptions({ inheritAttrs: false })
43
+
44
+ export type SCloudChromeBodySpacing = 'default' | 'none'
45
+ export type SCloudChromeDensity = 'compact' | 'default' | 'comfortable'
46
+
47
+ export interface Props {
48
+ title?: string
49
+ description?: string
50
+ zone?: 'top' | 'composer' | 'hidden'
51
+ editing?: boolean
52
+ dropActive?: boolean
53
+ empty?: boolean
54
+ emptyText?: string
55
+ surface?: 'cloud' | 'flat' | 'embedded'
56
+ edgeDivider?: boolean
57
+ bodyPadding?: SCloudChromeBodySpacing
58
+ bodyGap?: SCloudChromeBodySpacing
59
+ density?: SCloudChromeDensity
60
+ }
61
+
62
+ const props = withDefaults(defineProps<Props>(), {
63
+ title: undefined,
64
+ description: undefined,
65
+ zone: 'top',
66
+ editing: false,
67
+ dropActive: false,
68
+ empty: false,
69
+ emptyText: '',
70
+ surface: 'cloud',
71
+ edgeDivider: false,
72
+ bodyPadding: undefined,
73
+ bodyGap: undefined,
74
+ density: 'default',
75
+ })
76
+
77
+ const ownedAttrs = useOwnedAttrs({ component: 'SCloudChrome', owner: 'cloud chrome section' })
78
+
79
+ const resolvedBodyPadding = computed(() => props.bodyPadding ?? (
80
+ props.surface === 'embedded' ? 'none' : 'default'
81
+ ))
82
+ const resolvedBodyGap = computed(() => props.bodyGap ?? (
83
+ props.surface === 'embedded' ? 'none' : 'default'
84
+ ))
85
+ </script>
86
+
87
+ <style lang="postcss" src="./SCloudChrome.css"></style>
@@ -0,0 +1,10 @@
1
+ @reference "../../../styles/reference.css";
2
+
3
+ .s-cloud-chrome-empty {
4
+ min-height: var(--s-cloud-chrome-row-height);
5
+ @apply flex items-center border border-dashed px-3;
6
+ border-color: var(--s-cloud-chrome-empty-border);
7
+ border-radius: var(--s-cloud-chrome-empty-border-radius);
8
+ border-width: var(--s-cloud-chrome-empty-border-width);
9
+ background: var(--s-cloud-chrome-empty-background);
10
+ }
@@ -0,0 +1,18 @@
1
+ <template>
2
+ <div v-bind="ownedAttrs.bindings()" class="s-cloud-chrome-empty">
3
+ <SEmptyState presentation="inline" size="sm">
4
+ <template #title><slot /></template>
5
+ </SEmptyState>
6
+ </div>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { useOwnedAttrs } from '../../../internal/ownedAttrs'
11
+ import SEmptyState from '../data-display/SEmptyState.vue'
12
+
13
+ defineOptions({ inheritAttrs: false })
14
+
15
+ const ownedAttrs = useOwnedAttrs({ component: 'SCloudChromeEmpty', owner: 'empty-state root' })
16
+ </script>
17
+
18
+ <style lang="postcss" src="./SCloudChromeEmpty.css"></style>
@@ -0,0 +1,78 @@
1
+ @reference "../../../styles/reference.css";
2
+
3
+ .s-cloud-chrome-row {
4
+ min-height: var(--s-cloud-chrome-row-height);
5
+ height: var(--s-cloud-chrome-row-height);
6
+ min-width: 0;
7
+ background: var(--s-cloud-chrome-row-surface);
8
+ border: 1px solid var(--s-cloud-chrome-row-border);
9
+ grid-template-columns: auto minmax(0, 1fr) auto;
10
+ border-radius: var(--s-cloud-chrome-row-radius);
11
+ @apply grid items-center gap-1 px-1 text-sm;
12
+ }
13
+
14
+ .s-cloud-chrome-row--embedded {
15
+ background: transparent;
16
+ border-color: transparent;
17
+ border-radius: 0;
18
+ border-bottom-color: var(--s-cloud-chrome-row-divider);
19
+ box-shadow: none;
20
+ }
21
+
22
+ .s-cloud-chrome-row--embedded:first-child {
23
+ border-top-color: transparent;
24
+ }
25
+
26
+ .s-cloud-chrome-row--embedded:last-child {
27
+ border-bottom-color: var(--s-cloud-chrome-row-edge-divider);
28
+ }
29
+
30
+ .s-cloud-chrome-row--static {
31
+ grid-template-columns: minmax(0, 1fr) auto;
32
+ }
33
+
34
+ .s-cloud-chrome-row--hidden {
35
+ opacity: 0.82;
36
+ }
37
+
38
+ .s-cloud-chrome-row:focus-within {
39
+ box-shadow: var(--s-cloud-chrome-row-focus-shadow);
40
+ }
41
+
42
+ .s-cloud-chrome-row__drag-handle {
43
+ cursor: grab;
44
+ }
45
+
46
+ .s-cloud-chrome-row__drag-handle:active {
47
+ cursor: grabbing;
48
+ }
49
+
50
+ .s-cloud-chrome-row__content {
51
+ @apply min-w-0 overflow-hidden;
52
+ }
53
+
54
+ .s-cloud-chrome-row__actions {
55
+ @apply flex shrink-0 items-center gap-0.5;
56
+ }
57
+
58
+ .sortable-chosen.s-cloud-chrome-row {
59
+ cursor: grabbing;
60
+ }
61
+
62
+ .sortable-ghost.s-cloud-chrome-row {
63
+ opacity: 0.34;
64
+ background: var(--s-cloud-chrome-drop-surface);
65
+ border-color: var(--s-cloud-chrome-drop-border);
66
+ }
67
+
68
+ .sortable-drag.s-cloud-chrome-row,
69
+ .sortable-fallback.s-cloud-chrome-row {
70
+ pointer-events: none;
71
+ z-index: var(--s-layer-drag);
72
+ opacity: 0.96;
73
+ transform: scale(1.01);
74
+ box-shadow: var(--s-cloud-chrome-drag-shadow);
75
+ background: var(--s-cloud-chrome-row-drag-surface);
76
+ -webkit-backdrop-filter: var(--s-cloud-chrome-backdrop-filter);
77
+ backdrop-filter: var(--s-cloud-chrome-backdrop-filter);
78
+ }
@@ -0,0 +1,108 @@
1
+ <template>
2
+ <div
3
+ v-bind="ownedAttrs.bindings()"
4
+ class="s-cloud-chrome-row"
5
+ :class="{
6
+ 's-cloud-chrome-row--static': !editing || !draggable,
7
+ 's-cloud-chrome-row--hidden': hidden,
8
+ 's-cloud-chrome-row--embedded': appearance === 'embedded',
9
+ }"
10
+ :data-item-id="itemId"
11
+ >
12
+ <div v-if="editing && draggable" class="s-cloud-chrome-row__drag-handle">
13
+ <SDragHandle
14
+ :label="label"
15
+ :can-move-previous="canMoveUp"
16
+ :can-move-next="canMoveDown"
17
+ @drag-start="$emit('drag-start', $event)"
18
+ @reorder="handleReorder"
19
+ />
20
+ </div>
21
+
22
+ <div class="s-cloud-chrome-row__content">
23
+ <slot />
24
+ </div>
25
+
26
+ <div v-if="editing || $slots.actions" class="s-cloud-chrome-row__actions">
27
+ <slot name="actions" />
28
+ <SButton
29
+ v-if="editing && canHide && !hidden"
30
+ size="sm"
31
+ severity="secondary"
32
+ appearance="ghost"
33
+ icon-only
34
+ :leading-icon="HideIcon"
35
+ :title="`Скрыть: ${label}`"
36
+ :aria-label="`Скрыть: ${label}`"
37
+ @click="$emit('hide')"
38
+ />
39
+ <SButton
40
+ v-if="editing && canRestore"
41
+ size="sm"
42
+ severity="secondary"
43
+ appearance="ghost"
44
+ icon-only
45
+ :leading-icon="ResetIcon"
46
+ :title="`Вернуть: ${label}`"
47
+ :aria-label="`Вернуть: ${label}`"
48
+ @click="$emit('restore')"
49
+ />
50
+ </div>
51
+ </div>
52
+ </template>
53
+
54
+ <script setup lang="ts">
55
+ import { getSputnigUiIconComponent } from '../../icons/sputnigUiIcons'
56
+ import { useOwnedAttrs } from '../../../internal/ownedAttrs'
57
+ import SButton from '../controls/SButton.vue'
58
+ import SDragHandle from '../controls/SDragHandle.vue'
59
+
60
+ defineOptions({ inheritAttrs: false })
61
+
62
+ const HideIcon = getSputnigUiIconComponent('hide')
63
+ const ResetIcon = getSputnigUiIconComponent('reset')
64
+ const ownedAttrs = useOwnedAttrs({ component: 'SCloudChromeRow', owner: 'cloud chrome row root' })
65
+
66
+ export interface Props {
67
+ itemId?: string
68
+ label: string
69
+ editing?: boolean
70
+ hidden?: boolean
71
+ draggable?: boolean
72
+ canHide?: boolean
73
+ canRestore?: boolean
74
+ canMoveUp?: boolean
75
+ canMoveDown?: boolean
76
+ appearance?: 'raised' | 'embedded'
77
+ }
78
+
79
+ withDefaults(defineProps<Props>(), {
80
+ itemId: undefined,
81
+ editing: false,
82
+ hidden: false,
83
+ draggable: true,
84
+ canHide: false,
85
+ canRestore: false,
86
+ canMoveUp: false,
87
+ canMoveDown: false,
88
+ appearance: 'raised',
89
+ })
90
+
91
+ const emit = defineEmits<{
92
+ (event: 'drag-start', pointerEvent: PointerEvent): void
93
+ (event: 'hide'): void
94
+ (event: 'restore'): void
95
+ (event: 'move-up'): void
96
+ (event: 'move-down'): void
97
+ }>()
98
+
99
+ function handleReorder(direction: -1 | 1): void {
100
+ if (direction === -1) {
101
+ emit('move-up')
102
+ return
103
+ }
104
+ emit('move-down')
105
+ }
106
+ </script>
107
+
108
+ <style lang="postcss" src="./SCloudChromeRow.css"></style>
@@ -0,0 +1,57 @@
1
+ @reference "../../../styles/reference.css";
2
+
3
+ .s-collapsible-panel {
4
+ @apply min-h-0 min-w-0 w-full relative z-0 flex flex-col flex-none overflow-hidden rounded-lg border border-surface-200 dark:border-surface-700 bg-surface-0 dark:bg-surface-800;
5
+ }
6
+
7
+ .s-collapsible-panel[data-surface='plain'] {
8
+ @apply rounded-none border-0 bg-transparent dark:bg-transparent;
9
+ }
10
+
11
+
12
+ .s-collapsible-panel-header {
13
+ @apply flex min-w-0 shrink-0 items-center gap-1;
14
+ }
15
+
16
+ .s-collapsible-panel-trigger {
17
+ @apply min-w-0 flex-1;
18
+ }
19
+
20
+ .s-collapsible-panel-actions {
21
+ @apply flex shrink-0 items-center gap-1 pr-1;
22
+ }
23
+
24
+ .s-collapsible-panel-content {
25
+ @apply min-w-0 w-full overflow-x-hidden overflow-hidden; /* скрываем контент при анимации высоты */
26
+ background: inherit;
27
+ transition: max-height var(--s-motion-standard) ease;
28
+ will-change: max-height;
29
+ max-height: 0; /* закрыто по умолчанию */
30
+ }
31
+
32
+ .s-collapsible-panel-content.is-opened {
33
+ max-height: none; /* открыто — высота по контенту, остаётся в нормальном потоке */
34
+ transition: none;
35
+ overflow-y: visible;
36
+ }
37
+ .s-collapsible-panel-inner {
38
+ @apply p-4 text-sm text-surface-600 dark:text-surface-300;
39
+ }
40
+
41
+ /* При анимации скрываем бордеры, чтобы не мигал временный «разделитель» */
42
+ .s-collapsible-panel-content.is-animating {
43
+ border-color: transparent;
44
+ }
45
+ /* Во время анимации сохраняем нижний бордер заголовка, чтобы не было «пропадания» разделителя */
46
+ /* Density modes */
47
+ .s-collapsible-panel[data-density='compact'] .s-collapsible-panel-inner {
48
+ @apply p-3;
49
+ }
50
+
51
+ .s-collapsible-panel[data-density='dense'] .s-collapsible-panel-inner {
52
+ @apply p-2 text-xs;
53
+ }
54
+
55
+ .s-collapsible-panel[data-content-padding='none'] > .s-collapsible-panel-content > .s-collapsible-panel-inner {
56
+ padding: 0;
57
+ }