@gtkx/react 0.6.1 → 0.7.0

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 (84) hide show
  1. package/dist/batch.d.ts +4 -1
  2. package/dist/batch.js +19 -10
  3. package/dist/codegen/jsx-generator.d.ts +4 -4
  4. package/dist/codegen/jsx-generator.js +24 -27
  5. package/dist/container-interfaces.d.ts +19 -6
  6. package/dist/container-interfaces.js +26 -6
  7. package/dist/errors.d.ts +8 -0
  8. package/dist/errors.js +38 -0
  9. package/dist/factory.js +9 -3
  10. package/dist/generated/jsx.d.ts +38 -26
  11. package/dist/generated/jsx.js +12 -2
  12. package/dist/index.js +3 -1
  13. package/dist/node.d.ts +5 -0
  14. package/dist/node.js +62 -6
  15. package/dist/nodes/action-bar.d.ts +2 -6
  16. package/dist/nodes/action-bar.js +3 -12
  17. package/dist/nodes/column-view.d.ts +19 -44
  18. package/dist/nodes/column-view.js +70 -243
  19. package/dist/nodes/combo-row.d.ts +5 -0
  20. package/dist/nodes/combo-row.js +6 -0
  21. package/dist/nodes/drop-down.d.ts +9 -0
  22. package/dist/nodes/drop-down.js +12 -0
  23. package/dist/nodes/flow-box.d.ts +4 -6
  24. package/dist/nodes/flow-box.js +8 -16
  25. package/dist/nodes/grid.d.ts +15 -15
  26. package/dist/nodes/grid.js +21 -64
  27. package/dist/nodes/header-bar.d.ts +34 -11
  28. package/dist/nodes/header-bar.js +52 -24
  29. package/dist/nodes/indexed-child-container.d.ts +16 -0
  30. package/dist/nodes/indexed-child-container.js +22 -0
  31. package/dist/nodes/list-box.d.ts +3 -6
  32. package/dist/nodes/list-box.js +6 -14
  33. package/dist/nodes/list-item-factory.d.ts +19 -0
  34. package/dist/nodes/list-item-factory.js +58 -0
  35. package/dist/nodes/list-view.d.ts +24 -0
  36. package/dist/nodes/list-view.js +46 -0
  37. package/dist/nodes/menu.d.ts +25 -19
  38. package/dist/nodes/menu.js +30 -59
  39. package/dist/nodes/notebook.d.ts +13 -14
  40. package/dist/nodes/notebook.js +18 -56
  41. package/dist/nodes/paged-stack.d.ts +39 -0
  42. package/dist/nodes/paged-stack.js +54 -0
  43. package/dist/nodes/selectable-list.d.ts +41 -0
  44. package/dist/nodes/selectable-list.js +228 -0
  45. package/dist/nodes/stack-page-props.d.ts +11 -0
  46. package/dist/nodes/stack-page-props.js +23 -0
  47. package/dist/nodes/stack.d.ts +14 -28
  48. package/dist/nodes/stack.js +30 -142
  49. package/dist/nodes/string-list-container.d.ts +41 -0
  50. package/dist/nodes/string-list-container.js +90 -0
  51. package/dist/nodes/string-list-item.d.ts +15 -0
  52. package/dist/nodes/string-list-item.js +48 -0
  53. package/dist/nodes/string-list-store.d.ts +13 -0
  54. package/dist/nodes/string-list-store.js +44 -0
  55. package/dist/nodes/text-view.d.ts +1 -1
  56. package/dist/nodes/text-view.js +1 -5
  57. package/dist/nodes/toggle-button.d.ts +1 -1
  58. package/dist/nodes/toggle-button.js +1 -3
  59. package/dist/nodes/view-stack.d.ts +9 -0
  60. package/dist/nodes/view-stack.js +28 -0
  61. package/dist/nodes/virtual-item.d.ts +20 -0
  62. package/dist/nodes/virtual-item.js +57 -0
  63. package/dist/nodes/virtual-slot.d.ts +25 -0
  64. package/dist/nodes/virtual-slot.js +71 -0
  65. package/dist/nodes/widget.d.ts +0 -3
  66. package/dist/nodes/widget.js +0 -28
  67. package/dist/nodes/window.d.ts +1 -1
  68. package/dist/nodes/window.js +9 -15
  69. package/dist/predicates.d.ts +8 -0
  70. package/dist/predicates.js +8 -0
  71. package/dist/props.d.ts +7 -5
  72. package/dist/props.js +11 -9
  73. package/dist/reconciler/host-config.d.ts +19 -0
  74. package/dist/reconciler/host-config.js +89 -0
  75. package/dist/reconciler.d.ts +2 -26
  76. package/dist/reconciler.js +15 -106
  77. package/dist/render.d.ts +1 -2
  78. package/dist/render.js +16 -4
  79. package/dist/types.d.ts +19 -16
  80. package/package.json +4 -4
  81. package/dist/nodes/dropdown.d.ts +0 -39
  82. package/dist/nodes/dropdown.js +0 -103
  83. package/dist/nodes/list.d.ts +0 -43
  84. package/dist/nodes/list.js +0 -153
