@gtkx/components 0.21.0 → 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 (192) hide show
  1. package/LICENSE +373 -0
  2. package/README.md +173 -0
  3. package/dist/adw/index.d.ts +3 -0
  4. package/dist/adw/index.d.ts.map +1 -0
  5. package/dist/adw/index.js +2 -0
  6. package/dist/adw/index.js.map +1 -0
  7. package/dist/adw/toast.d.ts +10 -0
  8. package/dist/adw/toast.d.ts.map +1 -0
  9. package/dist/adw/toast.js +51 -0
  10. package/dist/adw/toast.js.map +1 -0
  11. package/dist/adw/types.d.ts +28 -0
  12. package/dist/adw/types.d.ts.map +1 -0
  13. package/dist/adw/types.js +2 -0
  14. package/dist/adw/types.js.map +1 -0
  15. package/dist/column-view.d.ts +6 -14
  16. package/dist/column-view.d.ts.map +1 -1
  17. package/dist/column-view.js +98 -100
  18. package/dist/column-view.js.map +1 -1
  19. package/dist/drop-down.d.ts +8 -37
  20. package/dist/drop-down.d.ts.map +1 -1
  21. package/dist/drop-down.js +109 -118
  22. package/dist/drop-down.js.map +1 -1
  23. package/dist/grid-view.d.ts +4 -11
  24. package/dist/grid-view.d.ts.map +1 -1
  25. package/dist/grid-view.js +25 -19
  26. package/dist/grid-view.js.map +1 -1
  27. package/dist/index.d.ts +6 -18
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +2 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/internal/cells.d.ts +50 -0
  32. package/dist/internal/cells.d.ts.map +1 -0
  33. package/dist/internal/cells.js +185 -0
  34. package/dist/internal/cells.js.map +1 -0
  35. package/dist/internal/collection-index.d.ts +21 -0
  36. package/dist/internal/collection-index.d.ts.map +1 -0
  37. package/dist/internal/collection-index.js +106 -0
  38. package/dist/internal/collection-index.js.map +1 -0
  39. package/dist/internal/collection-model.d.ts +12 -0
  40. package/dist/internal/collection-model.d.ts.map +1 -0
  41. package/dist/internal/collection-model.js +164 -0
  42. package/dist/internal/collection-model.js.map +1 -0
  43. package/dist/internal/collection.d.ts +18 -0
  44. package/dist/internal/collection.d.ts.map +1 -0
  45. package/dist/internal/collection.js +64 -0
  46. package/dist/internal/collection.js.map +1 -0
  47. package/dist/internal/expansion.d.ts +9 -0
  48. package/dist/internal/expansion.d.ts.map +1 -0
  49. package/dist/internal/expansion.js +75 -0
  50. package/dist/internal/expansion.js.map +1 -0
  51. package/dist/internal/selection.d.ts +12 -0
  52. package/dist/internal/selection.d.ts.map +1 -0
  53. package/dist/internal/selection.js +99 -0
  54. package/dist/internal/selection.js.map +1 -0
  55. package/dist/internal/use-collection.d.ts +18 -0
  56. package/dist/internal/use-collection.d.ts.map +1 -0
  57. package/dist/internal/use-collection.js +42 -0
  58. package/dist/internal/use-collection.js.map +1 -0
  59. package/dist/internal/use-widget-ref.d.ts +4 -0
  60. package/dist/internal/use-widget-ref.d.ts.map +1 -0
  61. package/dist/internal/use-widget-ref.js +8 -0
  62. package/dist/internal/use-widget-ref.js.map +1 -0
  63. package/dist/list-view.d.ts +4 -11
  64. package/dist/list-view.d.ts.map +1 -1
  65. package/dist/list-view.js +32 -28
  66. package/dist/list-view.js.map +1 -1
  67. package/dist/size-group.d.ts +12 -0
  68. package/dist/size-group.d.ts.map +1 -0
  69. package/dist/size-group.js +41 -0
  70. package/dist/size-group.js.map +1 -0
  71. package/dist/types.d.ts +104 -161
  72. package/dist/types.d.ts.map +1 -1
  73. package/dist/types.js.map +1 -1
  74. package/package.json +62 -52
  75. package/src/adw/index.ts +2 -0
  76. package/src/adw/toast.tsx +74 -0
  77. package/src/adw/types.ts +32 -0
  78. package/src/column-view.tsx +184 -184
  79. package/src/drop-down.tsx +173 -227
  80. package/src/grid-view.tsx +29 -65
  81. package/src/index.ts +16 -25
  82. package/src/internal/cells.tsx +345 -0
  83. package/src/internal/collection-index.ts +168 -0
  84. package/src/internal/collection-model.ts +246 -0
  85. package/src/internal/collection.ts +104 -0
  86. package/src/internal/expansion.ts +123 -0
  87. package/src/internal/selection.tsx +159 -0
  88. package/src/internal/use-collection.tsx +70 -0
  89. package/src/internal/use-widget-ref.ts +11 -0
  90. package/src/list-view.tsx +45 -78
  91. package/src/size-group.tsx +77 -0
  92. package/src/types.ts +171 -191
  93. package/dist/collection-view.d.ts +0 -30
  94. package/dist/collection-view.d.ts.map +0 -1
  95. package/dist/collection-view.js +0 -52
  96. package/dist/collection-view.js.map +0 -1
  97. package/dist/column-view-column.d.ts +0 -17
  98. package/dist/column-view-column.d.ts.map +0 -1
  99. package/dist/column-view-column.js +0 -51
  100. package/dist/column-view-column.js.map +0 -1
  101. package/dist/constraint-layout-apply.d.ts +0 -6
  102. package/dist/constraint-layout-apply.d.ts.map +0 -1
  103. package/dist/constraint-layout-apply.js +0 -107
  104. package/dist/constraint-layout-apply.js.map +0 -1
  105. package/dist/constraint-layout.d.ts +0 -13
  106. package/dist/constraint-layout.d.ts.map +0 -1
  107. package/dist/constraint-layout.js +0 -85
  108. package/dist/constraint-layout.js.map +0 -1
  109. package/dist/contexts/column-view-context.d.ts +0 -17
  110. package/dist/contexts/column-view-context.d.ts.map +0 -1
  111. package/dist/contexts/column-view-context.js +0 -10
  112. package/dist/contexts/column-view-context.js.map +0 -1
  113. package/dist/hooks/use-drop-down-selection.d.ts +0 -15
  114. package/dist/hooks/use-drop-down-selection.d.ts.map +0 -1
  115. package/dist/hooks/use-drop-down-selection.js +0 -35
  116. package/dist/hooks/use-drop-down-selection.js.map +0 -1
  117. package/dist/hooks/use-header-menu.d.ts +0 -4
  118. package/dist/hooks/use-header-menu.d.ts.map +0 -1
  119. package/dist/hooks/use-header-menu.js +0 -32
  120. package/dist/hooks/use-header-menu.js.map +0 -1
  121. package/dist/hooks/use-list-model.d.ts +0 -20
  122. package/dist/hooks/use-list-model.d.ts.map +0 -1
  123. package/dist/hooks/use-list-model.js +0 -70
  124. package/dist/hooks/use-list-model.js.map +0 -1
  125. package/dist/hooks/use-model-installation.d.ts +0 -9
  126. package/dist/hooks/use-model-installation.d.ts.map +0 -1
  127. package/dist/hooks/use-model-installation.js +0 -20
  128. package/dist/hooks/use-model-installation.js.map +0 -1
  129. package/dist/hooks/use-realized-slots.d.ts +0 -20
  130. package/dist/hooks/use-realized-slots.d.ts.map +0 -1
  131. package/dist/hooks/use-realized-slots.js +0 -66
  132. package/dist/hooks/use-realized-slots.js.map +0 -1
  133. package/dist/hooks/use-selection-model.d.ts +0 -12
  134. package/dist/hooks/use-selection-model.d.ts.map +0 -1
  135. package/dist/hooks/use-selection-model.js +0 -111
  136. package/dist/hooks/use-selection-model.js.map +0 -1
  137. package/dist/hooks/use-sort-handler.d.ts +0 -12
  138. package/dist/hooks/use-sort-handler.d.ts.map +0 -1
  139. package/dist/hooks/use-sort-handler.js +0 -87
  140. package/dist/hooks/use-sort-handler.js.map +0 -1
  141. package/dist/list-portal-host.d.ts +0 -11
  142. package/dist/list-portal-host.d.ts.map +0 -1
  143. package/dist/list-portal-host.js +0 -8
  144. package/dist/list-portal-host.js.map +0 -1
  145. package/dist/list-slot.d.ts +0 -14
  146. package/dist/list-slot.d.ts.map +0 -1
  147. package/dist/list-slot.js +0 -29
  148. package/dist/list-slot.js.map +0 -1
  149. package/dist/menu-items.d.ts +0 -5
  150. package/dist/menu-items.d.ts.map +0 -1
  151. package/dist/menu-items.js +0 -48
  152. package/dist/menu-items.js.map +0 -1
  153. package/dist/menu.d.ts +0 -18
  154. package/dist/menu.d.ts.map +0 -1
  155. package/dist/menu.js +0 -26
  156. package/dist/menu.js.map +0 -1
  157. package/dist/utils/item-resolver.d.ts +0 -28
  158. package/dist/utils/item-resolver.d.ts.map +0 -1
  159. package/dist/utils/item-resolver.js +0 -111
  160. package/dist/utils/item-resolver.js.map +0 -1
  161. package/dist/utils/list-item-flatten.d.ts +0 -32
  162. package/dist/utils/list-item-flatten.d.ts.map +0 -1
  163. package/dist/utils/list-item-flatten.js +0 -88
  164. package/dist/utils/list-item-flatten.js.map +0 -1
  165. package/dist/utils/position-only-model.d.ts +0 -10
  166. package/dist/utils/position-only-model.d.ts.map +0 -1
  167. package/dist/utils/position-only-model.js +0 -83
  168. package/dist/utils/position-only-model.js.map +0 -1
  169. package/dist/utils/realized-slot-store.d.ts +0 -30
  170. package/dist/utils/realized-slot-store.d.ts.map +0 -1
  171. package/dist/utils/realized-slot-store.js +0 -103
  172. package/dist/utils/realized-slot-store.js.map +0 -1
  173. package/src/collection-view.tsx +0 -125
  174. package/src/column-view-column.tsx +0 -73
  175. package/src/constraint-layout-apply.ts +0 -121
  176. package/src/constraint-layout.tsx +0 -130
  177. package/src/contexts/column-view-context.ts +0 -28
  178. package/src/hooks/use-drop-down-selection.ts +0 -53
  179. package/src/hooks/use-header-menu.ts +0 -33
  180. package/src/hooks/use-list-model.ts +0 -145
  181. package/src/hooks/use-model-installation.ts +0 -25
  182. package/src/hooks/use-realized-slots.ts +0 -93
  183. package/src/hooks/use-selection-model.ts +0 -121
  184. package/src/hooks/use-sort-handler.ts +0 -102
  185. package/src/list-portal-host.tsx +0 -27
  186. package/src/list-slot.tsx +0 -56
  187. package/src/menu-items.ts +0 -48
  188. package/src/menu.tsx +0 -34
  189. package/src/utils/item-resolver.ts +0 -143
  190. package/src/utils/list-item-flatten.ts +0 -113
  191. package/src/utils/position-only-model.ts +0 -115
  192. package/src/utils/realized-slot-store.ts +0 -126
