@gtkx/components 1.0.0-rc.1 → 1.0.0-rc.2

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 (210) hide show
  1. package/dist/adw/index.d.ts +3 -0
  2. package/dist/adw/index.d.ts.map +1 -0
  3. package/dist/adw/index.js +2 -0
  4. package/dist/adw/index.js.map +1 -0
  5. package/dist/adw/toast.d.ts +10 -0
  6. package/dist/adw/toast.d.ts.map +1 -0
  7. package/dist/adw/toast.js +51 -0
  8. package/dist/adw/toast.js.map +1 -0
  9. package/dist/adw/types.d.ts +28 -0
  10. package/dist/adw/types.d.ts.map +1 -0
  11. package/dist/adw/types.js +2 -0
  12. package/dist/adw/types.js.map +1 -0
  13. package/dist/column-view.d.ts +7 -29
  14. package/dist/column-view.d.ts.map +1 -1
  15. package/dist/column-view.js +98 -70
  16. package/dist/column-view.js.map +1 -1
  17. package/dist/drop-down.d.ts +8 -27
  18. package/dist/drop-down.d.ts.map +1 -1
  19. package/dist/drop-down.js +112 -81
  20. package/dist/drop-down.js.map +1 -1
  21. package/dist/grid-view.d.ts +6 -16
  22. package/dist/grid-view.d.ts.map +1 -1
  23. package/dist/grid-view.js +25 -33
  24. package/dist/grid-view.js.map +1 -1
  25. package/dist/index.d.ts +6 -12
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +1 -6
  28. package/dist/index.js.map +1 -1
  29. package/dist/internal/cells.d.ts +50 -0
  30. package/dist/internal/cells.d.ts.map +1 -0
  31. package/dist/internal/cells.js +185 -0
  32. package/dist/internal/cells.js.map +1 -0
  33. package/dist/internal/collection-index.d.ts +21 -0
  34. package/dist/internal/collection-index.d.ts.map +1 -0
  35. package/dist/internal/collection-index.js +106 -0
  36. package/dist/internal/collection-index.js.map +1 -0
  37. package/dist/internal/collection-model.d.ts +12 -0
  38. package/dist/internal/collection-model.d.ts.map +1 -0
  39. package/dist/internal/collection-model.js +164 -0
  40. package/dist/internal/collection-model.js.map +1 -0
  41. package/dist/internal/collection.d.ts +18 -0
  42. package/dist/internal/collection.d.ts.map +1 -0
  43. package/dist/internal/collection.js +64 -0
  44. package/dist/internal/collection.js.map +1 -0
  45. package/dist/internal/expansion.d.ts +9 -0
  46. package/dist/internal/expansion.d.ts.map +1 -0
  47. package/dist/internal/expansion.js +75 -0
  48. package/dist/internal/expansion.js.map +1 -0
  49. package/dist/internal/selection.d.ts +12 -0
  50. package/dist/internal/selection.d.ts.map +1 -0
  51. package/dist/internal/selection.js +99 -0
  52. package/dist/internal/selection.js.map +1 -0
  53. package/dist/internal/use-collection.d.ts +18 -0
  54. package/dist/internal/use-collection.d.ts.map +1 -0
  55. package/dist/internal/use-collection.js +42 -0
  56. package/dist/internal/use-collection.js.map +1 -0
  57. package/dist/internal/use-widget-ref.d.ts +4 -0
  58. package/dist/internal/use-widget-ref.d.ts.map +1 -0
  59. package/dist/internal/use-widget-ref.js +8 -0
  60. package/dist/internal/use-widget-ref.js.map +1 -0
  61. package/dist/list-view.d.ts +5 -20
  62. package/dist/list-view.d.ts.map +1 -1
  63. package/dist/list-view.js +32 -53
  64. package/dist/list-view.js.map +1 -1
  65. package/dist/size-group.d.ts +8 -16
  66. package/dist/size-group.d.ts.map +1 -1
  67. package/dist/size-group.js +35 -51
  68. package/dist/size-group.js.map +1 -1
  69. package/dist/types.d.ts +97 -24
  70. package/dist/types.d.ts.map +1 -1
  71. package/dist/types.js.map +1 -1
  72. package/package.json +17 -6
  73. package/src/adw/index.ts +2 -0
  74. package/src/adw/toast.tsx +74 -0
  75. package/src/adw/types.ts +32 -0
  76. package/src/column-view.tsx +176 -160
  77. package/src/drop-down.tsx +180 -167
  78. package/src/grid-view.tsx +29 -73
  79. package/src/index.ts +18 -25
  80. package/src/internal/cells.tsx +345 -0
  81. package/src/internal/collection-index.ts +168 -0
  82. package/src/internal/collection-model.ts +246 -0
  83. package/src/internal/collection.ts +104 -0
  84. package/src/internal/expansion.ts +123 -0
  85. package/src/internal/selection.tsx +159 -0
  86. package/src/internal/use-collection.tsx +70 -0
  87. package/src/internal/use-widget-ref.ts +11 -0
  88. package/src/list-view.tsx +43 -139
  89. package/src/size-group.tsx +63 -82
  90. package/src/types.ts +155 -24
  91. package/dist/cell.d.ts +0 -30
  92. package/dist/cell.d.ts.map +0 -1
  93. package/dist/cell.js +0 -45
  94. package/dist/cell.js.map +0 -1
  95. package/dist/column-view-column.d.ts +0 -27
  96. package/dist/column-view-column.d.ts.map +0 -1
  97. package/dist/column-view-column.js +0 -30
  98. package/dist/column-view-column.js.map +0 -1
  99. package/dist/constraint-layout-apply.d.ts +0 -55
  100. package/dist/constraint-layout-apply.d.ts.map +0 -1
  101. package/dist/constraint-layout-apply.js +0 -107
  102. package/dist/constraint-layout-apply.js.map +0 -1
  103. package/dist/constraint-layout.d.ts +0 -20
  104. package/dist/constraint-layout.d.ts.map +0 -1
  105. package/dist/constraint-layout.js +0 -88
  106. package/dist/constraint-layout.js.map +0 -1
  107. package/dist/fixed.d.ts +0 -26
  108. package/dist/fixed.d.ts.map +0 -1
  109. package/dist/fixed.js +0 -40
  110. package/dist/fixed.js.map +0 -1
  111. package/dist/grid.d.ts +0 -27
  112. package/dist/grid.d.ts.map +0 -1
  113. package/dist/grid.js +0 -48
  114. package/dist/grid.js.map +0 -1
  115. package/dist/hooks/use-cell-containers.d.ts +0 -18
  116. package/dist/hooks/use-cell-containers.d.ts.map +0 -1
  117. package/dist/hooks/use-cell-containers.js +0 -67
  118. package/dist/hooks/use-cell-containers.js.map +0 -1
  119. package/dist/hooks/use-collection-model.d.ts +0 -26
  120. package/dist/hooks/use-collection-model.d.ts.map +0 -1
  121. package/dist/hooks/use-collection-model.js +0 -35
  122. package/dist/hooks/use-collection-model.js.map +0 -1
  123. package/dist/hooks/use-collection-widget.d.ts +0 -28
  124. package/dist/hooks/use-collection-widget.d.ts.map +0 -1
  125. package/dist/hooks/use-collection-widget.js +0 -21
  126. package/dist/hooks/use-collection-widget.js.map +0 -1
  127. package/dist/hooks/use-drop-down-selection.d.ts +0 -16
  128. package/dist/hooks/use-drop-down-selection.d.ts.map +0 -1
  129. package/dist/hooks/use-drop-down-selection.js +0 -35
  130. package/dist/hooks/use-drop-down-selection.js.map +0 -1
  131. package/dist/hooks/use-expansion-model.d.ts +0 -12
  132. package/dist/hooks/use-expansion-model.d.ts.map +0 -1
  133. package/dist/hooks/use-expansion-model.js +0 -71
  134. package/dist/hooks/use-expansion-model.js.map +0 -1
  135. package/dist/hooks/use-header-menu.d.ts +0 -4
  136. package/dist/hooks/use-header-menu.d.ts.map +0 -1
  137. package/dist/hooks/use-header-menu.js +0 -20
  138. package/dist/hooks/use-header-menu.js.map +0 -1
  139. package/dist/hooks/use-installed-model.d.ts +0 -4
  140. package/dist/hooks/use-installed-model.d.ts.map +0 -1
  141. package/dist/hooks/use-installed-model.js +0 -15
  142. package/dist/hooks/use-installed-model.js.map +0 -1
  143. package/dist/hooks/use-list-model.d.ts +0 -19
  144. package/dist/hooks/use-list-model.d.ts.map +0 -1
  145. package/dist/hooks/use-list-model.js +0 -97
  146. package/dist/hooks/use-list-model.js.map +0 -1
  147. package/dist/hooks/use-placed-child.d.ts +0 -18
  148. package/dist/hooks/use-placed-child.d.ts.map +0 -1
  149. package/dist/hooks/use-placed-child.js +0 -47
  150. package/dist/hooks/use-placed-child.js.map +0 -1
  151. package/dist/hooks/use-selection-model.d.ts +0 -13
  152. package/dist/hooks/use-selection-model.d.ts.map +0 -1
  153. package/dist/hooks/use-selection-model.js +0 -103
  154. package/dist/hooks/use-selection-model.js.map +0 -1
  155. package/dist/hooks/use-sort-handler.d.ts +0 -17
  156. package/dist/hooks/use-sort-handler.d.ts.map +0 -1
  157. package/dist/hooks/use-sort-handler.js +0 -87
  158. package/dist/hooks/use-sort-handler.js.map +0 -1
  159. package/dist/menu-items.d.ts +0 -5
  160. package/dist/menu-items.d.ts.map +0 -1
  161. package/dist/menu-items.js +0 -48
  162. package/dist/menu-items.js.map +0 -1
  163. package/dist/menu.d.ts +0 -14
  164. package/dist/menu.d.ts.map +0 -1
  165. package/dist/menu.js +0 -24
  166. package/dist/menu.js.map +0 -1
  167. package/dist/overlay.d.ts +0 -24
  168. package/dist/overlay.d.ts.map +0 -1
  169. package/dist/overlay.js +0 -49
  170. package/dist/overlay.js.map +0 -1
  171. package/dist/utils/cell-container-store.d.ts +0 -28
  172. package/dist/utils/cell-container-store.d.ts.map +0 -1
  173. package/dist/utils/cell-container-store.js +0 -98
  174. package/dist/utils/cell-container-store.js.map +0 -1
  175. package/dist/utils/item-models.d.ts +0 -10
  176. package/dist/utils/item-models.d.ts.map +0 -1
  177. package/dist/utils/item-models.js +0 -82
  178. package/dist/utils/item-models.js.map +0 -1
  179. package/dist/utils/item-resolver.d.ts +0 -25
  180. package/dist/utils/item-resolver.d.ts.map +0 -1
  181. package/dist/utils/item-resolver.js +0 -102
  182. package/dist/utils/item-resolver.js.map +0 -1
  183. package/dist/utils/list-item-flatten.d.ts +0 -24
  184. package/dist/utils/list-item-flatten.d.ts.map +0 -1
  185. package/dist/utils/list-item-flatten.js +0 -68
  186. package/dist/utils/list-item-flatten.js.map +0 -1
  187. package/src/cell.tsx +0 -144
  188. package/src/column-view-column.tsx +0 -82
  189. package/src/constraint-layout-apply.ts +0 -173
  190. package/src/constraint-layout.tsx +0 -135
  191. package/src/fixed.tsx +0 -86
  192. package/src/grid.tsx +0 -88
  193. package/src/hooks/use-cell-containers.ts +0 -93
  194. package/src/hooks/use-collection-model.ts +0 -60
  195. package/src/hooks/use-collection-widget.ts +0 -47
  196. package/src/hooks/use-drop-down-selection.ts +0 -52
  197. package/src/hooks/use-expansion-model.ts +0 -82
  198. package/src/hooks/use-header-menu.ts +0 -34
  199. package/src/hooks/use-installed-model.ts +0 -20
  200. package/src/hooks/use-list-model.ts +0 -161
  201. package/src/hooks/use-placed-child.ts +0 -79
  202. package/src/hooks/use-selection-model.ts +0 -114
  203. package/src/hooks/use-sort-handler.ts +0 -107
  204. package/src/menu-items.ts +0 -48
  205. package/src/menu.tsx +0 -32
  206. package/src/overlay.tsx +0 -88
  207. package/src/utils/cell-container-store.ts +0 -114
  208. package/src/utils/item-models.ts +0 -113
  209. package/src/utils/item-resolver.ts +0 -138
  210. package/src/utils/list-item-flatten.ts +0 -90
