@gtkx/react 0.4.1 → 0.5.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.
@@ -64,9 +64,11 @@ export declare class JsxGenerator {
64
64
  private addNamespacePrefix;
65
65
  private buildSignalHandlerType;
66
66
  private generateExports;
67
+ private generateApplicationMenuComponents;
67
68
  private getWrapperExportMembers;
68
69
  private generateGenericWrapperComponents;
69
70
  private generateJsxNamespace;
71
+ private addMenuIntrinsicElements;
70
72
  private formatCode;
71
73
  }
72
74
  export {};
@@ -590,7 +590,6 @@ ${widgetPropsContent}
590
590
  isPopoverMenuWidget(widget.name);
591
591
  const docComment = widget.doc ? formatDoc(widget.doc).trimEnd() : "";
592
592
  if (hasMeaningfulSlots) {
593
- // For list widgets, generate wrapper components with proper generics
594
593
  if (isListWidget(widget.name) ||
595
594
  isColumnViewWidget(widget.name) ||
596
595
  isDropDownWidget(widget.name) ||
@@ -629,8 +628,11 @@ ${widgetPropsContent}
629
628
  }
630
629
  }
631
630
  }
632
- // Add ApplicationMenu and Menu namespace components
633
- lines.push(`/**
631
+ lines.push(this.generateApplicationMenuComponents());
632
+ return `${lines.join("\n")}\n`;
633
+ }
634
+ generateApplicationMenuComponents() {
635
+ return `/**
634
636
  * Sets the application-wide menu bar.
635
637
  * The menu will appear in the window's title bar on supported platforms.
636
638
  * Use Menu.Item, Menu.Section, and Menu.Submenu as children.
@@ -658,8 +660,7 @@ export const Menu = {
658
660
  \tSection: MenuSection,
659
661
  \tSubmenu: MenuSubmenu,
660
662
  };
661
- `);
662
- return `${lines.join("\n")}\n`;
663
+ `;
663
664
  }
664
665
  getWrapperExportMembers(widgetName, metadata) {
665
666
  const name = toPascalCase(widgetName);
@@ -682,7 +683,6 @@ export const Menu = {
682
683
  members.push(`Section: ${name}Section`);
683
684
  members.push(`Submenu: ${name}Submenu`);
684
685
  }
685
- // Add named child slots
686
686
  for (const slot of metadata.namedChildSlots) {
687
687
  members.push(`${slot.slotName}: ${name}${slot.slotName}`);
688
688
  }
@@ -747,7 +747,7 @@ export const Menu = {
747
747
  lines.push(`\t/** Function to convert an item to its display label. */`);
748
748
  lines.push(`\titemLabel?: (item: T) => string;`);
749
749
  lines.push(`\t/** Called when the selected item changes. */`);
750
- lines.push(`\tonSelectionChanged?: (item: T, index: number) => void;`);
750
+ lines.push(`\tonSelectionChanged?: (item: T | null, index: number) => void;`);
751
751
  lines.push(`}`);
752
752
  lines.push(``);
753
753
  lines.push(`function ${name}Root<T>(props: ${name}RootProps<T>): import("react").ReactElement {`);
@@ -840,11 +840,7 @@ export const Menu = {
840
840
  elements.push(`"${widgetName}.Page": StackPageProps;`);
841
841
  }
842
842
  }
843
- // Add shared Menu elements (used by PopoverMenu, PopoverMenuBar, and ApplicationMenu)
844
- elements.push(`"Menu.Item": MenuItemProps;`);
845
- elements.push(`"Menu.Section": MenuSectionProps;`);
846
- elements.push(`"Menu.Submenu": MenuSubmenuProps;`);
847
- // Add ApplicationMenu element
843
+ this.addMenuIntrinsicElements(elements);
848
844
  elements.push(`ApplicationMenu: MenuRootProps;`);
849
845
  return `
850
846
  declare global {
@@ -858,6 +854,11 @@ declare global {
858
854
  }
859
855
  `;
860
856
  }
857
+ addMenuIntrinsicElements(elements) {
858
+ elements.push(`"Menu.Item": MenuItemProps;`);
859
+ elements.push(`"Menu.Section": MenuSectionProps;`);
860
+ elements.push(`"Menu.Submenu": MenuSubmenuProps;`);
861
+ }
861
862
  async formatCode(code) {
862
863
  try {
863
864
  return await format(code, {
@@ -1,69 +1,69 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
2
  import type { Node } from "./node.js";
3
3
  /**
4
- * Interface for containers that manage child widgets with attach/detach semantics.
4
+ * Type for containers that manage child widgets with attach/detach semantics.
5
5
  * Used by ActionBar, FlowBox, ListBox, Overlay.
6
6
  */
7
- export interface ChildContainer {
7
+ export type ChildContainer = {
8
8
  attachChild(child: Gtk.Widget): void;
9
9
  insertChildBefore(child: Gtk.Widget, before: Gtk.Widget): void;
10
10
  detachChild(child: Gtk.Widget): void;
11
- }
11
+ };
12
12
  /**
13
- * Interface for page-based containers like Notebook.
13
+ * Type for page-based containers like Notebook.
14
14
  */
15
- export interface PageContainer {
15
+ export type PageContainer = {
16
16
  addPage(child: Gtk.Widget, label: string): void;
17
17
  insertPageBefore(child: Gtk.Widget, label: string, beforeChild: Gtk.Widget): void;
18
18
  removePage(child: Gtk.Widget): void;
19
19
  updatePageLabel(child: Gtk.Widget, label: string): void;
20
- }
20
+ };
21
21
  /**
22
22
  * Props for Stack pages.
23
23
  */
24
- export interface StackPageProps {
24
+ export type StackPageProps = {
25
25
  name?: string;
26
26
  title?: string;
27
27
  iconName?: string;
28
28
  needsAttention?: boolean;
29
29
  visible?: boolean;
30
30
  useUnderline?: boolean;
31
- }
31
+ };
32
32
  /**
33
- * Interface for Stack containers.
33
+ * Type for Stack containers.
34
34
  */
35
- export interface StackPageContainer {
35
+ export type StackPageContainer = {
36
36
  addStackPage(child: Gtk.Widget, props: StackPageProps): void;
37
37
  insertStackPageBefore(child: Gtk.Widget, props: StackPageProps, beforeChild: Gtk.Widget): void;
38
38
  removeStackPage(child: Gtk.Widget): void;
39
39
  updateStackPageProps(child: Gtk.Widget, props: StackPageProps): void;
40
- }
40
+ };
41
41
  /**
42
- * Interface for grid-based containers.
42
+ * Type for grid-based containers.
43
43
  */
44
- export interface GridContainer {
44
+ export type GridContainer = {
45
45
  attachToGrid(child: Gtk.Widget, column: number, row: number, colSpan: number, rowSpan: number): void;
46
46
  removeFromGrid(child: Gtk.Widget): void;
47
- }
47
+ };
48
48
  /**
49
- * Interface for item-based containers like ListView, ColumnView, DropDown.
49
+ * Type for item-based containers like ListView, ColumnView, DropDown.
50
50
  */
51
- export interface ItemContainer<T> {
51
+ export type ItemContainer<T> = {
52
52
  addItem(item: T): void;
53
53
  insertItemBefore(item: T, beforeItem: T): void;
54
54
  removeItem(item: T): void;
55
- }
55
+ };
56
56
  /**
57
- * Interface for column-based containers like ColumnView.
57
+ * Type for column-based containers like ColumnView.
58
58
  * Note: Column type is generic to support both raw Gtk.ColumnViewColumn and wrapper nodes.
59
59
  */
60
- export interface ColumnContainer {
60
+ export type ColumnContainer = {
61
61
  addColumn(column: unknown): void;
62
62
  insertColumnBefore(column: unknown, beforeColumn: unknown): void;
63
63
  removeColumn(column: unknown): void;
64
64
  getItems(): unknown[];
65
65
  getSortFn(): ((a: unknown, b: unknown, columnId: string) => number) | null;
66
- }
66
+ };
67
67
  export declare const isChildContainer: (node: Node) => node is Node & ChildContainer;
68
68
  export declare const isPageContainer: (node: Node) => node is Node & PageContainer;
69
69
  export declare const isStackPageContainer: (node: Node) => node is Node & StackPageContainer;
@@ -7502,7 +7502,7 @@ interface DropDownRootProps<T> extends Omit<DropDownProps, "itemLabel" | "onSele
7502
7502
  /** Function to convert an item to its display label. */
7503
7503
  itemLabel?: (item: T) => string;
7504
7504
  /** Called when the selected item changes. */
7505
- onSelectionChanged?: (item: T, index: number) => void;
7505
+ onSelectionChanged?: (item: T | null, index: number) => void;
7506
7506
  }
7507
7507
  declare function DropDownRoot<T>(props: DropDownRootProps<T>): import("react").ReactElement;
7508
7508
  declare function DropDownItem<T>(props: ListItemProps<T>): import("react").ReactElement;
@@ -23,6 +23,8 @@ interface ColumnViewState {
23
23
  export declare class ColumnViewNode extends Node<Gtk.ColumnView, ColumnViewState> implements ItemContainer<unknown>, ColumnContainer {
24
24
  static matches(type: string): boolean;
25
25
  initialize(props: Props): void;
26
+ private initializeStateWithPlaceholders;
27
+ private createGtkModels;
26
28
  private connectSorterChangedSignal;
27
29
  private waitForSortComplete;
28
30
  private disconnectSorterChangedSignal;
@@ -12,9 +12,12 @@ export class ColumnViewNode extends Node {
12
12
  return type === "ColumnView.Root";
13
13
  }
14
14
  initialize(props) {
15
- // State must be initialized before super.initialize() since updateProps accesses this.state.
16
- // GTK objects can't be created yet because this.widget doesn't exist until super.initialize().
17
- // The null placeholders are immediately replaced after super.initialize() completes.
15
+ this.initializeStateWithPlaceholders(props);
16
+ super.initialize(props);
17
+ this.createGtkModels();
18
+ this.connectSorterChangedSignal();
19
+ }
20
+ initializeStateWithPlaceholders(props) {
18
21
  this.state = {
19
22
  stringList: null,
20
23
  selectionModel: null,
@@ -31,7 +34,8 @@ export class ColumnViewNode extends Node {
31
34
  lastNotifiedColumn: null,
32
35
  lastNotifiedOrder: Gtk.SortType.ASCENDING,
33
36
  };
34
- super.initialize(props);
37
+ }
38
+ createGtkModels() {
35
39
  const stringList = new Gtk.StringList([]);
36
40
  const sortListModel = new Gtk.SortListModel(getInterface(stringList, Gio.ListModel), this.widget.getSorter());
37
41
  sortListModel.setIncremental(true);
@@ -40,7 +44,6 @@ export class ColumnViewNode extends Node {
40
44
  this.state.stringList = stringList;
41
45
  this.state.sortListModel = sortListModel;
42
46
  this.state.selectionModel = selectionModel;
43
- this.connectSorterChangedSignal();
44
47
  }
45
48
  connectSorterChangedSignal() {
46
49
  const sorter = this.widget.getSorter();
@@ -221,8 +224,6 @@ export class ColumnViewColumnNode extends Node {
221
224
  }
222
225
  columnView = null;
223
226
  initialize(props) {
224
- // Unlike ColumnViewNode, we can create GTK objects before super.initialize() here
225
- // since this is a virtual node (no widget created by parent class).
226
227
  const factory = new Gtk.SignalListItemFactory();
227
228
  const column = new Gtk.ColumnViewColumn(props.title, factory);
228
229
  const columnId = props.id ?? null;
@@ -20,6 +20,9 @@ interface ListViewState {
20
20
  export declare class ListViewNode extends Node<Gtk.ListView | Gtk.GridView, ListViewState> implements ItemContainer<unknown> {
21
21
  static matches(type: string): boolean;
22
22
  initialize(props: Props): void;
23
+ private initializeStateWithPlaceholders;
24
+ private createGtkModels;
25
+ private connectFactorySignals;
23
26
  private syncStringList;
24
27
  addItem(item: unknown): void;
25
28
  insertItemBefore(item: unknown, beforeItem: unknown): void;
@@ -11,9 +11,14 @@ export class ListViewNode extends Node {
11
11
  return type === "ListView.Root" || type === "GridView.Root";
12
12
  }
13
13
  initialize(props) {
14
- // State must be initialized before super.initialize() since updateProps accesses this.state.
15
- // GTK objects can't be created yet because this.widget doesn't exist until super.initialize().
16
- // The null placeholders are immediately replaced after super.initialize() completes.
14
+ this.initializeStateWithPlaceholders(props);
15
+ super.initialize(props);
16
+ this.createGtkModels();
17
+ this.connectFactorySignals();
18
+ this.widget.setModel(this.state.selectionModel);
19
+ this.widget.setFactory(this.state.factory);
20
+ }
21
+ initializeStateWithPlaceholders(props) {
17
22
  this.state = {
18
23
  stringList: null,
19
24
  selectionModel: null,
@@ -23,13 +28,17 @@ export class ListViewNode extends Node {
23
28
  items: [],
24
29
  committedLength: 0,
25
30
  };
26
- super.initialize(props);
31
+ }
32
+ createGtkModels() {
27
33
  const stringList = new Gtk.StringList([]);
28
34
  const selectionModel = new Gtk.SingleSelection(getInterface(stringList, Gio.ListModel));
29
35
  const factory = new Gtk.SignalListItemFactory();
30
36
  this.state.stringList = stringList;
31
37
  this.state.selectionModel = selectionModel;
32
38
  this.state.factory = factory;
39
+ }
40
+ connectFactorySignals() {
41
+ const factory = this.state.factory;
33
42
  factory.connect("setup", (_self, listItemObj) => {
34
43
  const listItem = getObject(listItemObj.id);
35
44
  const id = getObjectId(listItemObj.id);
@@ -66,8 +75,6 @@ export class ListViewNode extends Node {
66
75
  this.state.listItemCache.delete(id);
67
76
  }
68
77
  });
69
- this.widget.setModel(selectionModel);
70
- this.widget.setFactory(factory);
71
78
  }
72
79
  syncStringList = () => {
73
80
  const newLength = this.state.items.length;
@@ -56,7 +56,9 @@ export declare class MenuItemNode extends Node<never> {
56
56
  attachToParent(parent: Node): void;
57
57
  detachFromParent(parent: Node): void;
58
58
  protected consumedProps(): Set<string>;
59
+ private isFieldInitializationIncomplete;
59
60
  updateProps(oldProps: Props, newProps: Props): void;
61
+ private invokeCurrentCallback;
60
62
  private setupAction;
61
63
  private cleanupAction;
62
64
  private updateAccels;
@@ -138,27 +138,23 @@ export class MenuItemNode extends Node {
138
138
  consumed.add("accels");
139
139
  return consumed;
140
140
  }
141
+ isFieldInitializationIncomplete() {
142
+ return !this.entry;
143
+ }
141
144
  updateProps(oldProps, newProps) {
142
- // If entry doesn't exist yet, fields aren't initialized
143
- // This happens when base class constructor calls updateProps
144
- // before derived class field initializers run - skip in that case
145
- if (!this.entry) {
145
+ if (this.isFieldInitializationIncomplete()) {
146
146
  super.updateProps(oldProps, newProps);
147
147
  return;
148
148
  }
149
149
  const labelChanged = oldProps.label !== newProps.label;
150
- const hadCallback = oldProps.onActivate !== undefined;
151
- const hasCallback = newProps.onActivate !== undefined;
150
+ const callbackPresenceChanged = (oldProps.onActivate !== undefined) !== (newProps.onActivate !== undefined);
152
151
  const accelsChanged = oldProps.accels !== newProps.accels;
153
- // Always update the callback reference - the signal handler uses this
154
152
  this.onActivateCallback = newProps.onActivate;
155
153
  this.currentAccels = newProps.accels;
156
154
  if (labelChanged) {
157
155
  this.entry.label = newProps.label;
158
156
  }
159
- // Only cleanup/setup action if the presence of a callback changed
160
- // (not when the callback reference changes - we store the ref and call it)
161
- if (this.isAttached && hadCallback !== hasCallback) {
157
+ if (this.isAttached && callbackPresenceChanged) {
162
158
  this.cleanupAction();
163
159
  this.setupAction();
164
160
  }
@@ -167,15 +163,15 @@ export class MenuItemNode extends Node {
167
163
  }
168
164
  super.updateProps(oldProps, newProps);
169
165
  }
166
+ invokeCurrentCallback() {
167
+ this.onActivateCallback?.();
168
+ }
170
169
  setupAction() {
171
170
  if (!this.onActivateCallback)
172
171
  return;
173
172
  this.actionName = generateActionName();
174
173
  this.action = new Gio.SimpleAction(this.actionName);
175
- this.signalHandlerId = this.action.connect("activate", () => {
176
- // Call the current callback (may have been updated via updateProps)
177
- this.onActivateCallback?.();
178
- });
174
+ this.signalHandlerId = this.action.connect("activate", () => this.invokeCurrentCallback());
179
175
  const app = getCurrentApp();
180
176
  const action = getInterface(this.action, Gio.Action);
181
177
  if (!action) {
@@ -15,6 +15,7 @@ export declare class StackNode extends Node<Gtk.Stack> implements StackPageConta
15
15
  insertChildBefore(child: Gtk.Widget, _before: Gtk.Widget): void;
16
16
  detachChild(child: Gtk.Widget): void;
17
17
  protected consumedProps(): Set<string>;
18
+ private setVisibleChildOrDefer;
18
19
  updateProps(oldProps: Props, newProps: Props): void;
19
20
  }
20
21
  export declare class StackPageNode extends Node {
@@ -30,8 +30,6 @@ export class StackNode extends Node {
30
30
  }
31
31
  }
32
32
  insertStackPageBefore(child, props, _beforeChild) {
33
- // Stack doesn't have insertBefore, so we add and rely on order
34
- // For now, just add at the end - GTK Stack doesn't support insertion at position
35
33
  this.addStackPage(child, props);
36
34
  }
37
35
  removeStackPage(child) {
@@ -65,7 +63,6 @@ export class StackNode extends Node {
65
63
  this.widget.addChild(child);
66
64
  }
67
65
  insertChildBefore(child, _before) {
68
- // Stack doesn't support insertion at position
69
66
  this.widget.addChild(child);
70
67
  }
71
68
  detachChild(child) {
@@ -76,18 +73,19 @@ export class StackNode extends Node {
76
73
  consumed.add("visibleChildName");
77
74
  return consumed;
78
75
  }
76
+ setVisibleChildOrDefer(name) {
77
+ const child = this.widget.getChildByName(name);
78
+ if (child) {
79
+ this.widget.setVisibleChild(child);
80
+ this.pendingVisibleChildName = null;
81
+ }
82
+ else {
83
+ this.pendingVisibleChildName = name;
84
+ }
85
+ }
79
86
  updateProps(oldProps, newProps) {
80
87
  if (newProps.visibleChildName !== undefined) {
81
- const name = newProps.visibleChildName;
82
- const child = this.widget.getChildByName(name);
83
- if (child) {
84
- this.widget.setVisibleChild(child);
85
- this.pendingVisibleChildName = null;
86
- }
87
- else {
88
- // Child not yet added, defer until it's added
89
- this.pendingVisibleChildName = name;
90
- }
88
+ this.setVisibleChildOrDefer(newProps.visibleChildName);
91
89
  }
92
90
  super.updateProps(oldProps, newProps);
93
91
  }
package/dist/portal.d.ts CHANGED
@@ -8,6 +8,9 @@ import type { ReactNode, ReactPortal } from "react";
8
8
  * When called without a container argument, the portal renders at the root level.
9
9
  * This is useful for dialogs which don't need a parent container.
10
10
  *
11
+ * Implementation note: ReactPortal is an opaque type, so we manually construct
12
+ * the internal representation required by custom reconcilers.
13
+ *
11
14
  * @example
12
15
  * ```tsx
13
16
  * // Render dialog at root level (no container needed)
package/dist/portal.js CHANGED
@@ -8,6 +8,9 @@ import { ROOT_NODE_CONTAINER } from "./factory.js";
8
8
  * When called without a container argument, the portal renders at the root level.
9
9
  * This is useful for dialogs which don't need a parent container.
10
10
  *
11
+ * Implementation note: ReactPortal is an opaque type, so we manually construct
12
+ * the internal representation required by custom reconcilers.
13
+ *
11
14
  * @example
12
15
  * ```tsx
13
16
  * // Render dialog at root level (no container needed)
@@ -18,8 +21,6 @@ import { ROOT_NODE_CONTAINER } from "./factory.js";
18
21
  * ```
19
22
  */
20
23
  export const createPortal = (children, container, key) => {
21
- // ReactPortal is an opaque type but we need to construct it manually for custom reconcilers.
22
- // The shape matches React's internal portal representation.
23
24
  return {
24
25
  $$typeof: Symbol.for("react.portal"),
25
26
  key: key ?? null,
package/dist/types.d.ts CHANGED
@@ -4,23 +4,23 @@ import type { ReactElement, ReactNode } from "react";
4
4
  * Props for slot components that accept children.
5
5
  * Used by container widgets that render child elements in designated slots.
6
6
  */
7
- export interface SlotProps {
7
+ export type SlotProps = {
8
8
  children?: ReactNode;
9
- }
9
+ };
10
10
  /**
11
11
  * Props passed to list item components.
12
12
  * @typeParam I - The type of the data item
13
13
  */
14
- export interface ListItemProps<I = unknown> {
14
+ export type ListItemProps<I = unknown> = {
15
15
  /** The data item to render. */
16
16
  item: I;
17
- }
18
- export interface GridChildProps extends SlotProps {
17
+ };
18
+ export type GridChildProps = SlotProps & {
19
19
  column?: number;
20
20
  row?: number;
21
21
  columnSpan?: number;
22
22
  rowSpan?: number;
23
- }
23
+ };
24
24
  /**
25
25
  * Render function for ListView/GridView items.
26
26
  * Called with null during setup (for loading state) and with the actual item during bind.
@@ -30,10 +30,10 @@ export type RenderItemFn<T> = (item: T | null) => ReactElement;
30
30
  * Props for ListView and GridView components.
31
31
  * @typeParam T - The type of the data items in the list
32
32
  */
33
- export interface ListViewRenderProps<T = unknown> {
33
+ export type ListViewRenderProps<T = unknown> = {
34
34
  /** Render function called for each item in the list. */
35
35
  renderItem: RenderItemFn<T>;
36
- }
36
+ };
37
37
  /**
38
38
  * Comparison function for sorting items by column.
39
39
  * Returns negative if a < b, 0 if a === b, positive if a > b.
@@ -46,7 +46,7 @@ export type ColumnSortFn<T, C extends string = string> = (a: T, b: T, columnId:
46
46
  * Props for individual columns in a ColumnView.
47
47
  * @typeParam T - The type of the data items displayed in the column
48
48
  */
49
- export interface ColumnViewColumnProps<T = unknown> {
49
+ export type ColumnViewColumnProps<T = unknown> = {
50
50
  /** The column header title. */
51
51
  title?: string;
52
52
  /** Whether the column should expand to fill available space. */
@@ -63,13 +63,13 @@ export interface ColumnViewColumnProps<T = unknown> {
63
63
  * Always annotate your callback parameter type to include null, e.g.: `(item: MyItem | null) => ...`
64
64
  */
65
65
  renderCell: (item: T | null) => ReactElement;
66
- }
66
+ };
67
67
  /**
68
68
  * Props for the ColumnView root component.
69
69
  * @typeParam T - The type of the data items in the view
70
70
  * @typeParam C - The union type of column IDs
71
71
  */
72
- export interface ColumnViewRootProps<T = unknown, C extends string = string> {
72
+ export type ColumnViewRootProps<T = unknown, C extends string = string> = {
73
73
  /** The ID of the currently sorted column, or null if unsorted. */
74
74
  sortColumn?: C | null;
75
75
  /** The current sort direction. */
@@ -78,55 +78,55 @@ export interface ColumnViewRootProps<T = unknown, C extends string = string> {
78
78
  onSortChange?: (column: C | null, order: SortType) => void;
79
79
  /** Custom comparison function for sorting items. */
80
80
  sortFn?: ColumnSortFn<T, C>;
81
- }
82
- export interface NotebookPageProps extends SlotProps {
81
+ };
82
+ export type NotebookPageProps = SlotProps & {
83
83
  label: string;
84
- }
85
- export interface StackRootProps extends SlotProps {
84
+ };
85
+ export type StackRootProps = SlotProps & {
86
86
  visibleChildName?: string;
87
- }
88
- export interface StackPageProps extends SlotProps {
87
+ };
88
+ export type StackPageProps = SlotProps & {
89
89
  name?: string;
90
90
  title?: string;
91
91
  iconName?: string;
92
92
  needsAttention?: boolean;
93
93
  visible?: boolean;
94
94
  useUnderline?: boolean;
95
- }
95
+ };
96
96
  /**
97
97
  * Props for the Menu.Root component.
98
98
  * Root container for declarative menu structures.
99
99
  */
100
- export interface MenuRootProps {
100
+ export type MenuRootProps = {
101
101
  children?: ReactNode;
102
- }
102
+ };
103
103
  /**
104
104
  * Props for Menu.Item components.
105
105
  * Represents a single menu item with an action.
106
106
  */
107
- export interface MenuItemProps {
107
+ export type MenuItemProps = {
108
108
  /** The visible label for the menu item. */
109
109
  label: string;
110
110
  /** Callback invoked when the menu item is activated. */
111
111
  onActivate?: () => void;
112
112
  /** Keyboard accelerators for this menu item (e.g., `"<Control>q"` or `["<Control>q", "<Control>w"]`). */
113
113
  accels?: string | string[];
114
- }
114
+ };
115
115
  /**
116
116
  * Props for Menu.Section components.
117
117
  * Groups related menu items with optional label.
118
118
  */
119
- export interface MenuSectionProps {
119
+ export type MenuSectionProps = {
120
120
  /** Optional section label displayed as a header. */
121
121
  label?: string;
122
122
  children?: ReactNode;
123
- }
123
+ };
124
124
  /**
125
125
  * Props for Menu.Submenu components.
126
126
  * Creates a nested submenu with its own items.
127
127
  */
128
- export interface MenuSubmenuProps {
128
+ export type MenuSubmenuProps = {
129
129
  /** The submenu label shown in parent menu. */
130
130
  label: string;
131
131
  children?: ReactNode;
132
- }
132
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gtkx/react",
3
- "version": "0.4.1",
3
+ "version": "0.5.0",
4
4
  "description": "Build GTK4 desktop applications with React and TypeScript",
5
5
  "keywords": [
6
6
  "gtk",
@@ -36,10 +36,10 @@
36
36
  ],
37
37
  "dependencies": {
38
38
  "react-reconciler": "0.33.0",
39
- "@gtkx/ffi": "0.4.1"
39
+ "@gtkx/ffi": "0.5.0"
40
40
  },
41
41
  "devDependencies": {
42
- "@gtkx/gir": "0.4.1"
42
+ "@gtkx/gir": "0.5.0"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "react": "^19"