@gtkx/components 2.0.0-beta.1 → 2.0.0-beta.11

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 (79) hide show
  1. package/README.md +8 -165
  2. package/dist/column-view.d.ts.map +1 -1
  3. package/dist/column-view.js +20 -9
  4. package/dist/column-view.js.map +1 -1
  5. package/dist/index.d.ts +3 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +2 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/internal/cells.d.ts +19 -2
  10. package/dist/internal/cells.d.ts.map +1 -1
  11. package/dist/internal/cells.js +202 -39
  12. package/dist/internal/cells.js.map +1 -1
  13. package/dist/internal/collection-index.d.ts +3 -2
  14. package/dist/internal/collection-index.d.ts.map +1 -1
  15. package/dist/internal/collection-index.js +3 -3
  16. package/dist/internal/collection-index.js.map +1 -1
  17. package/dist/internal/collection-model.d.ts +28 -7
  18. package/dist/internal/collection-model.d.ts.map +1 -1
  19. package/dist/internal/collection-model.js +147 -127
  20. package/dist/internal/collection-model.js.map +1 -1
  21. package/dist/internal/collection.d.ts +5 -4
  22. package/dist/internal/collection.d.ts.map +1 -1
  23. package/dist/internal/collection.js +20 -21
  24. package/dist/internal/collection.js.map +1 -1
  25. package/dist/internal/controlled-sync.d.ts +6 -8
  26. package/dist/internal/controlled-sync.d.ts.map +1 -1
  27. package/dist/internal/controlled-sync.js +3 -3
  28. package/dist/internal/controlled-sync.js.map +1 -1
  29. package/dist/internal/drop-down.d.ts.map +1 -1
  30. package/dist/internal/drop-down.js +43 -44
  31. package/dist/internal/drop-down.js.map +1 -1
  32. package/dist/internal/expansion.js +4 -4
  33. package/dist/internal/expansion.js.map +1 -1
  34. package/dist/internal/selection.d.ts +1 -0
  35. package/dist/internal/selection.d.ts.map +1 -1
  36. package/dist/internal/selection.js +6 -6
  37. package/dist/internal/selection.js.map +1 -1
  38. package/dist/internal/tree-expansion.d.ts.map +1 -1
  39. package/dist/internal/tree-expansion.js +2 -11
  40. package/dist/internal/tree-expansion.js.map +1 -1
  41. package/dist/internal/tree-order.d.ts.map +1 -1
  42. package/dist/internal/tree-order.js +32 -76
  43. package/dist/internal/tree-order.js.map +1 -1
  44. package/dist/internal/use-collection.d.ts +5 -1
  45. package/dist/internal/use-collection.d.ts.map +1 -1
  46. package/dist/internal/use-collection.js +21 -7
  47. package/dist/internal/use-collection.js.map +1 -1
  48. package/dist/list-item-factory.d.ts +10 -0
  49. package/dist/list-item-factory.d.ts.map +1 -0
  50. package/dist/list-item-factory.js +14 -0
  51. package/dist/list-item-factory.js.map +1 -0
  52. package/dist/list-view.d.ts.map +1 -1
  53. package/dist/list-view.js +1 -0
  54. package/dist/list-view.js.map +1 -1
  55. package/dist/toast.d.ts +3 -5
  56. package/dist/toast.d.ts.map +1 -1
  57. package/dist/toast.js +3 -12
  58. package/dist/toast.js.map +1 -1
  59. package/dist/types.d.ts +44 -52
  60. package/dist/types.d.ts.map +1 -1
  61. package/dist/types.js.map +1 -1
  62. package/package.json +13 -10
  63. package/src/column-view.tsx +24 -12
  64. package/src/index.ts +3 -2
  65. package/src/internal/cells.tsx +330 -53
  66. package/src/internal/collection-index.ts +8 -6
  67. package/src/internal/collection-model.ts +190 -168
  68. package/src/internal/collection.ts +28 -24
  69. package/src/internal/controlled-sync.ts +9 -12
  70. package/src/internal/drop-down.tsx +64 -60
  71. package/src/internal/expansion.ts +4 -4
  72. package/src/internal/selection.tsx +8 -8
  73. package/src/internal/tree-expansion.ts +2 -14
  74. package/src/internal/tree-order.ts +33 -121
  75. package/src/internal/use-collection.tsx +29 -8
  76. package/src/list-item-factory.tsx +27 -0
  77. package/src/list-view.tsx +1 -0
  78. package/src/toast.tsx +4 -18
  79. package/src/types.ts +48 -52