package/dist/batch.d.ts CHANGED
@@ -2,11 +2,14 @@ type FlushCallback = () => void;
2
2
  /**
3
3
  * Marks the beginning of a React reconciler commit phase.
4
4
  * While in commit, flush callbacks are deferred until endCommit is called.
5
+ * Supports nested commits through depth tracking.
5
6
  */
6
7
  export declare const beginCommit: () => void;
7
8
  /**
8
9
  * Marks the end of a React reconciler commit phase.
9
- * Executes all pending flush callbacks that were deferred during the commit.
10
+ * Executes all pending flush callbacks that were deferred during the commit
11
+ * only when the outermost commit ends (depth reaches 0).
12
+ * If called without a matching beginCommit, resets the state (useful for test cleanup).
10
13
  */
11
14
  export declare const endCommit: () => void;
12
15
  /**
package/dist/batch.js CHANGED
@@ -1,21 +1,30 @@
1
- const pendingFlushes = new Set();
2
- let inCommit = false;
1
+ const state = {
2
+ depth: 0,
3
+ pendingFlushes: new Set(),
4
+ };
3
5
  /**
4
6
  * Marks the beginning of a React reconciler commit phase.
5
7
  * While in commit, flush callbacks are deferred until endCommit is called.
8
+ * Supports nested commits through depth tracking.
6
9
  */
7
10
  export const beginCommit = () => {
8
- inCommit = true;
11
+ state.depth++;
9
12
  };
10
13
  /**
11
14
  * Marks the end of a React reconciler commit phase.
12
- * Executes all pending flush callbacks that were deferred during the commit.
15
+ * Executes all pending flush callbacks that were deferred during the commit
16
+ * only when the outermost commit ends (depth reaches 0).
17
+ * If called without a matching beginCommit, resets the state (useful for test cleanup).
13
18
  */
