nexus-shared 3.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 (121) hide show
  1. package/CHANGELOG.md +446 -262
  2. package/LICENSE +21 -21
  3. package/README.md +1084 -1000
  4. package/dist/Client.Index.d.ts +3 -0
  5. package/dist/Client.Index.js +3 -0
  6. package/dist/Components/Chats/ChatParts.d.ts +2 -2
  7. package/dist/Components/Chats/ChatParts.js +3 -7
  8. package/dist/Components/Chats/ChatThread.js +3 -3
  9. package/dist/Components/Documents/Button.d.ts +6 -1
  10. package/dist/Components/Documents/Button.js +2 -2
  11. package/dist/Components/Documents/Menu.js +21 -9
  12. package/dist/Components/Documents/SplitButton.d.ts +3 -1
  13. package/dist/Components/Documents/SplitButton.js +7 -5
  14. package/dist/Components/Documents/TabButtons.d.ts +5 -2
  15. package/dist/Components/Documents/TabButtons.js +2 -2
  16. package/dist/Components/Forms/ApiForm.d.ts +1 -1
  17. package/dist/Components/Forms/ApiForm.js +1 -1
  18. package/dist/Components/Forms/Crud.js +177 -58
  19. package/dist/Components/Forms/CrudParts.d.ts +5 -1
  20. package/dist/Components/Forms/CrudParts.js +37 -5
  21. package/dist/Components/Forms/ExcelImport.d.ts +23 -7
  22. package/dist/Components/Forms/ExcelImport.js +189 -60
  23. package/dist/Components/Forms/Form.js +5 -13
  24. package/dist/Components/Forms/SubmitForm.d.ts +11 -2
  25. package/dist/Components/Forms/SubmitForm.js +23 -12
  26. package/dist/Components/Inputs/DropdownParts.d.ts +1 -1
  27. package/dist/Components/Inputs/DropdownParts.js +4 -6
  28. package/dist/Components/Inputs/NumberBox.js +24 -2
  29. package/dist/Components/Inputs/RowsInput.js +2 -2
  30. package/dist/Components/Inputs/Slider.js +4 -1
  31. package/dist/Components/Inputs/TabularForm.js +42 -10
  32. package/dist/Components/Inputs/TimePanel.js +4 -3
  33. package/dist/Components/Layouts/Popup.js +1 -4
  34. package/dist/Components/Layouts/ThemePicker.d.ts +20 -3
  35. package/dist/Components/Layouts/ThemePicker.js +77 -6
  36. package/dist/Components/Layouts/ThemeScript.d.ts +4 -2
  37. package/dist/Components/Layouts/ThemeScript.js +4 -2
  38. package/dist/Components/Layouts/ThemeSwitcher.d.ts +6 -3
  39. package/dist/Components/Layouts/ThemeSwitcher.js +9 -8
  40. package/dist/Components/Viewers/Avatar.d.ts +21 -0
  41. package/dist/Components/Viewers/Avatar.js +21 -0
  42. package/dist/Components/Viewers/DataTable.js +192 -44
  43. package/dist/Components/Viewers/DataTableColumns.d.ts +7 -3
  44. package/dist/Components/Viewers/DataTableColumns.js +25 -68
  45. package/dist/Components/Viewers/DataTableFilters.d.ts +21 -0
  46. package/dist/Components/Viewers/DataTableFilters.js +68 -0
  47. package/dist/Components/Viewers/DataTableParts.d.ts +2 -2
  48. package/dist/Components/Viewers/DataTableParts.js +3 -3
  49. package/dist/Helpers/AnimationHelpers.d.ts +11 -0
  50. package/dist/Helpers/AnimationHelpers.js +20 -2
  51. package/dist/Helpers/CrudBackend.d.ts +7 -4
  52. package/dist/Helpers/CrudBackend.js +4 -2
  53. package/dist/Helpers/ExcelBackend.d.ts +3 -3
  54. package/dist/Helpers/ExcelBackend.js +8 -2
  55. package/dist/Helpers/ExcelHelpers.d.ts +36 -8
  56. package/dist/Helpers/ExcelHelpers.js +55 -13
  57. package/dist/Helpers/FormStore.d.ts +9 -5
  58. package/dist/Helpers/FormStore.js +25 -5
  59. package/dist/Helpers/MessageBuilder.js +1 -0
  60. package/dist/Helpers/NumberHelpers.d.ts +7 -1
  61. package/dist/Helpers/NumberHelpers.js +41 -3
  62. package/dist/Helpers/PopoverHelpers.d.ts +17 -5
  63. package/dist/Helpers/PopoverHelpers.js +52 -17
  64. package/dist/Helpers/PopoverHooks.d.ts +24 -0
  65. package/dist/Helpers/PopoverHooks.js +62 -0
  66. package/dist/Helpers/RowsStore.d.ts +7 -2
  67. package/dist/Helpers/RowsStore.js +15 -3
  68. package/dist/Helpers/TableExport.js +12 -12
  69. package/dist/Helpers/TableFilters.d.ts +25 -0
  70. package/dist/Helpers/TableFilters.js +162 -0
  71. package/dist/Helpers/TableHelpers.d.ts +6 -3
  72. package/dist/Helpers/TableHelpers.js +8 -4
  73. package/dist/Helpers/TableStore.d.ts +11 -3
  74. package/dist/Helpers/TableStore.js +16 -5
  75. package/dist/Helpers/ThemeHelpers.d.ts +21 -4
  76. package/dist/Helpers/ThemeHelpers.js +46 -9
  77. package/dist/Helpers/UserPreferences.d.ts +14 -0
  78. package/dist/Helpers/UserPreferences.js +99 -0
  79. package/dist/Interfaces/CrudInterfaces.d.ts +20 -1
  80. package/dist/Interfaces/ExcelInterfaces.d.ts +12 -0
  81. package/dist/Interfaces/FormInterfaces.d.ts +33 -5
  82. package/dist/Interfaces/PreferenceInterfaces.d.ts +43 -0
  83. package/dist/Interfaces/PreferenceInterfaces.js +28 -0
  84. package/dist/Interfaces/TableInterfaces.d.ts +59 -12
  85. package/dist/Interfaces/ThemeInterfaces.d.ts +25 -0
  86. package/dist/Interfaces/ThemeInterfaces.js +15 -0
  87. package/dist/Services/ExcelApi.d.ts +3 -1
  88. package/dist/Services/ExcelApi.js +1 -1
  89. package/dist/Services/ThemeService.d.ts +18 -2
  90. package/dist/Services/ThemeService.js +80 -16
  91. package/dist/Shared.Index.d.ts +2 -0
  92. package/dist/Shared.Index.js +2 -0
  93. package/package.json +85 -85
  94. package/src/Styles/Nexus.Avatar.css +79 -0
  95. package/src/Styles/Nexus.Base.css +117 -70
  96. package/src/Styles/Nexus.Button.css +180 -153
  97. package/src/Styles/Nexus.Calendar.css +273 -275
  98. package/src/Styles/Nexus.Chat.css +1443 -1489
  99. package/src/Styles/Nexus.Choice.css +343 -345
  100. package/src/Styles/Nexus.Crud.css +168 -161
  101. package/src/Styles/Nexus.DateTime.css +81 -81
  102. package/src/Styles/Nexus.Dropdown.css +725 -774
  103. package/src/Styles/Nexus.Editor.css +295 -297
  104. package/src/Styles/Nexus.Excel.css +389 -370
  105. package/src/Styles/Nexus.Form.css +279 -321
  106. package/src/Styles/Nexus.Index.css +37 -36
  107. package/src/Styles/Nexus.Input.css +602 -637
  108. package/src/Styles/Nexus.Markdown.css +237 -265
  109. package/src/Styles/Nexus.Menu.css +237 -259
  110. package/src/Styles/Nexus.Popup.css +724 -731
  111. package/src/Styles/Nexus.RichText.css +2 -32
  112. package/src/Styles/Nexus.Rows.css +637 -596
  113. package/src/Styles/Nexus.Slider.css +276 -278
  114. package/src/Styles/Nexus.Tab.Buttons.css +432 -419
  115. package/src/Styles/Nexus.Table.css +1386 -1296
  116. package/src/Styles/Nexus.Theme.Picker.css +286 -232
  117. package/src/Styles/Nexus.Themes.css +194 -194
  118. package/src/Styles/Nexus.Time.css +144 -147
  119. package/src/Styles/Nexus.Toast.css +263 -265
  120. package/src/Styles/Nexus.Tokens.css +89 -72
  121. 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
+ }