nexus-shared 2.0.0 → 3.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 (176) hide show
  1. package/CHANGELOG.md +446 -0
  2. package/LICENSE +21 -21
  3. package/README.md +1084 -903
  4. package/dist/Client.Index.d.ts +14 -0
  5. package/dist/Client.Index.js +14 -0
  6. package/dist/Components/Chats/Chat.d.ts +28 -0
  7. package/dist/Components/Chats/Chat.js +19 -0
  8. package/dist/Components/Chats/ChatButton.d.ts +26 -0
  9. package/dist/Components/Chats/ChatButton.js +41 -0
  10. package/dist/Components/Chats/ChatComposer.d.ts +41 -0
  11. package/dist/Components/Chats/ChatComposer.js +177 -0
  12. package/dist/Components/Chats/ChatConversations.d.ts +35 -0
  13. package/dist/Components/Chats/ChatConversations.js +38 -0
  14. package/dist/Components/Chats/ChatPanel.d.ts +66 -0
  15. package/dist/Components/Chats/ChatPanel.js +94 -0
  16. package/dist/Components/Chats/ChatParts.d.ts +87 -0
  17. package/dist/Components/Chats/ChatParts.js +96 -0
  18. package/dist/Components/Chats/ChatThread.d.ts +22 -0
  19. package/dist/Components/Chats/ChatThread.js +96 -0
  20. package/dist/Components/Documents/Button.d.ts +6 -1
  21. package/dist/Components/Documents/Button.js +2 -2
  22. package/dist/Components/Documents/Menu.js +44 -28
  23. package/dist/Components/Documents/SplitButton.d.ts +3 -1
  24. package/dist/Components/Documents/SplitButton.js +12 -8
  25. package/dist/Components/Documents/TabButtons.d.ts +29 -8
  26. package/dist/Components/Documents/TabButtons.js +24 -5
  27. package/dist/Components/Forms/ApiForm.d.ts +6 -4
  28. package/dist/Components/Forms/ApiForm.js +15 -14
  29. package/dist/Components/Forms/Crud.js +342 -71
  30. package/dist/Components/Forms/CrudParts.d.ts +5 -1
  31. package/dist/Components/Forms/CrudParts.js +37 -5
  32. package/dist/Components/Forms/ExcelImport.d.ts +58 -0
  33. package/dist/Components/Forms/ExcelImport.js +319 -0
  34. package/dist/Components/Forms/Form.js +9 -13
  35. package/dist/Components/Forms/SubmitForm.d.ts +11 -2
  36. package/dist/Components/Forms/SubmitForm.js +23 -12
  37. package/dist/Components/Inputs/DateTimePicker.js +2 -1
  38. package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
  39. package/dist/Components/Inputs/DropdownParts.js +4 -6
  40. package/dist/Components/Inputs/GroupForm.js +4 -2
  41. package/dist/Components/Inputs/InputRenderer.d.ts +2 -0
  42. package/dist/Components/Inputs/InputRenderer.js +1 -1
  43. package/dist/Components/Inputs/NumberBox.js +24 -2
  44. package/dist/Components/Inputs/ReadOnlyNotice.js +2 -1
  45. package/dist/Components/Inputs/RowsInput.d.ts +12 -1
  46. package/dist/Components/Inputs/RowsInput.js +55 -6
  47. package/dist/Components/Inputs/Slider.js +4 -1
  48. package/dist/Components/Inputs/TabularForm.d.ts +7 -3
  49. package/dist/Components/Inputs/TabularForm.js +117 -20
  50. package/dist/Components/Inputs/TimePanel.js +4 -3
  51. package/dist/Components/Inputs/TimePicker.js +2 -1
  52. package/dist/Components/Layouts/Popup.js +1 -4
  53. package/dist/Components/Layouts/ThemePicker.d.ts +20 -3
  54. package/dist/Components/Layouts/ThemePicker.js +77 -6
  55. package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
  56. package/dist/Components/Layouts/ThemeScript.js +4 -2
  57. package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
  58. package/dist/Components/Layouts/ThemeSwitcher.js +39 -18
  59. package/dist/Components/Viewers/Avatar.d.ts +21 -0
  60. package/dist/Components/Viewers/Avatar.js +21 -0
  61. package/dist/Components/Viewers/DataTable.js +262 -60
  62. package/dist/Components/Viewers/DataTableColumns.d.ts +32 -0
  63. package/dist/Components/Viewers/DataTableColumns.js +200 -0
  64. package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
  65. package/dist/Components/Viewers/DataTableFilters.js +68 -0
  66. package/dist/Components/Viewers/DataTableParts.d.ts +8 -4
  67. package/dist/Components/Viewers/DataTableParts.js +24 -12
  68. package/dist/Helpers/AnimationHelpers.d.ts +11 -0
  69. package/dist/Helpers/AnimationHelpers.js +20 -2
  70. package/dist/Helpers/ApiClient.d.ts +22 -0
  71. package/dist/Helpers/ApiClient.js +4 -1
  72. package/dist/Helpers/ApiFormHelpers.d.ts +27 -4
  73. package/dist/Helpers/ApiFormHelpers.js +73 -9
  74. package/dist/Helpers/ApiModules.d.ts +0 -4
  75. package/dist/Helpers/ApiModules.js +1 -0
  76. package/dist/Helpers/ApiResponses.d.ts +14 -4
  77. package/dist/Helpers/ApiResponses.js +116 -25
  78. package/dist/Helpers/ApiRoutes.d.ts +0 -10
  79. package/dist/Helpers/ApiRoutes.js +2 -10
  80. package/dist/Helpers/ChatBackend.d.ts +134 -0
  81. package/dist/Helpers/ChatBackend.js +332 -0
  82. package/dist/Helpers/ChatHelpers.d.ts +189 -0
  83. package/dist/Helpers/ChatHelpers.js +486 -0
  84. package/dist/Helpers/ChatHooks.d.ts +81 -0
  85. package/dist/Helpers/ChatHooks.js +175 -0
  86. package/dist/Helpers/ChatStore.d.ts +132 -0
  87. package/dist/Helpers/ChatStore.js +394 -0
  88. package/dist/Helpers/ChatSummaries.d.ts +39 -0
  89. package/dist/Helpers/ChatSummaries.js +118 -0
  90. package/dist/Helpers/CrudBackend.d.ts +54 -9
  91. package/dist/Helpers/CrudBackend.js +103 -6
  92. package/dist/Helpers/CrudHelpers.d.ts +39 -4
  93. package/dist/Helpers/CrudHelpers.js +76 -11
  94. package/dist/Helpers/ExcelBackend.d.ts +106 -0
  95. package/dist/Helpers/ExcelBackend.js +296 -0
  96. package/dist/Helpers/ExcelHelpers.d.ts +126 -0
  97. package/dist/Helpers/ExcelHelpers.js +344 -0
  98. package/dist/Helpers/FormStore.d.ts +11 -5
  99. package/dist/Helpers/FormStore.js +44 -6
  100. package/dist/Helpers/MessageBuilder.js +1 -2
  101. package/dist/Helpers/NumberHelpers.d.ts +7 -1
  102. package/dist/Helpers/NumberHelpers.js +41 -3
  103. package/dist/Helpers/PopoverHelpers.d.ts +46 -9
  104. package/dist/Helpers/PopoverHelpers.js +163 -24
  105. package/dist/Helpers/PopoverHooks.d.ts +24 -0
  106. package/dist/Helpers/PopoverHooks.js +62 -0
  107. package/dist/Helpers/RowsStore.d.ts +14 -3
  108. package/dist/Helpers/RowsStore.js +37 -3
  109. package/dist/Helpers/TableColumns.d.ts +7 -0
  110. package/dist/Helpers/TableColumns.js +41 -13
  111. package/dist/Helpers/TableExport.js +12 -12
  112. package/dist/Helpers/TableFilters.d.ts +25 -0
  113. package/dist/Helpers/TableFilters.js +162 -0
  114. package/dist/Helpers/TableHelpers.d.ts +15 -4
  115. package/dist/Helpers/TableHelpers.js +28 -4
  116. package/dist/Helpers/TableStore.d.ts +11 -3
  117. package/dist/Helpers/TableStore.js +16 -5
  118. package/dist/Helpers/ThemeHelpers.d.ts +21 -4
  119. package/dist/Helpers/ThemeHelpers.js +46 -9
  120. package/dist/Helpers/UserPreferences.d.ts +14 -0
  121. package/dist/Helpers/UserPreferences.js +99 -0
  122. package/dist/Interfaces/ApiInterfaces.d.ts +29 -4
  123. package/dist/Interfaces/ApiInterfaces.js +16 -10
  124. package/dist/Interfaces/ChatInterfaces.d.ts +240 -0
  125. package/dist/Interfaces/ChatInterfaces.js +1 -0
  126. package/dist/Interfaces/CrudInterfaces.d.ts +92 -12
  127. package/dist/Interfaces/ExcelInterfaces.d.ts +227 -0
  128. package/dist/Interfaces/ExcelInterfaces.js +45 -0
  129. package/dist/Interfaces/FormInterfaces.d.ts +85 -7
  130. package/dist/Interfaces/MessageInterfaces.d.ts +1 -1
  131. package/dist/Interfaces/PreferenceInterfaces.d.ts +43 -0
  132. package/dist/Interfaces/PreferenceInterfaces.js +28 -0
  133. package/dist/Interfaces/TableInterfaces.d.ts +116 -9
  134. package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
  135. package/dist/Interfaces/ThemeInterfaces.js +15 -0
  136. package/dist/Services/BrowserApi.d.ts +18 -1
  137. package/dist/Services/BrowserApi.js +18 -0
  138. package/dist/Services/ChatApi.d.ts +37 -0
  139. package/dist/Services/ChatApi.js +98 -0
  140. package/dist/Services/ExcelApi.d.ts +48 -0
  141. package/dist/Services/ExcelApi.js +196 -0
  142. package/dist/Services/ServerApi.d.ts +6 -1
  143. package/dist/Services/ServerApi.js +3 -0
  144. package/dist/Services/ThemeService.d.ts +18 -2
  145. package/dist/Services/ThemeService.js +80 -16
  146. package/dist/Shared.Index.d.ts +10 -0
  147. package/dist/Shared.Index.js +10 -0
  148. package/package.json +85 -82
  149. package/src/Styles/Nexus.Avatar.css +79 -0
  150. package/src/Styles/Nexus.Base.css +117 -70
  151. package/src/Styles/Nexus.Button.css +180 -151
  152. package/src/Styles/Nexus.Calendar.css +273 -275
  153. package/src/Styles/Nexus.Chat.css +1443 -0
  154. package/src/Styles/Nexus.Choice.css +343 -345
  155. package/src/Styles/Nexus.Crud.css +168 -84
  156. package/src/Styles/Nexus.DateTime.css +81 -81
  157. package/src/Styles/Nexus.Dropdown.css +725 -774
  158. package/src/Styles/Nexus.Editor.css +295 -297
  159. package/src/Styles/Nexus.Excel.css +389 -0
  160. package/src/Styles/Nexus.Form.css +279 -298
  161. package/src/Styles/Nexus.Index.css +37 -34
  162. package/src/Styles/Nexus.Input.css +602 -637
  163. package/src/Styles/Nexus.Markdown.css +237 -265
  164. package/src/Styles/Nexus.Menu.css +237 -249
  165. package/src/Styles/Nexus.Popup.css +724 -731
  166. package/src/Styles/Nexus.RichText.css +2 -32
  167. package/src/Styles/Nexus.Rows.css +637 -566
  168. package/src/Styles/Nexus.Slider.css +276 -278
  169. package/src/Styles/Nexus.Tab.Buttons.css +432 -364
  170. package/src/Styles/Nexus.Table.css +1386 -1014
  171. package/src/Styles/Nexus.Theme.Picker.css +286 -159
  172. package/src/Styles/Nexus.Themes.css +194 -194
  173. package/src/Styles/Nexus.Time.css +144 -147
  174. package/src/Styles/Nexus.Toast.css +263 -265
  175. package/src/Styles/Nexus.Tokens.css +89 -72
  176. package/src/Styles/Nexus.Tree.css +431 -435
