@gtkx/components 2.0.0-beta.10 → 2.0.0-beta.12

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 (86) hide show
  1. package/README.md +8 -168
  2. package/dist/column-view.d.ts.map +1 -1
  3. package/dist/column-view.js +20 -10
  4. package/dist/column-view.js.map +1 -1
  5. package/dist/grid-view.js +1 -1
  6. package/dist/index.d.ts +4 -2
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +3 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/internal/cells.d.ts +10 -7
  11. package/dist/internal/cells.d.ts.map +1 -1
  12. package/dist/internal/cells.js +88 -51
  13. package/dist/internal/cells.js.map +1 -1
  14. package/dist/internal/collection-index.d.ts +3 -2
  15. package/dist/internal/collection-index.d.ts.map +1 -1
  16. package/dist/internal/collection-index.js +3 -3
  17. package/dist/internal/collection-index.js.map +1 -1
  18. package/dist/internal/collection-model.d.ts +23 -2
  19. package/dist/internal/collection-model.d.ts.map +1 -1
  20. package/dist/internal/collection-model.js +118 -98
  21. package/dist/internal/collection-model.js.map +1 -1
  22. package/dist/internal/collection.d.ts +5 -4
  23. package/dist/internal/collection.d.ts.map +1 -1
  24. package/dist/internal/collection.js +20 -21
  25. package/dist/internal/collection.js.map +1 -1
  26. package/dist/internal/controlled-sync.d.ts +6 -8
  27. package/dist/internal/controlled-sync.d.ts.map +1 -1
  28. package/dist/internal/controlled-sync.js +3 -3
  29. package/dist/internal/controlled-sync.js.map +1 -1
  30. package/dist/internal/drop-down.d.ts.map +1 -1
  31. package/dist/internal/drop-down.js +44 -45
  32. package/dist/internal/drop-down.js.map +1 -1
  33. package/dist/internal/expansion.js +4 -4
  34. package/dist/internal/expansion.js.map +1 -1
  35. package/dist/internal/keys.d.ts.map +1 -1
  36. package/dist/internal/selection.d.ts +1 -0
  37. package/dist/internal/selection.d.ts.map +1 -1
  38. package/dist/internal/selection.js +6 -6
  39. package/dist/internal/selection.js.map +1 -1
  40. package/dist/internal/tree-expansion.d.ts +1 -1
  41. package/dist/internal/tree-expansion.d.ts.map +1 -1
  42. package/dist/internal/tree-expansion.js +3 -12
  43. package/dist/internal/tree-expansion.js.map +1 -1
  44. package/dist/internal/tree-order.d.ts +1 -1
  45. package/dist/internal/tree-order.d.ts.map +1 -1
  46. package/dist/internal/tree-order.js +33 -77
  47. package/dist/internal/tree-order.js.map +1 -1
  48. package/dist/internal/use-collection.d.ts +5 -1
  49. package/dist/internal/use-collection.d.ts.map +1 -1
  50. package/dist/internal/use-collection.js +21 -7
  51. package/dist/internal/use-collection.js.map +1 -1
  52. package/dist/internal/use-widget-ref.d.ts.map +1 -1
  53. package/dist/list-item-factory.d.ts +10 -0
  54. package/dist/list-item-factory.d.ts.map +1 -0
  55. package/dist/list-item-factory.js +14 -0
  56. package/dist/list-item-factory.js.map +1 -0
  57. package/dist/list-view.js +1 -1
  58. package/dist/tab-collection.d.ts +9 -0
  59. package/dist/tab-collection.d.ts.map +1 -0
  60. package/dist/tab-collection.js +114 -0
  61. package/dist/tab-collection.js.map +1 -0
  62. package/dist/toast.d.ts +3 -5
  63. package/dist/toast.d.ts.map +1 -1
  64. package/dist/toast.js +3 -12
  65. package/dist/toast.js.map +1 -1
  66. package/dist/types.d.ts +67 -51
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js.map +1 -1
  69. package/package.json +13 -21
  70. package/src/column-view.tsx +23 -12
  71. package/src/index.ts +7 -2
  72. package/src/internal/cells.tsx +155 -103
  73. package/src/internal/collection-index.ts +8 -6
  74. package/src/internal/collection-model.ts +156 -134
  75. package/src/internal/collection.ts +28 -24
  76. package/src/internal/controlled-sync.ts +9 -12
  77. package/src/internal/drop-down.tsx +63 -63
  78. package/src/internal/expansion.ts +4 -4
  79. package/src/internal/selection.tsx +8 -8
  80. package/src/internal/tree-expansion.ts +3 -23
  81. package/src/internal/tree-order.ts +34 -130
  82. package/src/internal/use-collection.tsx +29 -8
  83. package/src/list-item-factory.tsx +27 -0
  84. package/src/tab-collection.tsx +124 -0
  85. package/src/toast.tsx +4 -18
  86. package/src/types.ts +81 -55
