@astronox/core 0.4.3 → 0.4.5
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.
- package/package.json +1 -1
- package/src/composition/Grid/Grid.css +37 -0
- package/src/patterns/Table/Table.css +2 -8
- package/src/patterns/Table/TableBody.astro +0 -17
- package/src/patterns/Table/TablePagination.css +10 -3
- package/src/patterns/Table/TableSkeleton.css +4 -24
- package/src/patterns/Table/tableProgressiveController.ts +17 -78
- package/src/patterns/Table/tableSortController.ts +3 -6
- package/src/patterns/Table/tableScrollPosition.ts +0 -41
package/package.json
CHANGED
|
@@ -103,6 +103,31 @@
|
|
|
103
103
|
grid-template-columns: minmax(0, 7fr) minmax(0, 3fr);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
.grid[data-layout='content-sidebar']:where(
|
|
107
|
+
:has(> [data-composition='grid-item'][data-position='sticky'])
|
|
108
|
+
) {
|
|
109
|
+
--grid-sticky-viewport-block-size: calc(
|
|
110
|
+
100vh - var(--nox-site-header-height) - var(--nox-layout-gap) * 2
|
|
111
|
+
);
|
|
112
|
+
--grid-sticky-viewport-block-size: calc(
|
|
113
|
+
100dvh - var(--nox-site-header-height) - var(--nox-layout-gap) * 2
|
|
114
|
+
);
|
|
115
|
+
--grid-sticky-peer-position: sticky;
|
|
116
|
+
--grid-sticky-peer-inset-block-start: var(--nox-layout-gap);
|
|
117
|
+
--table-progressive-runway-block-size: var(--grid-sticky-viewport-block-size);
|
|
118
|
+
|
|
119
|
+
min-block-size: var(--grid-sticky-viewport-block-size);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.grid[data-layout='content-sidebar']:where(
|
|
123
|
+
:has(> [data-composition='grid-item'][data-position='sticky'])
|
|
124
|
+
)
|
|
125
|
+
> [data-composition='grid-item'][data-position='static']
|
|
126
|
+
> .grid-item__content {
|
|
127
|
+
position: var(--grid-sticky-peer-position);
|
|
128
|
+
inset-block-start: var(--grid-sticky-peer-inset-block-start);
|
|
129
|
+
}
|
|
130
|
+
|
|
106
131
|
.grid[data-rows] {
|
|
107
132
|
grid-template-rows: repeat(var(--grid-rows), minmax(0, 1fr));
|
|
108
133
|
}
|
|
@@ -112,6 +137,9 @@
|
|
|
112
137
|
[data-layout='fixed'],
|
|
113
138
|
[data-layout='content-sidebar']
|
|
114
139
|
)[data-collapse-at='sm'] {
|
|
140
|
+
--grid-sticky-viewport-block-size: 0px;
|
|
141
|
+
--grid-sticky-peer-position: static;
|
|
142
|
+
--grid-sticky-peer-inset-block-start: auto;
|
|
115
143
|
grid-template-columns: 1fr;
|
|
116
144
|
}
|
|
117
145
|
|
|
@@ -164,6 +192,9 @@
|
|
|
164
192
|
[data-layout='fixed'],
|
|
165
193
|
[data-layout='content-sidebar']
|
|
166
194
|
)[data-collapse-at='md'] {
|
|
195
|
+
--grid-sticky-viewport-block-size: 0px;
|
|
196
|
+
--grid-sticky-peer-position: static;
|
|
197
|
+
--grid-sticky-peer-inset-block-start: auto;
|
|
167
198
|
grid-template-columns: 1fr;
|
|
168
199
|
}
|
|
169
200
|
|
|
@@ -216,6 +247,9 @@
|
|
|
216
247
|
[data-layout='fixed'],
|
|
217
248
|
[data-layout='content-sidebar']
|
|
218
249
|
)[data-collapse-at='lg'] {
|
|
250
|
+
--grid-sticky-viewport-block-size: 0px;
|
|
251
|
+
--grid-sticky-peer-position: static;
|
|
252
|
+
--grid-sticky-peer-inset-block-start: auto;
|
|
219
253
|
grid-template-columns: 1fr;
|
|
220
254
|
}
|
|
221
255
|
|
|
@@ -268,6 +302,9 @@
|
|
|
268
302
|
[data-layout='fixed'],
|
|
269
303
|
[data-layout='content-sidebar']
|
|
270
304
|
)[data-collapse-at='xl'] {
|
|
305
|
+
--grid-sticky-viewport-block-size: 0px;
|
|
306
|
+
--grid-sticky-peer-position: static;
|
|
307
|
+
--grid-sticky-peer-inset-block-start: auto;
|
|
271
308
|
grid-template-columns: 1fr;
|
|
272
309
|
}
|
|
273
310
|
|
|
@@ -49,10 +49,7 @@
|
|
|
49
49
|
|
|
50
50
|
.table[data-table-sticky-header]:has([data-sticky-surface])
|
|
51
51
|
[data-table-header] {
|
|
52
|
-
top: var(
|
|
53
|
-
--surface-group-sticky-occlusion-size,
|
|
54
|
-
calc(var(--nox-layout-gap) + var(--nox-section-responsive-block-size))
|
|
55
|
-
);
|
|
52
|
+
top: calc(var(--nox-layout-gap) + var(--nox-section-responsive-block-size));
|
|
56
53
|
}
|
|
57
54
|
|
|
58
55
|
@container nox-table (width < 32rem) {
|
|
@@ -63,10 +60,7 @@
|
|
|
63
60
|
|
|
64
61
|
.table[data-table-sticky-header]:has([data-sticky-surface])
|
|
65
62
|
[data-table-header] {
|
|
66
|
-
top: var(
|
|
67
|
-
--surface-group-sticky-occlusion-size,
|
|
68
|
-
calc(var(--nox-layout-gap) + var(--nox-section-compact-block-size))
|
|
69
|
-
);
|
|
63
|
+
top: calc(var(--nox-layout-gap) + var(--nox-section-compact-block-size));
|
|
70
64
|
}
|
|
71
65
|
}
|
|
72
66
|
|
|
@@ -55,23 +55,6 @@ const stateMessage =
|
|
|
55
55
|
data-tooltip-boundary
|
|
56
56
|
data-tone={dataTone}
|
|
57
57
|
>
|
|
58
|
-
<div
|
|
59
|
-
class="table-body__initial-skeleton"
|
|
60
|
-
data-table-initial-skeleton
|
|
61
|
-
aria-hidden="true"
|
|
62
|
-
>
|
|
63
|
-
{
|
|
64
|
-
columns.map((column) => (
|
|
65
|
-
<div
|
|
66
|
-
class="table-skeleton__cell"
|
|
67
|
-
data-align={getTableColumnAlignment(column)}
|
|
68
|
-
data-table-column-role={column.role}
|
|
69
|
-
>
|
|
70
|
-
<span class="table-skeleton__placeholder" />
|
|
71
|
-
</div>
|
|
72
|
-
))
|
|
73
|
-
}
|
|
74
|
-
</div>
|
|
75
58
|
<table class="table-body__table">
|
|
76
59
|
<caption class="table-body__visually-hidden">{caption}</caption>
|
|
77
60
|
<thead class="table-body__visually-hidden">
|
|
@@ -49,13 +49,19 @@
|
|
|
49
49
|
position: relative;
|
|
50
50
|
display: block;
|
|
51
51
|
overflow: visible;
|
|
52
|
-
block-size:
|
|
53
|
-
min-block-size:
|
|
52
|
+
block-size: var(--table-progressive-runway-block-size, 0px);
|
|
53
|
+
min-block-size: var(--table-progressive-runway-block-size, 0px);
|
|
54
54
|
border: 0;
|
|
55
55
|
border-radius: 0;
|
|
56
56
|
background: transparent;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
.table-pagination[data-table-progressive-enhanced='true']
|
|
60
|
+
.table-pagination__sentinel {
|
|
61
|
+
inset-block-start: 0;
|
|
62
|
+
inset-block-end: auto;
|
|
63
|
+
}
|
|
64
|
+
|
|
59
65
|
.table-pagination[data-table-progressive-enhanced='true']
|
|
60
66
|
.table-pagination__content {
|
|
61
67
|
block-size: 0;
|
|
@@ -76,7 +82,8 @@
|
|
|
76
82
|
.table-pagination__link:focus-visible {
|
|
77
83
|
z-index: 1;
|
|
78
84
|
inset-inline: 0;
|
|
79
|
-
inset-block-
|
|
85
|
+
inset-block-start: 0;
|
|
86
|
+
inset-block-end: auto;
|
|
80
87
|
display: grid;
|
|
81
88
|
overflow: visible;
|
|
82
89
|
width: auto;
|
|
@@ -7,23 +7,6 @@
|
|
|
7
7
|
border-block-start: 0;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
.table-body__initial-skeleton {
|
|
11
|
-
display: none;
|
|
12
|
-
min-width: 0;
|
|
13
|
-
min-height: var(--table-row-min-block-size);
|
|
14
|
-
grid-template-columns: var(--table-column-template);
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
[data-nox-table-enhanced]
|
|
18
|
-
.table:is(
|
|
19
|
-
[data-table-loading-state='pending'],
|
|
20
|
-
[data-table-loading-state='refreshing']
|
|
21
|
-
)
|
|
22
|
-
.table-body:not(:has(.table-skeleton__row))
|
|
23
|
-
> .table-body__initial-skeleton {
|
|
24
|
-
display: grid;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
10
|
.table-skeleton__row + .table-skeleton__row,
|
|
28
11
|
[data-nox-table-enhanced]
|
|
29
12
|
.table[data-table-loading-state='appending']
|
|
@@ -34,6 +17,9 @@
|
|
|
34
17
|
|
|
35
18
|
[data-nox-table-enhanced]
|
|
36
19
|
.table[data-table-loading-state='pending']
|
|
20
|
+
.table-body__row[data-table-row],
|
|
21
|
+
[data-nox-table-enhanced]
|
|
22
|
+
.table[data-table-loading-state='refreshing']
|
|
37
23
|
.table-body__row[data-table-row] {
|
|
38
24
|
display: none;
|
|
39
25
|
}
|
|
@@ -97,11 +83,6 @@
|
|
|
97
83
|
min-height: var(--table-index-row-block-size);
|
|
98
84
|
}
|
|
99
85
|
|
|
100
|
-
.table[data-table-layout='index'] .table-body__initial-skeleton {
|
|
101
|
-
block-size: var(--table-index-row-block-size);
|
|
102
|
-
min-height: var(--table-index-row-block-size);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
86
|
@media (prefers-reduced-motion: no-preference) {
|
|
106
87
|
.table-skeleton__placeholder {
|
|
107
88
|
animation: table-skeleton-pulse 1.4s ease-in-out infinite;
|
|
@@ -119,8 +100,7 @@
|
|
|
119
100
|
}
|
|
120
101
|
|
|
121
102
|
@container (width < 36rem) {
|
|
122
|
-
.table-skeleton__row
|
|
123
|
-
.table-body__initial-skeleton {
|
|
103
|
+
.table-skeleton__row {
|
|
124
104
|
min-height: var(--table-row-narrow-min-block-size);
|
|
125
105
|
}
|
|
126
106
|
}
|
|
@@ -3,7 +3,6 @@ import type {
|
|
|
3
3
|
TableProgressiveModel,
|
|
4
4
|
} from '../../display/contracts';
|
|
5
5
|
import { tableProgressiveBatchSize } from '../../display/tableProgressive';
|
|
6
|
-
import { mutateTablePreservingScroll } from './tableScrollPosition';
|
|
7
6
|
|
|
8
7
|
const initializedAttribute = 'data-table-progressive-initialized';
|
|
9
8
|
|
|
@@ -152,8 +151,6 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
152
151
|
let disposed = false;
|
|
153
152
|
let generation = 0;
|
|
154
153
|
let prepared = false;
|
|
155
|
-
let retainedWindowSize = Math.max(batchSize, getRows(activeRowsRoot).length);
|
|
156
|
-
let scheduledRenderFrame: number | null = null;
|
|
157
154
|
|
|
158
155
|
registerRows(getRows(activeRowsRoot));
|
|
159
156
|
|
|
@@ -184,11 +181,8 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
184
181
|
activeSkeletonTemplate.content.querySelectorAll<HTMLElement>(
|
|
185
182
|
'[data-table-skeleton-row]',
|
|
186
183
|
),
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
skeletonRows = Array.from({ length: count }, (_, index) =>
|
|
190
|
-
document.importNode(candidates[index % candidates.length]!, true),
|
|
191
|
-
);
|
|
184
|
+
).slice(0, count);
|
|
185
|
+
skeletonRows = candidates.map((row) => document.importNode(row, true));
|
|
192
186
|
insertBeforeEmpty(activeRowsRoot, empty, skeletonRows);
|
|
193
187
|
}
|
|
194
188
|
|
|
@@ -210,21 +204,6 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
210
204
|
);
|
|
211
205
|
}
|
|
212
206
|
|
|
213
|
-
function replaceRows(rows: readonly HTMLElement[]): void {
|
|
214
|
-
for (const row of rows) row.hidden = false;
|
|
215
|
-
mutateTablePreservingScroll(root, () => {
|
|
216
|
-
removeSkeleton();
|
|
217
|
-
detachRenderedRows();
|
|
218
|
-
insertBeforeEmpty(activeRowsRoot, empty, rows);
|
|
219
|
-
});
|
|
220
|
-
root.dispatchEvent(
|
|
221
|
-
new CustomEvent<TableRowsAppendedDetail>('table:rows-appended', {
|
|
222
|
-
bubbles: true,
|
|
223
|
-
detail: { rows },
|
|
224
|
-
}),
|
|
225
|
-
);
|
|
226
|
-
}
|
|
227
|
-
|
|
228
207
|
function updateEmptyState(): void {
|
|
229
208
|
if (empty) empty.hidden = results.length > 0;
|
|
230
209
|
}
|
|
@@ -307,12 +286,10 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
307
286
|
TableLoadingState,
|
|
308
287
|
'pending' | 'refreshing' | 'appending'
|
|
309
288
|
> = 'appending',
|
|
310
|
-
requestedCount = batchSize,
|
|
311
|
-
replace = false,
|
|
312
289
|
): Promise<void> {
|
|
313
290
|
if (request || disposed || cursor >= results.length) return;
|
|
314
291
|
|
|
315
|
-
const target = results.slice(cursor, cursor +
|
|
292
|
+
const target = results.slice(cursor, cursor + batchSize);
|
|
316
293
|
if (target.length === 0) {
|
|
317
294
|
removeSkeleton();
|
|
318
295
|
updatePagination();
|
|
@@ -328,9 +305,7 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
328
305
|
request = activeRequest;
|
|
329
306
|
setPaginationState(activePagination, activeStatus, 'loading');
|
|
330
307
|
updateTableState(loadingState);
|
|
331
|
-
|
|
332
|
-
addSkeleton(target.length);
|
|
333
|
-
}
|
|
308
|
+
addSkeleton(target.length);
|
|
334
309
|
|
|
335
310
|
try {
|
|
336
311
|
await loadSources(missing, activeRequest.signal);
|
|
@@ -361,16 +336,9 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
361
336
|
return;
|
|
362
337
|
}
|
|
363
338
|
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
removeSkeleton();
|
|
367
|
-
appendRows(rows as HTMLElement[]);
|
|
368
|
-
}
|
|
339
|
+
removeSkeleton();
|
|
340
|
+
appendRows(rows as HTMLElement[]);
|
|
369
341
|
cursor += target.length;
|
|
370
|
-
retainedWindowSize = Math.max(
|
|
371
|
-
retainedWindowSize,
|
|
372
|
-
getRows(activeRowsRoot).length,
|
|
373
|
-
);
|
|
374
342
|
updatePagination();
|
|
375
343
|
updateTableState('ready');
|
|
376
344
|
}
|
|
@@ -435,48 +403,23 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
435
403
|
offset: number,
|
|
436
404
|
state: Extract<TableLoadingState, 'pending' | 'refreshing'>,
|
|
437
405
|
): void {
|
|
438
|
-
retainedWindowSize = Math.max(
|
|
439
|
-
retainedWindowSize,
|
|
440
|
-
getRows(activeRowsRoot).length,
|
|
441
|
-
);
|
|
442
406
|
generation += 1;
|
|
443
407
|
request?.abort();
|
|
444
408
|
request = null;
|
|
445
|
-
|
|
446
|
-
window.cancelAnimationFrame(scheduledRenderFrame);
|
|
447
|
-
scheduledRenderFrame = null;
|
|
448
|
-
}
|
|
449
|
-
observer.disconnect();
|
|
409
|
+
activePagination.hidden = false;
|
|
450
410
|
updateTableState(state);
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
mutateTablePreservingScroll(root, () => {
|
|
454
|
-
detachRenderedRows();
|
|
455
|
-
addSkeleton(retainedWindowSize);
|
|
456
|
-
});
|
|
457
|
-
|
|
411
|
+
addSkeleton(batchSize);
|
|
412
|
+
detachRenderedRows();
|
|
458
413
|
applyQuery();
|
|
459
414
|
cursor = Math.min(offset, results.length);
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
replaceRows([]);
|
|
469
|
-
updatePagination();
|
|
470
|
-
updateTableState('empty');
|
|
471
|
-
return;
|
|
472
|
-
}
|
|
473
|
-
void renderNextBatch(
|
|
474
|
-
state,
|
|
475
|
-
Math.min(retainedWindowSize, results.length - cursor),
|
|
476
|
-
true,
|
|
477
|
-
);
|
|
478
|
-
});
|
|
479
|
-
});
|
|
415
|
+
updateEmptyState();
|
|
416
|
+
if (results.length === 0) {
|
|
417
|
+
removeSkeleton();
|
|
418
|
+
updatePagination();
|
|
419
|
+
updateTableState('empty');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
void renderNextBatch(state);
|
|
480
423
|
}
|
|
481
424
|
|
|
482
425
|
function refresh(): void {
|
|
@@ -492,10 +435,6 @@ export function initTableProgressive(root: HTMLElement): () => void {
|
|
|
492
435
|
destroy() {
|
|
493
436
|
disposed = true;
|
|
494
437
|
request?.abort();
|
|
495
|
-
if (scheduledRenderFrame !== null) {
|
|
496
|
-
window.cancelAnimationFrame(scheduledRenderFrame);
|
|
497
|
-
scheduledRenderFrame = null;
|
|
498
|
-
}
|
|
499
438
|
observer.disconnect();
|
|
500
439
|
removeSkeleton();
|
|
501
440
|
activePagination.hidden = !fallbackLink;
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
setTableProgressiveSort,
|
|
5
5
|
updateTableProgressiveEntry,
|
|
6
6
|
} from './tableProgressiveController';
|
|
7
|
-
import { mutateTablePreservingScroll } from './tableScrollPosition';
|
|
8
7
|
|
|
9
8
|
type SortDirection = 'ascending' | 'descending';
|
|
10
9
|
type SortType = 'number' | 'text';
|
|
@@ -97,11 +96,9 @@ export function initTableSort(root: HTMLElement): () => void {
|
|
|
97
96
|
orderDirty = activeState !== null;
|
|
98
97
|
if (rows.every((row, index) => row === sortedRows[index])) return;
|
|
99
98
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
rowsRoot.prepend(fragment);
|
|
104
|
-
});
|
|
99
|
+
const fragment = document.createDocumentFragment();
|
|
100
|
+
for (const row of sortedRows) fragment.append(row);
|
|
101
|
+
rowsRoot.prepend(fragment);
|
|
105
102
|
};
|
|
106
103
|
|
|
107
104
|
const scheduleSort = (): void => {
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
type ScrollRestoreState = {
|
|
2
|
-
frame: number;
|
|
3
|
-
originalOverflowAnchor: string;
|
|
4
|
-
scrollRoot: HTMLElement;
|
|
5
|
-
scrollTop: number;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
const restoreStates = new WeakMap<HTMLElement, ScrollRestoreState>();
|
|
9
|
-
|
|
10
|
-
export function mutateTablePreservingScroll(
|
|
11
|
-
root: HTMLElement,
|
|
12
|
-
mutation: () => void,
|
|
13
|
-
): void {
|
|
14
|
-
const scrollRoot = root.closest<HTMLElement>('[data-site-viewport]');
|
|
15
|
-
if (!scrollRoot) {
|
|
16
|
-
mutation();
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const previous = restoreStates.get(root);
|
|
21
|
-
if (previous) window.cancelAnimationFrame(previous.frame);
|
|
22
|
-
const originalOverflowAnchor =
|
|
23
|
-
previous?.originalOverflowAnchor ?? root.style.overflowAnchor;
|
|
24
|
-
const scrollTop = scrollRoot.scrollTop;
|
|
25
|
-
|
|
26
|
-
root.style.overflowAnchor = 'none';
|
|
27
|
-
mutation();
|
|
28
|
-
scrollRoot.scrollTop = scrollTop;
|
|
29
|
-
|
|
30
|
-
const state: ScrollRestoreState = {
|
|
31
|
-
frame: window.requestAnimationFrame(() => {
|
|
32
|
-
scrollRoot.scrollTop = scrollTop;
|
|
33
|
-
root.style.overflowAnchor = originalOverflowAnchor;
|
|
34
|
-
restoreStates.delete(root);
|
|
35
|
-
}),
|
|
36
|
-
originalOverflowAnchor,
|
|
37
|
-
scrollRoot,
|
|
38
|
-
scrollTop,
|
|
39
|
-
};
|
|
40
|
-
restoreStates.set(root, state);
|
|
41
|
-
}
|