@gtkx/components 2.0.0-beta.12 → 2.0.0-beta.13
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/README.md +1 -1
- package/dist/column-view.d.ts.map +1 -1
- package/dist/column-view.js +7 -3
- package/dist/column-view.js.map +1 -1
- package/dist/combo-row.d.ts.map +1 -1
- package/dist/combo-row.js +3 -1
- package/dist/combo-row.js.map +1 -1
- package/dist/grid-view.d.ts.map +1 -1
- package/dist/grid-view.js +3 -2
- package/dist/grid-view.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/cells.d.ts +5 -2
- package/dist/internal/cells.d.ts.map +1 -1
- package/dist/internal/cells.js +86 -43
- package/dist/internal/cells.js.map +1 -1
- package/dist/internal/collection-index.d.ts +3 -5
- package/dist/internal/collection-index.d.ts.map +1 -1
- package/dist/internal/collection-index.js +3 -7
- package/dist/internal/collection-index.js.map +1 -1
- package/dist/internal/collection-model.d.ts +15 -4
- package/dist/internal/collection-model.d.ts.map +1 -1
- package/dist/internal/collection-model.js +154 -73
- package/dist/internal/collection-model.js.map +1 -1
- package/dist/internal/collection.d.ts +3 -3
- package/dist/internal/collection.d.ts.map +1 -1
- package/dist/internal/collection.js +11 -9
- package/dist/internal/collection.js.map +1 -1
- package/dist/internal/controlled-sync.d.ts +2 -1
- package/dist/internal/controlled-sync.d.ts.map +1 -1
- package/dist/internal/controlled-sync.js +6 -1
- package/dist/internal/controlled-sync.js.map +1 -1
- package/dist/internal/drop-down.d.ts +10 -4
- package/dist/internal/drop-down.d.ts.map +1 -1
- package/dist/internal/drop-down.js +60 -8
- package/dist/internal/drop-down.js.map +1 -1
- package/dist/internal/expansion.d.ts.map +1 -1
- package/dist/internal/expansion.js +46 -19
- package/dist/internal/expansion.js.map +1 -1
- package/dist/internal/first-header.d.ts +11 -0
- package/dist/internal/first-header.d.ts.map +1 -0
- package/dist/internal/first-header.js +21 -0
- package/dist/internal/first-header.js.map +1 -0
- package/dist/internal/level-splice.d.ts +27 -0
- package/dist/internal/level-splice.d.ts.map +1 -0
- package/dist/internal/level-splice.js +98 -0
- package/dist/internal/level-splice.js.map +1 -0
- package/dist/internal/selection.d.ts.map +1 -1
- package/dist/internal/selection.js +23 -16
- package/dist/internal/selection.js.map +1 -1
- package/dist/internal/tree-expansion.d.ts +3 -1
- package/dist/internal/tree-expansion.d.ts.map +1 -1
- package/dist/internal/tree-expansion.js +31 -2
- package/dist/internal/tree-expansion.js.map +1 -1
- package/dist/internal/tree-order.d.ts +1 -0
- package/dist/internal/tree-order.d.ts.map +1 -1
- package/dist/internal/tree-order.js +2 -1
- package/dist/internal/tree-order.js.map +1 -1
- package/dist/internal/use-collection.d.ts +1 -0
- package/dist/internal/use-collection.d.ts.map +1 -1
- package/dist/internal/use-collection.js +6 -2
- package/dist/internal/use-collection.js.map +1 -1
- package/dist/list-item-factory.d.ts +1 -1
- package/dist/list-item-factory.d.ts.map +1 -1
- package/dist/list-item-factory.js +2 -2
- package/dist/list-item-factory.js.map +1 -1
- package/dist/list-view.d.ts.map +1 -1
- package/dist/list-view.js +8 -3
- package/dist/list-view.js.map +1 -1
- package/dist/types.d.ts +37 -47
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -8
- package/src/column-view.tsx +8 -4
- package/src/combo-row.tsx +4 -1
- package/src/grid-view.tsx +3 -2
- package/src/index.ts +0 -4
- package/src/internal/cells.tsx +141 -53
- package/src/internal/collection-index.ts +7 -14
- package/src/internal/collection-model.ts +211 -76
- package/src/internal/collection.ts +14 -13
- package/src/internal/controlled-sync.ts +8 -1
- package/src/internal/drop-down.tsx +111 -14
- package/src/internal/expansion.ts +52 -20
- package/src/internal/first-header.ts +23 -0
- package/src/internal/level-splice.ts +157 -0
- package/src/internal/selection.tsx +24 -19
- package/src/internal/tree-expansion.ts +52 -2
- package/src/internal/tree-order.ts +3 -1
- package/src/internal/use-collection.tsx +8 -2
- package/src/list-item-factory.tsx +2 -1
- package/src/list-view.tsx +10 -2
- package/src/types.ts +39 -51
- package/dist/tab-collection.d.ts +0 -9
- package/dist/tab-collection.d.ts.map +0 -1
- package/dist/tab-collection.js +0 -114
- package/dist/tab-collection.js.map +0 -1
- package/src/tab-collection.tsx +0 -124
package/src/internal/cells.tsx
CHANGED
|
@@ -15,7 +15,7 @@ import type {
|
|
|
15
15
|
ListSectionRenderer,
|
|
16
16
|
} from "../types.js";
|
|
17
17
|
import type { Collection } from "./collection.js";
|
|
18
|
-
import {
|
|
18
|
+
import { type LazyLevelStore, levelStoreFor, slotRefFor } from "./collection-model.js";
|
|
19
19
|
import { joinParts } from "./keys.js";
|
|
20
20
|
|
|
21
21
|
type CellSize = {
|
|
@@ -87,6 +87,7 @@ type PositionedHost = Gtk.ListItem | Gtk.ColumnViewRow;
|
|
|
87
87
|
type ItemSlot = {
|
|
88
88
|
itemKey: string;
|
|
89
89
|
item: ListItem;
|
|
90
|
+
position: number | undefined;
|
|
90
91
|
row: Gtk.TreeListRow | null;
|
|
91
92
|
args: ListItemRenderArgs<unknown>;
|
|
92
93
|
};
|
|
@@ -100,12 +101,14 @@ type ItemIdentity = {
|
|
|
100
101
|
itemKey: string;
|
|
101
102
|
item: ListItem | undefined;
|
|
102
103
|
position: number;
|
|
104
|
+
index: number;
|
|
103
105
|
isExpanded: boolean;
|
|
104
106
|
};
|
|
105
107
|
|
|
106
108
|
type ItemCellProps = {
|
|
107
109
|
entry: CellEntry<Gtk.ListItem>;
|
|
108
110
|
render: ListItemRenderer<never>;
|
|
111
|
+
rowProps: ListRowPropsResolver<never> | null | undefined;
|
|
109
112
|
state: RefObject<CollectionState>;
|
|
110
113
|
hasExpander: boolean;
|
|
111
114
|
expanderDescriptions: ExpanderDescriptions | null | undefined;
|
|
@@ -114,12 +117,22 @@ type ItemCellProps = {
|
|
|
114
117
|
type ItemPortalsProps = {
|
|
115
118
|
registry: CellRegistry<Gtk.ListItem>;
|
|
116
119
|
render: ListItemRenderer<never>;
|
|
120
|
+
rowProps?: ListRowPropsResolver<never> | null | undefined;
|
|
117
121
|
collection: Collection;
|
|
118
122
|
hasExpander?: boolean | undefined;
|
|
119
123
|
expandedIds?: string[] | null | undefined;
|
|
120
124
|
expanderDescriptions?: ExpanderDescriptions | null | undefined;
|
|
121
125
|
};
|
|
122
126
|
|
|
127
|
+
type PendingList<H extends FactoryHost> = {
|
|
128
|
+
entries: CellEntry<H>[];
|
|
129
|
+
isPending: boolean;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
type ItemCellListProps = Omit<ItemPortalsProps, "registry"> & PendingList<Gtk.ListItem>;
|
|
133
|
+
|
|
134
|
+
type ItemRowListProps = Omit<RowPortalsProps, "registry"> & PendingList<Gtk.ColumnViewRow>;
|
|
135
|
+
|
|
123
136
|
type ItemRowProps = {
|
|
124
137
|
entry: CellEntry<Gtk.ColumnViewRow>;
|
|
125
138
|
rowProps: ListRowPropsResolver<never>;
|
|
@@ -136,7 +149,7 @@ type RowPortalsProps = {
|
|
|
136
149
|
type HeaderCellProps = {
|
|
137
150
|
entry: CellEntry<Gtk.ListHeader>;
|
|
138
151
|
render: ListSectionRenderer<never>;
|
|
139
|
-
|
|
152
|
+
version: number;
|
|
140
153
|
};
|
|
141
154
|
|
|
142
155
|
type HeaderPortalsProps = {
|
|
@@ -152,6 +165,7 @@ type NativeItemKeyStore = {
|
|
|
152
165
|
type NativeItemCellProps<T extends GObject.Object> = {
|
|
153
166
|
entry: CellEntry<Gtk.ListItem>;
|
|
154
167
|
render: ListItemRenderer<T>;
|
|
168
|
+
rowProps: ListRowPropsResolver<T> | null | undefined;
|
|
155
169
|
keys: NativeItemKeyStore;
|
|
156
170
|
size: CellSize;
|
|
157
171
|
};
|
|
@@ -159,6 +173,7 @@ type NativeItemCellProps<T extends GObject.Object> = {
|
|
|
159
173
|
type NativeItemPortalsProps<T extends GObject.Object> = {
|
|
160
174
|
registry: CellRegistry<Gtk.ListItem>;
|
|
161
175
|
render: ListItemRenderer<T>;
|
|
176
|
+
rowProps: ListRowPropsResolver<T> | null | undefined;
|
|
162
177
|
size: CellSize;
|
|
163
178
|
};
|
|
164
179
|
|
|
@@ -175,11 +190,14 @@ type RowSlot = {
|
|
|
175
190
|
const ItemCell = memo(ItemCellImpl, isSameItemCell);
|
|
176
191
|
const ItemRow = memo(ItemRowImpl, isSameItemRow);
|
|
177
192
|
const HeaderCell = memo(HeaderCellImpl);
|
|
193
|
+
const ItemCellList = memo(ItemCellListImpl, isWaitingForSync);
|
|
194
|
+
const ItemRowList = memo(ItemRowListImpl, isWaitingForSync);
|
|
178
195
|
const CELL_OPTIONS: CellRegistryOptions<Gtk.ListItem> = { isHost: isListItem, prepare: prepareCell };
|
|
179
196
|
const HEADER_OPTIONS: CellRegistryOptions<Gtk.ListHeader> = { isHost: isListHeader, prepare: prepareCell };
|
|
180
197
|
const ROW_OPTIONS: CellRegistryOptions<Gtk.ColumnViewRow> = { isHost: isColumnViewRow };
|
|
181
198
|
const NO_SIZE: CellSize = { width: -1, height: -1 };
|
|
182
199
|
const NO_ROW_PROPS: ListRowProps = {};
|
|
200
|
+
const DEFAULT_ROW_PROPS = resolveRowProps(NO_ROW_PROPS);
|
|
183
201
|
const placeholders: WeakSet<Gtk.Widget> = new WeakSet();
|
|
184
202
|
|
|
185
203
|
const placeholder = (size: CellSize): Gtk.Widget => {
|
|
@@ -329,13 +347,27 @@ function isRowWanted(options: ItemSlotOptions, item: ListItem): boolean {
|
|
|
329
347
|
return options.expandedIds?.includes(item.id) ?? false;
|
|
330
348
|
}
|
|
331
349
|
|
|
350
|
+
function collectionIndex(collection: Collection, item: ListItem, position: number | undefined): number {
|
|
351
|
+
if (position === undefined) {
|
|
352
|
+
return 0;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if (collection.idAt(position) === item.id) {
|
|
356
|
+
return position;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const index = collection.positionFor(item.id);
|
|
360
|
+
|
|
361
|
+
return index === -1 ? position : index;
|
|
362
|
+
}
|
|
363
|
+
|
|
332
364
|
function itemArgs(
|
|
333
365
|
item: ListItem,
|
|
334
|
-
|
|
366
|
+
index: number,
|
|
335
367
|
row: Gtk.TreeListRow | null,
|
|
336
368
|
isExpanded: boolean,
|
|
337
369
|
): ListItemRenderArgs<unknown> {
|
|
338
|
-
const args: ListItemRenderArgs<unknown> = { item: item.value, index
|
|
370
|
+
const args: ListItemRenderArgs<unknown> = { item: item.value, index };
|
|
339
371
|
|
|
340
372
|
if (row === null) {
|
|
341
373
|
return args;
|
|
@@ -350,10 +382,6 @@ function itemArgs(
|
|
|
350
382
|
return args;
|
|
351
383
|
}
|
|
352
384
|
|
|
353
|
-
function keyForItem(ref: SlotRef, item: ListItem): string {
|
|
354
|
-
return joinParts([slotPathAt(ref.store, ref.slot), item.id]);
|
|
355
|
-
}
|
|
356
|
-
|
|
357
385
|
function slotFor(options: ItemSlotOptions): ItemSlot | null {
|
|
358
386
|
const ref = slotRefFor(options.item);
|
|
359
387
|
|
|
@@ -368,10 +396,16 @@ function slotFor(options: ItemSlotOptions): ItemSlot | null {
|
|
|
368
396
|
}
|
|
369
397
|
|
|
370
398
|
return {
|
|
371
|
-
itemKey:
|
|
399
|
+
itemKey: ref.key,
|
|
372
400
|
item,
|
|
401
|
+
position: options.position,
|
|
373
402
|
row: options.row,
|
|
374
|
-
args: itemArgs(
|
|
403
|
+
args: itemArgs(
|
|
404
|
+
item,
|
|
405
|
+
collectionIndex(options.collection, item, options.position),
|
|
406
|
+
options.row,
|
|
407
|
+
isRowWanted(options, item),
|
|
408
|
+
),
|
|
375
409
|
};
|
|
376
410
|
}
|
|
377
411
|
|
|
@@ -383,6 +417,7 @@ function useItemSlot(
|
|
|
383
417
|
const position = useProperty(entry.host, "position");
|
|
384
418
|
const item = useProperty(entry.host, "item") ?? null;
|
|
385
419
|
const row = item instanceof Gtk.TreeListRow ? item : null;
|
|
420
|
+
const { collection, expandedIds } = state.current;
|
|
386
421
|
|
|
387
422
|
if (position === identity.position) {
|
|
388
423
|
return identity.item === undefined
|
|
@@ -390,13 +425,12 @@ function useItemSlot(
|
|
|
390
425
|
: {
|
|
391
426
|
itemKey: identity.itemKey,
|
|
392
427
|
item: identity.item,
|
|
428
|
+
position,
|
|
393
429
|
row,
|
|
394
|
-
args: itemArgs(identity.item,
|
|
430
|
+
args: itemArgs(identity.item, identity.index, row, identity.isExpanded),
|
|
395
431
|
};
|
|
396
432
|
}
|
|
397
433
|
|
|
398
|
-
const { collection, expandedIds } = state.current;
|
|
399
|
-
|
|
400
434
|
return slotFor({ item, position, row, collection, expandedIds });
|
|
401
435
|
}
|
|
402
436
|
|
|
@@ -407,11 +441,13 @@ function itemIdentity(
|
|
|
407
441
|
): ItemIdentity {
|
|
408
442
|
const ref = slotRefFor(entry.host.getItem());
|
|
409
443
|
const item = ref === null ? undefined : collection.itemAt(ref);
|
|
444
|
+
const position = entry.host.getPosition();
|
|
410
445
|
|
|
411
446
|
return {
|
|
412
|
-
itemKey: ref === null || item === undefined ? "" :
|
|
447
|
+
itemKey: ref === null || item === undefined ? "" : ref.key,
|
|
413
448
|
item,
|
|
414
|
-
position
|
|
449
|
+
position,
|
|
450
|
+
index: item === undefined ? 0 : collectionIndex(collection, item, position),
|
|
415
451
|
isExpanded: item !== undefined && (expandedIds?.includes(item.id) ?? false),
|
|
416
452
|
};
|
|
417
453
|
}
|
|
@@ -421,6 +457,7 @@ function isSameItemIdentity(previous: ItemIdentity, next: ItemIdentity): boolean
|
|
|
421
457
|
previous.item === next.item &&
|
|
422
458
|
previous.itemKey === next.itemKey &&
|
|
423
459
|
previous.position === next.position &&
|
|
460
|
+
previous.index === next.index &&
|
|
424
461
|
previous.isExpanded === next.isExpanded
|
|
425
462
|
);
|
|
426
463
|
}
|
|
@@ -431,12 +468,17 @@ function isSameItemCell(previous: ItemCellProps, next: ItemCellProps): boolean {
|
|
|
431
468
|
return (
|
|
432
469
|
previous.entry === next.entry &&
|
|
433
470
|
previous.render === next.render &&
|
|
471
|
+
previous.rowProps === next.rowProps &&
|
|
434
472
|
previous.hasExpander === next.hasExpander &&
|
|
435
473
|
previous.expanderDescriptions === next.expanderDescriptions &&
|
|
436
474
|
isSameItemIdentity(identity, next)
|
|
437
475
|
);
|
|
438
476
|
}
|
|
439
477
|
|
|
478
|
+
function isWaitingForSync<H extends FactoryHost>(_previous: PendingList<H>, next: PendingList<H>): boolean {
|
|
479
|
+
return next.isPending;
|
|
480
|
+
}
|
|
481
|
+
|
|
440
482
|
function isSameItemRow(previous: ItemRowProps, next: ItemRowProps): boolean {
|
|
441
483
|
const identity = previous.entry.identity.current ?? previous;
|
|
442
484
|
|
|
@@ -468,7 +510,8 @@ function renderedIdentity(entry: CellEntry<PositionedHost>, slot: ItemSlot | nul
|
|
|
468
510
|
return {
|
|
469
511
|
itemKey: slot?.itemKey ?? "",
|
|
470
512
|
item: slot?.item,
|
|
471
|
-
position: slot?.
|
|
513
|
+
position: slot?.position ?? entry.host.getPosition(),
|
|
514
|
+
index: slot?.args.index ?? 0,
|
|
472
515
|
isExpanded: slot?.args.isExpanded ?? false,
|
|
473
516
|
};
|
|
474
517
|
}
|
|
@@ -542,10 +585,7 @@ function rowFlag(value: boolean | undefined): boolean {
|
|
|
542
585
|
return value ?? true;
|
|
543
586
|
}
|
|
544
587
|
|
|
545
|
-
function
|
|
546
|
-
const resolve = rowProps as ListRowPropsResolver<unknown>;
|
|
547
|
-
const props = slot === null ? NO_ROW_PROPS : resolve(slot.args);
|
|
548
|
-
|
|
588
|
+
function resolveRowProps(props: ListRowProps): ResolvedRowProps {
|
|
549
589
|
return {
|
|
550
590
|
accessibleLabel: rowText(props.accessibleLabel),
|
|
551
591
|
accessibleDescription: rowText(props.accessibleDescription),
|
|
@@ -555,7 +595,13 @@ function rowPropsFor(slot: ItemSlot | null, rowProps: ListRowPropsResolver<never
|
|
|
555
595
|
};
|
|
556
596
|
}
|
|
557
597
|
|
|
558
|
-
function
|
|
598
|
+
function rowPropsFor(slot: ItemSlot | null, rowProps: ListRowPropsResolver<never>): ResolvedRowProps {
|
|
599
|
+
const resolve = rowProps as ListRowPropsResolver<unknown>;
|
|
600
|
+
|
|
601
|
+
return resolveRowProps(slot === null ? NO_ROW_PROPS : resolve(slot.args));
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
function applyRowProps(host: PositionedHost, props: ResolvedRowProps, previous: ResolvedRowProps | null): void {
|
|
559
605
|
if (previous?.accessibleLabel !== props.accessibleLabel) {
|
|
560
606
|
host.accessibleLabel = props.accessibleLabel;
|
|
561
607
|
}
|
|
@@ -577,9 +623,24 @@ function applyRowProps(host: Gtk.ColumnViewRow, props: ResolvedRowProps, previou
|
|
|
577
623
|
}
|
|
578
624
|
}
|
|
579
625
|
|
|
626
|
+
function useAppliedRowProps(host: PositionedHost, props: ResolvedRowProps | null): void {
|
|
627
|
+
const previous = useRef<ResolvedRowProps | null>(null);
|
|
628
|
+
|
|
629
|
+
useLayoutEffect(() => {
|
|
630
|
+
if (props === null && previous.current === null) {
|
|
631
|
+
return;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
const next = props ?? DEFAULT_ROW_PROPS;
|
|
635
|
+
applyRowProps(host, next, previous.current);
|
|
636
|
+
previous.current = props === null ? null : next;
|
|
637
|
+
}, [host, props]);
|
|
638
|
+
}
|
|
639
|
+
|
|
580
640
|
function ItemCellImpl({
|
|
581
641
|
entry,
|
|
582
642
|
render,
|
|
643
|
+
rowProps,
|
|
583
644
|
state,
|
|
584
645
|
hasExpander,
|
|
585
646
|
expanderDescriptions,
|
|
@@ -587,6 +648,7 @@ function ItemCellImpl({
|
|
|
587
648
|
}: ItemCellProps): ReactNode {
|
|
588
649
|
const slot = useItemSlot(entry, state, identity);
|
|
589
650
|
useRememberIdentity(entry, slot);
|
|
651
|
+
useAppliedRowProps(entry.host, rowProps == null ? null : rowPropsFor(slot, rowProps));
|
|
590
652
|
const body = itemBody(slot, render, hasExpander, expanderDescriptions);
|
|
591
653
|
|
|
592
654
|
return createPortal(body, entry.host, entry.key);
|
|
@@ -595,30 +657,35 @@ function ItemCellImpl({
|
|
|
595
657
|
function ItemRowImpl({ entry, rowProps, state, ...identity }: ItemRowProps): ReactNode {
|
|
596
658
|
const slot = useItemSlot(entry, state, identity);
|
|
597
659
|
useRememberIdentity(entry, slot);
|
|
598
|
-
|
|
599
|
-
const previous = useRef<ResolvedRowProps | null>(null);
|
|
600
|
-
|
|
601
|
-
useLayoutEffect(() => {
|
|
602
|
-
applyRowProps(entry.host, props, previous.current);
|
|
603
|
-
previous.current = props;
|
|
604
|
-
}, [entry.host, props]);
|
|
660
|
+
useAppliedRowProps(entry.host, rowPropsFor(slot, rowProps));
|
|
605
661
|
|
|
606
662
|
return null;
|
|
607
663
|
}
|
|
608
664
|
|
|
609
|
-
function HeaderCellImpl({ entry, render
|
|
665
|
+
function HeaderCellImpl({ entry, render }: HeaderCellProps): ReactNode {
|
|
610
666
|
const item = useProperty(entry.host, "item") ?? null;
|
|
611
667
|
|
|
612
|
-
return createPortal(headerBody(
|
|
668
|
+
return createPortal(headerBody(levelStoreFor(item), render), entry.host, entry.key);
|
|
613
669
|
}
|
|
614
670
|
|
|
615
|
-
function NativeItemCell<T extends GObject.Object>({
|
|
671
|
+
function NativeItemCell<T extends GObject.Object>({
|
|
672
|
+
entry,
|
|
673
|
+
render,
|
|
674
|
+
rowProps,
|
|
675
|
+
keys,
|
|
676
|
+
size,
|
|
677
|
+
}: NativeItemCellProps<T>): ReactNode {
|
|
616
678
|
const position = useProperty(entry.host, "position");
|
|
617
679
|
const item = useProperty(entry.host, "item") ?? null;
|
|
680
|
+
const args = item !== null && position !== undefined ? { item: item as T, index: position } : null;
|
|
681
|
+
useAppliedRowProps(
|
|
682
|
+
entry.host,
|
|
683
|
+
rowProps == null ? null : resolveRowProps(args === null ? NO_ROW_PROPS : rowProps(args)),
|
|
684
|
+
);
|
|
618
685
|
let body: ReactNode = null;
|
|
619
686
|
|
|
620
|
-
if (item !== null &&
|
|
621
|
-
const content = render(
|
|
687
|
+
if (item !== null && args !== null) {
|
|
688
|
+
const content = render(args);
|
|
622
689
|
const child =
|
|
623
690
|
content == null || typeof content === "boolean" ? (
|
|
624
691
|
<GtkBox widthRequest={size.width} heightRequest={size.height} />
|
|
@@ -631,19 +698,15 @@ function NativeItemCell<T extends GObject.Object>({ entry, render, keys, size }:
|
|
|
631
698
|
return createPortal(body, entry.host, entry.key);
|
|
632
699
|
}
|
|
633
700
|
|
|
634
|
-
function headerBody(
|
|
635
|
-
|
|
636
|
-
return null;
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
const section = collection.sectionFor(ref.store.level.path);
|
|
701
|
+
function headerBody(store: LazyLevelStore | null, render: ListSectionRenderer<never>): ReactNode {
|
|
702
|
+
const section = store?.level.section;
|
|
640
703
|
|
|
641
|
-
if (section === undefined) {
|
|
704
|
+
if (store === null || section === undefined) {
|
|
642
705
|
return null;
|
|
643
706
|
}
|
|
644
707
|
|
|
645
708
|
const renderHeader = render as ListSectionRenderer<unknown>;
|
|
646
|
-
const key = joinParts([
|
|
709
|
+
const key = joinParts([store.key, section.id]);
|
|
647
710
|
|
|
648
711
|
return <Fragment key={key}>{renderHeader({ section: section.value })}</Fragment>;
|
|
649
712
|
}
|
|
@@ -652,15 +715,19 @@ function usePortalEntries<H extends FactoryHost>(registry: CellRegistry<H>): Cel
|
|
|
652
715
|
return useSyncExternalStore(registry.subscribe, registry.getEntries);
|
|
653
716
|
}
|
|
654
717
|
|
|
655
|
-
|
|
656
|
-
|
|
718
|
+
function useCollectionVersion(collection: Collection): number {
|
|
719
|
+
return useSyncExternalStore(collection.subscribe, collection.getVersion);
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function ItemCellListImpl({
|
|
723
|
+
entries,
|
|
657
724
|
render,
|
|
725
|
+
rowProps,
|
|
658
726
|
collection,
|
|
659
727
|
hasExpander,
|
|
660
728
|
expandedIds,
|
|
661
729
|
expanderDescriptions,
|
|
662
|
-
}:
|
|
663
|
-
const entries = usePortalEntries(registry);
|
|
730
|
+
}: ItemCellListProps): ReactNode {
|
|
664
731
|
const state = useLatestRef({ collection, expandedIds });
|
|
665
732
|
|
|
666
733
|
return entries.map((entry) => (
|
|
@@ -668,16 +735,23 @@ const ItemPortals = ({
|
|
|
668
735
|
key={entry.key}
|
|
669
736
|
entry={entry}
|
|
670
737
|
render={render}
|
|
738
|
+
rowProps={rowProps}
|
|
671
739
|
state={state}
|
|
672
740
|
hasExpander={hasExpander ?? true}
|
|
673
741
|
expanderDescriptions={expanderDescriptions}
|
|
674
742
|
{...itemIdentity(entry, collection, expandedIds)}
|
|
675
743
|
/>
|
|
676
744
|
));
|
|
677
|
-
}
|
|
745
|
+
}
|
|
678
746
|
|
|
679
|
-
const
|
|
747
|
+
const ItemPortals = ({ registry, ...props }: ItemPortalsProps): ReactNode => {
|
|
680
748
|
const entries = usePortalEntries(registry);
|
|
749
|
+
useCollectionVersion(props.collection);
|
|
750
|
+
|
|
751
|
+
return <ItemCellList {...props} entries={entries} isPending={props.collection.isPending()} />;
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
function ItemRowListImpl({ entries, rowProps, collection, expandedIds }: ItemRowListProps): ReactNode {
|
|
681
755
|
const state = useLatestRef({ collection, expandedIds });
|
|
682
756
|
|
|
683
757
|
return entries.map((entry) => (
|
|
@@ -689,19 +763,33 @@ const RowPortals = ({ registry, rowProps, collection, expandedIds }: RowPortalsP
|
|
|
689
763
|
{...itemIdentity(entry, collection, expandedIds)}
|
|
690
764
|
/>
|
|
691
765
|
));
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
const RowPortals = ({ registry, ...props }: RowPortalsProps): ReactNode => {
|
|
769
|
+
const entries = usePortalEntries(registry);
|
|
770
|
+
useCollectionVersion(props.collection);
|
|
771
|
+
|
|
772
|
+
return <ItemRowList {...props} entries={entries} isPending={props.collection.isPending()} />;
|
|
692
773
|
};
|
|
693
774
|
|
|
694
|
-
const HeaderPortals = ({ registry, render, collection }: HeaderPortalsProps): ReactNode =>
|
|
695
|
-
usePortalEntries(registry)
|
|
696
|
-
|
|
697
|
-
));
|
|
775
|
+
const HeaderPortals = ({ registry, render, collection }: HeaderPortalsProps): ReactNode => {
|
|
776
|
+
const entries = usePortalEntries(registry);
|
|
777
|
+
const version = useCollectionVersion(collection);
|
|
698
778
|
|
|
699
|
-
|
|
779
|
+
return entries.map((entry) => <HeaderCell key={entry.key} entry={entry} render={render} version={version} />);
|
|
780
|
+
};
|
|
781
|
+
|
|
782
|
+
function NativeItemPortals<T extends GObject.Object>({
|
|
783
|
+
registry,
|
|
784
|
+
render,
|
|
785
|
+
rowProps,
|
|
786
|
+
size,
|
|
787
|
+
}: NativeItemPortalsProps<T>): ReactNode {
|
|
700
788
|
const entries = usePortalEntries(registry);
|
|
701
789
|
const [keys] = useState(createNativeItemKeyStore);
|
|
702
790
|
|
|
703
791
|
return entries.map((entry) => (
|
|
704
|
-
<NativeItemCell key={entry.key} entry={entry} render={render} keys={keys} size={size} />
|
|
792
|
+
<NativeItemCell key={entry.key} entry={entry} render={render} rowProps={rowProps} keys={keys} size={size} />
|
|
705
793
|
));
|
|
706
794
|
}
|
|
707
795
|
|
|
@@ -1,28 +1,25 @@
|
|
|
1
1
|
import type { ListItem, ListSection } from "../types.js";
|
|
2
2
|
import { decodePartAt, encodePart } from "./keys.js";
|
|
3
3
|
|
|
4
|
+
type SectionIdentity = Pick<ListSection, "id" | "value">;
|
|
5
|
+
|
|
4
6
|
type Level = {
|
|
5
7
|
path: string;
|
|
6
8
|
items: ListItem[];
|
|
7
9
|
expandableFlags: boolean[];
|
|
10
|
+
section?: SectionIdentity | undefined;
|
|
8
11
|
};
|
|
9
12
|
|
|
10
|
-
type SectionIdentity = Pick<ListSection, "id" | "value">;
|
|
11
|
-
|
|
12
13
|
type CollectionIndex = {
|
|
13
14
|
isTree: boolean;
|
|
14
15
|
groups: Level[];
|
|
15
16
|
childLevel: (level: Level, slot: number) => Level | undefined;
|
|
16
|
-
levelFor: (levelPath: string) => Level | undefined;
|
|
17
|
-
itemAt: (levelPath: string, slot: number) => ListItem | undefined;
|
|
18
|
-
sectionFor: (levelPath: string) => SectionIdentity | undefined;
|
|
19
17
|
};
|
|
20
18
|
|
|
21
19
|
type IndexState = {
|
|
22
20
|
isTree: boolean;
|
|
23
21
|
groups: Level[];
|
|
24
22
|
levels: Map<string, Level>;
|
|
25
|
-
sections: Map<string, SectionIdentity>;
|
|
26
23
|
};
|
|
27
24
|
|
|
28
25
|
type ParentItem = ListItem & { children: ListItem[] };
|
|
@@ -97,10 +94,10 @@ function buildGroups(state: IndexState, source: ListItem[], sections: ListSectio
|
|
|
97
94
|
}
|
|
98
95
|
|
|
99
96
|
return sections.map((section, group) => {
|
|
100
|
-
const
|
|
101
|
-
|
|
97
|
+
const level = newLevel(state, encodePart(String(group)), section.data);
|
|
98
|
+
level.section = { id: section.id, value: section.value };
|
|
102
99
|
|
|
103
|
-
return
|
|
100
|
+
return level;
|
|
104
101
|
});
|
|
105
102
|
}
|
|
106
103
|
|
|
@@ -127,7 +124,6 @@ function createCollectionIndex(
|
|
|
127
124
|
isTree: isTreeSource(source, sections, isFlat),
|
|
128
125
|
groups: [],
|
|
129
126
|
levels: new Map(),
|
|
130
|
-
sections: new Map(),
|
|
131
127
|
};
|
|
132
128
|
|
|
133
129
|
state.groups = buildGroups(state, source, sections);
|
|
@@ -136,10 +132,7 @@ function createCollectionIndex(
|
|
|
136
132
|
isTree: state.isTree,
|
|
137
133
|
groups: state.groups,
|
|
138
134
|
childLevel: (level, slot) => childLevel(state, level, slot),
|
|
139
|
-
levelFor: (levelPath) => levelFor(state, levelPath),
|
|
140
|
-
itemAt: (levelPath, slot) => levelFor(state, levelPath)?.items[slot],
|
|
141
|
-
sectionFor: (levelPath) => state.sections.get(levelPath),
|
|
142
135
|
};
|
|
143
136
|
}
|
|
144
137
|
|
|
145
|
-
export { createCollectionIndex, type CollectionIndex, type Level
|
|
138
|
+
export { createCollectionIndex, type CollectionIndex, type Level };
|