@@ -1,74 +1,38 @@
1
- const NO_ITEM = { id: "", value: undefined };
2
- function advanceStack(stack, onSlot, onLeave) {
3
- const frame = stack.at(-1);
4
- if (frame === undefined) {
5
- return;
6
- }
7
- if (frame.cursor >= frame.level.items.length) {
8
- stack.pop();
9
- onLeave?.(frame);
10
- return;
11
- }
12
- const slot = frame.cursor;
13
- frame.cursor += 1;
14
- onSlot(frame, slot);
15
- }
16
- function frameFor(options, level) {
17
- return { level, cursor: 0, open: options.slots.get(level.path), marked: options.marks?.get(level.path) };
18
- }
19
- function descend(state, level, slot) {
20
- const child = state.options.index.childLevel(level, slot);
21
- if (child === undefined) {
22
- return;
23
- }
24
- state.order.expandedPaths.push(child.path);
25
- state.order.expandedIds.push(state.row.item.id);
26
- state.stack.push(frameFor(state.options, child));
27
- }
28
- function visitSlot(state, frame, slot) {
29
- const item = frame.level.items[slot];
30
- if (item === undefined) {
31
- return;
32
- }
33
- const { row } = state;
34
- row.item = item;
35
- row.isOpen = frame.open?.has(slot) ?? false;
36
- row.isMarked = frame.marked?.has(slot) ?? false;
37
- state.options.visit?.(row);
38
- row.position += 1;
39
- if (row.isOpen) {
40
- descend(state, frame.level, slot);
1
+ function walkLevel(options, level, state) {
2
+ const open = options.slots.get(level.path);
3
+ const marked = options.marks?.get(level.path);
4
+ for (const [slot, item] of level.items.entries()) {
5
+ const isOpen = open?.has(slot) ?? false;
6
+ options.visit?.({ item, position: state.position, isOpen, isMarked: marked?.has(slot) ?? false });
7
+ state.position += 1;
8
+ if (!isOpen) {
9
+ continue;
10
+ }
11
+ const child = options.index.childLevel(level, slot);
12
+ if (child !== undefined) {
13
+ state.order.expandedPaths.push(child.path);
14
+ state.order.expandedIds.push(item.id);
15
+ walkLevel(options, child, state);
16
+ }
41
17
  }
42
18
  }
43
19
  function walkVisible(options) {
44
- const order = { expandedPaths: [], expandedIds: [] };
45
- const row = { item: NO_ITEM, position: 0, isOpen: false, isMarked: false };
46
- const frames = options.index.groups.map((level) => frameFor(options, level));
47
- const state = { options, stack: frames.toReversed(), row, order };
48
- const onSlot = (frame, slot) => {
49
- visitSlot(state, frame, slot);
50
- };
51
- while (state.stack.length > 0) {
52
- advanceStack(state.stack, onSlot);
53
- }
54
- return order;
55
- }
56
- function openSlot(walk, frame, slot) {
57
- const item = frame.level.items[slot];
58
- if (item === undefined || !walk.ids.has(item.id) || walk.ancestors.has(item)) {
59
- return;
60
- }
61
- const child = walk.index.childLevel(frame.level, slot);
62
- if (child === undefined) {
63
- return;
20
+ const state = { position: 0, order: { expandedPaths: [], expandedIds: [] } };
21
+ for (const level of options.index.groups) {
22
+ walkLevel(options, level, state);
64
23
  }
65
- walk.paths.add(child.path);
66
- walk.ancestors.add(item);
67
- walk.stack.push({ level: child, cursor: 0, owner: item });
24
+ return state.order;
68
25
  }
69
- function leaveOpenFrame(walk, frame) {
70
- if (frame.owner !== null) {
71
- walk.ancestors.delete(frame.owner);
26
+ function expandLevel(index, level, ids, paths) {
27
+ for (const [slot, item] of level.items.entries()) {
28
+ if (!ids.has(item.id)) {
29
+ continue;
30
+ }
31
+ const child = index.childLevel(level, slot);
32
+ if (child !== undefined) {
33
+ paths.add(child.path);
34
+ expandLevel(index, child, ids, paths);
35
+ }
72
36
  }
73
37
  }
74
38
  function expandedPathsFor(index, ids) {
@@ -76,16 +40,8 @@ function expandedPathsFor(index, ids) {
76
40
  if (ids.size === 0 || !index.isTree) {
77
41
  return paths;
78
42
  }
79
- const frames = index.groups.map((level) => ({ level, cursor: 0, owner: null }));
80
- const walk = { index, ids, paths, stack: frames.toReversed(), ancestors: new Set() };
81
- const onSlot = (frame, slot) => {
82
- openSlot(walk, frame, slot);
83
- };
84
- const onLeave = (frame) => {
85
- leaveOpenFrame(walk, frame);
86
- };
87
- while (walk.stack.length > 0) {
88
- advanceStack(walk.stack, onSlot, onLeave);
43
+ for (const level of index.groups) {
44
+ expandLevel(index, level, ids, paths);
89
45
  }
90
46
  return paths;
91
47
  }
@@ -119,5 +75,5 @@ function findIds(index, slots, positions) {
119
75
  });
120
76
  return found;
121
77
  }
122
- export { expandedPathsFor, findIds, findRows, walkVisible, };
78
+ export { expandedPathsFor, findIds, findRows, walkVisible };
123
79
  //# sourceMappingURL=tree-order.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree-order.js","sourceRoot":"","sources":["../../src/internal/tree-order.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListItem } from \"../types.js\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport type { SlotMap } from \"./slots.js\";\n\ntype VisibleRow = {\n item: ListItem;\n position: number;\n isOpen: boolean;\n isMarked: boolean;\n};\n\ntype VisibleOrder = {\n expandedPaths: string[];\n expandedIds: string[];\n};\n\ntype MatchedRows = {\n positions: number[];\n ids: string[];\n};\n\ntype RowVisitor = (row: VisibleRow) => void;\n\ntype WalkOptions = {\n index: CollectionIndex;\n slots: SlotMap;\n marks?: SlotMap | undefined;\n visit?: RowVisitor | undefined;\n};\n\ntype LevelFrame = {\n level: Level;\n cursor: number;\n};\n\ntype WalkFrame = LevelFrame & {\n open: Set<number> | undefined;\n marked: Set<number> | undefined;\n};\n\ntype WalkState = {\n options: WalkOptions;\n stack: WalkFrame[];\n row: VisibleRow;\n order: VisibleOrder;\n};\n\ntype OpenFrame = LevelFrame & {\n owner: ListItem | null;\n};\n\ntype OpenWalk = {\n index: CollectionIndex;\n ids: Set<string>;\n paths: Set<string>;\n stack: OpenFrame[];\n ancestors: Set<ListItem>;\n};\n\nconst NO_ITEM: ListItem = { id: \"\", value: undefined };\n\nfunction advanceStack<F extends LevelFrame>(\n stack: F[],\n onSlot: (frame: F, slot: number) => void,\n onLeave?: (frame: F) => void,\n): void {\n const frame = stack.at(-1);\n\n if (frame === undefined) {\n return;\n }\n\n if (frame.cursor >= frame.level.items.length) {\n stack.pop();\n onLeave?.(frame);\n\n return;\n }\n\n const slot = frame.cursor;\n frame.cursor += 1;\n onSlot(frame, slot);\n}\n\nfunction frameFor(options: WalkOptions, level: Level): WalkFrame {\n return { level, cursor: 0, open: options.slots.get(level.path), marked: options.marks?.get(level.path) };\n}\n\nfunction descend(state: WalkState, level: Level, slot: number): void {\n const child = state.options.index.childLevel(level, slot);\n\n if (child === undefined) {\n return;\n }\n\n state.order.expandedPaths.push(child.path);\n state.order.expandedIds.push(state.row.item.id);\n state.stack.push(frameFor(state.options, child));\n}\n\nfunction visitSlot(state: WalkState, frame: WalkFrame, slot: number): void {\n const item = frame.level.items[slot];\n\n if (item === undefined) {\n return;\n }\n\n const { row } = state;\n row.item = item;\n row.isOpen = frame.open?.has(slot) ?? false;\n row.isMarked = frame.marked?.has(slot) ?? false;\n state.options.visit?.(row);\n row.position += 1;\n\n if (row.isOpen) {\n descend(state, frame.level, slot);\n }\n}\n\nfunction walkVisible(options: WalkOptions): VisibleOrder {\n const order: VisibleOrder = { expandedPaths: [], expandedIds: [] };\n const row: VisibleRow = { item: NO_ITEM, position: 0, isOpen: false, isMarked: false };\n const frames = options.index.groups.map((level) => frameFor(options, level));\n const state: WalkState = { options, stack: frames.toReversed(), row, order };\n\n const onSlot = (frame: WalkFrame, slot: number): void => {\n visitSlot(state, frame, slot);\n };\n\n while (state.stack.length > 0) {\n advanceStack(state.stack, onSlot);\n }\n\n return order;\n}\n\nfunction openSlot(walk: OpenWalk, frame: OpenFrame, slot: number): void {\n const item = frame.level.items[slot];\n\n if (item === undefined || !walk.ids.has(item.id) || walk.ancestors.has(item)) {\n return;\n }\n\n const child = walk.index.childLevel(frame.level, slot);\n\n if (child === undefined) {\n return;\n }\n\n walk.paths.add(child.path);\n walk.ancestors.add(item);\n walk.stack.push({ level: child, cursor: 0, owner: item });\n}\n\nfunction leaveOpenFrame(walk: OpenWalk, frame: OpenFrame): void {\n if (frame.owner !== null) {\n walk.ancestors.delete(frame.owner);\n }\n}\n\nfunction expandedPathsFor(index: CollectionIndex, ids: Set<string>): Set<string> {\n const paths: Set<string> = new Set();\n\n if (ids.size === 0 || !index.isTree) {\n return paths;\n }\n\n const frames = index.groups.map((level) => ({ level, cursor: 0, owner: null }));\n const walk: OpenWalk = { index, ids, paths, stack: frames.toReversed(), ancestors: new Set() };\n\n const onSlot = (frame: OpenFrame, slot: number): void => {\n openSlot(walk, frame, slot);\n };\n\n const onLeave = (frame: OpenFrame): void => {\n leaveOpenFrame(walk, frame);\n };\n\n while (walk.stack.length > 0) {\n advanceStack(walk.stack, onSlot, onLeave);\n }\n\n return paths;\n}\n\nfunction findRows(index: CollectionIndex, slots: SlotMap, ids: Set<string>): MatchedRows {\n const positions: number[] = [];\n const found: string[] = [];\n\n walkVisible({\n index,\n slots,\n visit: (row) => {\n if (!ids.has(row.item.id)) {\n return;\n }\n\n positions.push(row.position);\n found.push(row.item.id);\n },\n });\n\n return { positions, ids: found };\n}\n\nfunction findIds(index: CollectionIndex, slots: SlotMap, positions: Set<number>): string[] {\n const found: string[] = [];\n\n walkVisible({\n index,\n slots,\n visit: (row) => {\n if (!positions.has(row.position)) {\n return;\n }\n\n found.push(row.item.id);\n },\n });\n\n return found;\n}\n\nexport {\n expandedPathsFor,\n findIds,\n findRows,\n walkVisible,\n type MatchedRows,\n type VisibleOrder,\n type WalkOptions,\n};\n"]}
1
+ {"version":3,"file":"tree-order.js","sourceRoot":"","sources":["../../src/internal/tree-order.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ListItem } from \"../types.js\";\nimport type { CollectionIndex, Level } from \"./collection-index.js\";\nimport type { SlotMap } from \"./slots.js\";\n\ntype VisibleRow = {\n item: ListItem;\n position: number;\n isOpen: boolean;\n isMarked: boolean;\n};\n\ntype VisibleOrder = {\n expandedPaths: string[];\n expandedIds: string[];\n};\n\ntype MatchedRows = {\n positions: number[];\n ids: string[];\n};\n\ntype RowVisitor = (row: VisibleRow) => void;\n\ntype WalkOptions = {\n index: CollectionIndex;\n slots: SlotMap;\n marks?: SlotMap | undefined;\n visit?: RowVisitor | undefined;\n};\n\ntype WalkState = {\n position: number;\n order: VisibleOrder;\n};\n\nfunction walkLevel(options: WalkOptions, level: Level, state: WalkState): void {\n const open = options.slots.get(level.path);\n const marked = options.marks?.get(level.path);\n\n for (const [slot, item] of level.items.entries()) {\n const isOpen = open?.has(slot) ?? false;\n options.visit?.({ item, position: state.position, isOpen, isMarked: marked?.has(slot) ?? false });\n state.position += 1;\n\n if (!isOpen) {\n continue;\n }\n\n const child = options.index.childLevel(level, slot);\n\n if (child !== undefined) {\n state.order.expandedPaths.push(child.path);\n state.order.expandedIds.push(item.id);\n walkLevel(options, child, state);\n }\n }\n}\n\nfunction walkVisible(options: WalkOptions): VisibleOrder {\n const state: WalkState = { position: 0, order: { expandedPaths: [], expandedIds: [] } };\n\n for (const level of options.index.groups) {\n walkLevel(options, level, state);\n }\n\n return state.order;\n}\n\nfunction expandLevel(index: CollectionIndex, level: Level, ids: Set<string>, paths: Set<string>): void {\n for (const [slot, item] of level.items.entries()) {\n if (!ids.has(item.id)) {\n continue;\n }\n\n const child = index.childLevel(level, slot);\n\n if (child !== undefined) {\n paths.add(child.path);\n expandLevel(index, child, ids, paths);\n }\n }\n}\n\nfunction expandedPathsFor(index: CollectionIndex, ids: Set<string>): Set<string> {\n const paths: Set<string> = new Set();\n\n if (ids.size === 0 || !index.isTree) {\n return paths;\n }\n\n for (const level of index.groups) {\n expandLevel(index, level, ids, paths);\n }\n\n return paths;\n}\n\nfunction findRows(index: CollectionIndex, slots: SlotMap, ids: Set<string>): MatchedRows {\n const positions: number[] = [];\n const found: string[] = [];\n\n walkVisible({\n index,\n slots,\n visit: (row) => {\n if (!ids.has(row.item.id)) {\n return;\n }\n\n positions.push(row.position);\n found.push(row.item.id);\n },\n });\n\n return { positions, ids: found };\n}\n\nfunction findIds(index: CollectionIndex, slots: SlotMap, positions: Set<number>): string[] {\n const found: string[] = [];\n\n walkVisible({\n index,\n slots,\n visit: (row) => {\n if (!positions.has(row.position)) {\n return;\n }\n\n found.push(row.item.id);\n },\n });\n\n return found;\n}\n\nexport { expandedPathsFor, findIds, findRows, walkVisible, type MatchedRows, type VisibleOrder, type WalkOptions };\n"]}
@@ -11,7 +11,11 @@ type CollectionResult = {
11
11
  collection: Collection;
12
12
  selection: ReactElement;
13
13
  };
14
- declare function useCollectionData(options: CollectionDataOptions): Collection;
14
+ type CollectionDataResult = {
15
+ collection: Collection;
16
+ model: ReactElement;
17
+ };
18
+ declare function useCollectionData(options: CollectionDataOptions): CollectionDataResult;
15
19
  declare function useCollection(options: CollectionOptions): CollectionResult;
16
20
  export { useCollection, useCollectionData };
17
21
  //# sourceMappingURL=use-collection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-collection.d.ts","sourceRoot":"","sources":["../../src/internal/use-collection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOlD,KAAK,qBAAqB,GAAG;IACzB,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,cAAc,GAAG,cAAc,CAAC;AAEjF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,iBAAS,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,UAAU,CAWrE;AAED,iBAAS,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAkBnE;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
1
+ {"version":3,"file":"use-collection.d.ts","sourceRoot":"","sources":["../../src/internal/use-collection.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOlD,KAAK,qBAAqB,GAAG;IACzB,KAAK,CAAC,EAAE,QAAQ,EAAE,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,WAAW,EAAE,GAAG,SAAS,CAAC;IACrC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAChC,CAAC;AAEF,KAAK,iBAAiB,GAAG,qBAAqB,GAAG,cAAc,GAAG,cAAc,CAAC;AAEjF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,SAAS,EAAE,YAAY,CAAC;CAC3B,CAAC;AAEF,KAAK,oBAAoB,GAAG;IACxB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,iBAAS,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CAwB/E;AAED,iBAAS,aAAa,CAAC,OAAO,EAAE,iBAAiB,GAAG,gBAAgB,CAmBnE;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC"}
@@ -1,21 +1,34 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { GtkFlattenListModel } from "@gtkx/jsx/gtk";
1
3
  import { useLayoutEffect, useMemo, useState } from "react";
2
4
  import { createCollectionIndex } from "./collection-index.js";
3
- import { createCollectionModel } from "./collection-model.js";
5
+ import { CollectionRoot, createCollectionModel } from "./collection-model.js";
4
6
  import { createCollection } from "./collection.js";
5
7
  import { useExpansion } from "./expansion.js";
6
8
  import { useSelection } from "./selection.js";
7
9
  function useCollectionData(options) {
8
10
  const { items, sections, isFlat } = options;
9
- const [collectionModel] = useState(createCollectionModel);
11
+ const [gtkModel] = useState(createCollectionModel);
12
+ const [root, setRoot] = useState(null);
13
+ const [model, setModel] = useState(null);
10
14
  const index = useMemo(() => createCollectionIndex(items, sections, isFlat === true), [items, sections, isFlat]);
11
- const collection = useMemo(() => createCollection(collectionModel, index), [collectionModel, index]);
15
+ const collection = useMemo(() => createCollection(gtkModel, index, model), [gtkModel, index, model]);
12
16
  useLayoutEffect(() => {
13
- collectionModel.sync(index);
14
- }, [collectionModel, index]);
15
- return collection;
17
+ if (root !== null && model !== null) {
18
+ gtkModel.bind(root, model);
19
+ }
20
+ return gtkModel.clear;
21
+ }, [gtkModel, root, model]);
22
+ useLayoutEffect(() => {
23
+ gtkModel.sync(index);
24
+ }, [gtkModel, index, root, model]);
25
+ return {
26
+ collection,
27
+ model: _jsx(GtkFlattenListModel, { ref: setModel, model: _jsx(CollectionRoot, { ref: setRoot }) }),
28
+ };
16
29
  }
17
30
  function useCollection(options) {
18
- const collection = useCollectionData(options);
31
+ const { collection, model } = useCollectionData(options);
19
32
  const onItemsChanged = useExpansion({
20
33
  collection,
21
34
  expandedIds: options.expandedIds,
@@ -23,6 +36,7 @@ function useCollection(options) {
23
36
  });
24
37
  const selection = useSelection({
25
38
  collection,
39
+ model,
26
40
  selectedIds: options.selectedIds,
27
41
  onSelectionChanged: options.onSelectionChanged,
28
42
  selectionMode: options.selectionMode,
@@ -1 +1 @@
1
- {"version":3,"file":"use-collection.js","sourceRoot":"","sources":["../../src/internal/use-collection.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAe9C,SAAS,iBAAiB,CAAC,OAA8B;IACrD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC5C,MAAM,CAAC,eAAe,CAAC,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC;IAErG,eAAe,CAAC,GAAG,EAAE;QACjB,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7B,OAAO,UAAU,CAAC;AACtB,CAAC;AAED,SAAS,aAAa,CAAC,OAA0B;IAC7C,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9C,MAAM,cAAc,GAAG,YAAY,CAAC;QAChC,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC7C,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,YAAY,CAAC;QAC3B,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,cAAc;KACjB,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AACrC,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import type { ReactElement } from \"react\";\nimport { useLayoutEffect, useMemo, useState } from \"react\";\nimport type { ExpansionProps, ListItem, ListSection, SelectionProps } from \"../types.js\";\nimport type { Collection } from \"./collection.js\";\nimport { createCollectionIndex } from \"./collection-index.js\";\nimport { createCollectionModel } from \"./collection-model.js\";\nimport { createCollection } from \"./collection.js\";\nimport { useExpansion } from \"./expansion.js\";\nimport { useSelection } from \"./selection.js\";\n\ntype CollectionDataOptions = {\n items?: ListItem[] | undefined;\n sections?: ListSection[] | undefined;\n isFlat?: boolean | undefined;\n};\n\ntype CollectionOptions = CollectionDataOptions & SelectionProps & ExpansionProps;\n\ntype CollectionResult = {\n collection: Collection;\n selection: ReactElement;\n};\n\nfunction useCollectionData(options: CollectionDataOptions): Collection {\n const { items, sections, isFlat } = options;\n const [collectionModel] = useState(createCollectionModel);\n const index = useMemo(() => createCollectionIndex(items, sections, isFlat === true), [items, sections, isFlat]);\n const collection = useMemo(() => createCollection(collectionModel, index), [collectionModel, index]);\n\n useLayoutEffect(() => {\n collectionModel.sync(index);\n }, [collectionModel, index]);\n\n return collection;\n}\n\nfunction useCollection(options: CollectionOptions): CollectionResult {\n const collection = useCollectionData(options);\n\n const onItemsChanged = useExpansion({\n collection,\n expandedIds: options.expandedIds,\n onExpandedChange: options.onExpandedChange,\n });\n\n const selection = useSelection({\n collection,\n selectedIds: options.selectedIds,\n onSelectionChanged: options.onSelectionChanged,\n selectionMode: options.selectionMode,\n onItemsChanged,\n });\n\n return { collection, selection };\n}\n\nexport { useCollection, useCollectionData };\n"]}
1
+ {"version":3,"file":"use-collection.js","sourceRoot":"","sources":["../../src/internal/use-collection.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAA4B,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACxG,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAoB9C,SAAS,iBAAiB,CAAC,OAA8B;IACrD,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC5C,MAAM,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,qBAAqB,CAAC,CAAC;IACnD,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAA6B,IAAI,CAAC,CAAC;IACnE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAA8B,IAAI,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,qBAAqB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IAChH,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAErG,eAAe,CAAC,GAAG,EAAE;QACjB,IAAI,IAAI,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC/B,CAAC;QAED,OAAO,QAAQ,CAAC,KAAK,CAAC;IAC1B,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAE5B,eAAe,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;IAEnC,OAAO;QACH,UAAU;QACV,KAAK,EAAE,KAAC,mBAAmB,IAAC,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAC,cAAc,IAAC,GAAG,EAAE,OAAO,GAAI,GAAI;KACzF,CAAC;AACN,CAAC;AAED,SAAS,aAAa,CAAC,OAA0B;IAC7C,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAEzD,MAAM,cAAc,GAAG,YAAY,CAAC;QAChC,UAAU;QACV,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;KAC7C,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,YAAY,CAAC;QAC3B,UAAU;QACV,KAAK;QACL,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;QAC9C,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,cAAc;KACjB,CAAC,CAAC;IAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,CAAC;AACrC,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport type { ReactElement } from \"react\";\nimport { GtkFlattenListModel } from \"@gtkx/jsx/gtk\";\nimport { useLayoutEffect, useMemo, useState } from \"react\";\nimport type { ExpansionProps, ListItem, ListSection, SelectionProps } from \"../types.js\";\nimport type { Collection } from \"./collection.js\";\nimport { createCollectionIndex } from \"./collection-index.js\";\nimport { CollectionRoot, type CollectionRootStore, createCollectionModel } from \"./collection-model.js\";\nimport { createCollection } from \"./collection.js\";\nimport { useExpansion } from \"./expansion.js\";\nimport { useSelection } from \"./selection.js\";\n\ntype CollectionDataOptions = {\n items?: ListItem[] | undefined;\n sections?: ListSection[] | undefined;\n isFlat?: boolean | undefined;\n};\n\ntype CollectionOptions = CollectionDataOptions & SelectionProps & ExpansionProps;\n\ntype CollectionResult = {\n collection: Collection;\n selection: ReactElement;\n};\n\ntype CollectionDataResult = {\n collection: Collection;\n model: ReactElement;\n};\n\nfunction useCollectionData(options: CollectionDataOptions): CollectionDataResult {\n const { items, sections, isFlat } = options;\n const [gtkModel] = useState(createCollectionModel);\n const [root, setRoot] = useState<CollectionRootStore | null>(null);\n const [model, setModel] = useState<Gtk.FlattenListModel | null>(null);\n const index = useMemo(() => createCollectionIndex(items, sections, isFlat === true), [items, sections, isFlat]);\n const collection = useMemo(() => createCollection(gtkModel, index, model), [gtkModel, index, model]);\n\n useLayoutEffect(() => {\n if (root !== null && model !== null) {\n gtkModel.bind(root, model);\n }\n\n return gtkModel.clear;\n }, [gtkModel, root, model]);\n\n useLayoutEffect(() => {\n gtkModel.sync(index);\n }, [gtkModel, index, root, model]);\n\n return {\n collection,\n model: <GtkFlattenListModel ref={setModel} model={<CollectionRoot ref={setRoot} />} />,\n };\n}\n\nfunction useCollection(options: CollectionOptions): CollectionResult {\n const { collection, model } = useCollectionData(options);\n\n const onItemsChanged = useExpansion({\n collection,\n expandedIds: options.expandedIds,\n onExpandedChange: options.onExpandedChange,\n });\n\n const selection = useSelection({\n collection,\n model,\n selectedIds: options.selectedIds,\n onSelectionChanged: options.onSelectionChanged,\n selectionMode: options.selectionMode,\n onItemsChanged,\n });\n\n return { collection, selection };\n}\n\nexport { useCollection, useCollectionData };\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"use-widget-ref.d.ts","sourceRoot":"","sources":["../../src/internal/use-widget-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIjC,QAAA,MAAM,YAAY,GAAI,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAI7F,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
1
+ {"version":3,"file":"use-widget-ref.d.ts","sourceRoot":"","sources":["../../src/internal/use-widget-ref.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAIjC,QAAA,MAAM,YAAY,GAAI,CAAC,YAAY,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,KAAG,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAI7F,CAAC;AAEF,OAAO,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type * as GObject from "@gtkx/gi/gobject";
2
+ import type { ReactNode } from "react";
3
+ import type { ListItemFactoryProps } from "./types.js";
4
+ /**
5
+ * Creates a Gtk.SignalListItemFactory that renders objects from an existing native model with React.
6
+ * Estimated dimensions keep cells stable until their content mounts.
7
+ */
8
+ declare function ListItemFactory<T extends GObject.Object>({ renderItem, estimatedItemHeight, estimatedItemWidth, }: ListItemFactoryProps<T>): ReactNode;
9
+ export { ListItemFactory };
10
+ //# sourceMappingURL=list-item-factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item-factory.d.ts","sourceRoot":"","sources":["../src/list-item-factory.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,kBAAkB,CAAC;AACjD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAGvD;;;GAGG;AACH,iBAAS,eAAe,CAAC,CAAC,SAAS,OAAO,CAAC,MAAM,EAAE,EAC/C,UAAU,EACV,mBAAwB,EACxB,kBAAuB,GAC1B,EAAE,oBAAoB,CAAC,CAAC,CAAC,GAAG,SAAS,CAUrC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
3
+ import { NativeItemPortals, useItemCells } from "./internal/cells.js";
4
+ /**
5
+ * Creates a Gtk.SignalListItemFactory that renders objects from an existing native model with React.
6
+ * Estimated dimensions keep cells stable until their content mounts.
7
+ */
8
+ function ListItemFactory({ renderItem, estimatedItemHeight = -1, estimatedItemWidth = -1, }) {
9
+ const size = { width: estimatedItemWidth, height: estimatedItemHeight };
10
+ const cells = useItemCells(size);
11
+ return (_jsxs(_Fragment, { children: [_jsx(GtkSignalListItemFactory, { ...cells.handlers }), _jsx(NativeItemPortals, { registry: cells, render: renderItem, size: size })] }));
12
+ }
13
+ export { ListItemFactory };
14
+ //# sourceMappingURL=list-item-factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"list-item-factory.js","sourceRoot":"","sources":["../src/list-item-factory.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEtE;;;GAGG;AACH,SAAS,eAAe,CAA2B,EAC/C,UAAU,EACV,mBAAmB,GAAG,CAAC,CAAC,EACxB,kBAAkB,GAAG,CAAC,CAAC,GACD;IACtB,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,kBAAkB,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IACxE,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAEjC,OAAO,CACH,8BACI,KAAC,wBAAwB,OAAK,KAAK,CAAC,QAAQ,GAAI,EAChD,KAAC,iBAAiB,IAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,GAAI,IACvE,CACN,CAAC;AACN,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type { ReactNode } from \"react\";\nimport { GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport type { ListItemFactoryProps } from \"./types.js\";\nimport { NativeItemPortals, useItemCells } from \"./internal/cells.js\";\n\n/**\n * Creates a Gtk.SignalListItemFactory that renders objects from an existing native model with React.\n * Estimated dimensions keep cells stable until their content mounts.\n */\nfunction ListItemFactory<T extends GObject.Object>({\n renderItem,\n estimatedItemHeight = -1,\n estimatedItemWidth = -1,\n}: ListItemFactoryProps<T>): ReactNode {\n const size = { width: estimatedItemWidth, height: estimatedItemHeight };\n const cells = useItemCells(size);\n\n return (\n <>\n <GtkSignalListItemFactory {...cells.handlers} />\n <NativeItemPortals registry={cells} render={renderItem} size={size} />\n </>\n );\n}\n\nexport { ListItemFactory };\n"]}
package/dist/list-view.js CHANGED
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { GtkListView, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
3
3
  import { omit } from "@gtkx/utils";
4
4
  import { ItemPortals, useItemCells, useSectionHeader } from "./internal/cells.js";
@@ -0,0 +1,9 @@
1
+ import type { TabCollection, TabCollectionOptions } from "./types.js";
2
+ /**
3
+ * Creates a collection of JSX pages whose React state survives native transfers and source-window
4
+ * closure. Call append from an event handler because it commits synchronously. Page content lives in
5
+ * independent roots: pass context-dependent values through the item or wrap the content in providers.
6
+ */
7
+ declare const createTabCollection: <T>(options: TabCollectionOptions<T>) => TabCollection<T>;
8
+ export { createTabCollection };
9
+ //# sourceMappingURL=tab-collection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-collection.d.ts","sourceRoot":"","sources":["../src/tab-collection.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA6BtE;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,GAAI,CAAC,WAAY,oBAAoB,CAAC,CAAC,CAAC,KAAG,aAAa,CAAC,CAAC,CAkFlF,CAAC;AAEF,OAAO,EAAE,mBAAmB,EAAE,CAAC"}
@@ -0,0 +1,114 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import * as Adw from "@gtkx/gi/adw";
3
+ import { AdwTabPage } from "@gtkx/jsx/adw";
4
+ import { createRoot, flushSync } from "@gtkx/react";
5
+ import { getClassType } from "@gtkx/runtime";
6
+ import { createRef, useEffect } from "react";
7
+ const ManagedTab = ({ handle, item, options, forget }) => {
8
+ const { page: pageRef, parent, getPage } = handle;
9
+ useEffect(() => () => forget(handle), [handle, forget]);
10
+ return _jsx(AdwTabPage, { ...options.pageProps(item, getPage), ref: pageRef, parent: parent });
11
+ };
12
+ const ownerOf = (page) => {
13
+ const owner = page.getChild().getAncestor(getClassType(Adw.TabView));
14
+ if (!(owner instanceof Adw.TabView))
15
+ throw new Error("The tab has no native view");
16
+ return owner;
17
+ };
18
+ /**
19
+ * Creates a collection of JSX pages whose React state survives native transfers and source-window
20
+ * closure. Call append from an event handler because it commits synchronously. Page content lives in
21
+ * independent roots: pass context-dependent values through the item or wrap the content in providers.
22
+ */
23
+ const createTabCollection = (options) => {
24
+ const handles = new Set();
25
+ const forget = (handle) => {
26
+ handles.delete(handle);
27
+ };
28
+ const find = (page) => [...handles].find((handle) => handle.page.current === page);
29
+ const render = (handle) => {
30
+ handle.root.render(_jsx(ManagedTab, { handle: handle, item: handle.item, options: options, forget: forget }));
31
+ };
32
+ const remove = (handle) => {
33
+ handles.delete(handle);
34
+ handle.root.unmount();
35
+ };
36
+ return {
37
+ append: (view, item, appendOptions = {}) => {
38
+ if (appendOptions.parent && ownerOf(appendOptions.parent) !== view) {
39
+ throw new RangeError("The parent page belongs to another tab view");
40
+ }
41
+ const pageRef = createRef();
42
+ const handle = {
43
+ root: createRoot(view),
44
+ page: pageRef,
45
+ getPage: () => pageRef.current,
46
+ parent: appendOptions.parent,
47
+ item,
48
+ };
49
+ handles.add(handle);
50
+ try {
51
+ flushSync(() => render(handle));
52
+ }
53
+ catch (error) {
54
+ remove(handle);
55
+ throw error;
56
+ }
57
+ const page = handle.page.current;
58
+ if (page === null) {
59
+ remove(handle);
60
+ throw new Error("The tab page did not render");
61
+ }
62
+ if (appendOptions.parent === undefined) {
63
+ view.reorderPage(page, page.getPinned() ? view.getNPinnedPages() - 1 : view.getNPages() - 1);
64
+ }
65
+ if (appendOptions.select !== false)
66
+ view.setSelectedPage(page);
67
+ return page;
68
+ },
69
+ get: (page) => find(page)?.item,
70
+ update: (page, item) => {
71
+ const handle = find(page);
72
+ if (handle === undefined)
73
+ throw new Error("The tab is not managed by this collection");
74
+ handle.item = item;
75
+ render(handle);
76
+ },
77
+ remove: (page) => {
78
+ const handle = find(page);
79
+ if (handle)
80
+ remove(handle);
81
+ },
82
+ removeView: (view) => {
83
+ const pages = Array.from({ length: view.getNPages() }, (_, index) => view.getNthPage(index));
84
+ for (const page of pages) {
85
+ const handle = find(page);
86
+ if (handle)
87
+ remove(handle);
88
+ }
89
+ },
90
+ transfer: (page, target, position) => {
91
+ if (find(page) === undefined)
92
+ throw new Error("The tab is not managed by this collection");
93
+ const source = ownerOf(page);
94
+ const minimum = page.getPinned() ? 0 : target.getNPinnedPages();
95
+ const maximum = page.getPinned() ? target.getNPinnedPages() : target.getNPages();
96
+ const index = position ?? maximum;
97
+ if (!Number.isInteger(index) || index < minimum || index > maximum) {
98
+ throw new RangeError("The position is outside the tab's pinned or unpinned group");
99
+ }
100
+ if (source === target) {
101
+ target.reorderPage(page, Math.min(index, maximum - 1));
102
+ }
103
+ else {
104
+ source.transferPage(page, target, index);
105
+ }
106
+ },
107
+ dispose: () => {
108
+ for (const handle of [...handles])
109
+ remove(handle);
110
+ },
111
+ };
112
+ };
113
+ export { createTabCollection };
114
+ //# sourceMappingURL=tab-collection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tab-collection.js","sourceRoot":"","sources":["../src/tab-collection.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as Adw from \"@gtkx/gi/adw\";\nimport { AdwTabPage } from \"@gtkx/jsx/adw\";\nimport { createRoot, flushSync, type Root } from \"@gtkx/react\";\nimport { getClassType } from \"@gtkx/runtime\";\nimport { createRef, type RefObject, useEffect } from \"react\";\nimport type { TabCollection, TabCollectionOptions } from \"./types.js\";\n\ntype TabHandle<T> = {\n root: Root;\n page: RefObject<Adw.TabPage | null>;\n getPage: () => Adw.TabPage | null;\n parent: Adw.TabPage | undefined;\n item: T;\n};\n\ntype ManagedTabProps<T> = {\n handle: TabHandle<T>;\n item: T;\n options: TabCollectionOptions<T>;\n forget: (handle: TabHandle<T>) => void;\n};\n\nconst ManagedTab = <T,>({ handle, item, options, forget }: ManagedTabProps<T>) => {\n const { page: pageRef, parent, getPage } = handle;\n useEffect(() => () => forget(handle), [handle, forget]);\n return <AdwTabPage {...options.pageProps(item, getPage)} ref={pageRef} parent={parent} />;\n};\n\nconst ownerOf = (page: Adw.TabPage): Adw.TabView => {\n const owner = page.getChild().getAncestor(getClassType(Adw.TabView));\n if (!(owner instanceof Adw.TabView)) throw new Error(\"The tab has no native view\");\n return owner;\n};\n\n/**\n * Creates a collection of JSX pages whose React state survives native transfers and source-window\n * closure. Call append from an event handler because it commits synchronously. Page content lives in\n * independent roots: pass context-dependent values through the item or wrap the content in providers.\n */\nconst createTabCollection = <T,>(options: TabCollectionOptions<T>): TabCollection<T> => {\n const handles = new Set<TabHandle<T>>();\n const forget = (handle: TabHandle<T>) => {\n handles.delete(handle);\n };\n const find = (page: Adw.TabPage) => [...handles].find((handle) => handle.page.current === page);\n const render = (handle: TabHandle<T>) => {\n handle.root.render(<ManagedTab handle={handle} item={handle.item} options={options} forget={forget} />);\n };\n const remove = (handle: TabHandle<T>) => {\n handles.delete(handle);\n handle.root.unmount();\n };\n\n return {\n append: (view, item, appendOptions = {}) => {\n if (appendOptions.parent && ownerOf(appendOptions.parent) !== view) {\n throw new RangeError(\"The parent page belongs to another tab view\");\n }\n const pageRef = createRef<Adw.TabPage>();\n const handle: TabHandle<T> = {\n root: createRoot(view),\n page: pageRef,\n getPage: () => pageRef.current,\n parent: appendOptions.parent,\n item,\n };\n handles.add(handle);\n try {\n flushSync(() => render(handle));\n } catch (error) {\n remove(handle);\n throw error;\n }\n const page = handle.page.current;\n if (page === null) {\n remove(handle);\n throw new Error(\"The tab page did not render\");\n }\n if (appendOptions.parent === undefined) {\n view.reorderPage(page, page.getPinned() ? view.getNPinnedPages() - 1 : view.getNPages() - 1);\n }\n if (appendOptions.select !== false) view.setSelectedPage(page);\n return page;\n },\n get: (page) => find(page)?.item,\n update: (page, item) => {\n const handle = find(page);\n if (handle === undefined) throw new Error(\"The tab is not managed by this collection\");\n handle.item = item;\n render(handle);\n },\n remove: (page) => {\n const handle = find(page);\n if (handle) remove(handle);\n },\n removeView: (view) => {\n const pages = Array.from({ length: view.getNPages() }, (_, index) => view.getNthPage(index));\n for (const page of pages) {\n const handle = find(page);\n if (handle) remove(handle);\n }\n },\n transfer: (page, target, position) => {\n if (find(page) === undefined) throw new Error(\"The tab is not managed by this collection\");\n const source = ownerOf(page);\n const minimum = page.getPinned() ? 0 : target.getNPinnedPages();\n const maximum = page.getPinned() ? target.getNPinnedPages() : target.getNPages();\n const index = position ?? maximum;\n if (!Number.isInteger(index) || index < minimum || index > maximum) {\n throw new RangeError(\"The position is outside the tab's pinned or unpinned group\");\n }\n if (source === target) {\n target.reorderPage(page, Math.min(index, maximum - 1));\n } else {\n source.transferPage(page, target, index);\n }\n },\n dispose: () => {\n for (const handle of [...handles]) remove(handle);\n },\n };\n};\n\nexport { createTabCollection };\n"]}
package/dist/toast.d.ts CHANGED
@@ -1,10 +1,8 @@
1
1
  import type { ReactNode } from "react";
2
- import type { ToastController, ToastOverlayController, ToastProviderProps } from "./types.js";
3
- /** Shares an Adw.ToastOverlay reference with the toast hooks in every descendant. */
2
+ import type { ToastController, ToastProviderProps } from "./types.js";
3
+ /** Shares an Adw.ToastOverlay reference with useToast in every descendant. */
4
4
  declare function ToastProvider(props: ToastProviderProps): ReactNode;
5
5
  /** Returns a {@link ToastController} that shows and dismisses toasts on the nearest provider's overlay. */
6
6
  declare function useToast(): ToastController;
7
- /** Returns a {@link ToastOverlayController} for the nearest provider's overlay as a whole. */
8
- declare function useToastOverlay(): ToastOverlayController;
9
- export { ToastProvider, useToast, useToastOverlay };
7
+ export { ToastProvider, useToast };
10
8
  //# sourceMappingURL=toast.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAGlD,OAAO,KAAK,EAAE,eAAe,EAAgB,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAmC5G,qFAAqF;AACrF,iBAAS,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAE3D;AAED,2GAA2G;AAC3G,iBAAS,QAAQ,IAAI,eAAe,CAiBnC;AAED,8FAA8F;AAC9F,iBAAS,eAAe,IAAI,sBAAsB,CAWjD;AAED,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"toast.d.ts","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAa,MAAM,OAAO,CAAC;AAGlD,OAAO,KAAK,EAAE,eAAe,EAAgB,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAmCpF,8EAA8E;AAC9E,iBAAS,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,SAAS,CAE3D;AAED,2GAA2G;AAC3G,iBAAS,QAAQ,IAAI,eAAe,CAiBnC;AAED,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC"}
package/dist/toast.js CHANGED
@@ -5,7 +5,7 @@ const ToastContext = createContext(null);
5
5
  const useOverlayRef = () => {
6
6
  const overlayRef = useContext(ToastContext);
7
7
  if (overlayRef === null) {
8
- throw new Error("useToast and useToastOverlay must be used within a ToastProvider");
8
+ throw new Error("useToast must be used within a ToastProvider");
9
9
  }
10
10
  return overlayRef;
11
11
  };
@@ -24,7 +24,7 @@ const buildToast = (options) => {
24
24
  }
25
25
  return toast;
26
26
  };
27
- /** Shares an Adw.ToastOverlay reference with the toast hooks in every descendant. */
27
+ /** Shares an Adw.ToastOverlay reference with useToast in every descendant. */
28
28
  function ToastProvider(props) {
29
29
  return _jsx(ToastContext.Provider, { value: props.overlayRef, children: props.children });
30
30
  }
@@ -37,19 +37,10 @@ function useToast() {
37
37
  overlayRef.current?.addToast(toast);
38
38
  return toast;
39
39
  },
40
- dismiss: (toast) => {
41
- toast.dismiss();
42
- },
43
- }), [overlayRef]);
44
- }
45
- /** Returns a {@link ToastOverlayController} for the nearest provider's overlay as a whole. */
46
- function useToastOverlay() {
47
- const overlayRef = useOverlayRef();
48
- return useMemo(() => ({
49
40
  dismissAll: () => {
50
41
  overlayRef.current?.dismissAll();
51
42
  },
52
43
  }), [overlayRef]);
53
44
  }
54
- export { ToastProvider, useToast, useToastOverlay };
45
+ export { ToastProvider, useToast };
55
46
  //# sourceMappingURL=toast.js.map
package/dist/toast.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"toast.js","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAK3D,MAAM,YAAY,GAAG,aAAa,CAAoB,IAAI,CAAC,CAAC;AAE5D,MAAM,aAAa,GAAG,GAAe,EAAE;IACnC,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACxF,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAqB,EAAa,EAAE;IACpD,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC5B,eAAe,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACtB,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YACvB,WAAW,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,qFAAqF;AACrF,SAAS,aAAa,CAAC,KAAyB;IAC5C,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,YAAG,KAAK,CAAC,QAAQ,GAAyB,CAAC;AACpG,CAAC;AAED,2GAA2G;AAC3G,SAAS,QAAQ;IACb,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,OAAO,CACV,GAAG,EAAE,CAAC,CAAC;QACH,IAAI,EAAE,CAAC,OAAsB,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YACxC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEpC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,EAAE,CAAC,KAAgB,EAAE,EAAE;YAC1B,KAAK,CAAC,OAAO,EAAE,CAAC;QACpB,CAAC;KACJ,CAAC,EACF,CAAC,UAAU,CAAC,CACf,CAAC;AACN,CAAC;AAED,8FAA8F;AAC9F,SAAS,eAAe;IACpB,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,OAAO,CACV,GAAG,EAAE,CAAC,CAAC;QACH,UAAU,EAAE,GAAG,EAAE;YACb,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QACrC,CAAC;KACJ,CAAC,EACF,CAAC,UAAU,CAAC,CACf,CAAC;AACN,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import type { ReactNode, RefObject } from \"react\";\nimport * as Adw from \"@gtkx/gi/adw\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ToastController, ToastOptions, ToastOverlayController, ToastProviderProps } from \"./types.js\";\n\ntype OverlayRef = RefObject<Adw.ToastOverlay | null>;\n\nconst ToastContext = createContext<OverlayRef | null>(null);\n\nconst useOverlayRef = (): OverlayRef => {\n const overlayRef = useContext(ToastContext);\n\n if (overlayRef === null) {\n throw new Error(\"useToast and useToastOverlay must be used within a ToastProvider\");\n }\n\n return overlayRef;\n};\n\nconst buildToast = (options: ToastOptions): Adw.Toast => {\n const { onButtonClicked, onDismissed, ...props } = options;\n const toast = new Adw.Toast(props);\n\n if (onButtonClicked != null) {\n toast.on(\"button-clicked\", () => {\n onButtonClicked(toast);\n });\n }\n\n if (onDismissed != null) {\n toast.on(\"dismissed\", () => {\n onDismissed(toast);\n });\n }\n\n return toast;\n};\n\n/** Shares an Adw.ToastOverlay reference with the toast hooks in every descendant. */\nfunction ToastProvider(props: ToastProviderProps): ReactNode {\n return <ToastContext.Provider value={props.overlayRef}>{props.children}</ToastContext.Provider>;\n}\n\n/** Returns a {@link ToastController} that shows and dismisses toasts on the nearest provider's overlay. */\nfunction useToast(): ToastController {\n const overlayRef = useOverlayRef();\n\n return useMemo<ToastController>(\n () => ({\n show: (options?: ToastOptions) => {\n const toast = buildToast(options ?? {});\n overlayRef.current?.addToast(toast);\n\n return toast;\n },\n dismiss: (toast: Adw.Toast) => {\n toast.dismiss();\n },\n }),\n [overlayRef],\n );\n}\n\n/** Returns a {@link ToastOverlayController} for the nearest provider's overlay as a whole. */\nfunction useToastOverlay(): ToastOverlayController {\n const overlayRef = useOverlayRef();\n\n return useMemo<ToastOverlayController>(\n () => ({\n dismissAll: () => {\n overlayRef.current?.dismissAll();\n },\n }),\n [overlayRef],\n );\n}\n\nexport { ToastProvider, useToast, useToastOverlay };\n"]}
1
+ {"version":3,"file":"toast.js","sourceRoot":"","sources":["../src/toast.tsx"],"names":[],"mappings":";AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAK3D,MAAM,YAAY,GAAG,aAAa,CAAoB,IAAI,CAAC,CAAC;AAE5D,MAAM,aAAa,GAAG,GAAe,EAAE;IACnC,MAAM,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAE5C,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,UAAU,CAAC;AACtB,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,CAAC,OAAqB,EAAa,EAAE;IACpD,MAAM,EAAE,eAAe,EAAE,WAAW,EAAE,GAAG,KAAK,EAAE,GAAG,OAAO,CAAC;IAC3D,MAAM,KAAK,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAEnC,IAAI,eAAe,IAAI,IAAI,EAAE,CAAC;QAC1B,KAAK,CAAC,EAAE,CAAC,gBAAgB,EAAE,GAAG,EAAE;YAC5B,eAAe,CAAC,KAAK,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC;IACP,CAAC;IAED,IAAI,WAAW,IAAI,IAAI,EAAE,CAAC;QACtB,KAAK,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YACvB,WAAW,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,8EAA8E;AAC9E,SAAS,aAAa,CAAC,KAAyB;IAC5C,OAAO,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,CAAC,UAAU,YAAG,KAAK,CAAC,QAAQ,GAAyB,CAAC;AACpG,CAAC;AAED,2GAA2G;AAC3G,SAAS,QAAQ;IACb,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,OAAO,CACV,GAAG,EAAE,CAAC,CAAC;QACH,IAAI,EAAE,CAAC,OAAsB,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;YACxC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;YAEpC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,UAAU,EAAE,GAAG,EAAE;YACb,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC;QACrC,CAAC;KACJ,CAAC,EACF,CAAC,UAAU,CAAC,CACf,CAAC;AACN,CAAC;AAED,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import type { ReactNode, RefObject } from \"react\";\nimport * as Adw from \"@gtkx/gi/adw\";\nimport { createContext, useContext, useMemo } from \"react\";\nimport type { ToastController, ToastOptions, ToastProviderProps } from \"./types.js\";\n\ntype OverlayRef = RefObject<Adw.ToastOverlay | null>;\n\nconst ToastContext = createContext<OverlayRef | null>(null);\n\nconst useOverlayRef = (): OverlayRef => {\n const overlayRef = useContext(ToastContext);\n\n if (overlayRef === null) {\n throw new Error(\"useToast must be used within a ToastProvider\");\n }\n\n return overlayRef;\n};\n\nconst buildToast = (options: ToastOptions): Adw.Toast => {\n const { onButtonClicked, onDismissed, ...props } = options;\n const toast = new Adw.Toast(props);\n\n if (onButtonClicked != null) {\n toast.on(\"button-clicked\", () => {\n onButtonClicked(toast);\n });\n }\n\n if (onDismissed != null) {\n toast.on(\"dismissed\", () => {\n onDismissed(toast);\n });\n }\n\n return toast;\n};\n\n/** Shares an Adw.ToastOverlay reference with useToast in every descendant. */\nfunction ToastProvider(props: ToastProviderProps): ReactNode {\n return <ToastContext.Provider value={props.overlayRef}>{props.children}</ToastContext.Provider>;\n}\n\n/** Returns a {@link ToastController} that shows and dismisses toasts on the nearest provider's overlay. */\nfunction useToast(): ToastController {\n const overlayRef = useOverlayRef();\n\n return useMemo<ToastController>(\n () => ({\n show: (options?: ToastOptions) => {\n const toast = buildToast(options ?? {});\n overlayRef.current?.addToast(toast);\n\n return toast;\n },\n dismissAll: () => {\n overlayRef.current?.dismissAll();\n },\n }),\n [overlayRef],\n );\n}\n\nexport { ToastProvider, useToast };\n"]}