14
19
  export const endCommit = () => {
15
- inCommit = false;
16
- if (pendingFlushes.size > 0) {
17
- const callbacks = [...pendingFlushes];
18
- pendingFlushes.clear();
20
+ if (state.depth <= 0) {
21
+ state.depth = 0;
22
+ return;
23
+ }
24
+ state.depth--;
25
+ if (state.depth === 0 && state.pendingFlushes.size > 0) {
26
+ const callbacks = [...state.pendingFlushes];
27
+ state.pendingFlushes.clear();
19
28
  queueMicrotask(() => {
20
29
  for (const callback of callbacks) {
21
30
  callback();
@@ -28,8 +37,8 @@ export const endCommit = () => {
28
37
  * This ensures GTK state updates happen after React has finished its batch of changes.
29
38
  */
30
39
  export const scheduleFlush = (callback) => {
31
- if (inCommit) {
32
- pendingFlushes.add(callback);
40
+ if (state.depth > 0) {
41
+ state.pendingFlushes.add(callback);
33
42
  }
34
43
  else {
35
44
  callback();
@@ -2,19 +2,19 @@ import type { GirClass, GirNamespace, TypeMapper, TypeRegistry } from "@gtkx/gir
2
2
  /**
3
3
  * Configuration options for the JSX type generator.
4
4
  */
5
- interface JsxGeneratorOptions {
5
+ type JsxGeneratorOptions = {
6
6
  /** Optional Prettier configuration for formatting output. */
7
7
  prettierConfig?: unknown;
8
- }
8
+ };
9
9
  /**
10
10
  * Result of the JSX generation containing both public and internal files.
11
11
  */
12
- interface JsxGeneratorResult {
12
+ type JsxGeneratorResult = {
13
13
  /** Public JSX types and components for user consumption. */
14
14
  jsx: string;
15
15
  /** Internal metadata for reconciler use (not exported to users). */
16
16
  internal: string;
17
- }
17
+ };
18
18
  /**
19
19
  * Generates JSX type definitions for React components from GTK widget classes.
20
20
  * Creates TypeScript interfaces for props and augments React's JSX namespace.
@@ -5,7 +5,7 @@ const COLUMN_VIEW_WIDGET = "ColumnView";
5
5
  const DROPDOWN_WIDGETS = new Set(["DropDown"]);
6
6
  const GRID_WIDGETS = new Set(["Grid"]);
7
7
  const NOTEBOOK_WIDGET = "Notebook";
8
- const STACK_WIDGET = "Stack";
8
+ const STACK_WIDGETS = new Set(["Stack", "ViewStack", "AdwViewStack"]);
9
9
  const POPOVER_MENU_WIDGET = "PopoverMenu";
10
10
  const TOOLBAR_VIEW_WIDGET = "ToolbarView";
11
11
  const INTERNALLY_PROVIDED_PARAMS = {
@@ -37,7 +37,7 @@ const isColumnViewWidget = (widgetName) => widgetName === COLUMN_VIEW_WIDGET;
37
37
  const isDropDownWidget = (widgetName) => DROPDOWN_WIDGETS.has(widgetName);
38
38
  const isGridWidget = (widgetName) => GRID_WIDGETS.has(widgetName);
39
39
  const isNotebookWidget = (widgetName) => widgetName === NOTEBOOK_WIDGET;
40
- const isStackWidget = (widgetName) => widgetName === STACK_WIDGET;
40
+ const isStackWidget = (widgetName) => STACK_WIDGETS.has(widgetName);
41
41
  const isPopoverMenuWidget = (widgetName) => widgetName === POPOVER_MENU_WIDGET;
42
42
  const isToolbarViewWidget = (widgetName) => widgetName === TOOLBAR_VIEW_WIDGET;
43
43
  const sanitizeDoc = (doc) => {
@@ -162,7 +162,7 @@ export class JsxGenerator {
162
162
  `import { createElement } from "react";`,
163
163
  `import type { ReactNode, Ref } from "react";`,
164
164
  ...namespaceImports,
165
- `import type { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps } from "../types.js";`,
165
+ `import type { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps, StringListItemProps } from "../types.js";`,
166
166
  "",
167
167
  ].join("\n");
168
168
  }
@@ -174,7 +174,7 @@ export class JsxGenerator {
174
174
  this.typeMapper.setTypeRegistry(this.typeRegistry, "Gtk");
175
175
  const widgetPropsContent = this.generateWidgetPropsContent(widgetClass);
176
176
  return `
177
- export { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps };
177
+ export { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps, StringListItemProps };
178
178
 
179
179
  ${widgetPropsContent}
180
180
  `;
@@ -382,6 +382,15 @@ ${widgetPropsContent}
382
382
  lines.push(`\t${this.generateSignalHandler(signal, widget.name)}`);
383
383
  }
384
384
  }
385
+ if (isListWidget(widget.name) || isColumnViewWidget(widget.name)) {
386
+ lines.push("");
387
+ lines.push(`\t/** Array of selected item IDs */`);
388
+ lines.push(`\tselected?: string[];`);
389
+ lines.push(`\t/** Called when selection changes with array of selected item IDs */`);
390
+ lines.push(`\tonSelectionChanged?: (ids: string[]) => void;`);
391
+ lines.push(`\t/** Selection mode: SINGLE (default) or MULTIPLE */`);
392
+ lines.push(`\tselectionMode?: import("@gtkx/ffi/gtk").SelectionMode;`);
393
+ }
385
394
  if (isListWidget(widget.name)) {
386
395
  lines.push("");
387
396
  lines.push(`\t/**`);
@@ -392,10 +401,10 @@ ${widgetPropsContent}
392
401
  }
393
402
  if (isDropDownWidget(widget.name)) {
394
403
  lines.push("");
395
- lines.push(`\t/** Function to convert item to display label */`);
396
- lines.push(`\titemLabel?: (item: unknown) => string;`);
397
- lines.push(`\t/** Called when selection changes */`);
398
- lines.push(`\tonSelectionChanged?: (item: unknown, index: number) => void;`);
404
+ lines.push(`\t/** ID of the initially selected item */`);
405
+ lines.push(`\tselectedId?: string;`);
406
+ lines.push(`\t/** Called when selection changes with the selected item's ID */`);
407
+ lines.push(`\tonSelectionChanged?: (id: string) => void;`);
399
408
  }
400
409
  lines.push("");
401
410
  const ffiTypeName = toPascalCase(widget.name);
@@ -830,13 +839,12 @@ export const Menu = {
830
839
  }
831
840
  else if (isColumnViewWidget(widgetName)) {
832
841
  lines.push(`/**`);
833
- lines.push(` * Props for the ${name}.Root component with type-safe item and column rendering.`);
834
- lines.push(` * @typeParam T - The type of items in the column view.`);
835
- lines.push(` * @typeParam C - The union type of column IDs for type-safe sorting.`);
842
+ lines.push(` * Props for the ${name}.Root component with column sorting UI indicators.`);
843
+ lines.push(` * @typeParam C - The union type of column IDs for type-safe sorting indicators.`);
836
844
  lines.push(` */`);
837
- lines.push(`interface ${name}RootPropsExtended<T = unknown, C extends string = string> extends ${name}Props, ColumnViewRootProps<T, C> {}`);
845
+ lines.push(`interface ${name}RootPropsExtended<C extends string = string> extends ${name}Props, ColumnViewRootProps<C> {}`);
838
846
  lines.push(``);
839
- lines.push(`function ${name}Root<T = unknown, C extends string = string>(props: ${name}RootPropsExtended<T, C>): import("react").ReactElement {`);
847
+ lines.push(`function ${name}Root<C extends string = string>(props: ${name}RootPropsExtended<C>): import("react").ReactElement {`);
840
848
  lines.push(`\treturn createElement("${name}.Root", props);`);
841
849
  lines.push(`}`);
842
850
  lines.push(``);
@@ -858,22 +866,11 @@ export const Menu = {
858
866
  lines.push(`}`);
859
867
  }
860
868
  else if (isDropDownWidget(widgetName)) {
861
- lines.push(`/**`);
862
- lines.push(` * Props for the ${name}.Root component with type-safe item handling.`);
863
- lines.push(` * @typeParam T - The type of items in the dropdown.`);
864
- lines.push(` */`);
865
- lines.push(`interface ${name}RootProps<T> extends Omit<${name}Props, "itemLabel" | "onSelectionChanged"> {`);
866
- lines.push(`\t/** Function to convert an item to its display label. */`);
867
- lines.push(`\titemLabel?: (item: T) => string;`);
868
- lines.push(`\t/** Called when the selected item changes. */`);
869
- lines.push(`\tonSelectionChanged?: (item: T | null, index: number) => void;`);
870
- lines.push(`}`);
871
- lines.push(``);
872
- lines.push(`function ${name}Root<T>(props: ${name}RootProps<T>): import("react").ReactElement {`);
869
+ lines.push(`function ${name}Root(props: ${name}Props): import("react").ReactElement {`);
873
870
  lines.push(`\treturn createElement("${name}.Root", props);`);
874
871
  lines.push(`}`);
875
872
  lines.push(``);
876
- lines.push(`function ${name}Item<T>(props: ListItemProps<T>): import("react").ReactElement {`);
873
+ lines.push(`function ${name}Item(props: StringListItemProps): import("react").ReactElement {`);
877
874
  lines.push(`\treturn createElement("${name}.Item", props);`);
878
875
  lines.push(`}`);
879
876
  }
@@ -949,7 +946,7 @@ export const Menu = {
949
946
  elements.push(`"${widgetName}.Item": ListItemProps;`);
950
947
  }
951
948
  if (isDropDownWidget(widget.name)) {
952
- elements.push(`"${widgetName}.Item": ListItemProps;`);
949
+ elements.push(`"${widgetName}.Item": StringListItemProps;`);
953
950
  }
954
951
  if (isGridWidget(widget.name)) {
955
952
  elements.push(`"${widgetName}.Child": GridChildProps;`);
@@ -20,6 +20,7 @@ export type PageContainer = {
20
20
  };
21
21
  /**
22
22
  * Props for Stack pages.
23
+ * Used by Gtk.Stack and Adw.ViewStack.
23
24
  */
24
25
  export type StackPageProps = {
25
26
  name?: string;
@@ -28,6 +29,7 @@ export type StackPageProps = {
28
29
  needsAttention?: boolean;
29
30
  visible?: boolean;
30
31
  useUnderline?: boolean;
32
+ badgeNumber?: number;
31
33
  };
32
34
  /**
33
35
  * Type for Stack containers.
@@ -46,12 +48,14 @@ export type GridContainer = {
46
48
  removeFromGrid(child: Gtk.Widget): void;
47
49
  };
48
50
  /**
49
- * Type for item-based containers like ListView, ColumnView, DropDown.
51
+ * Type for item-based containers like ListView, GridView, ColumnView.
52
+ * Items are identified by string IDs for selection support.
50
53
  */
51
54
  export type ItemContainer<T> = {
52
- addItem(item: T): void;
53
- insertItemBefore(item: T, beforeItem: T): void;
54
- removeItem(item: T): void;
55
+ addItem(id: string, item: T): void;
56
+ insertItemBefore(id: string, item: T, beforeId: string): void;
57
+ removeItem(id: string): void;
58
+ updateItem(id: string, item: T): void;
55
59
  };
56
60
  /**
57
61
  * Type for column-based containers like ColumnView.
@@ -62,11 +66,20 @@ export type ColumnContainer = {
62
66
  insertColumnBefore(column: unknown, beforeColumn: unknown): void;
63
67
  removeColumn(column: unknown): void;
64
68
  getItems(): unknown[];
65
- getSortFn(): ((a: unknown, b: unknown, columnId: string) => number) | null;
66
69
  };
67
70
  export declare const isChildContainer: (node: Node) => node is Node & ChildContainer;
68
71
  export declare const isPageContainer: (node: Node) => node is Node & PageContainer;
69
72
  export declare const isStackPageContainer: (node: Node) => node is Node & StackPageContainer;
70
73
  export declare const isGridContainer: (node: Node) => node is Node & GridContainer;
71
- export declare const isItemContainer: <T>(node: Node) => node is Node & ItemContainer<T>;
74
+ export declare const isItemContainer: (node: Node) => node is Node & ItemContainer<unknown>;
72
75
  export declare const isColumnContainer: (node: Node) => node is Node & ColumnContainer;
76
+ /**
77
+ * Type for containers that support packStart/packEnd semantics.
78
+ * Used by HeaderBar, ActionBar.
79
+ */
80
+ export type PackContainer = {
81
+ packStart(child: Gtk.Widget): void;
82
+ packEnd(child: Gtk.Widget): void;
83
+ removeFromPack(child: Gtk.Widget): void;
84
+ };
85
+ export declare const isPackContainer: (node: Node) => node is Node & PackContainer;
@@ -1,6 +1,26 @@
1
- export const isChildContainer = (node) => "attachChild" in node && "detachChild" in node && "insertChildBefore" in node;
2
- export const isPageContainer = (node) => "addPage" in node && "removePage" in node && "insertPageBefore" in node && "updatePageLabel" in node;
3
- export const isStackPageContainer = (node) => "addStackPage" in node && "removeStackPage" in node && "updateStackPageProps" in node;
4
- export const isGridContainer = (node) => "attachToGrid" in node && "removeFromGrid" in node;
5
- export const isItemContainer = (node) => "addItem" in node && "insertItemBefore" in node && "removeItem" in node;
6
- export const isColumnContainer = (node) => "addColumn" in node && "removeColumn" in node && "getSortFn" in node;
1
+ const createContainerGuard = (requiredMethods) => (node) => requiredMethods.every((method) => method in node);
2
+ export const isChildContainer = createContainerGuard([
3
+ "attachChild",
4
+ "detachChild",
5
+ "insertChildBefore",
6
+ ]);
7
+ export const isPageContainer = createContainerGuard([
8
+ "addPage",
9
+ "removePage",
10
+ "insertPageBefore",
11
+ "updatePageLabel",
12
+ ]);
13
+ export const isStackPageContainer = createContainerGuard([
14
+ "addStackPage",
15
+ "removeStackPage",
16
+ "updateStackPageProps",
17
+ ]);
18
+ export const isGridContainer = createContainerGuard(["attachToGrid", "removeFromGrid"]);
19
+ export const isItemContainer = createContainerGuard([
20
+ "addItem",
21
+ "insertItemBefore",
22
+ "removeItem",
23
+ "updateItem",
24
+ ]);
25
+ export const isColumnContainer = createContainerGuard(["addColumn", "removeColumn", "getItems"]);
26
+ export const isPackContainer = createContainerGuard(["packStart", "packEnd", "removeFromPack"]);
@@ -0,0 +1,8 @@
1
+ export declare class GTKXError extends Error {
2
+ widgetType?: string | undefined;
3
+ componentStack?: string | undefined;
4
+ constructor(message: string, widgetType?: string | undefined, componentStack?: string | undefined);
5
+ toString(): string;
6
+ }
7
+ export declare function formatRenderError(error: unknown, widgetType?: string): GTKXError;
8
+ export declare function formatBoundaryError(error: unknown): GTKXError;
package/dist/errors.js ADDED
@@ -0,0 +1,38 @@
1
+ export class GTKXError extends Error {
2
+ widgetType;
3
+ componentStack;
4
+ constructor(message, widgetType, componentStack) {
5
+ super(message);
6
+ this.widgetType = widgetType;
7
+ this.componentStack = componentStack;
8
+ this.name = "GTKXError";
9
+ if (Error.captureStackTrace) {
10
+ Error.captureStackTrace(this, GTKXError);
11
+ }
12
+ }
13
+ toString() {
14
+ const parts = [`GTKXError: ${this.message}`];
15
+ if (this.widgetType) {
16
+ parts.push(`Widget Type: ${this.widgetType}`);
17
+ }
18
+ if (this.componentStack) {
19
+ parts.push(`Component Stack:\n${this.componentStack}`);
20
+ }
21
+ return parts.join("\n");
22
+ }
23
+ }
24
+ export function formatRenderError(error, widgetType) {
25
+ if (error instanceof GTKXError) {
26
+ return error;
27
+ }
28
+ const message = error instanceof Error ? error.message : String(error);
29
+ const formattedMessage = widgetType ? `Failed to render ${widgetType}: ${message}` : `Render error: ${message}`;
30
+ return new GTKXError(formattedMessage, widgetType);
31
+ }
32
+ export function formatBoundaryError(error) {
33
+ if (error instanceof GTKXError) {
34
+ return error;
35
+ }
36
+ const message = error instanceof Error ? error.message : String(error);
37
+ return new GTKXError(`Error caught by boundary: ${message}`);
38
+ }
package/dist/factory.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { AboutDialogNode } from "./nodes/about-dialog.js";
2
2
  import { ActionBarNode } from "./nodes/action-bar.js";
3
3
  import { ColumnViewColumnNode, ColumnViewItemNode, ColumnViewNode } from "./nodes/column-view.js";
4
- import { DropDownItemNode, DropDownNode } from "./nodes/dropdown.js";
4
+ import { ComboRowNode } from "./nodes/combo-row.js";
5
+ import { DropDownItemNode, DropDownNode } from "./nodes/drop-down.js";
5
6
  import { FlowBoxNode } from "./nodes/flow-box.js";
6
7
  import { GridChildNode, GridNode } from "./nodes/grid.js";
7
- import { AdwHeaderBarNode, HeaderBarNode } from "./nodes/header-bar.js";
8
- import { ListItemNode, ListViewNode } from "./nodes/list.js";
8
+ import { AdwHeaderBarNode, HeaderBarNode, PackEndNode, PackStartNode } from "./nodes/header-bar.js";
9
9
  import { ListBoxNode } from "./nodes/list-box.js";
10
+ import { ListItemNode, ListViewNode } from "./nodes/list-view.js";
10
11
  import { ApplicationMenuNode, MenuItemNode, MenuSectionNode, MenuSubmenuNode, PopoverMenuBarNode, PopoverMenuRootNode, } from "./nodes/menu.js";
11
12
  import { NotebookNode, NotebookPageNode } from "./nodes/notebook.js";
12
13
  import { OverlayNode } from "./nodes/overlay.js";
@@ -16,6 +17,7 @@ import { StackNode, StackPageNode } from "./nodes/stack.js";
16
17
  import { TextViewNode } from "./nodes/text-view.js";
17
18
  import { ToggleButtonNode } from "./nodes/toggle-button.js";
18
19
  import { ToolbarViewSlotNode } from "./nodes/toolbar-view.js";
20
+ import { ViewStackNode } from "./nodes/view-stack.js";
19
21
  import { WidgetNode } from "./nodes/widget.js";
20
22
  import { WindowNode } from "./nodes/window.js";
21
23
  export { ROOT_NODE_CONTAINER } from "./nodes/root.js";
@@ -31,6 +33,8 @@ const VIRTUAL_NODES = [
31
33
  MenuSectionNode,
32
34
  MenuSubmenuNode,
33
35
  ToolbarViewSlotNode,
36
+ PackStartNode,
37
+ PackEndNode,
34
38
  SlotNode,
35
39
  ];
36
40
  const SPECIALIZED_NODES = [
@@ -47,12 +51,14 @@ const CONTAINER_NODES = [
47
51
  FlowBoxNode,
48
52
  ListBoxNode,
49
53
  DropDownNode,
54
+ ComboRowNode,
50
55
  GridNode,
51
56
  OverlayNode,
52
57
  ColumnViewNode,
53
58
  ListViewNode,
54
59
  NotebookNode,
55
60
  StackNode,
61
+ ViewStackNode,
56
62
  AdwHeaderBarNode,
57
63
  HeaderBarNode,
58
64
  ];
@@ -12,8 +12,8 @@ import type * as Pango from "@gtkx/ffi/pango";
12
12
  import type * as Vte from "@gtkx/ffi/vte";
13
13
  import type * as WebKit from "@gtkx/ffi/webkit";
14
14
  import type * as cairo from "@gtkx/ffi/cairo";
15
- import type { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps } from "../types.js";
16
- export { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps, };
15
+ import type { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps, StringListItemProps } from "../types.js";
16
+ export { ColumnViewColumnProps, ColumnViewRootProps, GridChildProps, ListItemProps, ListViewRenderProps, MenuItemProps, MenuRootProps, MenuSectionProps, MenuSubmenuProps, NotebookPageProps, SlotProps, StackPageProps, StackRootProps, StringListItemProps, };
17
17
  /**
18
18
  * The base class for all widgets.
19
19
  *
@@ -1599,6 +1599,12 @@ export interface ColumnViewProps extends WidgetProps {
1599
1599
  * signal.
1600
1600
  */
1601
1601
  onActivate?: (self: Gtk.ColumnView, position: number) => void;
1602
+ /** Array of selected item IDs */
1603
+ selected?: string[];
1604
+ /** Called when selection changes with array of selected item IDs */
1605
+ onSelectionChanged?: (ids: string[]) => void;
1606
+ /** Selection mode: SINGLE (default) or MULTIPLE */
1607
+ selectionMode?: import("@gtkx/ffi/gtk").SelectionMode;
1602
1608
  ref?: Ref<Gtk.ColumnView>;
1603
1609
  }
1604
1610
  /** Props for the {@link ComboBox} widget. */
@@ -1869,10 +1875,10 @@ export interface DropDownProps extends WidgetProps {
1869
1875
  * emitting it causes the drop down to pop up its dropdown.
1870
1876
  */
1871
1877
  onActivate?: (self: Gtk.DropDown) => void;
1872
- /** Function to convert item to display label */
1873
- itemLabel?: (item: unknown) => string;
1874
- /** Called when selection changes */
1875
- onSelectionChanged?: (item: unknown, index: number) => void;
1878
+ /** ID of the initially selected item */
1879
+ selectedId?: string;
1880
+ /** Called when selection changes with the selected item's ID */
1881
+ onSelectionChanged?: (id: string) => void;
1876
1882
  ref?: Ref<Gtk.DropDown>;
1877
1883
  }
1878
1884
  /** Props for the {@link EditableLabel} widget. */
@@ -2922,6 +2928,12 @@ export interface GridViewProps extends ListBaseProps {
2922
2928
  * this signal.
2923
2929
  */
2924
2930
  onActivate?: (self: Gtk.GridView, position: number) => void;
2931
+ /** Array of selected item IDs */
2932
+ selected?: string[];
2933
+ /** Called when selection changes with array of selected item IDs */
2934
+ onSelectionChanged?: (ids: string[]) => void;
2935
+ /** Selection mode: SINGLE (default) or MULTIPLE */
2936
+ selectionMode?: import("@gtkx/ffi/gtk").SelectionMode;
2925
2937
  /**
2926
2938
  * Render function for list items.
2927
2939
  * Called with null during setup (for loading state) and with the actual item during bind.
@@ -3742,6 +3754,12 @@ export interface ListViewProps extends ListBaseProps {
3742
3754
  * this signal.
3743
3755
  */
3744
3756
  onActivate?: (self: Gtk.ListView, position: number) => void;
3757
+ /** Array of selected item IDs */
3758
+ selected?: string[];
3759
+ /** Called when selection changes with array of selected item IDs */
3760
+ onSelectionChanged?: (ids: string[]) => void;
3761
+ /** Selection mode: SINGLE (default) or MULTIPLE */
3762
+ selectionMode?: import("@gtkx/ffi/gtk").SelectionMode;
3745
3763
  /**
3746
3764
  * Render function for list items.
3747
3765
  * Called with null during setup (for loading state) and with the actual item during bind.
@@ -12011,13 +12029,12 @@ export declare const ColorChooserWidget: "ColorChooserWidget";
12011
12029
  */
12012
12030
  export declare const ColorDialogButton: "ColorDialogButton";
12013
12031
  /**
12014
- * Props for the ColumnView.Root component with type-safe item and column rendering.
12015
- * @typeParam T - The type of items in the column view.
12016
- * @typeParam C - The union type of column IDs for type-safe sorting.
12032
+ * Props for the ColumnView.Root component with column sorting UI indicators.
12033
+ * @typeParam C - The union type of column IDs for type-safe sorting indicators.
12017
12034
  */
12018
- interface ColumnViewRootPropsExtended<T = unknown, C extends string = string> extends ColumnViewProps, ColumnViewRootProps<T, C> {
12035
+ interface ColumnViewRootPropsExtended<C extends string = string> extends ColumnViewProps, ColumnViewRootProps<C> {
12019
12036
  }
12020
- declare function ColumnViewRoot<T = unknown, C extends string = string>(props: ColumnViewRootPropsExtended<T, C>): import("react").ReactElement;
12037
+ declare function ColumnViewRoot<C extends string = string>(props: ColumnViewRootPropsExtended<C>): import("react").ReactElement;
12021
12038
  /**
12022
12039
  * Props for ColumnView.Column with type-safe cell rendering.
12023
12040
  * @typeParam T - The type of items passed to the renderCell function.
@@ -12439,18 +12456,8 @@ export declare const DragIcon: "DragIcon";
12439
12456
  * creating your own `GtkWidget` subclass.
12440
12457
  */
12441
12458
  export declare const DrawingArea: "DrawingArea";
12442
- /**
12443
- * Props for the DropDown.Root component with type-safe item handling.
12444
- * @typeParam T - The type of items in the dropdown.
12445
- */
12446
- interface DropDownRootProps<T> extends Omit<DropDownProps, "itemLabel" | "onSelectionChanged"> {
12447
- /** Function to convert an item to its display label. */
12448
- itemLabel?: (item: T) => string;
12449
- /** Called when the selected item changes. */
12450
- onSelectionChanged?: (item: T | null, index: number) => void;
12451
- }
12452
- declare function DropDownRoot<T>(props: DropDownRootProps<T>): import("react").ReactElement;
12453
- declare function DropDownItem<T>(props: ListItemProps<T>): import("react").ReactElement;
12459
+ declare function DropDownRoot(props: DropDownProps): import("react").ReactElement;
12460
+ declare function DropDownItem(props: StringListItemProps): import("react").ReactElement;
12454
12461
  /**
12455
12462
  * Allows the user to choose an item from a list of options.
12456
12463
  *
@@ -19628,6 +19635,9 @@ export declare const AdwToolbarView: {
19628
19635
  Top: "AdwToolbarView.Top";
19629
19636
  Bottom: "AdwToolbarView.Bottom";
19630
19637
  };
19638
+ declare function AdwViewStackRoot(props: StackRootProps & AdwViewStackProps): import("react").ReactElement;
19639
+ declare function AdwViewStackPage(props: StackPageProps): import("react").ReactElement;
19640
+ declare function AdwViewStackVisibleChild(props: SlotProps): import("react").ReactElement;
19631
19641
  /**
19632
19642
  * A view container for [class@ViewSwitcher].
19633
19643
  *
@@ -19687,8 +19697,9 @@ export declare const AdwToolbarView: {
19687
19697
  * which are the accessible parent objects of the child widgets.
19688
19698
  */
19689
19699
  export declare const AdwViewStack: {
19690
- Root: "AdwViewStack.Root";
19691
- VisibleChild: "AdwViewStack.VisibleChild";
19700
+ Root: typeof AdwViewStackRoot;
19701
+ Page: typeof AdwViewStackPage;
19702
+ VisibleChild: typeof AdwViewStackVisibleChild;
19692
19703
  };
19693
19704
  /**
19694
19705
  * An adaptive view switcher.
@@ -20254,7 +20265,7 @@ declare global {
20254
20265
  "DragIcon.Child": SlotProps;
20255
20266
  DrawingArea: DrawingAreaProps;
20256
20267
  "DropDown.Root": DropDownProps;
20257
- "DropDown.Item": ListItemProps;
20268
+ "DropDown.Item": StringListItemProps;
20258
20269
  EditableLabel: EditableLabelProps;
20259
20270
  EmojiChooser: EmojiChooserProps;
20260
20271
  Entry: EntryProps;
@@ -20454,6 +20465,7 @@ declare global {
20454
20465
  "AdwToolbarView.Bottom": SlotProps;
20455
20466
  "AdwViewStack.Root": AdwViewStackProps;
20456
20467
  "AdwViewStack.VisibleChild": SlotProps;
20468
+ "AdwViewStack.Page": StackPageProps;
20457
20469
  AdwViewSwitcher: AdwViewSwitcherProps;
20458
20470
  AdwViewSwitcherBar: AdwViewSwitcherBarProps;
20459
20471
  AdwViewSwitcherTitle: AdwViewSwitcherTitleProps;
@@ -8749,6 +8749,15 @@ export const AdwToolbarView = {
8749
8749
  Top: "AdwToolbarView.Top",
8750
8750
  Bottom: "AdwToolbarView.Bottom",
8751
8751
  };
8752
+ function AdwViewStackRoot(props) {
8753
+ return createElement("AdwViewStack.Root", props);
8754
+ }
8755
+ function AdwViewStackPage(props) {
8756
+ return createElement("AdwViewStack.Page", props);
8757
+ }
8758
+ function AdwViewStackVisibleChild(props) {
8759
+ return createElement("AdwViewStack.VisibleChild", props);
8760
+ }
8752
8761
  /**
8753
8762
  * A view container for [class@ViewSwitcher].
8754
8763
  *
@@ -8808,8 +8817,9 @@ export const AdwToolbarView = {
8808
8817
  * which are the accessible parent objects of the child widgets.
8809
8818
  */
8810
8819
  export const AdwViewStack = {
8811
- Root: "AdwViewStack.Root",
8812
- VisibleChild: "AdwViewStack.VisibleChild",
8820
+ Root: AdwViewStackRoot,
8821
+ Page: AdwViewStackPage,
8822
+ VisibleChild: AdwViewStackVisibleChild,
8813
8823
  };
8814
8824
  /**
8815
8825
  * An adaptive view switcher.
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ export { reconciler } from "./reconciler.js";
10
10
  export { render } from "./render.js";
11
11
  import { stop } from "@gtkx/ffi";
12
12
  import { reconciler } from "./reconciler.js";
13
- import { container } from "./render.js";
13
+ import { getContainer } from "./render.js";
14
14
  /**
15
15
  * Updates the React tree without restarting the GTK application.
16
16
  * Used for hot module replacement (HMR) during development.
@@ -19,6 +19,7 @@ import { container } from "./render.js";
19
19
  * @throws Error if called before render()
20
20
  */
21
21
  export const update = (element) => {
22
+ const container = getContainer();
22
23
  if (!container) {
23
24
  throw new Error("Cannot update before render() is called");
24
25
  }
@@ -30,6 +31,7 @@ export const update = (element) => {
30
31
  * @returns Always returns true (useful for signal handlers)
31
32
  */
32
33
  export const quit = () => {
34
+ const container = getContainer();
33
35
  if (container) {
34
36
  reconciler.getInstance().updateContainer(null, container, null, () => {
35
37
  setTimeout(() => {
package/dist/node.d.ts CHANGED
@@ -1,11 +1,14 @@
1
1
  import * as Gtk from "@gtkx/ffi/gtk";
2
2
  import type { Props, ROOT_NODE_CONTAINER } from "./factory.js";
3
+ export declare const normalizeWidgetType: (type: string) => string;
3
4
  export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget | undefined, S extends object | undefined = object | undefined> {
4
5
  static matches(_type: string, _existingWidget?: Gtk.Widget | typeof ROOT_NODE_CONTAINER): boolean;
6
+ static consumedPropNames: string[];
5
7
  protected signalHandlers: Map<string, number>;
6
8
  protected widget: T;
7
9
  protected widgetType: string;
8
10
  protected nodeType: string;
11
+ protected parent: Node | null;
9
12
  private _state;
10
13
  protected get state(): S;
11
14
  protected set state(value: S);
@@ -23,6 +26,8 @@ export declare abstract class Node<T extends Gtk.Widget | undefined = Gtk.Widget
23
26
  insertBefore(child: Node, before: Node): void;
24
27
  attachToParent(parent: Node): void;
25
28
  detachFromParent(parent: Node): void;
29
+ protected disconnectAllSignals(): void;
30
+ hasParent(): boolean;
26
31
  attachToParentBefore(parent: Node, before: Node): void;
27
32
  protected consumedProps(): Set<string>;
28
33
  updateProps(oldProps: Props, newProps: Props): void;