package/dist/drop-down.js CHANGED
@@ -1,89 +1,120 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { GtkDropDown, GtkLabel } from "@gtkx/jsx/gtk";
3
- import { useMergeRefs } from "@gtkx/react/internal";
4
- import { useCallback, useRef, useState } from "react";
5
- import { CellRenderHost, HeaderRenderHost, itemRenderer } from "./cell.js";
6
- import { makeFactoryInstaller, useCellContainers } from "./hooks/use-cell-containers.js";
7
- import { useDropDownSelection } from "./hooks/use-drop-down-selection.js";
8
- import { useInstalledModel } from "./hooks/use-installed-model.js";
9
- import { useListModel } from "./hooks/use-list-model.js";
10
- const itemFactoryInstaller = makeFactoryInstaller((widget, factory) => widget.setFactory(factory));
11
- const listFactoryInstaller = makeFactoryInstaller((widget, factory) => widget.setListFactory(factory));
12
- const headerFactoryInstaller = makeFactoryInstaller((widget, factory) => widget.setHeaderFactory(factory));
13
- const defaultRenderer = (value) => {
14
- if (value === undefined || value === null)
15
- return null;
16
- return _jsx(GtkLabel, { children: String(value) });
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { GtkDropDown, GtkLabel, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
3
+ import { useSignal } from "@gtkx/react";
4
+ import { omit } from "@gtkx/utils";
5
+ import { useEffectEvent, useLayoutEffect, useRef } from "react";
6
+ import { HeaderPortals, ItemPortals, useHeaderCells, useItemCells } from "./internal/cells.js";
7
+ import { useCollectionData } from "./internal/use-collection.js";
8
+ import { useWidgetRef } from "./internal/use-widget-ref.js";
9
+ const DROP_DOWN_PROPS = [
10
+ "component",
11
+ "items",
12
+ "sections",
13
+ "selectedId",
14
+ "onSelectionChanged",
15
+ "renderItem",
16
+ "renderListItem",
17
+ "renderHeader",
18
+ "ref",
19
+ ];
20
+ /**
21
+ * Renders a drop-down backed by a collection model, with customizable renderers for the
22
+ * collapsed display, popup rows, and popup section headers, and controlled selection.
23
+ * The backing widget defaults to GtkDropDown and is swappable through `component`.
24
+ */
25
+ const DropDown = DropDownImpl;
26
+ const describeValue = (value) => {
27
+ if (typeof value === "string") {
28
+ return value;
29
+ }
30
+ try {
31
+ return JSON.stringify(value);
32
+ }
33
+ catch {
34
+ return String(value);
35
+ }
36
+ };
37
+ const defaultItemContent = (value) => value == null ? null : _jsx(GtkLabel, { children: describeValue(value) });
38
+ const defaultRenderItem = ({ item }) => defaultItemContent(item);
39
+ const faceRenderer = (props) => props.renderItem ?? defaultRenderItem;
40
+ const listRenderer = (props) => props.renderListItem ?? props.renderItem ?? defaultRenderItem;
41
+ const resolvePosition = (widget, collection, selectedId) => {
42
+ const requested = selectedId == null ? -1 : collection.positionFor(selectedId);
43
+ return requested >= 0 ? requested : widget.getSelected();
44
+ };
45
+ const updateKnownSelection = (tracker, effectiveId, selectedId) => {
46
+ const { known, onSelectionChanged } = tracker;
47
+ const expectedId = selectedId ?? known.current;
48
+ const isNew = effectiveId !== known.current;
49
+ known.current = effectiveId;
50
+ if (expectedId !== null && effectiveId !== expectedId && isNew) {
51
+ onSelectionChanged?.(effectiveId);
52
+ }
53
+ };
54
+ const reportKnownSelection = (tracker, id) => {
55
+ const { known, onSelectionChanged } = tracker;
56
+ if (id === null || id === known.current) {
57
+ return;
58
+ }
59
+ known.current = id;
60
+ onSelectionChanged?.(id);
17
61
  };
18
- const toItemRenderer = (renderItem) => {
19
- if (typeof renderItem !== "function")
20
- return defaultRenderer;
21
- return itemRenderer(renderItem);
62
+ const reportSelectedNotify = (options, tracker, applying) => {
63
+ const { widget, collection } = options;
64
+ if (widget === null || applying.current) {
65
+ return;
66
+ }
67
+ reportKnownSelection(tracker, collection.idAt(widget.getSelected()));
22
68
  };
23
- const toListRenderer = (renderListItem, renderItem) => {
24
- if (typeof renderListItem === "function")
25
- return itemRenderer(renderListItem);
26
- return toItemRenderer(renderItem);
69
+ const applySelectedPosition = (widget, position, applying) => {
70
+ applying.current = true;
71
+ try {
72
+ widget.selected = position;
73
+ }
74
+ finally {
75
+ applying.current = false;
76
+ }
27
77
  };
28
- const createSelectionResolver = (resolver, selectedPosition) => ({
29
- positionOfId: (id) => resolver.positionOfId(id),
30
- idOf: (position) => resolver.idOf(position),
31
- resolve: (_position, treeRow) => resolver.resolve(selectedPosition, treeRow),
32
- });
33
- const useDropDownWiring = (props) => {
34
- const widgetRef = useRef(null);
35
- const [widget, setWidget] = useState(null);
36
- const captureWidget = useCallback((value) => {
37
- widgetRef.current = value;
38
- setWidget(value);
39
- }, []);
40
- const setRef = useMergeRefs(props.ref, captureWidget);
41
- const listModel = useListModel({ items: props.items, sections: props.sections });
42
- const useHeader = typeof props.renderHeader === "function";
43
- const selectionStore = useCellContainers({ object: widgetRef, installer: itemFactoryInstaller });
44
- const listStore = useCellContainers({ object: widgetRef, installer: listFactoryInstaller });
45
- const headerStore = useCellContainers({
46
- object: useHeader ? widgetRef : null,
47
- installer: headerFactoryInstaller,
78
+ const useDropDownSelection = (options) => {
79
+ const { widget, collection, applying } = options;
80
+ const { selectedId } = options.props;
81
+ const known = useRef(null);
82
+ const syncKnownSelection = useEffectEvent((position) => {
83
+ const effectiveId = collection.idAt(position);
84
+ if (effectiveId === null) {
85
+ known.current = null;
86
+ return;
87
+ }
88
+ const { onSelectionChanged } = options.props;
89
+ updateKnownSelection({ known, onSelectionChanged }, effectiveId, selectedId);
48
90
  });
49
- useInstalledModel(widgetRef, listModel.model, (widget, value) => widget.setModel(value));
50
- const selectedPosition = useDropDownSelection({
51
- widget,
52
- resolver: listModel.resolver,
53
- selectedId: props.selectedId,
54
- onSelectionChanged: props.onSelectionChanged,
91
+ useLayoutEffect(() => {
92
+ if (widget === null) {
93
+ return;
94
+ }
95
+ const position = resolvePosition(widget, collection, selectedId);
96
+ applySelectedPosition(widget, position, applying);
97
+ syncKnownSelection(position);
98
+ }, [widget, collection, selectedId, applying]);
99
+ useSignal(widget, "notify::selected", () => {
100
+ reportSelectedNotify(options, { known, onSelectionChanged: options.props.onSelectionChanged }, applying);
55
101
  });
56
- const controlledPosition = props.selectedId === undefined || props.selectedId === null
57
- ? -1
58
- : listModel.resolver.positionOfId(props.selectedId);
59
- const selectionPosition = controlledPosition >= 0 ? controlledPosition : selectedPosition < 0 ? 0 : selectedPosition;
60
- return {
61
- setRef,
62
- resolver: listModel.resolver,
63
- selectionResolver: createSelectionResolver(listModel.resolver, selectionPosition),
64
- headerResolver: listModel.headerResolver,
65
- selectionStore,
66
- listStore,
67
- headerStore,
68
- useHeader,
69
- };
70
102
  };
71
- /**
72
- * Renders a drop-down widget (Gtk.DropDown by default, or the widget given as `component`) backed by a
73
- * collection model, with customizable rendering for the selected item, the popup list rows, and section
74
- * headers.
75
- */
76
- export const DropDown = (props) => {
77
- const { component, ref, items, sections, renderItem, renderListItem, renderHeader, selectedId, onSelectionChanged, ...intrinsicProps } = props;
103
+ function DropDownImpl(props) {
104
+ const { component, items, sections, renderListItem, renderHeader, ref } = props;
105
+ const rest = omit(props, DROP_DOWN_PROPS);
106
+ const [widget, refCallback] = useWidgetRef(ref);
107
+ const applying = useRef(false);
108
+ const collection = useCollectionData({ items, sections, applying });
109
+ const faceCells = useItemCells({ width: -1, height: -1 });
110
+ const listCells = useItemCells({ width: -1, height: -1 });
111
+ const headerCells = useHeaderCells({ width: -1, height: -1 });
112
+ useDropDownSelection({ widget, collection, applying, props });
78
113
  const Component = component ?? GtkDropDown;
79
- const wiring = useDropDownWiring({
80
- ref,
81
- items,
82
- sections,
83
- selectedId,
84
- onSelectionChanged,
85
- renderHeader,
86
- });
87
- return (_jsxs(_Fragment, { children: [_jsx(Component, { ...intrinsicProps, ref: wiring.setRef }), _jsx(CellRenderHost, { store: wiring.selectionStore, resolver: wiring.selectionResolver, render: toItemRenderer(renderItem) }), _jsx(CellRenderHost, { store: wiring.listStore, resolver: wiring.resolver, render: toListRenderer(renderListItem, renderItem) }), _jsx(HeaderRenderHost, { useHeader: wiring.useHeader, store: wiring.headerStore, resolver: wiring.headerResolver, renderHeader: renderHeader })] }));
88
- };
114
+ const hasHeader = typeof renderHeader === "function";
115
+ return (_jsxs(_Fragment, { children: [_jsx(Component, { ref: refCallback, model: collection.model, factory: _jsx(GtkSignalListItemFactory, { ...faceCells.handlers }), ...(renderListItem != null && {
116
+ listFactory: _jsx(GtkSignalListItemFactory, { ...listCells.handlers }),
117
+ }), ...(hasHeader && { headerFactory: _jsx(GtkSignalListItemFactory, { ...headerCells.handlers }) }), ...rest }), _jsx(ItemPortals, { store: faceCells, render: faceRenderer(props), collection: collection }), renderListItem != null && (_jsx(ItemPortals, { store: listCells, render: listRenderer(props), collection: collection })), hasHeader && _jsx(HeaderPortals, { store: headerCells, render: renderHeader, collection: collection })] }));
118
+ }
119
+ export { DropDown };
89
120
  //# sourceMappingURL=drop-down.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"drop-down.js","sourceRoot":"","sources":["../src/drop-down.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { GtkDropDown, GtkLabel } from \"@gtkx/jsx/gtk\";\nimport { useMergeRefs } from \"@gtkx/react/internal\";\nimport { type ElementType, type ReactNode, type Ref, useCallback, useRef, useState } from \"react\";\nimport { type CellRenderer, CellRenderHost, HeaderRenderHost, itemRenderer } from \"./cell.js\";\nimport { makeFactoryInstaller, useCellContainers } from \"./hooks/use-cell-containers.js\";\nimport { useDropDownSelection } from \"./hooks/use-drop-down-selection.js\";\nimport { useInstalledModel } from \"./hooks/use-installed-model.js\";\nimport { useListModel } from \"./hooks/use-list-model.js\";\nimport type { ItemNode, RenderItemProps, SectionNode, WidgetProps } from \"./types.js\";\nimport type { CellContainerStore } from \"./utils/cell-container-store.js\";\nimport type { ItemResolver } from \"./utils/item-resolver.js\";\n\nexport type DropDownItemRenderer<T> = (props: RenderItemProps<T>) => ReactNode;\n\nconst itemFactoryInstaller = makeFactoryInstaller<Gtk.DropDown>((widget, factory) => widget.setFactory(factory));\n\nconst listFactoryInstaller = makeFactoryInstaller<Gtk.DropDown>((widget, factory) => widget.setListFactory(factory));\n\nconst headerFactoryInstaller = makeFactoryInstaller<Gtk.DropDown>((widget, factory) =>\n widget.setHeaderFactory(factory),\n);\n\nconst defaultRenderer: CellRenderer<unknown, unknown> = (value) => {\n if (value === undefined || value === null) return null;\n return <GtkLabel>{String(value)}</GtkLabel>;\n};\n\nconst toItemRenderer = <T, S>(renderItem: DropDownItemRenderer<T> | null | undefined): CellRenderer<T, S> => {\n if (typeof renderItem !== \"function\") return defaultRenderer as CellRenderer<T, S>;\n return itemRenderer<T, S>(renderItem);\n};\n\nconst toListRenderer = <T, S>(\n renderListItem: DropDownItemRenderer<T> | null | undefined,\n renderItem: DropDownItemRenderer<T> | null | undefined,\n): CellRenderer<T, S> => {\n if (typeof renderListItem === \"function\") return itemRenderer<T, S>(renderListItem);\n return toItemRenderer<T, S>(renderItem);\n};\n\nconst createSelectionResolver = <T, S>(resolver: ItemResolver<T, S>, selectedPosition: number): ItemResolver<T, S> => ({\n positionOfId: (id) => resolver.positionOfId(id),\n idOf: (position) => resolver.idOf(position),\n resolve: (_position, treeRow) => resolver.resolve(selectedPosition, treeRow),\n});\n\n/** Declarative props for {@link DropDown}'s backing collection and cell rendering. */\nexport type DropDownDeclarativeProps<T = unknown, S = unknown> = {\n items?: ItemNode<T>[] | undefined;\n sections?: SectionNode<S, T>[] | undefined;\n /** Id of the currently selected item, making the selection controlled. */\n selectedId?: string | null | undefined;\n onSelectionChanged?: ((id: string) => void) | null | undefined;\n renderItem?: DropDownItemRenderer<T> | null | undefined;\n /** Renderer for items in the open popup list, falling back to renderItem when omitted. */\n renderListItem?: DropDownItemRenderer<T> | null | undefined;\n /** Renderer for section headers in the popup list. */\n renderHeader?: ((info: { section: S }) => ReactNode) | null | undefined;\n};\n\n/**\n * Props for {@link DropDown}. The backing widget is chosen through the `component` prop, defaulting to\n * GtkDropDown, and its own props combine with {@link DropDownDeclarativeProps}.\n */\nexport type DropDownProps<T = unknown, S = unknown, C extends ElementType = typeof GtkDropDown> = WidgetProps<\n C,\n DropDownDeclarativeProps<T, S>,\n \"model\" | \"factory\" | \"listFactory\" | \"headerFactory\"\n>;\n\ninterface NormalizedDropDownProps<T, S> {\n ref: Ref<Gtk.DropDown | null> | undefined;\n items: ItemNode<T>[] | undefined;\n sections: SectionNode<S, T>[] | undefined;\n selectedId: string | null | undefined;\n onSelectionChanged: ((id: string) => void) | null | undefined;\n renderHeader: ((info: { section: S }) => ReactNode) | null | undefined;\n}\n\ninterface DropDownWiring<T, S> {\n setRef: (value: Gtk.DropDown | null) => void;\n resolver: ItemResolver<T, S>;\n selectionResolver: ItemResolver<T, S>;\n headerResolver: ItemResolver<T, S>;\n selectionStore: CellContainerStore;\n listStore: CellContainerStore;\n headerStore: CellContainerStore;\n useHeader: boolean;\n}\n\nconst useDropDownWiring = <T, S>(props: NormalizedDropDownProps<T, S>): DropDownWiring<T, S> => {\n const widgetRef = useRef<Gtk.DropDown | null>(null);\n const [widget, setWidget] = useState<Gtk.DropDown | null>(null);\n const captureWidget = useCallback((value: Gtk.DropDown | null) => {\n widgetRef.current = value;\n setWidget(value);\n }, []);\n const setRef = useMergeRefs<Gtk.DropDown>(props.ref, captureWidget);\n\n const listModel = useListModel<T, S>({ items: props.items, sections: props.sections });\n\n const useHeader = typeof props.renderHeader === \"function\";\n\n const selectionStore = useCellContainers<Gtk.DropDown>({ object: widgetRef, installer: itemFactoryInstaller });\n const listStore = useCellContainers<Gtk.DropDown>({ object: widgetRef, installer: listFactoryInstaller });\n const headerStore = useCellContainers<Gtk.DropDown>({\n object: useHeader ? widgetRef : null,\n installer: headerFactoryInstaller,\n });\n\n useInstalledModel(widgetRef, listModel.model, (widget, value) => widget.setModel(value));\n\n const selectedPosition = useDropDownSelection<T, S>({\n widget,\n resolver: listModel.resolver,\n selectedId: props.selectedId,\n onSelectionChanged: props.onSelectionChanged,\n });\n\n const controlledPosition =\n props.selectedId === undefined || props.selectedId === null\n ? -1\n : listModel.resolver.positionOfId(props.selectedId);\n const selectionPosition =\n controlledPosition >= 0 ? controlledPosition : selectedPosition < 0 ? 0 : selectedPosition;\n\n return {\n setRef,\n resolver: listModel.resolver,\n selectionResolver: createSelectionResolver(listModel.resolver, selectionPosition),\n headerResolver: listModel.headerResolver,\n selectionStore,\n listStore,\n headerStore,\n useHeader,\n };\n};\n\n/**\n * Renders a drop-down widget (Gtk.DropDown by default, or the widget given as `component`) backed by a\n * collection model, with customizable rendering for the selected item, the popup list rows, and section\n * headers.\n */\nexport const DropDown = <T = unknown, S = unknown, C extends ElementType = typeof GtkDropDown>(\n props: DropDownProps<T, S, C>,\n): ReactNode => {\n const {\n component,\n ref,\n items,\n sections,\n renderItem,\n renderListItem,\n renderHeader,\n selectedId,\n onSelectionChanged,\n ...intrinsicProps\n } = props;\n const Component: ElementType = component ?? GtkDropDown;\n\n const wiring = useDropDownWiring<T, S>({\n ref,\n items,\n sections,\n selectedId,\n onSelectionChanged,\n renderHeader,\n });\n\n return (\n <>\n <Component {...intrinsicProps} ref={wiring.setRef} />\n <CellRenderHost\n store={wiring.selectionStore}\n resolver={wiring.selectionResolver}\n render={toItemRenderer<T, S>(renderItem)}\n />\n <CellRenderHost\n store={wiring.listStore}\n resolver={wiring.resolver}\n render={toListRenderer<T, S>(renderListItem, renderItem)}\n />\n <HeaderRenderHost\n useHeader={wiring.useHeader}\n store={wiring.headerStore}\n resolver={wiring.headerResolver}\n renderHeader={renderHeader}\n />\n </>\n );\n};\n"]}
1
+ {"version":3,"file":"drop-down.js","sourceRoot":"","sources":["../src/drop-down.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type { ElementType, ReactNode, Ref, RefObject } from \"react\";\nimport { GtkDropDown, GtkLabel, GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport { useSignal } from \"@gtkx/react\";\nimport { omit } from \"@gtkx/utils\";\nimport { useEffectEvent, useLayoutEffect, useRef } from \"react\";\nimport type { Collection } from \"./internal/collection.js\";\nimport type { DropDownProps, ItemRenderer, RenderItemArgs } from \"./types.js\";\nimport { HeaderPortals, ItemPortals, useHeaderCells, useItemCells } from \"./internal/cells.js\";\nimport { useCollectionData } from \"./internal/use-collection.js\";\nimport { useWidgetRef } from \"./internal/use-widget-ref.js\";\n\ntype SelectableWidget = GObject.Object & { getSelected: () => number; selected: number };\n\ntype DropDownRuntimeProps = DropDownProps & {\n component?: ElementType | undefined;\n ref?: Ref<SelectableWidget | null> | undefined;\n} & Record<string, unknown>;\n\ntype SelectionOptions = {\n widget: SelectableWidget | null;\n collection: Collection;\n applying: RefObject<boolean>;\n props: DropDownRuntimeProps;\n};\n\ntype KnownSelection = {\n known: { current: string | null };\n onSelectionChanged: ((id: string) => void) | null | undefined;\n};\n\ntype DropDownComponent = <T = unknown, S = unknown, C extends ElementType = typeof GtkDropDown>(\n props: DropDownProps<T, S, C>,\n) => ReactNode;\n\nconst DROP_DOWN_PROPS: string[] = [\n \"component\",\n \"items\",\n \"sections\",\n \"selectedId\",\n \"onSelectionChanged\",\n \"renderItem\",\n \"renderListItem\",\n \"renderHeader\",\n \"ref\",\n];\n\n/**\n * Renders a drop-down backed by a collection model, with customizable renderers for the\n * collapsed display, popup rows, and popup section headers, and controlled selection.\n * The backing widget defaults to GtkDropDown and is swappable through `component`.\n */\nconst DropDown: DropDownComponent = DropDownImpl as DropDownComponent;\n\nconst describeValue = (value: unknown): string => {\n if (typeof value === \"string\") {\n return value;\n }\n\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n};\n\nconst defaultItemContent = (value: unknown): ReactNode =>\n value == null ? null : <GtkLabel>{describeValue(value)}</GtkLabel>;\n\nconst defaultRenderItem = ({ item }: RenderItemArgs<unknown>): ReactNode => defaultItemContent(item);\n\nconst faceRenderer = (props: DropDownRuntimeProps): ItemRenderer<never> =>\n props.renderItem ?? defaultRenderItem;\n\nconst listRenderer = (props: DropDownRuntimeProps): ItemRenderer<never> =>\n props.renderListItem ?? props.renderItem ?? defaultRenderItem;\n\nconst resolvePosition = (\n widget: SelectableWidget,\n collection: Collection,\n selectedId: string | null | undefined,\n): number => {\n const requested = selectedId == null ? -1 : collection.positionFor(selectedId);\n\n return requested >= 0 ? requested : widget.getSelected();\n};\n\nconst updateKnownSelection = (\n tracker: KnownSelection,\n effectiveId: string,\n selectedId: string | null | undefined,\n): void => {\n const { known, onSelectionChanged } = tracker;\n const expectedId = selectedId ?? known.current;\n const isNew = effectiveId !== known.current;\n known.current = effectiveId;\n\n if (expectedId !== null && effectiveId !== expectedId && isNew) {\n onSelectionChanged?.(effectiveId);\n }\n};\n\nconst reportKnownSelection = (tracker: KnownSelection, id: string | null): void => {\n const { known, onSelectionChanged } = tracker;\n\n if (id === null || id === known.current) {\n return;\n }\n\n known.current = id;\n onSelectionChanged?.(id);\n};\n\nconst reportSelectedNotify = (\n options: SelectionOptions,\n tracker: KnownSelection,\n applying: RefObject<boolean>,\n): void => {\n const { widget, collection } = options;\n\n if (widget === null || applying.current) {\n return;\n }\n\n reportKnownSelection(tracker, collection.idAt(widget.getSelected()));\n};\n\nconst applySelectedPosition = (widget: SelectableWidget, position: number, applying: RefObject<boolean>): void => {\n applying.current = true;\n\n try {\n widget.selected = position;\n } finally {\n applying.current = false;\n }\n};\n\nconst useDropDownSelection = (options: SelectionOptions): void => {\n const { widget, collection, applying } = options;\n const { selectedId } = options.props;\n const known = useRef<string | null>(null);\n\n const syncKnownSelection = useEffectEvent((position: number): void => {\n const effectiveId = collection.idAt(position);\n\n if (effectiveId === null) {\n known.current = null;\n\n return;\n }\n\n const { onSelectionChanged } = options.props;\n updateKnownSelection({ known, onSelectionChanged }, effectiveId, selectedId);\n });\n\n useLayoutEffect(() => {\n if (widget === null) {\n return;\n }\n\n const position = resolvePosition(widget, collection, selectedId);\n applySelectedPosition(widget, position, applying);\n syncKnownSelection(position);\n }, [widget, collection, selectedId, applying]);\n\n useSignal(widget, \"notify::selected\", (): void => {\n reportSelectedNotify(options, { known, onSelectionChanged: options.props.onSelectionChanged }, applying);\n });\n};\n\nfunction DropDownImpl(props: DropDownRuntimeProps): ReactNode {\n const { component, items, sections, renderListItem, renderHeader, ref } = props;\n const rest = omit(props, DROP_DOWN_PROPS);\n const [widget, refCallback] = useWidgetRef<SelectableWidget>(ref);\n const applying = useRef(false);\n const collection = useCollectionData({ items, sections, applying });\n const faceCells = useItemCells({ width: -1, height: -1 });\n const listCells = useItemCells({ width: -1, height: -1 });\n const headerCells = useHeaderCells({ width: -1, height: -1 });\n useDropDownSelection({ widget, collection, applying, props });\n const Component = component ?? GtkDropDown;\n const hasHeader = typeof renderHeader === \"function\";\n\n return (\n <>\n <Component\n ref={refCallback}\n model={collection.model}\n factory={<GtkSignalListItemFactory {...faceCells.handlers} />}\n {...(renderListItem != null && {\n listFactory: <GtkSignalListItemFactory {...listCells.handlers} />,\n })}\n {...(hasHeader && { headerFactory: <GtkSignalListItemFactory {...headerCells.handlers} /> })}\n {...rest}\n />\n <ItemPortals store={faceCells} render={faceRenderer(props)} collection={collection} />\n {renderListItem != null && (\n <ItemPortals store={listCells} render={listRenderer(props)} collection={collection} />\n )}\n {hasHeader && <HeaderPortals store={headerCells} render={renderHeader} collection={collection} />}\n </>\n );\n}\n\nexport { DropDown };\n"]}
@@ -1,19 +1,9 @@
1
- import { type GtkGridViewProps } from "@gtkx/jsx/gtk";
2
- import { type ReactNode } from "react";
3
- import type { CollectionItemSizeProps, ControlledSelectionProps, ItemNode, RenderItemProps } from "./types.js";
4
- export type GridViewDeclarativeProps<T = unknown> = CollectionItemSizeProps & ControlledSelectionProps & {
5
- items?: ItemNode<T>[] | undefined;
6
- renderItem: (props: RenderItemProps<T>) => ReactNode;
7
- };
1
+ import type { ReactNode } from "react";
2
+ import type { GridViewProps } from "./types.js";
8
3
  /**
9
- * Props for {@link GridView}. Combines the underlying Gtk.GridView props with
10
- * declarative collection props: items, a per-cell renderItem, controlled selection,
11
- * and estimated item sizing.
4
+ * Renders a Gtk.GridView of uniform cells from declarative items, with per-cell
5
+ * rendering, controlled selection, and estimated item sizing.
12
6
  */
13
- export type GridViewProps<T = unknown> = Omit<GtkGridViewProps, "model" | "factory" | keyof GridViewDeclarativeProps<T>> & GridViewDeclarativeProps<T>;
14
- /**
15
- * Renders a Gtk.GridView: a scrollable grid of uniformly sized cells backed by a
16
- * collection model, with each cell drawn by renderItem.
17
- */
18
- export declare const GridView: <T = unknown>(props: GridViewProps<T>) => ReactNode;
7
+ declare function GridView<T = unknown>(props: GridViewProps<T>): ReactNode;
8
+ export { GridView };
19
9
  //# sourceMappingURL=grid-view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"grid-view.d.ts","sourceRoot":"","sources":["../src/grid-view.tsx"],"names":[],"mappings":"AACA,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAAE,KAAK,SAAS,EAAoB,MAAM,OAAO,CAAC;AAKzD,OAAO,KAAK,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAI/G,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,OAAO,IAAI,uBAAuB,GACvE,wBAAwB,GAAG;IACvB,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;IAClC,UAAU,EAAE,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;CACxD,CAAC;AAEN;;;;GAIG;AACH,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,OAAO,IAAI,IAAI,CACzC,gBAAgB,EAChB,OAAO,GAAG,SAAS,GAAG,MAAM,wBAAwB,CAAC,CAAC,CAAC,CAC1D,GACG,wBAAwB,CAAC,CAAC,CAAC,CAAC;AAEhC;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,GAAG,OAAO,SAAS,aAAa,CAAC,CAAC,CAAC,KAAG,SA+C/D,CAAC"}
1
+ {"version":3,"file":"grid-view.d.ts","sourceRoot":"","sources":["../src/grid-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAchD;;;GAGG;AACH,iBAAS,QAAQ,CAAC,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,SAAS,CAajE;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
package/dist/grid-view.js CHANGED
@@ -1,36 +1,28 @@
1
- import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { GtkGridView } from "@gtkx/jsx/gtk";
3
- import { useMergeRefs } from "@gtkx/react/internal";
4
- import { useRef } from "react";
5
- import { CellRenderHost, itemRenderer } from "./cell.js";
6
- import { makeFactoryInstaller, useCellContainers } from "./hooks/use-cell-containers.js";
7
- import { useCollectionModel } from "./hooks/use-collection-model.js";
8
- import { useInstalledModel } from "./hooks/use-installed-model.js";
9
- const factoryInstaller = makeFactoryInstaller((widget, factory) => widget.setFactory(factory));
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { GtkGridView, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
3
+ import { omit } from "@gtkx/utils";
4
+ import { ItemPortals, useItemCells } from "./internal/cells.js";
5
+ import { useCollection } from "./internal/use-collection.js";
6
+ const GRID_VIEW_PROPS = [
7
+ "items",
8
+ "renderItem",
9
+ "selectedIds",
10
+ "onSelectionChanged",
11
+ "selectionMode",
12
+ "estimatedItemHeight",
13
+ "estimatedItemWidth",
14
+ ];
10
15
  /**
11
- * Renders a Gtk.GridView: a scrollable grid of uniformly sized cells backed by a
12
- * collection model, with each cell drawn by renderItem.
16
+ * Renders a Gtk.GridView of uniform cells from declarative items, with per-cell
17
+ * rendering, controlled selection, and estimated item sizing.
13
18
  */
14
- export const GridView = (props) => {
15
- const { ref, items, renderItem, selectedIds, selectionMode, onSelectionChanged, estimatedItemHeight, estimatedItemWidth, ...intrinsicProps } = props;
16
- const cellRenderer = itemRenderer(renderItem);
17
- const widgetRef = useRef(null);
18
- const setRef = useMergeRefs(ref, widgetRef);
19
- const collection = useCollectionModel({
20
- items,
21
- sections: undefined,
22
- selectionMode,
23
- selectedIds,
24
- onSelectionChanged,
25
- renderHeader: undefined,
26
- });
27
- const itemStore = useCellContainers({
28
- object: widgetRef,
29
- installer: factoryInstaller,
30
- estimatedHeight: estimatedItemHeight,
31
- estimatedWidth: estimatedItemWidth,
32
- });
33
- useInstalledModel(widgetRef, collection.installedModel, (widget, value) => widget.setModel(value));
34
- return (_jsxs(_Fragment, { children: [_jsx(GtkGridView, { ...intrinsicProps, ref: setRef }), _jsx(CellRenderHost, { store: itemStore, resolver: collection.resolver, render: cellRenderer })] }));
35
- };
19
+ function GridView(props) {
20
+ const { renderItem, estimatedItemHeight, estimatedItemWidth } = props;
21
+ const rest = omit(props, GRID_VIEW_PROPS);
22
+ const size = { width: estimatedItemWidth ?? -1, height: estimatedItemHeight ?? -1 };
23
+ const { collection, selection } = useCollection({ ...props, flat: true });
24
+ const itemCells = useItemCells(size);
25
+ return (_jsxs(_Fragment, { children: [_jsx(GtkGridView, { model: selection, factory: _jsx(GtkSignalListItemFactory, { ...itemCells.handlers }), ...rest }), _jsx(ItemPortals, { store: itemCells, render: renderItem, collection: collection })] }));
26
+ }
27
+ export { GridView };
36
28
  //# sourceMappingURL=grid-view.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../src/grid-view.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAA4B,MAAM,EAAE,MAAM,OAAO,CAAC;AACzD,OAAO,EAAqB,cAAc,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,MAAM,gBAAgB,GAAG,oBAAoB,CAAe,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AAmB7G;;;GAGG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAc,KAAuB,EAAa,EAAE;IACxE,MAAM,EACF,GAAG,EACH,KAAK,EACL,UAAU,EACV,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,GAAG,cAAc,EACpB,GAAG,KAKH,CAAC;IAEF,MAAM,YAAY,GAA6B,YAAY,CAAa,UAAU,CAAC,CAAC;IAEpF,MAAM,SAAS,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACpD,MAAM,MAAM,GAAG,YAAY,CAAe,GAAG,EAAE,SAAS,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,kBAAkB,CAAa;QAC9C,KAAK;QACL,QAAQ,EAAE,SAAS;QACnB,aAAa;QACb,WAAW;QACX,kBAAkB;QAClB,YAAY,EAAE,SAAS;KAC1B,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,iBAAiB,CAAe;QAC9C,MAAM,EAAE,SAAS;QACjB,SAAS,EAAE,gBAAgB;QAC3B,eAAe,EAAE,mBAAmB;QACpC,cAAc,EAAE,kBAAkB;KACrC,CAAC,CAAC;IAEH,iBAAiB,CAAC,SAAS,EAAE,UAAU,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IAEnG,OAAO,CACH,8BACI,KAAC,WAAW,OAAK,cAAc,EAAE,GAAG,EAAE,MAAM,GAAI,EAChD,KAAC,cAAc,IAAC,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAI,IAC1F,CACN,CAAC;AACN,CAAC,CAAC","sourcesContent":["import type * as Gtk from \"@gtkx/gi/gtk\";\nimport { GtkGridView, type GtkGridViewProps } from \"@gtkx/jsx/gtk\";\nimport { useMergeRefs } from \"@gtkx/react/internal\";\nimport { type ReactNode, type Ref, useRef } from \"react\";\nimport { type CellRenderer, CellRenderHost, itemRenderer } from \"./cell.js\";\nimport { makeFactoryInstaller, useCellContainers } from \"./hooks/use-cell-containers.js\";\nimport { useCollectionModel } from \"./hooks/use-collection-model.js\";\nimport { useInstalledModel } from \"./hooks/use-installed-model.js\";\nimport type { CollectionItemSizeProps, ControlledSelectionProps, ItemNode, RenderItemProps } from \"./types.js\";\n\nconst factoryInstaller = makeFactoryInstaller<Gtk.GridView>((widget, factory) => widget.setFactory(factory));\n\nexport type GridViewDeclarativeProps<T = unknown> = CollectionItemSizeProps &\n ControlledSelectionProps & {\n items?: ItemNode<T>[] | undefined;\n renderItem: (props: RenderItemProps<T>) => ReactNode;\n };\n\n/**\n * Props for {@link GridView}. Combines the underlying Gtk.GridView props with\n * declarative collection props: items, a per-cell renderItem, controlled selection,\n * and estimated item sizing.\n */\nexport type GridViewProps<T = unknown> = Omit<\n GtkGridViewProps,\n \"model\" | \"factory\" | keyof GridViewDeclarativeProps<T>\n> &\n GridViewDeclarativeProps<T>;\n\n/**\n * Renders a Gtk.GridView: a scrollable grid of uniformly sized cells backed by a\n * collection model, with each cell drawn by renderItem.\n */\nexport const GridView = <T = unknown>(props: GridViewProps<T>): ReactNode => {\n const {\n ref,\n items,\n renderItem,\n selectedIds,\n selectionMode,\n onSelectionChanged,\n estimatedItemHeight,\n estimatedItemWidth,\n ...intrinsicProps\n } = props as GridViewDeclarativeProps<T> & {\n ref?: Ref<Gtk.GridView | null>;\n estimatedItemHeight?: number;\n estimatedItemWidth?: number;\n [key: string]: unknown;\n };\n\n const cellRenderer: CellRenderer<T, unknown> = itemRenderer<T, unknown>(renderItem);\n\n const widgetRef = useRef<Gtk.GridView | null>(null);\n const setRef = useMergeRefs<Gtk.GridView>(ref, widgetRef);\n\n const collection = useCollectionModel<T, unknown>({\n items,\n sections: undefined,\n selectionMode,\n selectedIds,\n onSelectionChanged,\n renderHeader: undefined,\n });\n\n const itemStore = useCellContainers<Gtk.GridView>({\n object: widgetRef,\n installer: factoryInstaller,\n estimatedHeight: estimatedItemHeight,\n estimatedWidth: estimatedItemWidth,\n });\n\n useInstalledModel(widgetRef, collection.installedModel, (widget, value) => widget.setModel(value));\n\n return (\n <>\n <GtkGridView {...intrinsicProps} ref={setRef} />\n <CellRenderHost store={itemStore} resolver={collection.resolver} render={cellRenderer} />\n </>\n );\n};\n"]}
1
+ {"version":3,"file":"grid-view.js","sourceRoot":"","sources":["../src/grid-view.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AACtE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,eAAe,GAAG;IACpB,OAAO;IACP,YAAY;IACZ,aAAa;IACb,oBAAoB;IACpB,eAAe;IACf,qBAAqB;IACrB,oBAAoB;CACoB,CAAC;AAE7C;;;GAGG;AACH,SAAS,QAAQ,CAAc,KAAuB;IAClD,MAAM,EAAE,UAAU,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,GAAG,KAAK,CAAC;IACtE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,EAAE,KAAK,EAAE,kBAAkB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAmB,IAAI,CAAC,CAAC,EAAE,CAAC;IACpF,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,aAAa,CAAC,EAAE,GAAG,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1E,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAErC,OAAO,CACH,8BACI,KAAC,WAAW,IAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,KAAC,wBAAwB,OAAK,SAAS,CAAC,QAAQ,GAAI,KAAM,IAAI,GAAI,EAC1G,KAAC,WAAW,IAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,GAAI,IAC9E,CACN,CAAC;AACN,CAAC;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC","sourcesContent":["import type { ReactNode } from \"react\";\nimport { GtkGridView, GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport { omit } from \"@gtkx/utils\";\nimport type { GridViewProps } from \"./types.js\";\nimport { ItemPortals, useItemCells } from \"./internal/cells.js\";\nimport { useCollection } from \"./internal/use-collection.js\";\n\nconst GRID_VIEW_PROPS = [\n \"items\",\n \"renderItem\",\n \"selectedIds\",\n \"onSelectionChanged\",\n \"selectionMode\",\n \"estimatedItemHeight\",\n \"estimatedItemWidth\",\n] as const satisfies (keyof GridViewProps)[];\n\n/**\n * Renders a Gtk.GridView of uniform cells from declarative items, with per-cell\n * rendering, controlled selection, and estimated item sizing.\n */\nfunction GridView<T = unknown>(props: GridViewProps<T>): ReactNode {\n const { renderItem, estimatedItemHeight, estimatedItemWidth } = props;\n const rest = omit(props, GRID_VIEW_PROPS);\n const size = { width: estimatedItemWidth ?? -1, height: estimatedItemHeight ?? -1 };\n const { collection, selection } = useCollection({ ...props, flat: true });\n const itemCells = useItemCells(size);\n\n return (\n <>\n <GtkGridView model={selection} factory={<GtkSignalListItemFactory {...itemCells.handlers} />} {...rest} />\n <ItemPortals store={itemCells} render={renderItem} collection={collection} />\n </>\n );\n}\n\nexport { GridView };\n"]}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,7 @@
1
- export { type ColumnDef, type ColumnDefDeclarativeProps, ColumnView, type ColumnViewDeclarativeProps, type ColumnViewProps, type ColumnViewSortProps, } from "./column-view.js";
2
- export { ConstraintLayout, type ConstraintLayoutProps } from "./constraint-layout.js";
3
- export type { ConstraintGuideProps, ConstraintProps, ConstraintVflProps } from "./constraint-layout-apply.js";
4
- export { DropDown, type DropDownDeclarativeProps, type DropDownItemRenderer, type DropDownProps } from "./drop-down.js";
5
- export { Fixed, type FixedChildProps, type FixedPlacementProps, type FixedProps } from "./fixed.js";
6
- export { Grid, type GridChildProps, type GridPlacement, type GridProps } from "./grid.js";
7
- export { GridView, type GridViewDeclarativeProps, type GridViewProps } from "./grid-view.js";
8
- export { ListView, type ListViewDeclarativeProps, type ListViewProps } from "./list-view.js";
9
- export { Menu, type MenuItemsProps, type MenuProps } from "./menu.js";
10
- export { Overlay, type OverlayChildProps, type OverlayPlacementProps, type OverlayProps } from "./overlay.js";
11
- export { SizeGroup, type SizeGroupChildProps, type SizeGroupProps } from "./size-group.js";
12
- export type { ChildProps, CollectionItemSizeProps, ControlledExpansionProps, ControlledSelectionProps, ItemNode, MenuEntry, RenderItemProps, SectionNode, WidgetProps, } from "./types.js";
1
+ export { ColumnView } from "./column-view.js";
2
+ export { DropDown } from "./drop-down.js";
3
+ export { GridView } from "./grid-view.js";
4
+ export { ListView } from "./list-view.js";
5
+ export { SizeGroup } from "./size-group.js";
6
+ export type { ChildProps, Column, ColumnViewProps, DropDownProps, GridViewProps, HeaderRenderer, Item, ItemRenderer, ListViewProps, RenderHeaderArgs, RenderItemArgs, Section, SizeGroupChildProps, SizeGroupProps, WidgetProps, } from "./types.js";
13
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,KAAK,SAAS,EACd,KAAK,yBAAyB,EAC9B,UAAU,EACV,KAAK,0BAA0B,EAC/B,KAAK,eAAe,EACpB,KAAK,mBAAmB,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACtF,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAC9G,OAAO,EAAE,QAAQ,EAAE,KAAK,wBAAwB,EAAE,KAAK,oBAAoB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxH,OAAO,EAAE,KAAK,EAAE,KAAK,eAAe,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,IAAI,EAAE,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAE,KAAK,wBAAwB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAE,KAAK,wBAAwB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,IAAI,EAAE,KAAK,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC9G,OAAO,EAAE,SAAS,EAAE,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAC3F,YAAY,EACR,UAAU,EACV,uBAAuB,EACvB,wBAAwB,EACxB,wBAAwB,EACxB,QAAQ,EACR,SAAS,EACT,eAAe,EACf,WAAW,EACX,WAAW,GACd,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EACR,UAAU,EACV,MAAM,EACN,eAAe,EACf,aAAa,EACb,aAAa,EACb,cAAc,EACd,IAAI,EACJ,YAAY,EACZ,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,OAAO,EACP,mBAAmB,EACnB,cAAc,EACd,WAAW,GACd,MAAM,YAAY,CAAC"}
package/dist/index.js CHANGED
@@ -1,11 +1,6 @@
1
- export { ColumnView, } from "./column-view.js";
2
- export { ConstraintLayout } from "./constraint-layout.js";
1
+ export { ColumnView } from "./column-view.js";
3
2
  export { DropDown } from "./drop-down.js";
4
- export { Fixed } from "./fixed.js";
5
- export { Grid } from "./grid.js";
6
3
  export { GridView } from "./grid-view.js";
7
4
  export { ListView } from "./list-view.js";
8
- export { Menu } from "./menu.js";
9
- export { Overlay } from "./overlay.js";
10
5
  export { SizeGroup } from "./size-group.js";
11
6
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,UAAU,GAIb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAA8B,MAAM,wBAAwB,CAAC;AAEtF,OAAO,EAAE,QAAQ,EAAgF,MAAM,gBAAgB,CAAC;AACxH,OAAO,EAAE,KAAK,EAAmE,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,IAAI,EAA2D,MAAM,WAAW,CAAC;AAC1F,OAAO,EAAE,QAAQ,EAAqD,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,QAAQ,EAAqD,MAAM,gBAAgB,CAAC;AAC7F,OAAO,EAAE,IAAI,EAAuC,MAAM,WAAW,CAAC;AACtE,OAAO,EAAE,OAAO,EAAyE,MAAM,cAAc,CAAC;AAC9G,OAAO,EAAE,SAAS,EAAiD,MAAM,iBAAiB,CAAC","sourcesContent":["export {\n type ColumnDef,\n type ColumnDefDeclarativeProps,\n ColumnView,\n type ColumnViewDeclarativeProps,\n type ColumnViewProps,\n type ColumnViewSortProps,\n} from \"./column-view.js\";\nexport { ConstraintLayout, type ConstraintLayoutProps } from \"./constraint-layout.js\";\nexport type { ConstraintGuideProps, ConstraintProps, ConstraintVflProps } from \"./constraint-layout-apply.js\";\nexport { DropDown, type DropDownDeclarativeProps, type DropDownItemRenderer, type DropDownProps } from \"./drop-down.js\";\nexport { Fixed, type FixedChildProps, type FixedPlacementProps, type FixedProps } from \"./fixed.js\";\nexport { Grid, type GridChildProps, type GridPlacement, type GridProps } from \"./grid.js\";\nexport { GridView, type GridViewDeclarativeProps, type GridViewProps } from \"./grid-view.js\";\nexport { ListView, type ListViewDeclarativeProps, type ListViewProps } from \"./list-view.js\";\nexport { Menu, type MenuItemsProps, type MenuProps } from \"./menu.js\";\nexport { Overlay, type OverlayChildProps, type OverlayPlacementProps, type OverlayProps } from \"./overlay.js\";\nexport { SizeGroup, type SizeGroupChildProps, type SizeGroupProps } from \"./size-group.js\";\nexport type {\n ChildProps,\n CollectionItemSizeProps,\n ControlledExpansionProps,\n ControlledSelectionProps,\n ItemNode,\n MenuEntry,\n RenderItemProps,\n SectionNode,\n WidgetProps,\n} from \"./types.js\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC","sourcesContent":["export { ColumnView } from \"./column-view.js\";\nexport { DropDown } from \"./drop-down.js\";\nexport { GridView } from \"./grid-view.js\";\nexport { ListView } from \"./list-view.js\";\nexport { SizeGroup } from \"./size-group.js\";\nexport type {\n ChildProps,\n Column,\n ColumnViewProps,\n DropDownProps,\n GridViewProps,\n HeaderRenderer,\n Item,\n ItemRenderer,\n ListViewProps,\n RenderHeaderArgs,\n RenderItemArgs,\n Section,\n SizeGroupChildProps,\n SizeGroupProps,\n WidgetProps,\n} from \"./types.js\";\n"]}
@@ -0,0 +1,50 @@
1
+ import type * as GObject from "@gtkx/gi/gobject";
2
+ import type { ReactNode } from "react";
3
+ import * as Gtk from "@gtkx/gi/gtk";
4
+ import type { HeaderRenderer, ItemRenderer } from "../types.js";
5
+ import type { Collection } from "./collection.js";
6
+ type CellSize = {
7
+ width: number;
8
+ height: number;
9
+ };
10
+ type CellHost = GObject.Object & {
11
+ getChild: () => Gtk.Widget | null;
12
+ setChild: (child: Gtk.Widget | null) => void;
13
+ };
14
+ type CellEntry<C extends CellHost> = {
15
+ key: string;
16
+ cell: C;
17
+ item: GObject.Object | null;
18
+ listeners: Set<() => void>;
19
+ subscribe: (onChange: () => void) => () => void;
20
+ getItem: () => GObject.Object | null;
21
+ };
22
+ type FactoryHandlers = {
23
+ onSetup: (cell: GObject.Object) => void;
24
+ onBind: (cell: GObject.Object) => void;
25
+ onUnbind: (cell: GObject.Object) => void;
26
+ onTeardown: (cell: GObject.Object) => void;
27
+ };
28
+ type CellStore<C extends CellHost> = {
29
+ handlers: FactoryHandlers;
30
+ setSize: (size: CellSize) => void;
31
+ subscribe: (onChange: () => void) => () => void;
32
+ getSnapshot: () => CellEntry<C>[];
33
+ };
34
+ type ItemPortalsProps = {
35
+ store: CellStore<Gtk.ListItem>;
36
+ render: ItemRenderer<never>;
37
+ collection: Collection;
38
+ expandedIds?: string[] | null | undefined;
39
+ };
40
+ type HeaderPortalsProps = {
41
+ store: CellStore<Gtk.ListHeader>;
42
+ render: HeaderRenderer<never>;
43
+ collection: Collection;
44
+ };
45
+ declare function useItemCells(size: CellSize): CellStore<Gtk.ListItem>;
46
+ declare function useHeaderCells(size: CellSize): CellStore<Gtk.ListHeader>;
47
+ declare const ItemPortals: ({ store, render, collection, expandedIds }: ItemPortalsProps) => ReactNode;
48
+ declare const HeaderPortals: ({ store, render, collection }: HeaderPortalsProps) => ReactNode;
49
+ export { useItemCells, useHeaderCells, ItemPortals, HeaderPortals, type CellSize, type CellStore, };
50
+ //# sourceMappingURL=cells.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cells.d.ts","sourceRoot":"","sources":["../../src/internal/cells.tsx"],"names":[],"mappings":"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"}