@@ -1,435 +1,431 @@
1
- @layer nexus.components {
2
- /*
3
- * Tree view: a panel with a toolbar and a scrolling list of rows. Rows have a fixed height (the component places
4
- * rows by it: keep --nx-tree-row and --nx-tree-pad in step with ROW_HEIGHT and PAD in TreeView.tsx). The checkbox
5
- * is the CheckBox control itself, so checked, mixed, and read-only boxes look the same as everywhere else.
6
- */
7
- .nx-tree {
8
- --nx-tree-row: 32px;
9
- --nx-tree-pad: 4px;
10
- --nx-tree-indent: 20px;
11
- --nx-tree-font: var(--nx-text-md);
12
- --nx-tree-open: 200ms;
13
- --nx-tree-close: 160ms;
14
- /* A line under every parent's chevron, soft enough to leave the rows in front. */
15
- --nx-tree-guide: color-mix(in oklab, var(--nx-border-strong) 55%, transparent);
16
-
17
- display: flex;
18
- flex-direction: column;
19
- min-width: 0;
20
- overflow: hidden;
21
- border: 1px solid var(--nx-field-border);
22
- border-radius: var(--nx-radius);
23
- background: var(--nx-field-bg);
24
- color: var(--nx-text);
25
- font-size: var(--nx-tree-font);
26
- line-height: 1.35;
27
- transition: border-color var(--nx-duration);
28
- }
29
-
30
- .nx-tree--sm {
31
- --nx-tree-row: 28px;
32
- --nx-tree-indent: 18px;
33
- --nx-tree-font: var(--nx-text-sm);
34
- }
35
-
36
- .nx-tree--lg {
37
- --nx-tree-row: 38px;
38
- --nx-tree-indent: 22px;
39
- --nx-tree-font: var(--nx-text-lg);
40
- }
41
-
42
- .nx-tree:hover {
43
- border-color: var(--nx-field-border-hover);
44
- }
45
-
46
- .nx-tree:focus-within {
47
- border-color: var(--nx-field-accent);
48
- }
49
-
50
- .nx-field:is([data-readonly], [data-disabled]) .nx-tree {
51
- border-color: var(--nx-field-border);
52
- }
53
-
54
- /* Toolbar: select all and counts at the start, tools at the end, a line under it. */
55
- .nx-tree__toolbar {
56
- display: flex;
57
- flex-wrap: wrap;
58
- align-items: center;
59
- gap: var(--nx-space-1) var(--nx-space-3);
60
- min-height: calc(var(--nx-control-sm) + 12px);
61
- padding: 6px 6px 6px var(--nx-space-3);
62
- border-bottom: 1px solid var(--nx-border);
63
- font-size: var(--nx-text-sm);
64
- }
65
-
66
- .nx-tree__all {
67
- flex: none;
68
- }
69
-
70
- .nx-tree__all .nx-choice__label {
71
- font-weight: 500;
72
- }
73
-
74
- /* A read-only tree has one lock, after its label; select all still shows the note when clicked. */
75
- .nx-tree__all .nx-field__lock {
76
- display: none;
77
- }
78
-
79
- .nx-tree__summary {
80
- display: inline-flex;
81
- align-items: center;
82
- gap: 6px;
83
- min-width: 0;
84
- margin-right: auto;
85
- color: var(--nx-text-muted);
86
- font-variant-numeric: tabular-nums;
87
- white-space: nowrap;
88
- }
89
-
90
- .nx-tree__summary .nx-icon {
91
- width: 14px;
92
- height: 14px;
93
- vertical-align: 0;
94
- }
95
-
96
- .nx-tree__tools {
97
- display: inline-flex;
98
- align-items: center;
99
- gap: 2px;
100
- }
101
-
102
- .nx-tree__tools .nx-btn--secondary {
103
- margin-left: var(--nx-space-1);
104
- }
105
-
106
- /* Rows */
107
- .nx-tree__viewport {
108
- position: relative;
109
- overflow: auto;
110
- overscroll-behavior: contain;
111
- outline: none;
112
- scrollbar-width: thin;
113
- scrollbar-color: var(--nx-field-scrollbar) transparent;
114
- }
115
-
116
- .nx-tree__viewport:focus-visible {
117
- box-shadow: inset 0 0 0 2px var(--nx-primary);
118
- }
119
-
120
- .nx-tree__list {
121
- min-width: 0;
122
- padding-inline: var(--nx-tree-pad);
123
- }
124
-
125
- .nx-tree__row {
126
- --nx-tree-depth: 0;
127
- /* Muted texts of a row. On a hovered or focused row they move toward the text color, so they keep 4.5:1 on the
128
- hover tint in every theme. */
129
- --nx-tree-muted: var(--nx-text-muted);
130
- --nx-tree-count: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 25%);
131
-
132
- display: flex;
133
- align-items: center;
134
- gap: 6px;
135
- height: var(--nx-tree-row);
136
- padding: 0 4px 0 calc(var(--nx-tree-depth) * var(--nx-tree-indent));
137
- border-radius: var(--nx-radius);
138
- /* Guides: one line per level, centered under the chevron of the parent at that level. */
139
- background-image: repeating-linear-gradient(
140
- to right,
141
- transparent 0 calc(var(--nx-tree-indent) / 2 - 0.5px),
142
- var(--nx-tree-guide) calc(var(--nx-tree-indent) / 2 - 0.5px) calc(var(--nx-tree-indent) / 2 + 0.5px),
143
- transparent calc(var(--nx-tree-indent) / 2 + 0.5px) var(--nx-tree-indent)
144
- );
145
- background-repeat: no-repeat;
146
- background-size: calc(var(--nx-tree-depth) * var(--nx-tree-indent)) 100%;
147
- white-space: nowrap;
148
- cursor: pointer;
149
- user-select: none;
150
- outline: none;
151
- -webkit-tap-highlight-color: transparent;
152
- }
153
-
154
- .nx-tree__row[role="treeitem"]:hover {
155
- background-color: var(--nx-surface-hover);
156
- }
157
-
158
- .nx-tree__row:focus-visible {
159
- background-color: var(--nx-surface-hover);
160
- box-shadow: inset 0 0 0 2px var(--nx-primary);
161
- }
162
-
163
- .nx-tree__row[role="treeitem"]:is(:hover, :focus-visible) {
164
- --nx-tree-muted: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 35%);
165
- --nx-tree-count: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 50%);
166
- }
167
-
168
- .nx-tree__toggle {
169
- display: grid;
170
- flex: none;
171
- place-items: center;
172
- width: var(--nx-tree-indent);
173
- height: var(--nx-tree-indent);
174
- margin-right: -2px;
175
- border-radius: var(--nx-radius-sm);
176
- color: var(--nx-tree-muted);
177
- }
178
-
179
- .nx-tree__toggle .nx-icon {
180
- width: 14px;
181
- height: 14px;
182
- vertical-align: 0;
183
- transition: transform var(--nx-tree-open) cubic-bezier(0.2, 0, 0, 1);
184
- }
185
-
186
- .nx-tree__row[aria-expanded="true"] > .nx-tree__toggle .nx-icon {
187
- transform: rotate(90deg);
188
- }
189
-
190
- .nx-tree__toggle:has(.nx-icon):hover {
191
- background: color-mix(in oklab, var(--nx-text) 10%, transparent);
192
- color: var(--nx-text);
193
- }
194
-
195
- /* The CheckBox control, without its label's line-height offset; the row takes the clicks. */
196
- .nx-tree__check {
197
- flex: none;
198
- align-items: center;
199
- gap: 0;
200
- }
201
-
202
- .nx-tree__check .nx-choice__control {
203
- margin: 0;
204
- pointer-events: none;
205
- }
206
-
207
- .nx-tree__row:hover .nx-choice__control:not(:checked, :indeterminate, :disabled) {
208
- border-color: var(--nx-choice-border-hover);
209
- }
210
-
211
- .nx-tree__icon {
212
- display: grid;
213
- flex: none;
214
- place-items: center;
215
- color: var(--nx-tree-muted);
216
- }
217
-
218
- .nx-tree__icon .nx-icon {
219
- width: 1.15em;
220
- height: 1.15em;
221
- vertical-align: 0;
222
- }
223
-
224
- .nx-tree__text {
225
- display: flex;
226
- flex: 1 1 auto;
227
- align-items: baseline;
228
- gap: var(--nx-space-2);
229
- min-width: 0;
230
- overflow: hidden;
231
- }
232
-
233
- .nx-tree__label {
234
- flex: 0 1 auto;
235
- min-width: 2em;
236
- overflow: hidden;
237
- text-overflow: ellipsis;
238
- }
239
-
240
- .nx-tree__description {
241
- flex: 0 100 auto;
242
- min-width: 0;
243
- overflow: hidden;
244
- color: var(--nx-tree-muted);
245
- font-size: calc(var(--nx-tree-font) - 1px);
246
- text-overflow: ellipsis;
247
- }
248
-
249
- .nx-tree__count {
250
- flex: none;
251
- padding: 0 6px;
252
- border-radius: var(--nx-radius-full);
253
- background: color-mix(in oklab, var(--nx-text) 7%, transparent);
254
- color: var(--nx-tree-count);
255
- font-size: var(--nx-text-xs);
256
- font-variant-numeric: tabular-nums;
257
- line-height: 18px;
258
- }
259
-
260
- .nx-tree__lock,
261
- .nx-tree__busy {
262
- display: grid;
263
- flex: none;
264
- place-items: center;
265
- color: var(--nx-tree-muted);
266
- }
267
-
268
- .nx-tree__lock .nx-icon,
269
- .nx-tree__busy {
270
- width: 14px;
271
- height: 14px;
272
- vertical-align: 0;
273
- }
274
-
275
- /* A locked item: the read-only box (data-readonly), a muted label, and a lock. */
276
- .nx-tree__row--locked {
277
- cursor: default;
278
- }
279
-
280
- .nx-tree__row--locked .nx-tree__label {
281
- color: var(--nx-tree-muted);
282
- }
283
-
284
- /* Actions show on the row under the pointer or with focus; on touch screens, always. They keep their space, so
285
- labels do not jump when they appear. */
286
- .nx-tree__actions {
287
- display: flex;
288
- flex: none;
289
- gap: 1px;
290
- margin-left: auto;
291
- visibility: hidden;
292
- }
293
-
294
- .nx-tree__row:is(:hover, :focus-visible, :focus-within) > .nx-tree__actions {
295
- visibility: visible;
296
- }
297
-
298
- @media (hover: none) {
299
- .nx-tree__actions {
300
- visibility: visible;
301
- }
302
- }
303
-
304
- .nx-btn.nx-tree__action {
305
- --nx-btn-height: calc(var(--nx-tree-row) - 6px);
306
- }
307
-
308
- .nx-tree__action .nx-icon {
309
- width: 15px;
310
- height: 15px;
311
- }
312
-
313
- /* The name box of a row being added or renamed. */
314
- .nx-tree__edit {
315
- display: flex;
316
- flex: 1 1 auto;
317
- align-items: center;
318
- gap: 1px;
319
- min-width: 0;
320
- }
321
-
322
- .nx-tree__input {
323
- flex: 1 1 auto;
324
- width: 0;
325
- min-width: 6em;
326
- height: calc(var(--nx-tree-row) - 6px);
327
- margin: 0 2px 0 0;
328
- padding: 0 6px;
329
- border: 1px solid var(--nx-field-accent);
330
- border-radius: var(--nx-radius-sm);
331
- background: var(--nx-surface);
332
- box-shadow: var(--nx-field-ring);
333
- color: var(--nx-text);
334
- font: inherit;
335
- outline: none;
336
- }
337
-
338
- .nx-tree__input[aria-invalid="true"] {
339
- border-color: var(--nx-danger);
340
- box-shadow: 0 0 0 3px color-mix(in oklab, var(--nx-danger) 30%, transparent);
341
- }
342
-
343
- .nx-tree__input:read-only {
344
- color: var(--nx-text-muted);
345
- }
346
-
347
- /*
348
- * Expand and collapse: the rows that come or go sit in a group whose height opens from 0, or closes to 0. Only the
349
- * rows in view are in the group, so opening 10,000 children animates about 30 rows.
350
- */
351
- .nx-tree__motion {
352
- height: var(--nx-tree-motion-height);
353
- overflow: hidden;
354
- }
355
-
356
- .nx-tree__motion--open {
357
- animation: nx-tree-open var(--nx-tree-open) cubic-bezier(0.2, 0, 0, 1);
358
- }
359
-
360
- .nx-tree__motion--close {
361
- height: 0;
362
- pointer-events: none;
363
- animation: nx-tree-close var(--nx-tree-close) cubic-bezier(0.3, 0, 0.8, 0.15);
364
- }
365
-
366
- @keyframes nx-tree-open {
367
- from {
368
- height: 0;
369
- opacity: 0.35;
370
- }
371
- }
372
-
373
- @keyframes nx-tree-close {
374
- from {
375
- height: var(--nx-tree-motion-height);
376
- opacity: 1;
377
- }
378
- to {
379
- height: 0;
380
- opacity: 0;
381
- }
382
- }
383
-
384
- /* Loading and empty */
385
- .nx-tree__row--skeleton {
386
- cursor: default;
387
- }
388
-
389
- .nx-tree__skeleton {
390
- display: inline-block;
391
- height: 0.7em;
392
- border-radius: var(--nx-radius-full);
393
- background: color-mix(in oklab, var(--nx-text) 11%, transparent);
394
- animation: nx-tree-pulse 1.2s ease-in-out infinite;
395
- }
396
-
397
- @keyframes nx-tree-pulse {
398
- 50% {
399
- opacity: 0.45;
400
- }
401
- }
402
-
403
- .nx-tree__empty {
404
- margin: 0;
405
- padding: var(--nx-space-6) var(--nx-space-4);
406
- color: var(--nx-text-muted);
407
- font-size: var(--nx-text-sm);
408
- text-align: center;
409
- }
410
-
411
- /* States of the whole tree */
412
- .nx-field[data-disabled] .nx-tree__row {
413
- cursor: not-allowed;
414
- }
415
-
416
- .nx-field[data-disabled] .nx-tree__row:hover {
417
- background-color: transparent;
418
- }
419
-
420
- .nx-field[data-readonly] .nx-tree__row {
421
- cursor: default;
422
- }
423
-
424
- @media (prefers-reduced-motion: reduce) {
425
- .nx-tree__motion,
426
- .nx-tree__skeleton {
427
- animation: none;
428
- }
429
-
430
- .nx-tree,
431
- .nx-tree__toggle .nx-icon {
432
- transition: none;
433
- }
434
- }
435
- }
1
+ @layer nexus.components {
2
+ /*
3
+ * Tree view: a panel with a toolbar and a scrolling list of rows. Rows have a fixed height (the component places
4
+ * rows by it: keep --nx-tree-row and --nx-tree-pad in step with ROW_HEIGHT and PAD in TreeView.tsx). The checkbox
5
+ * is the CheckBox control itself, so checked, mixed, and read-only boxes look the same as everywhere else.
6
+ */
7
+ .nx-tree {
8
+ --nx-tree-row: 32px;
9
+ --nx-tree-pad: 4px;
10
+ --nx-tree-indent: 20px;
11
+ --nx-tree-font: var(--nx-text-md);
12
+ --nx-tree-open: 200ms;
13
+ --nx-tree-close: 160ms;
14
+ /* A line under every parent's chevron, soft enough to leave the rows in front. */
15
+ --nx-tree-guide: color-mix(in oklab, var(--nx-border-strong) 55%, transparent);
16
+
17
+ display: flex;
18
+ flex-direction: column;
19
+ min-width: 0;
20
+ overflow: hidden;
21
+ border: 1px solid var(--nx-field-border);
22
+ border-radius: var(--nx-radius);
23
+ background: var(--nx-field-bg);
24
+ color: var(--nx-text);
25
+ font-size: var(--nx-tree-font);
26
+ line-height: 1.35;
27
+ transition: border-color var(--nx-duration);
28
+ }
29
+
30
+ .nx-tree--sm {
31
+ --nx-tree-row: 28px;
32
+ --nx-tree-indent: 18px;
33
+ --nx-tree-font: var(--nx-text-sm);
34
+ }
35
+
36
+ .nx-tree--lg {
37
+ --nx-tree-row: 38px;
38
+ --nx-tree-indent: 22px;
39
+ --nx-tree-font: var(--nx-text-lg);
40
+ }
41
+
42
+ .nx-tree:hover {
43
+ border-color: var(--nx-field-border-hover);
44
+ }
45
+
46
+ .nx-tree:focus-within {
47
+ border-color: var(--nx-field-accent);
48
+ }
49
+
50
+ .nx-field:is([data-readonly], [data-disabled]) .nx-tree {
51
+ border-color: var(--nx-field-border);
52
+ }
53
+
54
+ /* Toolbar: select all and counts at the start, tools at the end, a line under it. */
55
+ .nx-tree__toolbar {
56
+ display: flex;
57
+ flex-wrap: wrap;
58
+ align-items: center;
59
+ gap: var(--nx-space-1) var(--nx-space-3);
60
+ min-height: calc(var(--nx-control-sm) + 12px);
61
+ padding: 6px 6px 6px var(--nx-space-3);
62
+ border-bottom: 1px solid var(--nx-border);
63
+ font-size: var(--nx-text-sm);
64
+ }
65
+
66
+ .nx-tree__all {
67
+ flex: none;
68
+ }
69
+
70
+ .nx-tree__all .nx-choice__label {
71
+ font-weight: 500;
72
+ }
73
+
74
+ /* A read-only tree has one lock, after its label; select all still shows the note when clicked. */
75
+ .nx-tree__all .nx-field__lock {
76
+ display: none;
77
+ }
78
+
79
+ .nx-tree__summary {
80
+ display: inline-flex;
81
+ align-items: center;
82
+ gap: 6px;
83
+ min-width: 0;
84
+ margin-right: auto;
85
+ color: var(--nx-text-muted);
86
+ font-variant-numeric: tabular-nums;
87
+ white-space: nowrap;
88
+ }
89
+
90
+ .nx-tree__summary .nx-icon {
91
+ width: 14px;
92
+ height: 14px;
93
+ vertical-align: 0;
94
+ }
95
+
96
+ .nx-tree__tools {
97
+ display: inline-flex;
98
+ align-items: center;
99
+ gap: 2px;
100
+ }
101
+
102
+ .nx-tree__tools .nx-btn--secondary {
103
+ margin-left: var(--nx-space-1);
104
+ }
105
+
106
+ /* Rows */
107
+ .nx-tree__viewport {
108
+ position: relative;
109
+ overflow: auto;
110
+ overscroll-behavior: contain;
111
+ outline: none;
112
+ }
113
+
114
+ .nx-tree__viewport:focus-visible {
115
+ box-shadow: inset 0 0 0 2px var(--nx-primary);
116
+ }
117
+
118
+ .nx-tree__list {
119
+ min-width: 0;
120
+ padding-inline: var(--nx-tree-pad);
121
+ }
122
+
123
+ .nx-tree__row {
124
+ --nx-tree-depth: 0;
125
+ /* Muted texts of a row. On a hovered or focused row they move toward the text color, so they keep 4.5:1 on the
126
+ hover tint in every theme. */
127
+ --nx-tree-muted: var(--nx-text-muted);
128
+ --nx-tree-count: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 25%);
129
+
130
+ display: flex;
131
+ align-items: center;
132
+ gap: 6px;
133
+ height: var(--nx-tree-row);
134
+ padding: 0 4px 0 calc(var(--nx-tree-depth) * var(--nx-tree-indent));
135
+ border-radius: var(--nx-radius);
136
+ /* Guides: one line per level, centered under the chevron of the parent at that level. */
137
+ background-image: repeating-linear-gradient(
138
+ to right,
139
+ transparent 0 calc(var(--nx-tree-indent) / 2 - 0.5px),
140
+ var(--nx-tree-guide) calc(var(--nx-tree-indent) / 2 - 0.5px) calc(var(--nx-tree-indent) / 2 + 0.5px),
141
+ transparent calc(var(--nx-tree-indent) / 2 + 0.5px) var(--nx-tree-indent)
142
+ );
143
+ background-repeat: no-repeat;
144
+ background-size: calc(var(--nx-tree-depth) * var(--nx-tree-indent)) 100%;
145
+ white-space: nowrap;
146
+ cursor: pointer;
147
+ user-select: none;
148
+ outline: none;
149
+ -webkit-tap-highlight-color: transparent;
150
+ }
151
+
152
+ .nx-tree__row[role="treeitem"]:hover {
153
+ background-color: var(--nx-surface-hover);
154
+ }
155
+
156
+ .nx-tree__row:focus-visible {
157
+ background-color: var(--nx-surface-hover);
158
+ box-shadow: inset 0 0 0 2px var(--nx-primary);
159
+ }
160
+
161
+ .nx-tree__row[role="treeitem"]:is(:hover, :focus-visible) {
162
+ --nx-tree-muted: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 35%);
163
+ --nx-tree-count: color-mix(in oklab, var(--nx-text-muted), var(--nx-text) 50%);
164
+ }
165
+
166
+ .nx-tree__toggle {
167
+ display: grid;
168
+ flex: none;
169
+ place-items: center;
170
+ width: var(--nx-tree-indent);
171
+ height: var(--nx-tree-indent);
172
+ margin-right: -2px;
173
+ border-radius: var(--nx-radius-sm);
174
+ color: var(--nx-tree-muted);
175
+ }
176
+
177
+ .nx-tree__toggle .nx-icon {
178
+ width: 14px;
179
+ height: 14px;
180
+ vertical-align: 0;
181
+ transition: transform var(--nx-tree-open) cubic-bezier(0.2, 0, 0, 1);
182
+ }
183
+
184
+ .nx-tree__row[aria-expanded="true"] > .nx-tree__toggle .nx-icon {
185
+ transform: rotate(90deg);
186
+ }
187
+
188
+ .nx-tree__toggle:has(.nx-icon):hover {
189
+ background: color-mix(in oklab, var(--nx-text) 10%, transparent);
190
+ color: var(--nx-text);
191
+ }
192
+
193
+ /* The CheckBox control, without its label's line-height offset; the row takes the clicks. */
194
+ .nx-tree__check {
195
+ flex: none;
196
+ align-items: center;
197
+ gap: 0;
198
+ }
199
+
200
+ .nx-tree__check .nx-choice__control {
201
+ margin: 0;
202
+ pointer-events: none;
203
+ }
204
+
205
+ .nx-tree__row:hover .nx-choice__control:not(:checked, :indeterminate, :disabled) {
206
+ border-color: var(--nx-choice-border-hover);
207
+ }
208
+
209
+ .nx-tree__icon {
210
+ display: grid;
211
+ flex: none;
212
+ place-items: center;
213
+ color: var(--nx-tree-muted);
214
+ }
215
+
216
+ .nx-tree__icon .nx-icon {
217
+ width: 1.15em;
218
+ height: 1.15em;
219
+ vertical-align: 0;
220
+ }
221
+
222
+ .nx-tree__text {
223
+ display: flex;
224
+ flex: 1 1 auto;
225
+ align-items: baseline;
226
+ gap: var(--nx-space-2);
227
+ min-width: 0;
228
+ overflow: hidden;
229
+ }
230
+
231
+ .nx-tree__label {
232
+ flex: 0 1 auto;
233
+ min-width: 2em;
234
+ overflow: hidden;
235
+ text-overflow: ellipsis;
236
+ }
237
+
238
+ .nx-tree__description {
239
+ flex: 0 100 auto;
240
+ min-width: 0;
241
+ overflow: hidden;
242
+ color: var(--nx-tree-muted);
243
+ font-size: calc(var(--nx-tree-font) - 1px);
244
+ text-overflow: ellipsis;
245
+ }
246
+
247
+ .nx-tree__count {
248
+ flex: none;
249
+ padding: 0 6px;
250
+ border-radius: var(--nx-radius-full);
251
+ background: color-mix(in oklab, var(--nx-text) 7%, transparent);
252
+ color: var(--nx-tree-count);
253
+ font-size: var(--nx-text-xs);
254
+ font-variant-numeric: tabular-nums;
255
+ line-height: 18px;
256
+ }
257
+
258
+ .nx-tree__lock,
259
+ .nx-tree__busy {
260
+ display: grid;
261
+ flex: none;
262
+ place-items: center;
263
+ color: var(--nx-tree-muted);
264
+ }
265
+
266
+ .nx-tree__lock .nx-icon,
267
+ .nx-tree__busy {
268
+ width: 14px;
269
+ height: 14px;
270
+ vertical-align: 0;
271
+ }
272
+
273
+ /* A locked item: the read-only box (data-readonly), a muted label, and a lock. */
274
+ .nx-tree__row--locked {
275
+ cursor: default;
276
+ }
277
+
278
+ .nx-tree__row--locked .nx-tree__label {
279
+ color: var(--nx-tree-muted);
280
+ }
281
+
282
+ /* Actions show on the row under the pointer or with focus; on touch screens, always. They keep their space, so
283
+ labels do not jump when they appear. */
284
+ .nx-tree__actions {
285
+ display: flex;
286
+ flex: none;
287
+ gap: 1px;
288
+ margin-left: auto;
289
+ visibility: hidden;
290
+ }
291
+
292
+ .nx-tree__row:is(:hover, :focus-visible, :focus-within) > .nx-tree__actions {
293
+ visibility: visible;
294
+ }
295
+
296
+ @media (hover: none) {
297
+ .nx-tree__actions {
298
+ visibility: visible;
299
+ }
300
+ }
301
+
302
+ .nx-btn.nx-tree__action {
303
+ --nx-btn-height: calc(var(--nx-tree-row) - 6px);
304
+ }
305
+
306
+ .nx-tree__action .nx-icon {
307
+ width: 15px;
308
+ height: 15px;
309
+ }
310
+
311
+ /* The name box of a row being added or renamed. */
312
+ .nx-tree__edit {
313
+ display: flex;
314
+ flex: 1 1 auto;
315
+ align-items: center;
316
+ gap: 1px;
317
+ min-width: 0;
318
+ }
319
+
320
+ .nx-tree__input {
321
+ flex: 1 1 auto;
322
+ width: 0;
323
+ min-width: 6em;
324
+ height: calc(var(--nx-tree-row) - 6px);
325
+ margin: 0 2px 0 0;
326
+ padding: 0 6px;
327
+ border: 1px solid var(--nx-field-accent);
328
+ border-radius: var(--nx-radius-sm);
329
+ background: var(--nx-surface);
330
+ box-shadow: var(--nx-field-ring);
331
+ color: var(--nx-text);
332
+ font: inherit;
333
+ outline: none;
334
+ }
335
+
336
+ .nx-tree__input[aria-invalid="true"] {
337
+ border-color: var(--nx-danger);
338
+ box-shadow: 0 0 0 3px color-mix(in oklab, var(--nx-danger) 30%, transparent);
339
+ }
340
+
341
+ .nx-tree__input:read-only {
342
+ color: var(--nx-text-muted);
343
+ }
344
+
345
+ /*
346
+ * Expand and collapse: the rows that come or go sit in a group whose height opens from 0, or closes to 0. Only the
347
+ * rows in view are in the group, so opening 10,000 children animates about 30 rows.
348
+ */
349
+ .nx-tree__motion {
350
+ height: var(--nx-tree-motion-height);
351
+ overflow: hidden;
352
+ }
353
+
354
+ .nx-tree__motion--open {
355
+ animation: nx-tree-open var(--nx-tree-open) cubic-bezier(0.2, 0, 0, 1);
356
+ }
357
+
358
+ .nx-tree__motion--close {
359
+ height: 0;
360
+ pointer-events: none;
361
+ animation: nx-tree-close var(--nx-tree-close) cubic-bezier(0.3, 0, 0.8, 0.15);
362
+ }
363
+
364
+ @keyframes nx-tree-open {
365
+ from {
366
+ height: 0;
367
+ opacity: 0.35;
368
+ }
369
+ }
370
+
371
+ @keyframes nx-tree-close {
372
+ from {
373
+ height: var(--nx-tree-motion-height);
374
+ opacity: 1;
375
+ }
376
+ to {
377
+ height: 0;
378
+ opacity: 0;
379
+ }
380
+ }
381
+
382
+ /* Loading and empty */
383
+ .nx-tree__row--skeleton {
384
+ cursor: default;
385
+ }
386
+
387
+ .nx-tree__skeleton {
388
+ display: inline-block;
389
+ height: 0.7em;
390
+ border-radius: var(--nx-radius-full);
391
+ background: color-mix(in oklab, var(--nx-text) 11%, transparent);
392
+ animation: nx-tree-pulse 1.2s ease-in-out infinite;
393
+ }
394
+
395
+ @keyframes nx-tree-pulse {
396
+ 50% {
397
+ opacity: 0.45;
398
+ }
399
+ }
400
+
401
+ .nx-tree__empty {
402
+ margin: 0;
403
+ padding: var(--nx-space-6) var(--nx-space-4);
404
+ color: var(--nx-text-muted);
405
+ font-size: var(--nx-text-sm);
406
+ text-align: center;
407
+ }
408
+
409
+ /* States of the whole tree */
410
+ .nx-field[data-disabled] .nx-tree__row {
411
+ cursor: not-allowed;
412
+ }
413
+
414
+ .nx-field[data-disabled] .nx-tree__row:hover {
415
+ background-color: transparent;
416
+ }
417
+
418
+ .nx-field[data-readonly] .nx-tree__row {
419
+ cursor: default;
420
+ }
421
+
422
+ [data-nx-motion="reduce"] .nx-tree__motion,
423
+ [data-nx-motion="reduce"] .nx-tree__skeleton {
424
+ animation: none;
425
+ }
426
+
427
+ [data-nx-motion="reduce"] .nx-tree,
428
+ [data-nx-motion="reduce"] .nx-tree__toggle .nx-icon {
429
+ transition: none;
430
+ }
431
+ }