package/src/toast.tsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { ReactNode, RefObject } from "react";
2
2
  import * as Adw from "@gtkx/gi/adw";
3
3
  import { createContext, useContext, useMemo } from "react";
4
- import type { ToastController, ToastOptions, ToastOverlayController, ToastProviderProps } from "./types.js";
4
+ import type { ToastController, ToastOptions, ToastProviderProps } from "./types.js";
5
5
 
6
6
  type OverlayRef = RefObject<Adw.ToastOverlay | null>;
7
7
 
@@ -11,7 +11,7 @@ const useOverlayRef = (): OverlayRef => {
11
11
  const overlayRef = useContext(ToastContext);
12
12
 
13
13
  if (overlayRef === null) {
14
- throw new Error("useToast and useToastOverlay must be used within a ToastProvider");
14
+ throw new Error("useToast must be used within a ToastProvider");
15
15
  }
16
16
 
17
17
  return overlayRef;
@@ -36,7 +36,7 @@ const buildToast = (options: ToastOptions): Adw.Toast => {
36
36
  return toast;
37
37
  };
38
38
 
39
- /** Shares an Adw.ToastOverlay reference with the toast hooks in every descendant. */
39
+ /** Shares an Adw.ToastOverlay reference with useToast in every descendant. */
40
40
  function ToastProvider(props: ToastProviderProps): ReactNode {
41
41
  return <ToastContext.Provider value={props.overlayRef}>{props.children}</ToastContext.Provider>;
42
42
  }
@@ -53,20 +53,6 @@ function useToast(): ToastController {
53
53
 
54
54
  return toast;
55
55
  },
56
- dismiss: (toast: Adw.Toast) => {
57
- toast.dismiss();
58
- },
59
- }),
60
- [overlayRef],
61
- );
62
- }
63
-
64
- /** Returns a {@link ToastOverlayController} for the nearest provider's overlay as a whole. */
65
- function useToastOverlay(): ToastOverlayController {
66
- const overlayRef = useOverlayRef();
67
-
68
- return useMemo<ToastOverlayController>(
69
- () => ({
70
56
  dismissAll: () => {
71
57
  overlayRef.current?.dismissAll();
72
58
  },
@@ -75,4 +61,4 @@ function useToastOverlay(): ToastOverlayController {
75
61
  );
76
62
  }
77
63
 
78
- export { ToastProvider, useToast, useToastOverlay };
64
+ export { ToastProvider, useToast };
package/src/types.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import type * as Adw from "@gtkx/gi/adw";
2
+ import type * as GObject from "@gtkx/gi/gobject";
2
3
  import type * as Gtk from "@gtkx/gi/gtk";
3
4
  import type { AdwComboRowProps, AdwToastProps } from "@gtkx/jsx/adw";
4
5
  import type {
@@ -8,6 +9,7 @@ import type {
8
9
  GtkGridViewProps,
9
10
  GtkListViewProps,
10
11
  } from "@gtkx/jsx/gtk";
12
+ import type { Primitive } from "@gtkx/utils";
11
13
  import type { ReactNode, RefObject } from "react";
12
14
 
13
15
  /**
@@ -15,11 +17,11 @@ import type { ReactNode, RefObject } from "react";
15
17
  * arbitrary value. Nested items form a tree.
16
18
  */
17
19
  type ListItem<T = unknown> = {
18
- /** Stable identifier used to track the item across updates and selection, naming every row that carries it. */
20
+ /** Stable identifier, unique across the collection, used to preserve identity across updates and selection. */
19
21
  id: string;
20
22
  /** Payload handed to the cell renderer as `ListItemRenderArgs.item`. */
21
23
  value: T;
22
- /** Child items nested under this one, which turn a plain item list into a tree, read only as rows are drawn. */
24
+ /** Child items in an acyclic tree, read only as rows are drawn. */
23
25
  children?: ListItem<T>[] | undefined;
24
26
  /** Hides the tree expander arrow even when the item has children, through `hide-expander`. */
25
27
  shouldHideExpander?: boolean | undefined;
@@ -31,7 +33,7 @@ type ListItem<T = unknown> = {
31
33
 
32
34
  /** A group of items rendered under a shared section header. */
33
35
  type ListSection<S = unknown, T = unknown> = {
34
- /** Stable identifier used to track the section across updates. */
36
+ /** Stable identifier, unique among sections, used to track the section across updates. */
35
37
  id: string;
36
38
  /** Payload handed to the section header renderer as `ListSectionRenderArgs.section`. */
37
39
  value: S;
@@ -90,12 +92,25 @@ type ItemSizeProps = {
90
92
  estimatedItemWidth?: number | undefined;
91
93
  };
92
94
 
95
+ type ListItemFactoryProps<T extends GObject.Object> = ItemSizeProps & {
96
+ renderItem: ListItemRenderer<T>;
97
+ };
98
+
99
+ /** The flat-collection hint shared by {@link ListView} and {@link ColumnView}. */
100
+ type FlatnessProps = {
101
+ /**
102
+ * Declares every item a leaf, so the view skips tree discovery when synchronising a large collection
103
+ * instead of scanning each item for `children`. Must not be set when any item has children: those
104
+ * items would render as plain rows that never expand.
105
+ */
106
+ isFlat?: boolean | undefined;
107
+ };
108
+
93
109
  /** Controlled selection shared by the multi-item collection views. */
94
110
  type SelectionProps = {
95
111
  /**
96
112
  * Ids of the items to keep selected; omitting it keeps nothing selected, and `onSelectionChanged` is how a
97
- * user's selection is adopted into it. An id repeated in several branches of a tree names every matching row,
98
- * and a single-selection view takes the first of them.
113
+ * user's selection is adopted into it.
99
114
  */
100
115
  selectedIds?: string[] | null | undefined;
101
116
  /** Called with one id per selected row whenever the selection changes, and once on mount. */
@@ -120,9 +135,7 @@ type ExpanderDescriptions = {
120
135
  type ExpansionProps = {
121
136
  /**
122
137
  * Ids of the items to keep expanded; omitting it keeps every row collapsed, and `onExpandedChange` is how a
123
- * user's expansion is adopted into it. An id repeated in several branches names every matching row, so all of
124
- * them expand together. An item whose children lead back to itself expands one level at a time, since a row
125
- * repeating an item already expanded above it stays collapsed.
138
+ * user's expansion is adopted into it.
126
139
  */
127
140
  expandedIds?: string[] | null | undefined;
128
141
  /** Called with one id per expanded row, in visible order, whenever expansion changes. */
@@ -146,12 +159,15 @@ type SortProps = {
146
159
  };
147
160
 
148
161
  /** The data a collection view renders, either as a plain item list or grouped into sections. */
149
- type SourceProps<T, S> = {
150
- /** Items to render, nesting through `ListItem.children` for a tree; ignored once `sections` is given. */
162
+ type SourceProps<T, S> = ({
163
+ /** Items to render, nesting through `ListItem.children` for a tree. */
151
164
  items?: ListItem<T>[] | undefined;
152
- /** Items grouped under section headers, rendered in place of `items`. */
153
- sections?: ListSection<S, T>[] | undefined;
154
- };
165
+ } & Partial<Record<"sections", undefined>> & Partial<Record<"renderHeader", null | undefined>>) | ({
166
+ /** Items grouped under section headers. */
167
+ sections: ListSection<S, T>[];
168
+ /** Renders the header shown above each section. */
169
+ renderHeader?: ListSectionRenderer<S> | null | undefined;
170
+ } & Partial<Record<"items", undefined>>);
155
171
 
156
172
  /** One column of a {@link ColumnView}, pairing Gtk.ColumnViewColumn props with a cell renderer. */
157
173
  type ColumnViewColumn<T = unknown> = Omit<GtkColumnViewColumnProps, "factory" | "sorter" | "id" | "title"> & {
@@ -172,39 +188,33 @@ type ColumnViewOwnProps<T, S> = SelectionProps &
172
188
  ExpansionProps &
173
189
  SortProps &
174
190
  SourceProps<T, S> &
191
+ FlatnessProps &
175
192
  Omit<ItemSizeProps, "estimatedItemWidth"> & {
176
193
  /** Columns to render, in order; each carries its own cell renderer. */
177
194
  columns: ColumnViewColumn<T>[];
178
- /** Renders the header shown above each section. */
179
- renderHeader?: ListSectionRenderer<S> | null | undefined;
180
195
  /** Resolves the props of the row carrying one item's cells, such as its screen-reader label. */
181
196
  rowProps?: ListRowPropsResolver<T> | null | undefined;
182
197
  };
183
198
 
184
199
  /**
185
- * Props for {@link ColumnView}. Combines the underlying Gtk.ColumnView props with
186
- * declarative collection props: flat items or grouped sections, controlled selection
187
- * and expansion, sorting (sortColumn, sortOrder, onSortChanged), an optional section
188
- * header renderer, per-row props, and the columns to render.
200
+ * Native `Gtk.ColumnView` props with declarative columns and collections, controlled selection, expansion, and sorting.
189
201
  */
190
202
  type ColumnViewProps<T = unknown, S = unknown> = Omit<
191
203
  GtkColumnViewProps,
192
- "columns" | "model" | "headerFactory" | "rowFactory" | keyof ColumnViewOwnProps<T, S>
204
+ "children" | "columns" | "model" | "headerFactory" | "rowFactory" | keyof ColumnViewOwnProps<T, S>
193
205
  > &
194
206
  ColumnViewOwnProps<T, S>;
195
207
 
196
208
  /** The declarative collection props {@link DropDown} and `ComboRow` add on top of their widget's own. */
197
209
  type DropDownOwnProps<T, S> = SourceProps<T, S> & {
198
210
  /** Id of the currently selected item, making the selection controlled. */
199
- selectedId?: string | null | undefined;
200
- /** Called with the id of the item that became selected. */
201
- onSelectionChanged?: ((id: string) => void) | null | undefined;
202
- /** Renders the collapsed display, and the popup rows too unless `renderListItem` is given. */
211
+ selectedId?: string | undefined;
212
+ /** Called with the selected id, or `null` when the model becomes empty. */
213
+ onSelectionChanged?: ((id: string | null) => void) | null | undefined;
214
+ /** Renders the collapsed display and, unless overridden, the popup rows. Required for non-primitive values. */
203
215
  renderItem?: ListItemRenderer<T> | null | undefined;
204
216
  /** Renderer for items in the open popup list, falling back to renderItem when omitted. */
205
217
  renderListItem?: ListItemRenderer<T> | null | undefined;
206
- /** Renderer for section headers in the popup list. */
207
- renderHeader?: ListSectionRenderer<S> | null | undefined;
208
218
  };
209
219
 
210
220
  /** A drop-down-shaped widget's props with its model and factories swapped for the declarative collection props. */
@@ -212,12 +222,11 @@ type DropDownWidgetProps<Widget, T, S> = Omit<
212
222
  Widget,
213
223
  "model" | "factory" | "listFactory" | "headerFactory" | keyof DropDownOwnProps<T, S>
214
224
  > &
215
- DropDownOwnProps<T, S>;
225
+ DropDownOwnProps<T, S> &
226
+ (SourceProps<T & Primitive, S> | Record<"renderItem", ListItemRenderer<T>>);
216
227
 
217
228
  /**
218
- * Props for {@link DropDown}. Combines the underlying Gtk.DropDown props with the declarative
219
- * collection props: flat items or grouped sections, controlled single selection, and renderers
220
- * for the collapsed display, popup rows, and popup section headers.
229
+ * Native `Gtk.DropDown` props with declarative collections, controlled selection, and display/popup renderers.
221
230
  */
222
231
  type DropDownProps<T = unknown, S = unknown> = DropDownWidgetProps<GtkDropDownProps, T, S>;
223
232
 
@@ -231,9 +240,7 @@ type GridViewOwnProps<T> = ItemSizeProps &
231
240
  };
232
241
 
233
242
  /**
234
- * Props for {@link GridView}. Combines the underlying Gtk.GridView props with
235
- * declarative collection props: items, a per-cell renderItem, controlled selection,
236
- * and estimated item sizing.
243
+ * Native `Gtk.GridView` props with declarative cells, controlled selection, and estimated sizing.
237
244
  */
238
245
  type GridViewProps<T = unknown> = Omit<GtkGridViewProps, "model" | "factory" | keyof GridViewOwnProps<T>> &
239
246
  GridViewOwnProps<T>;
@@ -242,18 +249,15 @@ type GridViewProps<T = unknown> = Omit<GtkGridViewProps, "model" | "factory" | k
242
249
  type ListViewOwnProps<T, S> = ItemSizeProps &
243
250
  SelectionProps &
244
251
  ExpansionProps &
245
- SourceProps<T, S> & {
252
+ SourceProps<T, S> &
253
+ FlatnessProps & {
246
254
  /** Renders the contents of one row. */
247
255
  renderItem: ListItemRenderer<T>;
248
- /** Renders the header shown above each section. */
249
- renderHeader?: ListSectionRenderer<S> | null | undefined;
250
256
  };
251
257
 
252
258
  /**
253
- * Props for {@link ListView}. Combines the underlying Gtk.ListView props with
254
- * declarative collection props: flat items or grouped sections, a per-row renderItem,
255
- * an optional section header renderer, controlled selection and expansion, and
256
- * estimated item sizing.
259
+ * Native `Gtk.ListView` props with declarative rows and sections, controlled selection and expansion,
260
+ * and estimated sizing.
257
261
  */
258
262
  type ListViewProps<T = unknown, S = unknown> = Omit<
259
263
  GtkListViewProps,
@@ -262,9 +266,7 @@ type ListViewProps<T = unknown, S = unknown> = Omit<
262
266
  ListViewOwnProps<T, S>;
263
267
 
264
268
  /**
265
- * Props for {@link ComboRow}. Combines the underlying Adw.ComboRow props with the declarative
266
- * collection props: flat items or grouped sections, controlled single selection, and renderers
267
- * for the row display, popup rows, and popup section headers.
269
+ * Native `Adw.ComboRow` props with declarative collections, controlled selection, and display/popup renderers.
268
270
  */
269
271
  type ComboRowProps<T = unknown, S = unknown> = DropDownWidgetProps<AdwComboRowProps, T, S>;
270
272
  /**
@@ -273,16 +275,10 @@ type ComboRowProps<T = unknown, S = unknown> = DropDownWidgetProps<AdwComboRowPr
273
275
  */
274
276
  type ToastOptions = Adw.ToastConstructorProps & Pick<AdwToastProps, "onButtonClicked" | "onDismissed">;
275
277
 
276
- /** Imperative controls for individual toasts, returned by {@link useToast}. */
278
+ /** Imperative controls for toasts, returned by {@link useToast}. */
277
279
  type ToastController = {
278
280
  /** Builds a toast, shows it through the overlay, and returns it. */
279
281
  show: (options?: ToastOptions) => Adw.Toast;
280
- /** Dismisses a single toast, typically one returned by `ToastController.show`. */
281
- dismiss: (toast: Adw.Toast) => void;
282
- };
283
-
284
- /** Imperative controls for the overlay as a whole, returned by {@link useToastOverlay}. */
285
- type ToastOverlayController = {
286
282
  /** Dismisses the shown toast and every queued one. */
287
283
  dismissAll: () => void;
288
284
  };
@@ -291,7 +287,7 @@ type ToastOverlayController = {
291
287
  type ToastProviderProps = {
292
288
  /** Ref also given to the `AdwToastOverlay` the toasts appear over. */
293
289
  overlayRef: RefObject<Adw.ToastOverlay | null>;
294
- /** Subtree whose `useToast` and `useToastOverlay` calls target that overlay. */
290
+ /** Subtree whose `useToast` calls target that overlay. */
295
291
  children?: ReactNode | undefined;
296
292
  };
297
293
 
@@ -307,6 +303,7 @@ export {
307
303
  type ListRowProps,
308
304
  type ListSectionRenderArgs,
309
305
  type ListItemRenderer,
306
+ type ListItemFactoryProps,
310
307
  type ListRowPropsResolver,
311
308
  type ListSectionRenderer,
312
309
  type ColumnViewColumn,
@@ -317,6 +314,5 @@ export {
317
314
  type ComboRowProps,
318
315
  type ToastOptions,
319
316
  type ToastController,
320
- type ToastOverlayController,
321
317
  type ToastProviderProps,
322
318
  };