package/src/list-view.tsx CHANGED
@@ -1,85 +1,52 @@
1
- import type * as Gio from "@gtkx/gi/gio";
2
- import type * as Gtk from "@gtkx/gi/gtk";
3
- import { GtkListView, type GtkListViewProps } from "@gtkx/jsx/gtk";
4
- import type { ReactNode, Ref } from "react";
5
- import { CollectionView, type ModelBinding } from "./collection-view.js";
6
- import type { SlotRenderer } from "./list-slot.js";
1
+ import type { ReactNode } from "react";
2
+ import { GtkListView, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
3
+ import { omit } from "@gtkx/utils";
7
4
  import type { ListViewProps } from "./types.js";
8
-
9
- const factoryBinding = {
10
- install: (widget: Gtk.ListView, factory: Gtk.SignalListItemFactory) => widget.setFactory(factory),
11
- uninstall: (widget: Gtk.ListView) => widget.setFactory(null),
12
- };
13
-
14
- const headerFactoryBinding = {
15
- install: (widget: Gtk.ListView, factory: Gtk.SignalListItemFactory) => widget.setHeaderFactory(factory),
16
- uninstall: (widget: Gtk.ListView) => widget.setHeaderFactory(null),
17
- };
18
-
19
- const modelBinding: ModelBinding<Gtk.ListView> = {
20
- install: (widget, model) => widget.setModel(model as Gtk.SelectionModel),
21
- };
5
+ import { HeaderPortals, ItemPortals, useHeaderCells, useItemCells } from "./internal/cells.js";
6
+ import { useCollection } from "./internal/use-collection.js";
7
+
8
+ const LIST_VIEW_PROPS = [
9
+ "items",
10
+ "sections",
11
+ "renderItem",
12
+ "renderHeader",
13
+ "selectedIds",
14
+ "onSelectionChanged",
15
+ "selectionMode",
16
+ "expandedIds",
17
+ "onExpandedChange",
18
+ "estimatedItemHeight",
19
+ "estimatedItemWidth",
20
+ ] as const satisfies (keyof ListViewProps)[];
22
21
 
23
22
  /**
24
- * Props for the {@link ListView} component: the raw `GtkListView` element
25
- * surface with its factory/model wiring replaced by the declarative
26
- * {@link ListViewProps} API.
23
+ * Renders a Gtk.ListView from declarative items or sections, with per-row rendering,
24
+ * controlled selection, controlled tree expansion, and estimated item sizing.
27
25
  */
28
- export type ListViewComponentProps<T = unknown, S = unknown> = Omit<GtkListViewProps, keyof ListViewProps<T, S>> &
29
- ListViewProps<T, S>;
30
-
31
- /**
32
- * A `GtkListView` driven by a declarative `items`/`renderItem` API with
33
- * optional controlled selection, section headers, and tree autoexpansion.
34
- * Supplying an external `model` switches to the uncontrolled form.
35
- */
36
- export const ListView = <T = unknown, S = unknown>(props: ListViewComponentProps<T, S>): ReactNode => {
37
- const {
38
- ref,
39
- items,
40
- model,
41
- renderItem,
42
- autoexpand,
43
- renderHeader,
44
- selected,
45
- selectionMode,
46
- onSelectionChanged,
47
- estimatedItemHeight,
48
- estimatedItemWidth,
49
- ...intrinsicProps
50
- } = props as ListViewProps<T, S> & {
51
- ref?: Ref<Gtk.ListView | null>;
52
- estimatedItemHeight?: number;
53
- estimatedItemWidth?: number;
54
- [key: string]: unknown;
55
- };
56
-
57
- const renderItemFn = renderItem as (item: T, row?: Gtk.TreeListRow | null) => ReactNode;
58
- const slotRenderer: SlotRenderer<T, S> = (value, treeRow, isHeader) => {
59
- if (isHeader) return null;
60
- return treeRow === null ? renderItemFn(value as T) : renderItemFn(value as T, treeRow);
61
- };
62
-
63
- const useHeader = model === undefined && typeof renderHeader === "function";
26
+ function ListView<T = unknown, S = unknown>(props: ListViewProps<T, S>): ReactNode {
27
+ const { renderItem, renderHeader, expandedIds, estimatedItemHeight, estimatedItemWidth } = props;
28
+ const rest = omit(props, LIST_VIEW_PROPS);
29
+ const size = { width: estimatedItemWidth ?? -1, height: estimatedItemHeight ?? -1 };
30
+ const { collection, selection } = useCollection(props);
31
+ const itemCells = useItemCells(size);
32
+ const headerCells = useHeaderCells(size);
64
33
 
65
34
  return (
66
- <CollectionView<T, S, Gtk.ListView>
67
- element={GtkListView}
68
- intrinsicProps={intrinsicProps}
69
- ref={ref}
70
- items={model === undefined ? items : undefined}
71
- model={model as Gio.ListModel | undefined}
72
- renderItem={slotRenderer}
73
- autoexpand={autoexpand}
74
- renderHeader={useHeader ? (value) => renderHeader?.(value as S) ?? null : undefined}
75
- estimatedHeight={estimatedItemHeight}
76
- estimatedWidth={estimatedItemWidth}
77
- selected={selected}
78
- selectionMode={selectionMode}
79
- onSelectionChanged={onSelectionChanged}
80
- factoryBinding={factoryBinding}
81
- headerFactoryBinding={useHeader ? headerFactoryBinding : undefined}
82
- modelBinding={modelBinding}
83
- />
35
+ <>
36
+ <GtkListView
37
+ model={selection}
38
+ factory={<GtkSignalListItemFactory {...itemCells.handlers} />}
39
+ {...(renderHeader != null && {
40
+ headerFactory: <GtkSignalListItemFactory {...headerCells.handlers} />,
41
+ })}
42
+ {...rest}
43
+ />
44
+ <ItemPortals store={itemCells} render={renderItem} collection={collection} expandedIds={expandedIds} />
45
+ {renderHeader != null && (
46
+ <HeaderPortals store={headerCells} render={renderHeader} collection={collection} />
47
+ )}
48
+ </>
84
49
  );
85
- };
50
+ }
51
+
52
+ export { ListView };
@@ -0,0 +1,77 @@
1
+ import type * as Gtk from "@gtkx/gi/gtk";
2
+ import type { ElementType, ReactNode, Ref, RefCallback } from "react";
3
+ import { GtkSizeGroup } from "@gtkx/jsx/gtk";
4
+ import { useMergedRef } from "@gtkx/react/internal";
5
+ import { createContext, useCallback, useContext, useState } from "react";
6
+ import type { SizeGroupChildProps, SizeGroupProps } from "./types.js";
7
+
8
+ type Register = RefCallback<Gtk.Widget | null>;
9
+
10
+ type SizeGroupChildRuntimeProps = {
11
+ component: ElementType;
12
+ ref?: Ref<Gtk.Widget | null> | undefined;
13
+ } & Record<string, unknown>;
14
+
15
+ type SizeGroupComponent = ((props: SizeGroupProps) => ReactNode) & {
16
+ Child: <C extends ElementType>(props: SizeGroupChildProps<C>) => ReactNode;
17
+ };
18
+
19
+ const SizeGroupContext = createContext<Register | null>(null);
20
+ const SizeGroupChild = SizeGroupChildImpl as <C extends ElementType>(props: SizeGroupChildProps<C>) => ReactNode;
21
+ /**
22
+ * Creates a Gtk.SizeGroup that keeps widgets joined through `SizeGroup.Child`
23
+ * at a common size in the given mode, without contributing a widget of its own.
24
+ */
25
+ const SizeGroup: SizeGroupComponent = Object.assign(SizeGroupRoot, { Child: SizeGroupChild });
26
+
27
+ const useRegister = (): Register => {
28
+ const register = useContext(SizeGroupContext);
29
+
30
+ if (register === null) {
31
+ throw new Error("<SizeGroup.Child> must be a child of <SizeGroup>");
32
+ }
33
+
34
+ return register;
35
+ };
36
+
37
+ function SizeGroupChildImpl(props: SizeGroupChildRuntimeProps): ReactNode {
38
+ const { component: Component, ref, ...rest } = props;
39
+ const refCallback = useMergedRef<Gtk.Widget | null>(ref, useRegister());
40
+
41
+ return <Component {...rest} ref={refCallback} />;
42
+ }
43
+
44
+ const addWidget = (widgets: Gtk.Widget[], widget: Gtk.Widget): Gtk.Widget[] =>
45
+ widgets.includes(widget) ? widgets : [...widgets, widget];
46
+
47
+ const removeWidget = (widgets: Gtk.Widget[], widget: Gtk.Widget): Gtk.Widget[] =>
48
+ widgets.filter((entry) => entry !== widget);
49
+
50
+ function SizeGroupRoot(props: SizeGroupProps): ReactNode {
51
+ const { mode, ref, children } = props;
52
+ const [widgets, setWidgets] = useState<Gtk.Widget[]>([]);
53
+
54
+ const register = useCallback<Register>(
55
+ (widget) => {
56
+ if (widget === null) {
57
+ return;
58
+ }
59
+
60
+ setWidgets((previous) => addWidget(previous, widget));
61
+
62
+ return () => {
63
+ setWidgets((previous) => removeWidget(previous, widget));
64
+ };
65
+ },
66
+ [setWidgets],
67
+ );
68
+
69
+ return (
70
+ <>
71
+ <GtkSizeGroup ref={ref} mode={mode} widgets={widgets} />
72
+ <SizeGroupContext.Provider value={register}>{children}</SizeGroupContext.Provider>
73
+ </>
74
+ );
75
+ }
76
+
77
+ export { SizeGroup };
package/src/types.ts CHANGED
@@ -1,227 +1,207 @@
1
- import type * as Gio from "@gtkx/gi/gio";
2
- import type * as GObject from "@gtkx/gi/gobject";
3
1
  import type * as Gtk from "@gtkx/gi/gtk";
4
- import type { ReactNode } from "react";
2
+ import type {
3
+ GtkColumnViewColumnProps,
4
+ GtkColumnViewProps,
5
+ GtkDropDown,
6
+ GtkGridViewProps,
7
+ GtkListViewProps,
8
+ } from "@gtkx/jsx/gtk";
9
+ import type { ComponentPropsWithRef, ElementType, ReactNode, Ref } from "react";
10
+
11
+ /** Props of a container's Child component: the widget to render and its own props. */
12
+ type ChildProps<C extends ElementType> = {
13
+ component: C;
14
+ } & ComponentPropsWithRef<C>;
15
+
16
+ /** Props of a component whose backing widget defaults to one type but can be swapped through `component`. */
17
+ type WidgetProps<C extends ElementType, Own = unknown, ExtraOmit extends string = never> = Own & {
18
+ component?: C;
19
+ } & Omit<ComponentPropsWithRef<C>, ExtraOmit | keyof Own>;
5
20
 
6
21
  /**
7
- * A declarative item rendered by the {@link ListView}, {@link GridView},
8
- * {@link ColumnView}, and {@link DropDown} components.
9
- *
10
- * A non-section item carries an arbitrary value of type `T` and may declare
11
- * tree `children`. A section item carries a value of type `S` and groups a list
12
- * of child items underneath a header.
22
+ * A single item in a collection model, identified by a stable id and holding an
23
+ * arbitrary value. Nested items form a tree.
13
24
  */
14
- export type ListItem<T = unknown, S = unknown> =
15
- | {
16
- id: string;
17
- value: T;
18
- section?: false | undefined;
19
- children?: ListItem<T, S>[] | undefined;
20
- hideExpander?: boolean | undefined;
21
- indentForDepth?: boolean | undefined;
22
- indentForIcon?: boolean | undefined;
23
- }
24
- | {
25
- id: string;
26
- value: S;
27
- section: true;
28
- children: ListItem<T, S>[];
29
- };
30
-
31
- type ListViewSharedProps = {
25
+ type Item<T = unknown> = {
26
+ /** Stable identifier used to track the item across updates and selection. */
27
+ id: string;
28
+ value: T;
29
+ children?: Item<T>[] | undefined;
30
+ /** Hides the tree expander arrow even when the item has children. */
31
+ hideExpander?: boolean | undefined;
32
+ /** Adds indentation matching the item's depth in the tree. */
33
+ indentForDepth?: boolean | undefined;
34
+ /** Reserves indentation space for an expander icon. */
35
+ indentForIcon?: boolean | undefined;
36
+ };
37
+
38
+ /** A group of items rendered under a shared section header. */
39
+ type Section<S = unknown, T = unknown> = {
40
+ /** Stable identifier used to track the section across updates. */
41
+ id: string;
42
+ value: S;
43
+ /** Items belonging to this section. */
44
+ data: Item<T>[];
45
+ };
46
+
47
+ /** Arguments passed to an {@link ItemRenderer} when rendering one cell. */
48
+ type RenderItemArgs<T> = {
49
+ item: T;
50
+ index: number;
51
+ /** Depth of the item within a tree, starting at zero for top-level items. */
52
+ depth?: number | undefined;
53
+ /** Whether the item is currently expanded in a tree view. */
54
+ isExpanded?: boolean | undefined;
55
+ };
56
+
57
+ /** Arguments passed to a {@link HeaderRenderer} when rendering one section header. */
58
+ type RenderHeaderArgs<S> = {
59
+ section: S;
60
+ };
61
+
62
+ /** Renders the contents of one cell of a collection view. */
63
+ type ItemRenderer<T> = (args: RenderItemArgs<T>) => ReactNode;
64
+ /** Renders the contents of one section header of a collection view. */
65
+ type HeaderRenderer<S> = (args: RenderHeaderArgs<S>) => ReactNode;
66
+
67
+ type ItemSizeProps = {
32
68
  estimatedItemHeight?: number | undefined;
33
69
  estimatedItemWidth?: number | undefined;
34
70
  };
35
71
 
36
- type ListViewControlledSelectionProps = {
37
- selected?: string[] | null | undefined;
72
+ type SelectionProps = {
73
+ selectedIds?: string[] | null | undefined;
38
74
  onSelectionChanged?: ((ids: string[]) => void) | null | undefined;
39
75
  selectionMode?: Gtk.SelectionMode | null | undefined;
40
76
  };
41
77
 
42
- type UncontrolledItemType<T> = [T] extends [GObject.Object] ? T : GObject.Object;
43
-
44
- /**
45
- * Props for the {@link ListView} component, replacing the raw `GtkListView`
46
- * factory/model surface with a declarative `items`/`renderItem` API, optional
47
- * controlled selection, section headers, and tree autoexpansion. Supplying an
48
- * external `model` switches to the uncontrolled form.
49
- */
50
- export type ListViewProps<T = unknown, S = unknown> = ListViewSharedProps &
51
- (
52
- | (ListViewControlledSelectionProps & {
53
- items?: ListItem<T, S>[] | undefined;
54
- renderItem: (item: T, row?: Gtk.TreeListRow | null) => ReactNode;
55
- autoexpand?: boolean | undefined;
56
- renderHeader?: ((item: S) => ReactNode) | null | undefined;
57
- model?: never;
58
- })
59
- | {
60
- model: Gio.ListModel;
61
- renderItem: (item: UncontrolledItemType<T>) => ReactNode;
62
- items?: never;
63
- autoexpand?: never;
64
- renderHeader?: never;
65
- selected?: never;
66
- onSelectionChanged?: never;
67
- selectionMode?: never;
68
- }
69
- );
70
-
71
- /**
72
- * Props for the {@link GridView} component, replacing the raw `GtkGridView`
73
- * factory/model surface with a declarative `items`/`renderItem` API and
74
- * optional controlled selection. Supplying an external `model` switches to the
75
- * uncontrolled form.
76
- */
77
- export type GridViewProps<T = unknown> = ListViewSharedProps &
78
- (
79
- | (ListViewControlledSelectionProps & {
80
- items?: ListItem<T>[] | undefined;
81
- renderItem: (item: T) => ReactNode;
82
- model?: never;
83
- })
84
- | {
85
- model: Gio.ListModel;
86
- renderItem: (item: UncontrolledItemType<T>) => ReactNode;
87
- items?: never;
88
- selected?: never;
89
- onSelectionChanged?: never;
90
- selectionMode?: never;
91
- }
92
- );
93
-
94
- type ColumnViewSortProps = {
95
- sortColumn?: string | null | undefined;
96
- sortOrder?: Gtk.SortType | null | undefined;
97
- onSortChanged?: ((column: string | null, order: Gtk.SortType) => void) | null | undefined;
98
- estimatedRowHeight?: number | null | undefined;
78
+ type ExpansionProps = {
79
+ expandedIds?: string[] | null | undefined;
80
+ onExpandedChange?: ((ids: string[]) => void) | null | undefined;
99
81
  };
100
82
 
101
- /**
102
- * Props for the {@link ColumnView} component, replacing the raw `GtkColumnView`
103
- * surface with a declarative `items` model, optional controlled selection,
104
- * controlled sorting, and section headers. Columns are declared as
105
- * {@link ColumnViewColumn} children. Supplying an external `model` switches to
106
- * the uncontrolled form.
107
- */
108
- export type ColumnViewProps<T = unknown, S = unknown> = ColumnViewSortProps &
109
- (
110
- | (ListViewControlledSelectionProps & {
111
- items?: ListItem<T, S>[] | undefined;
112
- renderHeader?: ((item: S) => ReactNode) | null | undefined;
113
- model?: never;
114
- })
115
- | {
116
- model: Gio.ListModel;
117
- items?: never;
118
- renderHeader?: never;
119
- selected?: never;
120
- onSelectionChanged?: never;
121
- selectionMode?: never;
122
- }
123
- );
83
+ type SourceProps<T, S> = {
84
+ items?: Item<T>[] | undefined;
85
+ sections?: Section<S, T>[] | undefined;
86
+ };
124
87
 
125
- /**
126
- * Props for a single {@link ColumnViewColumn} of a {@link ColumnView},
127
- * replacing the raw `GtkColumnViewColumn` factory/sorter surface with a
128
- * declarative `renderCell` callback and an optional header context menu.
129
- */
130
- export type ColumnViewColumnProps<T = unknown> = {
131
- title: string;
132
- expand?: boolean | undefined;
133
- resizable?: boolean | undefined;
134
- fixedWidth?: number | undefined;
88
+ /** One column of a {@link ColumnView}, pairing Gtk.ColumnViewColumn props with a cell renderer. */
89
+ type Column<T = unknown> = Omit<GtkColumnViewColumnProps, "factory" | "sorter" | "id" | "title"> & {
90
+ /** Stable identifier, also used to address the column through sorting props. */
135
91
  id: string;
92
+ title: string;
93
+ renderCell: ItemRenderer<T>;
94
+ /** Whether clicking the column header sorts by it. */
136
95
  sortable?: boolean | undefined;
137
- visible?: boolean | undefined;
138
- renderCell: (item: T) => ReactNode;
139
96
  headerMenu?: ReactNode;
140
97
  };
141
98
 
142
- /**
143
- * Props shared by the {@link DropDown} and {@link ComboRow} components,
144
- * replacing the raw factory/model surface with declarative `items`, controlled
145
- * `selectedId`, and per-slot renderers for the selected face, the popup list,
146
- * and section headers. Supplying an external `model` switches to the
147
- * uncontrolled form.
148
- */
149
- export type DropDownProps<T = unknown, S = unknown> =
150
- | {
151
- items?: ListItem<T, S>[] | undefined;
152
- selectedId?: string | null | undefined;
153
- onSelectionChanged?: ((id: string) => void) | null | undefined;
154
- renderItem?: ((item: T) => ReactNode) | null | undefined;
155
- renderListItem?: ((item: T) => ReactNode) | null | undefined;
156
- renderHeader?: ((item: S) => ReactNode) | null | undefined;
157
- model?: never;
158
- }
159
- | {
160
- model: Gio.ListModel;
161
- renderItem?: ((item: UncontrolledItemType<T>) => ReactNode) | null | undefined;
162
- renderListItem?: ((item: UncontrolledItemType<T>) => ReactNode) | null | undefined;
163
- items?: never;
164
- selectedId?: never;
165
- onSelectionChanged?: never;
166
- renderHeader?: never;
167
- };
99
+ type ColumnViewOwnProps<T, S> = SelectionProps &
100
+ ExpansionProps &
101
+ SourceProps<T, S> &
102
+ Omit<ItemSizeProps, "estimatedItemWidth"> & {
103
+ columns: Column<T>[];
104
+ renderHeader?: HeaderRenderer<S> | null | undefined;
105
+ /** Id of the column the view is sorted by, making sorting controlled. */
106
+ sortColumn?: string | null | undefined;
107
+ sortOrder?: Gtk.SortType | null | undefined;
108
+ onSortChanged?: ((column: string | null, order: Gtk.SortType) => void) | null | undefined;
109
+ };
168
110
 
169
111
  /**
170
- * A single declarative entry in a {@link Menu} model. An entry is a plain item
171
- * (`label` plus `action`), a `submenu`, or a `section` of nested entries.
112
+ * Props for {@link ColumnView}. Combines the underlying Gtk.ColumnView props with
113
+ * declarative collection props: flat items or grouped sections, controlled selection
114
+ * and expansion, sorting (sortColumn, sortOrder, onSortChanged), an optional section
115
+ * header renderer, and the columns to render.
172
116
  */
173
- export type MenuEntry = {
174
- label?: string | undefined;
175
- action?: string | undefined;
176
- submenu?: MenuEntry[] | undefined;
177
- section?: MenuEntry[] | undefined;
117
+ type ColumnViewProps<T = unknown, S = unknown> = Omit<
118
+ GtkColumnViewProps,
119
+ "columns" | "model" | "headerFactory" | keyof ColumnViewOwnProps<T, S>
120
+ > &
121
+ ColumnViewOwnProps<T, S>;
122
+
123
+ type DropDownOwnProps<T, S> = SourceProps<T, S> & {
124
+ /** Id of the currently selected item, making the selection controlled. */
125
+ selectedId?: string | null | undefined;
126
+ onSelectionChanged?: ((id: string) => void) | null | undefined;
127
+ renderItem?: ItemRenderer<T> | null | undefined;
128
+ /** Renderer for items in the open popup list, falling back to renderItem when omitted. */
129
+ renderListItem?: ItemRenderer<T> | null | undefined;
130
+ /** Renderer for section headers in the popup list. */
131
+ renderHeader?: HeaderRenderer<S> | null | undefined;
178
132
  };
179
133
 
180
134
  /**
181
- * The declarative menu-model surface added by the {@link Menu} component on top
182
- * of the raw `GMenu` element.
135
+ * Props for {@link DropDown}. The backing widget is chosen through the `component` prop, defaulting to
136
+ * GtkDropDown, and its own props combine with the declarative collection props.
183
137
  */
184
- export type MenuItemsProps = {
185
- items?: MenuEntry[] | null | undefined;
186
- };
138
+ type DropDownProps<T = unknown, S = unknown, C extends ElementType = typeof GtkDropDown> = WidgetProps<
139
+ C,
140
+ DropDownOwnProps<T, S>,
141
+ "model" | "factory" | "listFactory" | "headerFactory"
142
+ >;
143
+
144
+ type GridViewOwnProps<T> = ItemSizeProps &
145
+ SelectionProps & {
146
+ items?: Item<T>[] | undefined;
147
+ renderItem: ItemRenderer<T>;
148
+ };
187
149
 
188
150
  /**
189
- * Props for a `<ConstraintLayout.Constraint>` declaring a single relation
190
- * between a target attribute and a source attribute within a
191
- * {@link ConstraintLayout}.
151
+ * Props for {@link GridView}. Combines the underlying Gtk.GridView props with
152
+ * declarative collection props: items, a per-cell renderItem, controlled selection,
153
+ * and estimated item sizing.
192
154
  */
193
- export type ConstraintProps = {
194
- target?: string;
195
- targetAttribute: Gtk.ConstraintAttribute;
196
- relation?: Gtk.ConstraintRelation;
197
- source?: string;
198
- sourceAttribute?: Gtk.ConstraintAttribute;
199
- multiplier?: number;
200
- constant?: number;
201
- strength?: number;
202
- };
155
+ type GridViewProps<T = unknown> = Omit<GtkGridViewProps, "model" | "factory" | keyof GridViewOwnProps<T>> &
156
+ GridViewOwnProps<T>;
157
+
158
+ type ListViewOwnProps<T, S> = ItemSizeProps &
159
+ SelectionProps &
160
+ ExpansionProps &
161
+ SourceProps<T, S> & {
162
+ renderItem: ItemRenderer<T>;
163
+ renderHeader?: HeaderRenderer<S> | null | undefined;
164
+ };
203
165
 
204
166
  /**
205
- * Props for a `<ConstraintLayout.Guide>` declaring an invisible layout guide
206
- * that other constraints can reference by `id` within a {@link ConstraintLayout}.
167
+ * Props for {@link ListView}. Combines the underlying Gtk.ListView props with
168
+ * declarative collection props: flat items or grouped sections, a per-row renderItem,
169
+ * an optional section header renderer, controlled selection and expansion, and
170
+ * estimated item sizing.
207
171
  */
208
- export type ConstraintGuideProps = {
209
- id: string;
210
- minWidth?: number;
211
- minHeight?: number;
212
- natWidth?: number;
213
- natHeight?: number;
214
- maxWidth?: number;
215
- maxHeight?: number;
216
- strength?: Gtk.ConstraintStrength;
172
+ type ListViewProps<T = unknown, S = unknown> = Omit<
173
+ GtkListViewProps,
174
+ "model" | "factory" | "headerFactory" | keyof ListViewOwnProps<T, S>
175
+ > &
176
+ ListViewOwnProps<T, S>;
177
+
178
+ /** Props for {@link SizeGroup}. */
179
+ type SizeGroupProps = {
180
+ /** How the group equalizes sizes: horizontal, vertical, or both. */
181
+ mode?: Gtk.SizeGroupMode | null | undefined;
182
+ ref?: Ref<Gtk.SizeGroup | null>;
183
+ children?: ReactNode;
217
184
  };
218
185
 
219
- /**
220
- * Props for a `<ConstraintLayout.Vfl>` declaring constraints through the GTK
221
- * Visual Format Language within a {@link ConstraintLayout}.
222
- */
223
- export type ConstraintVflProps = {
224
- lines: string[];
225
- hspacing?: number;
226
- vspacing?: number;
186
+ /** Adds a single widget, rendered by the given component, to the enclosing {@link SizeGroup}. */
187
+ type SizeGroupChildProps<C extends ElementType> = ChildProps<C>;
188
+
189
+ export {
190
+ type SelectionProps,
191
+ type ExpansionProps,
192
+ type ChildProps,
193
+ type WidgetProps,
194
+ type Item,
195
+ type Section,
196
+ type RenderItemArgs,
197
+ type RenderHeaderArgs,
198
+ type ItemRenderer,
199
+ type HeaderRenderer,
200
+ type Column,
201
+ type ColumnViewProps,
202
+ type DropDownProps,
203
+ type GridViewProps,
204
+ type ListViewProps,
205
+ type SizeGroupProps,
206
+ type SizeGroupChildProps,
227
207
  };
@@ -1,30 +0,0 @@
1
- import type * as Gio from "@gtkx/gi/gio";
2
- import type * as Gtk from "@gtkx/gi/gtk";
3
- import { type ElementType, type ReactNode, type Ref } from "react";
4
- import { type FactoryBinding } from "./hooks/use-realized-slots.js";
5
- import type { SlotRenderer } from "./list-slot.js";
6
- import type { ListItem } from "./types.js";
7
- export interface ModelBinding<W extends Gtk.Widget> {
8
- install(widget: W, model: Gio.ListModel): void;
9
- }
10
- export interface CollectionViewProps<T, S, W extends Gtk.Widget> {
11
- element: ElementType;
12
- intrinsicProps: Record<string, unknown>;
13
- ref: Ref<W | null> | undefined;
14
- items: ListItem<T, S>[] | undefined;
15
- model: Gio.ListModel | undefined;
16
- renderItem: SlotRenderer<T, S>;
17
- autoexpand: boolean | undefined;
18
- renderHeader: ((value: S | undefined) => ReactNode) | undefined;
19
- estimatedHeight: number | undefined;
20
- estimatedWidth: number | undefined;
21
- selected: string[] | null | undefined;
22
- selectionMode: Gtk.SelectionMode | null | undefined;
23
- onSelectionChanged: ((ids: string[]) => void) | null | undefined;
24
- factoryBinding: FactoryBinding<W>;
25
- headerFactoryBinding: FactoryBinding<W> | undefined;
26
- modelBinding: ModelBinding<W>;
27
- children?: ReactNode;
28
- }
29
- export declare const CollectionView: <T, S, W extends Gtk.Widget>(props: CollectionViewProps<T, S, W>) => ReactNode;
30
- //# sourceMappingURL=collection-view.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"collection-view.d.ts","sourceRoot":"","sources":["../src/collection-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AAEzC,OAAO,EAEH,KAAK,WAAW,EAEhB,KAAK,SAAS,EACd,KAAK,GAAG,EAGX,MAAM,OAAO,CAAC;AAGf,OAAO,EAAE,KAAK,cAAc,EAAoB,MAAM,+BAA+B,CAAC;AAGtF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAI3C,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,GAAG,CAAC,MAAM;IAC9C,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;CAClD;AAED,MAAM,WAAW,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,MAAM;IAC3D,OAAO,EAAE,WAAW,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACxC,GAAG,EAAE,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IAC/B,KAAK,EAAE,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC;IACpC,KAAK,EAAE,GAAG,CAAC,SAAS,GAAG,SAAS,CAAC;IACjC,UAAU,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,UAAU,EAAE,OAAO,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,SAAS,KAAK,SAAS,CAAC,GAAG,SAAS,CAAC;IAChE,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,cAAc,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IACtC,aAAa,EAAE,GAAG,CAAC,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;IACpD,kBAAkB,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IACjE,cAAc,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;IAClC,oBAAoB,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,SAAS,CAAC;IACpD,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AA8DD,eAAO,MAAM,cAAc,GAAI,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG,CAAC,MAAM,EAAE,OAAO,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAG,SAkBhG,CAAC"}