@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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/adw/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElD;;;GAGG;AACH,KAAK,YAAY,GAAG,GAAG,CAAC,qBAAqB,GAAG,IAAI,CAAC,aAAa,EAAE,iBAAiB,GAAG,aAAa,CAAC,CAAC;AAEvG,+EAA+E;AAC/E,KAAK,eAAe,GAAG;IACnB,oEAAoE;IACpE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,YAAY,KAAK,GAAG,CAAC,KAAK,CAAC;IAC5C,wFAAwF;IACxF,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,KAAK,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,2FAA2F;AAC3F,KAAK,sBAAsB,GAAG;IAC1B,sDAAsD;IACtD,UAAU,EAAE,MAAM,IAAI,CAAC;CAC1B,CAAC;AAEF,uCAAuC;AACvC,KAAK,kBAAkB,GAAG;IACtB,sEAAsE;IACtE,UAAU,EAAE,SAAS,CAAC,GAAG,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IAC/C,QAAQ,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;CACpC,CAAC;AAEF,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,KAAK,sBAAsB,EAAE,KAAK,kBAAkB,EAAE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/adw/types.ts"],"names":[],"mappings":"AA+BA,OAAO,EAAiG,CAAC","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport type { AdwToastProps } from \"@gtkx/jsx/adw\";\nimport type { ReactNode, RefObject } from \"react\";\n\n/**\n * Describes a toast raised through {@link useToast}: the construct-time properties of an\n * `Adw.Toast` plus its `button-clicked` and `dismissed` handlers.\n */\ntype ToastOptions = Adw.ToastConstructorProps & Pick<AdwToastProps, \"onButtonClicked\" | \"onDismissed\">;\n\n/** Imperative controls for individual toasts, returned by {@link useToast}. */\ntype ToastController = {\n /** Builds a toast, shows it through the overlay, and returns it. */\n show: (options?: ToastOptions) => Adw.Toast;\n /** Dismisses a single toast, typically one returned by {@link ToastController.show}. */\n dismiss: (toast: Adw.Toast) => void;\n};\n\n/** Imperative controls for the overlay as a whole, returned by {@link useToastOverlay}. */\ntype ToastOverlayController = {\n /** Dismisses the shown toast and every queued one. */\n dismissAll: () => void;\n};\n\n/** Props for {@link ToastProvider}. */\ntype ToastProviderProps = {\n /** Ref also given to the `AdwToastOverlay` the toasts appear over. */\n overlayRef: RefObject<Adw.ToastOverlay | null>;\n children?: ReactNode | undefined;\n};\n\nexport { type ToastOptions, type ToastController, type ToastOverlayController, type ToastProviderProps };\n"]}
@@ -1,18 +1,10 @@
1
- import { type GtkColumnViewProps } from "@gtkx/jsx/gtk";
2
- import { type ReactNode } from "react";
1
+ import type { ReactNode } from "react";
3
2
  import type { ColumnViewProps } from "./types.js";
4
3
  /**
5
- * Props for the {@link ColumnView} component: the raw `GtkColumnView` element
6
- * surface (minus its imperative `columns` property) with its model/sort wiring
7
- * replaced by the declarative {@link ColumnViewProps} API. Columns are declared
8
- * as {@link ColumnViewColumn} children.
4
+ * Renders a Gtk.ColumnView from declarative items or sections and a columns array,
5
+ * with controlled selection, expansion, and sorting, per-column header menus, and
6
+ * section header rendering.
9
7
  */
10
- export type ColumnViewComponentProps<T = unknown, S = unknown> = Omit<GtkColumnViewProps, "columns" | keyof ColumnViewProps<T, S>> & ColumnViewProps<T, S>;
11
- /**
12
- * A `GtkColumnView` driven by a declarative `items` model with optional
13
- * controlled selection, controlled sorting, and section headers. Columns are
14
- * declared as {@link ColumnViewColumn} children. Supplying an external `model`
15
- * switches to the uncontrolled form.
16
- */
17
- export declare const ColumnView: <T = unknown, S = unknown>(props: ColumnViewComponentProps<T, S>) => ReactNode;
8
+ declare function ColumnView<T = unknown, S = unknown>(props: ColumnViewProps<T, S>): ReactNode;
9
+ export { ColumnView };
18
10
  //# sourceMappingURL=column-view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"column-view.d.ts","sourceRoot":"","sources":["../src/column-view.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAiB,KAAK,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAEvE,OAAO,EAAiB,KAAK,SAAS,EAAoD,MAAM,OAAO,CAAC;AAaxG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAmClD;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,IAAI,CACjE,kBAAkB,EAClB,SAAS,GAAG,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAC1C,GACG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAoF1B;;;;;GAKG;AACH,eAAO,MAAM,UAAU,GAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,OAAO,wBAAwB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,SAqD5F,CAAC"}
1
+ {"version":3,"file":"column-view.d.ts","sourceRoot":"","sources":["../src/column-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAU,eAAe,EAAE,MAAM,YAAY,CAAC;AAiK1D;;;;GAIG;AACH,iBAAS,UAAU,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,KAAK,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CA6BrF;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}
@@ -1,108 +1,106 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { GtkColumnView } from "@gtkx/jsx/gtk";
3
- import { useForwardedRef } from "@gtkx/react";
4
- import { createElement, useCallback, useMemo, useRef, useState } from "react";
5
- import { ColumnViewContext, } from "./contexts/column-view-context.js";
6
- import { useListModel } from "./hooks/use-list-model.js";
7
- import { useModelInstallation } from "./hooks/use-model-installation.js";
8
- import { useRealizedSlots } from "./hooks/use-realized-slots.js";
9
- import { useSelectionModel } from "./hooks/use-selection-model.js";
10
- import { useSortHandler } from "./hooks/use-sort-handler.js";
11
- import { ListPortalHost } from "./list-portal-host.js";
12
- const headerFactoryBinding = {
13
- install: (widget, factory) => widget.setHeaderFactory(factory),
14
- uninstall: (widget) => widget.setHeaderFactory(null),
2
+ import * as Gtk from "@gtkx/gi/gtk";
3
+ import { GtkColumnView, GtkColumnViewColumn, GtkCustomSorter, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
4
+ import { useProperty, useSignal } from "@gtkx/react";
5
+ import { omit } from "@gtkx/utils";
6
+ import { useLayoutEffect, useRef } from "react";
7
+ import { HeaderPortals, ItemPortals, useHeaderCells, useItemCells } from "./internal/cells.js";
8
+ import { useCollection } from "./internal/use-collection.js";
9
+ import { useWidgetRef } from "./internal/use-widget-ref.js";
10
+ const COLUMN_VIEW_PROPS = [
11
+ "items",
12
+ "sections",
13
+ "renderHeader",
14
+ "columns",
15
+ "selectedIds",
16
+ "onSelectionChanged",
17
+ "selectionMode",
18
+ "expandedIds",
19
+ "onExpandedChange",
20
+ "sortColumn",
21
+ "sortOrder",
22
+ "onSortChanged",
23
+ "estimatedItemHeight",
24
+ "children",
25
+ "ref",
26
+ ];
27
+ const columnById = (view, id) => {
28
+ const columns = view.getColumns();
29
+ for (let index = 0; index < columns.getNItems(); index++) {
30
+ const column = columns.getItem(index);
31
+ if (column instanceof Gtk.ColumnViewColumn && column.getId() === id) {
32
+ return column;
33
+ }
34
+ }
35
+ return null;
15
36
  };
16
- const useColumnRegistry = () => {
17
- const [registrations, setRegistrations] = useState(() => new Map());
18
- const register = useCallback((registration) => {
19
- setRegistrations((current) => {
20
- const next = new Map(current);
21
- next.set(registration.id, registration);
22
- return next;
23
- });
24
- }, []);
25
- const unregister = useCallback((id) => {
26
- setRegistrations((current) => {
27
- if (!current.has(id))
28
- return current;
29
- const next = new Map(current);
30
- next.delete(id);
31
- return next;
32
- });
33
- }, []);
34
- const columns = useMemo(() => [...registrations.values()], [registrations]);
35
- return { columns, register, unregister };
37
+ const getSortTarget = (view, sortColumn) => {
38
+ if (view === null || sortColumn === undefined) {
39
+ return null;
40
+ }
41
+ if (sortColumn === null) {
42
+ return { view, column: null };
43
+ }
44
+ const column = columnById(view, sortColumn);
45
+ return column === null ? null : { view, column };
36
46
  };
37
- const headerRenderer = (renderHeader) => (value) => renderHeader ? renderHeader(value) : null;
38
- const useColumnViewWiring = (props, registry) => {
39
- const widgetRef = useRef(null);
40
- const captureWidget = useCallback((value) => {
41
- widgetRef.current = value;
42
- }, []);
43
- const [, setRef] = useForwardedRef(props.ref, captureWidget);
44
- const externalModel = props.model;
45
- const listModel = useListModel(externalModel === undefined ? { items: props.items } : { model: externalModel });
46
- const controlledSelection = useSelectionModel({
47
- base: listModel.model,
48
- selectionMode: props.selectionMode,
49
- selected: props.selected,
50
- onSelectionChanged: props.onSelectionChanged,
51
- resolver: listModel.resolver,
52
- });
53
- const installedModel = externalModel === undefined ? controlledSelection : externalModel;
54
- useModelInstallation(widgetRef, installedModel, (widget, model) => widget.setModel(model));
55
- const useHeader = externalModel === undefined && typeof props.renderHeader === "function";
56
- const headers = useRealizedSlots({
57
- target: useHeader ? widgetRef : null,
58
- binding: headerFactoryBinding,
59
- estimatedHeight: props.estimatedRowHeight ?? undefined,
60
- });
61
- useSortHandler({
62
- columnView: widgetRef,
63
- sortColumn: props.sortColumn,
64
- sortOrder: props.sortOrder,
65
- onSortChanged: props.onSortChanged,
66
- columns: registry.columns,
47
+ const applySort = (sorting, view, column, order) => {
48
+ sorting.current = true;
49
+ try {
50
+ view.sortByColumn(column, order ?? Gtk.SortType.ASCENDING);
51
+ }
52
+ finally {
53
+ sorting.current = false;
54
+ }
55
+ };
56
+ const emitSortChanged = (sorter, sorting, sort) => {
57
+ if (sorter === null || sorting.current) {
58
+ return;
59
+ }
60
+ sort.onSortChanged?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());
61
+ };
62
+ const syncSort = (sorting, view, sortColumn, sortOrder) => {
63
+ const target = getSortTarget(view, sortColumn);
64
+ if (target === null) {
65
+ return;
66
+ }
67
+ applySort(sorting, target.view, target.column, sortOrder);
68
+ };
69
+ const useColumnSorting = (view, sort, columns) => {
70
+ const sorting = useRef(false);
71
+ const sorter = useProperty(view, "sorter");
72
+ const columnSorter = sorter instanceof Gtk.ColumnViewSorter ? sorter : null;
73
+ useSignal(columnSorter, "changed", () => {
74
+ emitSortChanged(columnSorter, sorting, sort);
67
75
  });
68
- const contextValue = useMemo(() => ({
69
- columnView: widgetRef,
70
- resolver: listModel.resolver,
71
- register: registry.register,
72
- unregister: registry.unregister,
73
- }), [listModel.resolver, registry.register, registry.unregister]);
74
- return {
75
- setRef,
76
- resolver: listModel.resolver,
77
- headerResolver: listModel.headerResolver,
78
- headerStore: headers.store,
79
- useHeader,
80
- contextValue,
81
- };
76
+ const { sortColumn, sortOrder } = sort;
77
+ useLayoutEffect(() => {
78
+ syncSort(sorting, view, sortColumn, sortOrder);
79
+ }, [view, sortColumn, sortOrder, columns]);
80
+ };
81
+ const ColumnCells = ({ column, collection, expandedIds, size }) => {
82
+ const cells = useItemCells(size);
83
+ const rest = omit(column, ["id", "renderCell", "sortable"]);
84
+ return (_jsxs(_Fragment, { children: [_jsx(GtkColumnViewColumn, { id: column.id, factory: _jsx(GtkSignalListItemFactory, { ...cells.handlers }), sorter: column.sortable === true ? _jsx(GtkCustomSorter, {}) : null, ...rest }), _jsx(ItemPortals, { store: cells, render: column.renderCell, collection: collection, expandedIds: expandedIds })] }));
82
85
  };
86
+ const ColumnList = ({ columns, collection, expandedIds, size }) => columns.map((column) => (_jsx(ColumnCells, { column: column, collection: collection, expandedIds: expandedIds, size: size }, column.id)));
83
87
  /**
84
- * A `GtkColumnView` driven by a declarative `items` model with optional
85
- * controlled selection, controlled sorting, and section headers. Columns are
86
- * declared as {@link ColumnViewColumn} children. Supplying an external `model`
87
- * switches to the uncontrolled form.
88
+ * Renders a Gtk.ColumnView from declarative items or sections and a columns array,
89
+ * with controlled selection, expansion, and sorting, per-column header menus, and
90
+ * section header rendering.
88
91
  */
89
- export const ColumnView = (props) => {
90
- const { ref, items, model, selected, selectionMode, onSelectionChanged, sortColumn, sortOrder, onSortChanged, renderHeader, estimatedRowHeight, children, ...intrinsicProps } = props;
91
- const registry = useColumnRegistry();
92
- const wiring = useColumnViewWiring({
93
- ref,
94
- items,
95
- model,
96
- selected,
97
- selectionMode,
98
- onSelectionChanged,
99
- sortColumn,
100
- sortOrder,
101
- onSortChanged,
102
- renderHeader,
103
- estimatedRowHeight,
104
- }, registry);
105
- const intrinsic = createElement(GtkColumnView, { ...intrinsicProps, ref: wiring.setRef }, _jsx(ColumnViewContext.Provider, { value: wiring.contextValue, children: children }));
106
- return (_jsxs(_Fragment, { children: [intrinsic, wiring.useHeader ? (_jsx(ListPortalHost, { store: wiring.headerStore, resolver: wiring.headerResolver, render: headerRenderer(renderHeader) })) : null] }));
107
- };
92
+ function ColumnView(props) {
93
+ const { renderHeader, columns, expandedIds, sortColumn, sortOrder, onSortChanged, estimatedItemHeight, ref } = props;
94
+ const rest = omit(props, COLUMN_VIEW_PROPS);
95
+ const [view, refCallback] = useWidgetRef(ref);
96
+ const size = { width: -1, height: estimatedItemHeight ?? -1 };
97
+ const { collection, selection } = useCollection(props);
98
+ const headerCells = useHeaderCells(size);
99
+ const columnList = columns;
100
+ useColumnSorting(view, { sortColumn, sortOrder, onSortChanged }, columnList);
101
+ return (_jsxs(_Fragment, { children: [_jsx(GtkColumnView, { ref: refCallback, model: selection, ...(renderHeader != null && {
102
+ headerFactory: _jsx(GtkSignalListItemFactory, { ...headerCells.handlers }),
103
+ }), ...rest, children: _jsx(ColumnList, { columns: columnList, collection: collection, expandedIds: expandedIds, size: size }) }), renderHeader != null && (_jsx(HeaderPortals, { store: headerCells, render: renderHeader, collection: collection }))] }));
104
+ }
105
+ export { ColumnView };
108
106
  //# sourceMappingURL=column-view.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"column-view.js","sourceRoot":"","sources":["../src/column-view.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"column-view.js","sourceRoot":"","sources":["../src/column-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { GtkColumnView, GtkColumnViewColumn, GtkCustomSorter, GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport { useProperty, useSignal } from \"@gtkx/react\";\nimport { omit } from \"@gtkx/utils\";\nimport { useLayoutEffect, useRef } from \"react\";\nimport type { CellSize } from \"./internal/cells.js\";\nimport type { Collection } from \"./internal/collection.js\";\nimport type { Column, ColumnViewProps } from \"./types.js\";\nimport { HeaderPortals, ItemPortals, useHeaderCells, useItemCells } from \"./internal/cells.js\";\nimport { useCollection } from \"./internal/use-collection.js\";\nimport { useWidgetRef } from \"./internal/use-widget-ref.js\";\n\ntype SortProps = {\n sortColumn?: string | null | undefined;\n sortOrder?: Gtk.SortType | null | undefined;\n onSortChanged?: ((column: string | null, order: Gtk.SortType) => void) | null | undefined;\n};\n\ntype SortTarget = { view: Gtk.ColumnView; column: Gtk.ColumnViewColumn | null };\n\ntype ColumnCellsProps = {\n column: Column<never>;\n collection: Collection;\n expandedIds: string[] | null | undefined;\n size: CellSize;\n};\n\ntype ColumnListProps = Omit<ColumnCellsProps, \"column\"> & {\n columns: Column<never>[];\n};\n\nconst COLUMN_VIEW_PROPS = [\n \"items\",\n \"sections\",\n \"renderHeader\",\n \"columns\",\n \"selectedIds\",\n \"onSelectionChanged\",\n \"selectionMode\",\n \"expandedIds\",\n \"onExpandedChange\",\n \"sortColumn\",\n \"sortOrder\",\n \"onSortChanged\",\n \"estimatedItemHeight\",\n \"children\",\n \"ref\",\n] as const satisfies (keyof ColumnViewProps)[];\n\nconst columnById = (view: Gtk.ColumnView, id: string): Gtk.ColumnViewColumn | null => {\n const columns = view.getColumns();\n\n for (let index = 0; index < columns.getNItems(); index++) {\n const column = columns.getItem(index);\n\n if (column instanceof Gtk.ColumnViewColumn && column.getId() === id) {\n return column;\n }\n }\n\n return null;\n};\n\nconst getSortTarget = (view: Gtk.ColumnView | null, sortColumn: string | null | undefined): SortTarget | null => {\n if (view === null || sortColumn === undefined) {\n return null;\n }\n\n if (sortColumn === null) {\n return { view, column: null };\n }\n\n const column = columnById(view, sortColumn);\n\n return column === null ? null : { view, column };\n};\n\nconst applySort = (\n sorting: { current: boolean },\n view: Gtk.ColumnView,\n column: Gtk.ColumnViewColumn | null,\n order: Gtk.SortType | null | undefined,\n): void => {\n sorting.current = true;\n\n try {\n view.sortByColumn(column, order ?? Gtk.SortType.ASCENDING);\n } finally {\n sorting.current = false;\n }\n};\n\nconst emitSortChanged = (\n sorter: Gtk.ColumnViewSorter | null,\n sorting: { current: boolean },\n sort: SortProps,\n): void => {\n if (sorter === null || sorting.current) {\n return;\n }\n\n sort.onSortChanged?.(sorter.getPrimarySortColumn()?.getId() ?? null, sorter.getPrimarySortOrder());\n};\n\nconst syncSort = (\n sorting: { current: boolean },\n view: Gtk.ColumnView | null,\n sortColumn: string | null | undefined,\n sortOrder: Gtk.SortType | null | undefined,\n): void => {\n const target = getSortTarget(view, sortColumn);\n\n if (target === null) {\n return;\n }\n\n applySort(sorting, target.view, target.column, sortOrder);\n};\n\nconst useColumnSorting = (view: Gtk.ColumnView | null, sort: SortProps, columns: Column<never>[]): void => {\n const sorting = useRef(false);\n const sorter = useProperty(view, \"sorter\");\n const columnSorter = sorter instanceof Gtk.ColumnViewSorter ? sorter : null;\n\n useSignal(columnSorter, \"changed\", (): void => {\n emitSortChanged(columnSorter, sorting, sort);\n });\n\n const { sortColumn, sortOrder } = sort;\n\n useLayoutEffect(() => {\n syncSort(sorting, view, sortColumn, sortOrder);\n }, [view, sortColumn, sortOrder, columns]);\n};\n\nconst ColumnCells = ({ column, collection, expandedIds, size }: ColumnCellsProps): ReactNode => {\n const cells = useItemCells(size);\n const rest = omit(column, [\"id\", \"renderCell\", \"sortable\"]);\n\n return (\n <>\n <GtkColumnViewColumn\n id={column.id}\n factory={<GtkSignalListItemFactory {...cells.handlers} />}\n sorter={column.sortable === true ? <GtkCustomSorter /> : null}\n {...rest}\n />\n <ItemPortals\n store={cells}\n render={column.renderCell}\n collection={collection}\n expandedIds={expandedIds}\n />\n </>\n );\n};\n\nconst ColumnList = ({ columns, collection, expandedIds, size }: ColumnListProps): ReactNode =>\n columns.map((column) => (\n <ColumnCells\n key={column.id}\n column={column}\n collection={collection}\n expandedIds={expandedIds}\n size={size}\n />\n ));\n\n/**\n * Renders a Gtk.ColumnView from declarative items or sections and a columns array,\n * with controlled selection, expansion, and sorting, per-column header menus, and\n * section header rendering.\n */\nfunction ColumnView<T = unknown, S = unknown>(props: ColumnViewProps<T, S>): ReactNode {\n const { renderHeader, columns, expandedIds, sortColumn, sortOrder, onSortChanged, estimatedItemHeight, ref } =\n props;\n\n const rest = omit(props, COLUMN_VIEW_PROPS);\n const [view, refCallback] = useWidgetRef<Gtk.ColumnView>(ref);\n const size = { width: -1, height: estimatedItemHeight ?? -1 };\n const { collection, selection } = useCollection(props);\n const headerCells = useHeaderCells(size);\n const columnList = columns as Column<never>[];\n useColumnSorting(view, { sortColumn, sortOrder, onSortChanged }, columnList);\n\n return (\n <>\n <GtkColumnView\n ref={refCallback}\n model={selection}\n {...(renderHeader != null && {\n headerFactory: <GtkSignalListItemFactory {...headerCells.handlers} />,\n })}\n {...rest}\n >\n <ColumnList columns={columnList} collection={collection} expandedIds={expandedIds} size={size} />\n </GtkColumnView>\n {renderHeader != null && (\n <HeaderPortals store={headerCells} render={renderHeader} collection={collection} />\n )}\n </>\n );\n}\n\nexport { ColumnView };\n"]}
@@ -1,41 +1,12 @@
1
- import type * as Gio from "@gtkx/gi/gio";
2
- import type * as Gtk from "@gtkx/gi/gtk";
3
- import { type AdwComboRowProps } from "@gtkx/jsx/adw";
4
- import { type GtkDropDownProps } from "@gtkx/jsx/gtk";
5
- import { type ReactNode } from "react";
1
+ import type { ElementType, ReactNode } from "react";
2
+ import { GtkDropDown } from "@gtkx/jsx/gtk";
6
3
  import type { DropDownProps } from "./types.js";
7
- export interface DropDownWidget extends Gtk.Widget {
8
- getSelected(): number;
9
- setSelected(position: number): void;
10
- setModel(model: Gio.ListModel | null): void;
11
- setFactory(factory: Gtk.ListItemFactory | null): void;
12
- setListFactory(factory: Gtk.ListItemFactory | null): void;
13
- setHeaderFactory(factory: Gtk.ListItemFactory | null): void;
14
- }
4
+ type DropDownComponent = <T = unknown, S = unknown, C extends ElementType = typeof GtkDropDown>(props: DropDownProps<T, S, C>) => ReactNode;
15
5
  /**
16
- * Props for the {@link DropDown} component: the raw `GtkDropDown` element
17
- * surface with its factory/model wiring replaced by the declarative
18
- * {@link DropDownProps} API.
6
+ * Renders a drop-down backed by a collection model, with customizable renderers for the
7
+ * collapsed display, popup rows, and popup section headers, and controlled selection.
8
+ * The backing widget defaults to GtkDropDown and is swappable through `component`.
19
9
  */
20
- export type DropDownComponentProps<T = unknown, S = unknown> = Omit<GtkDropDownProps, keyof DropDownProps<T, S>> & DropDownProps<T, S>;
21
- /**
22
- * Props for the {@link ComboRow} component: the raw `AdwComboRow` element
23
- * surface with its factory/model wiring replaced by the declarative
24
- * {@link DropDownProps} API.
25
- */
26
- export type ComboRowComponentProps<T = unknown, S = unknown> = Omit<AdwComboRowProps, keyof DropDownProps<T, S>> & DropDownProps<T, S>;
27
- /**
28
- * A `GtkDropDown` driven by a declarative `items` model with a controlled
29
- * `selectedId` and per-slot renderers for the selected face, the popup list,
30
- * and section headers. Supplying an external `model` switches to the
31
- * uncontrolled form.
32
- */
33
- export declare const DropDown: <T = unknown, S = unknown>(props: DropDownComponentProps<T, S>) => ReactNode;
34
- /**
35
- * An `AdwComboRow` driven by a declarative `items` model with a controlled
36
- * `selectedId` and per-slot renderers for the selected face, the popup list,
37
- * and section headers. Supplying an external `model` switches to the
38
- * uncontrolled form.
39
- */
40
- export declare const ComboRow: <T = unknown, S = unknown>(props: ComboRowComponentProps<T, S>) => ReactNode;
10
+ declare const DropDown: DropDownComponent;
11
+ export { DropDown };
41
12
  //# sourceMappingURL=drop-down.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"drop-down.d.ts","sourceRoot":"","sources":["../src/drop-down.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACnE,OAAO,EAAe,KAAK,gBAAgB,EAAY,MAAM,eAAe,CAAC;AAE7E,OAAO,EAIH,KAAK,SAAS,EAKjB,MAAM,OAAO,CAAC;AAOf,OAAO,KAAK,EAAE,aAAa,EAAY,MAAM,YAAY,CAAC;AAI1D,MAAM,WAAW,cAAe,SAAQ,GAAG,CAAC,MAAM;IAC9C,WAAW,IAAI,MAAM,CAAC;IACtB,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;IAC5C,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;IACtD,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;IAC1D,gBAAgB,CAAC,OAAO,EAAE,GAAG,CAAC,eAAe,GAAG,IAAI,GAAG,IAAI,CAAC;CAC/D;AA6LD;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC5G,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAExB;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,gBAAgB,EAAE,MAAM,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAC5G,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,OAAO,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,SAGxF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,OAAO,sBAAsB,CAAC,CAAC,EAAE,CAAC,CAAC,KAAG,SAGxF,CAAC"}
1
+ {"version":3,"file":"drop-down.d.ts","sourceRoot":"","sources":["../src/drop-down.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAkB,MAAM,OAAO,CAAC;AACpE,OAAO,EAAE,WAAW,EAAsC,MAAM,eAAe,CAAC;AAKhF,OAAO,KAAK,EAAE,aAAa,EAAgC,MAAM,YAAY,CAAC;AAwB9E,KAAK,iBAAiB,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EAAE,CAAC,SAAS,WAAW,GAAG,OAAO,WAAW,EAC1F,KAAK,EAAE,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAC5B,SAAS,CAAC;AAcf;;;;GAIG;AACH,QAAA,MAAM,QAAQ,EAAE,iBAAqD,CAAC;AAwJtE,OAAO,EAAE,QAAQ,EAAE,CAAC"}
package/dist/drop-down.js CHANGED
@@ -1,129 +1,120 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AdwComboRow } from "@gtkx/jsx/adw";
3
- import { GtkDropDown, GtkLabel } from "@gtkx/jsx/gtk";
4
- import { useForwardedRef } from "@gtkx/react";
5
- import { createElement, useCallback, useRef, useState, } from "react";
6
- import { useDropDownSelection } from "./hooks/use-drop-down-selection.js";
7
- import { useListModel } from "./hooks/use-list-model.js";
8
- import { useModelInstallation } from "./hooks/use-model-installation.js";
9
- import { useRealizedSlots } from "./hooks/use-realized-slots.js";
10
- import { ListPortalHost } from "./list-portal-host.js";
11
- const itemFactoryBinding = {
12
- install: (widget, factory) => widget.setFactory(factory),
13
- uninstall: (widget) => widget.setFactory(null),
14
- };
15
- const listFactoryBinding = {
16
- install: (widget, factory) => widget.setListFactory(factory),
17
- uninstall: (widget) => widget.setListFactory(null),
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
+ }
18
36
  };
19
- const headerFactoryBinding = {
20
- install: (widget, factory) => widget.setHeaderFactory(factory),
21
- uninstall: (widget) => widget.setHeaderFactory(null),
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();
22
44
  };
23
- const defaultRenderer = (value, _treeRow, isHeader) => {
24
- if (isHeader || value === undefined || value === null)
25
- return null;
26
- return createElement(GtkLabel, { label: String(value) });
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
+ }
27
53
  };
28
- const toItemRenderer = (renderItem) => {
29
- if (typeof renderItem !== "function")
30
- return defaultRenderer;
31
- return (value, _treeRow, isHeader) => (isHeader ? null : renderItem(value));
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);
32
61
  };
33
- const toPopupRenderer = (renderListItem, renderItem) => {
34
- if (typeof renderListItem === "function")
35
- return (value, _treeRow, isHeader) => (isHeader ? null : renderListItem(value));
36
- return toItemRenderer(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()));
37
68
  };
38
- const toHeaderRenderer = (renderHeader) => {
39
- if (typeof renderHeader !== "function")
40
- return () => null;
41
- return (value) => renderHeader(value);
69
+ const applySelectedPosition = (widget, position, applying) => {
70
+ applying.current = true;
71
+ try {
72
+ widget.selected = position;
73
+ }
74
+ finally {
75
+ applying.current = false;
76
+ }
42
77
  };
43
- const createFaceResolver = (resolver, selectedPosition) => ({
44
- count: resolver.count,
45
- positionOf: (id) => resolver.positionOf(id),
46
- idOf: (position) => resolver.idOf(position),
47
- resolve: (_position, treeRow) => resolver.resolve(selectedPosition, treeRow, null),
48
- });
49
- const useDropDownWiring = (props) => {
50
- const widgetRef = useRef(null);
51
- const [widget, setWidget] = useState(null);
52
- const captureWidget = useCallback((value) => {
53
- widgetRef.current = value;
54
- setWidget(value);
55
- }, []);
56
- const [, setRef] = useForwardedRef(props.ref, captureWidget);
57
- const externalModel = props.model;
58
- const listModel = useListModel(externalModel === undefined ? { items: props.items ?? undefined } : { model: externalModel });
59
- const useHeader = externalModel === undefined && typeof props.renderHeader === "function";
60
- const face = useRealizedSlots({ target: widgetRef, binding: itemFactoryBinding });
61
- const popup = useRealizedSlots({ target: widgetRef, binding: listFactoryBinding });
62
- const header = useRealizedSlots({
63
- target: useHeader ? widgetRef : null,
64
- binding: headerFactoryBinding,
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);
65
90
  });
66
- useModelInstallation(widgetRef, listModel.model, (widget, model) => widget.setModel(model));
67
- const selectedPosition = useDropDownSelection({
68
- widget,
69
- resolver: listModel.resolver,
70
- selectedId: props.selectedId,
71
- 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);
72
101
  });
73
- const controlledPosition = props.selectedId === undefined || props.selectedId === null
74
- ? -1
75
- : listModel.resolver.positionOf(props.selectedId);
76
- const facePosition = controlledPosition >= 0 ? controlledPosition : selectedPosition < 0 ? 0 : selectedPosition;
77
- return {
78
- setRef,
79
- resolver: listModel.resolver,
80
- faceResolver: createFaceResolver(listModel.resolver, facePosition),
81
- headerResolver: listModel.headerResolver,
82
- faceStore: face.store,
83
- popupStore: popup.store,
84
- headerStore: header.store,
85
- useHeader,
86
- };
87
- };
88
- const DropDownImpl = (props) => {
89
- const { setRef, resolver, faceResolver, headerResolver, faceStore, popupStore, headerStore, useHeader } = useDropDownWiring(props);
90
- const intrinsic = createElement(props.element, { ...props.intrinsicProps, ref: setRef });
91
- return (_jsxs(_Fragment, { children: [intrinsic, _jsx(ListPortalHost, { store: faceStore, resolver: faceResolver, render: toItemRenderer(props.renderItem) }), _jsx(ListPortalHost, { store: popupStore, resolver: resolver, render: toPopupRenderer(props.renderListItem, props.renderItem) }), useHeader ? (_jsx(ListPortalHost, { store: headerStore, resolver: headerResolver, render: toHeaderRenderer(props.renderHeader) })) : null] }));
92
- };
93
- const extractDropDownProps = (props) => {
94
- const { ref, items, model, renderItem, renderListItem, renderHeader, selectedId, onSelectionChanged, ...intrinsicProps } = props;
95
- return {
96
- impl: {
97
- ref,
98
- items: items,
99
- model: model,
100
- renderItem: renderItem,
101
- renderListItem: renderListItem,
102
- renderHeader: renderHeader,
103
- selectedId: selectedId,
104
- onSelectionChanged: onSelectionChanged,
105
- },
106
- intrinsicProps: intrinsicProps,
107
- };
108
- };
109
- /**
110
- * A `GtkDropDown` driven by a declarative `items` model with a controlled
111
- * `selectedId` and per-slot renderers for the selected face, the popup list,
112
- * and section headers. Supplying an external `model` switches to the
113
- * uncontrolled form.
114
- */
115
- export const DropDown = (props) => {
116
- const { impl, intrinsicProps } = extractDropDownProps(props);
117
- return _jsx(DropDownImpl, { element: GtkDropDown, intrinsicProps: intrinsicProps, ...impl });
118
- };
119
- /**
120
- * An `AdwComboRow` driven by a declarative `items` model with a controlled
121
- * `selectedId` and per-slot renderers for the selected face, the popup list,
122
- * and section headers. Supplying an external `model` switches to the
123
- * uncontrolled form.
124
- */
125
- export const ComboRow = (props) => {
126
- const { impl, intrinsicProps } = extractDropDownProps(props);
127
- return _jsx(DropDownImpl, { element: AdwComboRow, intrinsicProps: intrinsicProps, ...impl });
128
102
  };
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 });
113
+ const Component = component ?? GtkDropDown;
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 };
129
120
  //# sourceMappingURL=drop-down.js.map