@gtkx/react 0.13.3 → 0.15.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 (62) hide show
  1. package/README.md +8 -7
  2. package/dist/generated/internal.js +98 -0
  3. package/dist/generated/jsx.d.ts +908 -1572
  4. package/dist/host-config.js +2 -2
  5. package/dist/jsx.d.ts +176 -36
  6. package/dist/jsx.js +96 -5
  7. package/dist/nodes/adjustment.d.ts +48 -0
  8. package/dist/nodes/adjustment.js +70 -0
  9. package/dist/nodes/application.js +6 -6
  10. package/dist/nodes/calendar.js +3 -16
  11. package/dist/nodes/column-view-column.d.ts +1 -0
  12. package/dist/nodes/column-view-column.js +4 -0
  13. package/dist/nodes/column-view.js +6 -6
  14. package/dist/nodes/drawing-area.d.ts +1 -0
  15. package/dist/nodes/drawing-area.js +19 -0
  16. package/dist/nodes/expander-row.js +1 -0
  17. package/dist/nodes/index.d.ts +9 -0
  18. package/dist/nodes/index.js +9 -0
  19. package/dist/nodes/internal/constants.js +14 -0
  20. package/dist/nodes/internal/list-item-renderer.d.ts +1 -0
  21. package/dist/nodes/internal/list-item-renderer.js +6 -1
  22. package/dist/nodes/internal/predicates.d.ts +4 -0
  23. package/dist/nodes/internal/predicates.js +3 -0
  24. package/dist/nodes/internal/signal-store.d.ts +1 -0
  25. package/dist/nodes/internal/signal-store.js +7 -0
  26. package/dist/nodes/internal/tree-list-item-renderer.d.ts +1 -0
  27. package/dist/nodes/internal/tree-list-item-renderer.js +9 -1
  28. package/dist/nodes/level-bar.js +3 -16
  29. package/dist/nodes/list-view.js +11 -2
  30. package/dist/nodes/models/list.d.ts +6 -1
  31. package/dist/nodes/models/list.js +21 -6
  32. package/dist/nodes/models/tree-list.d.ts +6 -1
  33. package/dist/nodes/models/tree-list.js +21 -7
  34. package/dist/nodes/navigation-page.js +32 -23
  35. package/dist/nodes/notebook-page-tab.d.ts +1 -0
  36. package/dist/nodes/notebook-page-tab.js +15 -9
  37. package/dist/nodes/notebook-page.js +9 -6
  38. package/dist/nodes/scale.js +3 -16
  39. package/dist/nodes/scrolled-window.d.ts +1 -0
  40. package/dist/nodes/scrolled-window.js +22 -0
  41. package/dist/nodes/shortcut-controller.d.ts +37 -0
  42. package/dist/nodes/shortcut-controller.js +74 -0
  43. package/dist/nodes/shortcut.d.ts +38 -0
  44. package/dist/nodes/shortcut.js +46 -0
  45. package/dist/nodes/slot.js +11 -2
  46. package/dist/nodes/source-buffer.d.ts +73 -0
  47. package/dist/nodes/source-buffer.js +149 -0
  48. package/dist/nodes/source-view.d.ts +1 -0
  49. package/dist/nodes/source-view.js +42 -0
  50. package/dist/nodes/stack-page.js +15 -9
  51. package/dist/nodes/text-buffer.d.ts +43 -0
  52. package/dist/nodes/text-buffer.js +81 -0
  53. package/dist/nodes/text-view.d.ts +1 -0
  54. package/dist/nodes/text-view.js +45 -0
  55. package/dist/nodes/tree-list-view.js +11 -2
  56. package/dist/nodes/widget.d.ts +9 -0
  57. package/dist/nodes/widget.js +166 -13
  58. package/dist/nodes/window.js +7 -5
  59. package/dist/render.d.ts +14 -14
  60. package/dist/render.js +14 -14
  61. package/dist/types.d.ts +110 -1
  62. package/package.json +3 -3
@@ -1,4 +1,4 @@
1
- import { batch, beginBatch, endBatch, getNativeId } from "@gtkx/ffi";
1
+ import { beginBatch, endBatch, getNativeId } from "@gtkx/ffi";
2
2
  import React from "react";
3
3
  import { createNode } from "./factory.js";
4
4
  import { signalStore } from "./nodes/internal/signal-store.js";
@@ -71,11 +71,11 @@ export function createHostConfig() {
71
71
  parent.insertBefore(child, beforeChild);
72
72
  },
73
73
  prepareForCommit: () => {
74
+ signalStore.blockAll();
74
75
  beginBatch();
75
76
  return null;
76
77
  },
77
78
  resetAfterCommit: () => {
78
- batch(() => signalStore.blockAll());
79
79
  endBatch();
80
80
  flushAfterCommit();
81
81
  signalStore.unblockAll();
package/dist/jsx.d.ts CHANGED
@@ -1,8 +1,16 @@
1
1
  import type * as Gtk from "@gtkx/ffi/gtk";
2
2
  import type { ReactElement, ReactNode } from "react";
3
+ import type { AdjustmentProps } from "./nodes/adjustment.js";
3
4
  import type { RenderItemFn } from "./nodes/internal/list-item-renderer.js";
4
5
  import type { TreeRenderItemFn } from "./nodes/internal/tree-list-item-renderer.js";
5
- export type { EventControllerProps } from "./types.js";
6
+ import type { ShortcutProps as ShortcutNodeProps } from "./nodes/shortcut.js";
7
+ import type { ShortcutControllerProps as ShortcutControllerNodeProps } from "./nodes/shortcut-controller.js";
8
+ import type { SourceBufferProps } from "./nodes/source-buffer.js";
9
+ import type { TextBufferProps } from "./nodes/text-buffer.js";
10
+ export type { AdjustmentProps } from "./nodes/adjustment.js";
11
+ export type { SourceBufferProps } from "./nodes/source-buffer.js";
12
+ export type { TextBufferProps } from "./nodes/text-buffer.js";
13
+ export type { DragSourceProps, DropTargetProps, EventControllerProps, GestureDragProps } from "./types.js";
6
14
  /**
7
15
  * Props for slot-based child positioning.
8
16
  *
@@ -14,6 +22,13 @@ export type SlotProps = {
14
22
  /** Content to place in the slot */
15
23
  children?: ReactNode;
16
24
  };
25
+ /**
26
+ * Props for virtual child containers that don't expose slot id.
27
+ */
28
+ export type VirtualSlotProps = {
29
+ /** Content to place in the slot */
30
+ children?: ReactNode;
31
+ };
17
32
  /**
18
33
  * Props for items in a {@link ListView} or {@link GridView}.
19
34
  *
@@ -60,7 +75,7 @@ export type StringListItemProps = {
60
75
  *
61
76
  * @see {@link GridChild} for usage
62
77
  */
63
- export type GridChildProps = Omit<SlotProps, "id"> & {
78
+ export type GridChildProps = VirtualSlotProps & {
64
79
  /** Column index (0-based) */
65
80
  column?: number;
66
81
  /** Row index (0-based) */
@@ -75,7 +90,7 @@ export type GridChildProps = Omit<SlotProps, "id"> & {
75
90
  *
76
91
  * @see {@link FixedChild} for usage
77
92
  */
78
- export type FixedChildProps = Omit<SlotProps, "id"> & {
93
+ export type FixedChildProps = VirtualSlotProps & {
79
94
  /** X coordinate in pixels */
80
95
  x?: number;
81
96
  /** Y coordinate in pixels */
@@ -124,25 +139,25 @@ export type ColumnViewRootProps<C extends string = string> = {
124
139
  /** Sort direction (ascending or descending) */
125
140
  sortOrder?: Gtk.SortType;
126
141
  /** Callback when sort changes */
127
- onSortChange?: (column: C | null, order: Gtk.SortType) => void;
142
+ onSortChanged?: (column: C | null, order: Gtk.SortType) => void;
128
143
  /** Estimated row height in pixels for proper virtualization before content loads */
129
144
  estimatedRowHeight?: number;
130
145
  };
131
146
  /**
132
147
  * Props for notebook (tabbed) pages.
133
148
  */
134
- export type NotebookPageProps = Omit<SlotProps, "id"> & {
149
+ export type NotebookPageProps = VirtualSlotProps & {
135
150
  /** Tab label text (optional when using Notebook.PageTab) */
136
151
  label?: string;
137
152
  };
138
153
  /**
139
154
  * Props for custom notebook page tab widgets.
140
155
  */
141
- export type NotebookPageTabProps = SlotProps;
156
+ export type NotebookPageTabProps = VirtualSlotProps;
142
157
  /**
143
158
  * Props for the root Stack component.
144
159
  */
145
- export type StackRootProps = Omit<SlotProps, "id"> & {
160
+ export type StackRootProps = VirtualSlotProps & {
146
161
  /** ID of the currently visible page */
147
162
  page?: string;
148
163
  };
@@ -151,7 +166,7 @@ export type StackRootProps = Omit<SlotProps, "id"> & {
151
166
  *
152
167
  * @see {@link StackPage} for usage
153
168
  */
154
- export type StackPageProps = Omit<SlotProps, "id"> & {
169
+ export type StackPageProps = VirtualSlotProps & {
155
170
  /** Unique identifier for this page (used with page prop) */
156
171
  id?: string;
157
172
  /** Display title shown in stack switchers */
@@ -205,7 +220,7 @@ export type MenuSubmenuProps = {
205
220
  /**
206
221
  * Props for children within an Overlay container.
207
222
  */
208
- export type OverlayChildProps = Omit<SlotProps, "id"> & {
223
+ export type OverlayChildProps = VirtualSlotProps & {
209
224
  /** Whether to include this child in size measurement */
210
225
  measure?: boolean;
211
226
  /** Whether to clip this overlay child to the main child bounds */
@@ -307,33 +322,62 @@ export type ExpanderRowChildProps = {
307
322
  /** Children to add to this slot */
308
323
  children?: ReactNode;
309
324
  };
325
+ type NavigationPageBaseProps = {
326
+ title?: string;
327
+ canPop?: boolean;
328
+ children?: ReactNode;
329
+ };
330
+ /**
331
+ * Props for the ShortcutController element in JSX.
332
+ *
333
+ * Extends the base ShortcutControllerProps with support for children.
334
+ *
335
+ * @see {@link x.ShortcutController} for usage examples
336
+ */
337
+ export type ShortcutControllerProps = ShortcutControllerNodeProps & {
338
+ /** Shortcut children to add to this controller */
339
+ children?: ReactNode;
340
+ };
341
+ /**
342
+ * Props for the Shortcut element in JSX.
343
+ *
344
+ * @see {@link x.Shortcut} for usage examples
345
+ */
346
+ export type ShortcutProps = ShortcutNodeProps;
310
347
  /**
311
- * Props for the NavigationPage virtual element.
348
+ * Props for the NavigationPage virtual element with type-safe targeting.
312
349
  *
313
- * Used to declaratively define pages in an AdwNavigationView.
350
+ * The `for` prop is required and determines valid `id` values:
351
+ * - `AdwNavigationView`: `id` can be any string (page tags for navigation history)
352
+ * - `AdwNavigationSplitView`: `id` is narrowed to `"content" | "sidebar"` (slot positions)
314
353
  *
315
354
  * @example
316
355
  * ```tsx
356
+ * // In NavigationView - id can be any string
317
357
  * <AdwNavigationView history={["home", "details"]}>
318
- * <x.NavigationPage id="home" title="Home">
358
+ * <x.NavigationPage for={AdwNavigationView} id="home" title="Home">
319
359
  * <HomeContent />
320
360
  * </x.NavigationPage>
321
- * <x.NavigationPage id="details" title="Details">
322
- * <DetailsContent />
323
- * </x.NavigationPage>
324
361
  * </AdwNavigationView>
362
+ *
363
+ * // In NavigationSplitView - id is narrowed to "content" | "sidebar"
364
+ * <AdwNavigationSplitView>
365
+ * <x.NavigationPage for={AdwNavigationSplitView} id="sidebar" title="Sidebar">
366
+ * <SidebarContent />
367
+ * </x.NavigationPage>
368
+ * <x.NavigationPage for={AdwNavigationSplitView} id="content" title="Content">
369
+ * <MainContent />
370
+ * </x.NavigationPage>
371
+ * </AdwNavigationSplitView>
325
372
  * ```
326
373
  */
327
- export type NavigationPageProps = {
328
- /** Unique identifier for this page (used in history array) */
374
+ export type NavigationPageProps = (NavigationPageBaseProps & {
375
+ for: "AdwNavigationView";
329
376
  id: string;
330
- /** Title displayed in the header bar */
331
- title?: string;
332
- /** Whether the page can be popped via back button/gestures */
333
- canPop?: boolean;
334
- /** Page content */
335
- children?: ReactNode;
336
- };
377
+ }) | (NavigationPageBaseProps & {
378
+ for: "AdwNavigationSplitView";
379
+ id: import("./generated/jsx.js").WidgetSlotNames["AdwNavigationSplitView"];
380
+ });
337
381
  /**
338
382
  * Type mapping widget names to their available slot IDs.
339
383
  */
@@ -693,6 +737,24 @@ export declare const x: {
693
737
  * ```
694
738
  */
695
739
  MenuSubmenu: "MenuSubmenu";
740
+ /**
741
+ * Declarative adjustment configuration for adjustable widgets.
742
+ *
743
+ * Works with Scale, Scrollbar, ScaleButton, SpinButton, and ListBox.
744
+ *
745
+ * @example
746
+ * ```tsx
747
+ * <GtkScale>
748
+ * <x.Adjustment
749
+ * value={50}
750
+ * lower={0}
751
+ * upper={100}
752
+ * onValueChanged={(v) => console.log(v)}
753
+ * />
754
+ * </GtkScale>
755
+ * ```
756
+ */
757
+ Adjustment: "Adjustment";
696
758
  /**
697
759
  * A mark to display on a GtkScale slider.
698
760
  *
@@ -706,6 +768,38 @@ export declare const x: {
706
768
  * ```
707
769
  */
708
770
  ScaleMark: "ScaleMark";
771
+ /**
772
+ * Declarative text buffer for a GtkTextView.
773
+ *
774
+ * @example
775
+ * ```tsx
776
+ * <GtkTextView>
777
+ * <x.TextBuffer
778
+ * text="Hello!"
779
+ * enableUndo
780
+ * onTextChanged={(text) => console.log(text)}
781
+ * />
782
+ * </GtkTextView>
783
+ * ```
784
+ */
785
+ TextBuffer: "TextBuffer";
786
+ /**
787
+ * Declarative source buffer for a GtkSourceView with syntax highlighting.
788
+ *
789
+ * @example
790
+ * ```tsx
791
+ * <GtkSourceView>
792
+ * <x.SourceBuffer
793
+ * text={code}
794
+ * language="typescript"
795
+ * styleScheme="Adwaita-dark"
796
+ * highlightMatchingBrackets
797
+ * onTextChanged={(text) => console.log(text)}
798
+ * />
799
+ * </GtkSourceView>
800
+ * ```
801
+ */
802
+ SourceBuffer: "SourceBuffer";
709
803
  /**
710
804
  * A day mark on a GtkCalendar.
711
805
  *
@@ -772,28 +866,69 @@ export declare const x: {
772
866
  */
773
867
  ExpanderRowAction: "ExpanderRowAction";
774
868
  /**
775
- * A page within an AdwNavigationView.
869
+ * Type-safe page component for AdwNavigationView or AdwNavigationSplitView.
870
+ *
871
+ * The `for` prop is required and determines valid `id` values:
872
+ * - `AdwNavigationView`: any string (page tags for navigation history)
873
+ * - `AdwNavigationSplitView`: `"content"` or `"sidebar"` (slot positions)
776
874
  *
777
875
  * @example
778
876
  * ```tsx
877
+ * // In NavigationView - id can be any string
779
878
  * <AdwNavigationView history={["home"]}>
780
- * <x.NavigationPage id="home" title="Home">
879
+ * <x.NavigationPage for={AdwNavigationView} id="home" title="Home">
781
880
  * <GtkLabel label="Welcome!" />
782
881
  * </x.NavigationPage>
783
- * <x.NavigationPage id="settings" title="Settings">
784
- * <GtkLabel label="Settings page" />
785
- * </x.NavigationPage>
786
882
  * </AdwNavigationView>
883
+ *
884
+ * // In NavigationSplitView - id is narrowed to "content" | "sidebar"
885
+ * <AdwNavigationSplitView>
886
+ * <x.NavigationPage for={AdwNavigationSplitView} id="sidebar" title="Sidebar">
887
+ * <GtkLabel label="Sidebar" />
888
+ * </x.NavigationPage>
889
+ * <x.NavigationPage for={AdwNavigationSplitView} id="content" title="Content">
890
+ * <GtkLabel label="Content" />
891
+ * </x.NavigationPage>
892
+ * </AdwNavigationSplitView>
787
893
  * ```
788
894
  */
789
895
  NavigationPage: "NavigationPage";
896
+ /**
897
+ * Declarative keyboard shortcut controller.
898
+ *
899
+ * Attach keyboard shortcuts to a widget. Must contain `x.Shortcut` children.
900
+ *
901
+ * @example
902
+ * ```tsx
903
+ * <GtkBox>
904
+ * <x.ShortcutController scope={Gtk.ShortcutScope.GLOBAL}>
905
+ * <x.Shortcut trigger="<Control>f" onActivate={() => setSearchMode(s => !s)} />
906
+ * <x.Shortcut trigger="<Control>q" onActivate={quit} />
907
+ * </x.ShortcutController>
908
+ * </GtkBox>
909
+ * ```
910
+ */
911
+ ShortcutController: "ShortcutController";
912
+ /**
913
+ * A keyboard shortcut definition.
914
+ *
915
+ * Must be a child of `x.ShortcutController`.
916
+ *
917
+ * @example
918
+ * ```tsx
919
+ * <x.Shortcut trigger="<Control>s" onActivate={save} />
920
+ * <x.Shortcut trigger={["F5", "<Control>r"]} onActivate={refresh} />
921
+ * <x.Shortcut trigger="Escape" onActivate={cancel} disabled={!canCancel} />
922
+ * ```
923
+ */
924
+ Shortcut: "Shortcut";
790
925
  };
791
926
  declare global {
792
927
  namespace React {
793
928
  namespace JSX {
794
929
  interface IntrinsicElements {
795
- ActionRowPrefix: SlotProps;
796
- ActionRowSuffix: SlotProps;
930
+ ActionRowPrefix: VirtualSlotProps;
931
+ ActionRowSuffix: VirtualSlotProps;
797
932
  CalendarMark: CalendarMarkProps;
798
933
  ColumnViewColumn: ColumnViewColumnProps<any>;
799
934
  ExpanderRowAction: ExpanderRowChildProps;
@@ -806,18 +941,23 @@ declare global {
806
941
  MenuSection: MenuSectionProps;
807
942
  MenuSubmenu: MenuSubmenuProps;
808
943
  NotebookPage: NotebookPageProps;
809
- NotebookPageTab: NotebookPageTabProps;
944
+ NotebookPageTab: VirtualSlotProps;
810
945
  OverlayChild: OverlayChildProps;
811
- PackEnd: SlotProps;
812
- PackStart: SlotProps;
946
+ PackEnd: VirtualSlotProps;
947
+ PackStart: VirtualSlotProps;
948
+ Adjustment: AdjustmentProps;
813
949
  ScaleMark: ScaleMarkProps;
950
+ SourceBuffer: SourceBufferProps;
951
+ TextBuffer: TextBufferProps;
814
952
  SimpleListItem: StringListItemProps;
815
953
  StackPage: StackPageProps;
816
954
  Toggle: ToggleProps;
817
- ToolbarBottom: SlotProps;
818
- ToolbarTop: SlotProps;
955
+ ToolbarBottom: VirtualSlotProps;
956
+ ToolbarTop: VirtualSlotProps;
819
957
  TreeListItem: TreeListItemProps<any>;
820
958
  NavigationPage: NavigationPageProps;
959
+ ShortcutController: ShortcutControllerProps;
960
+ Shortcut: ShortcutProps;
821
961
  }
822
962
  }
823
963
  }
package/dist/jsx.js CHANGED
@@ -319,6 +319,24 @@ export const x = {
319
319
  * ```
320
320
  */
321
321
  MenuSubmenu: "MenuSubmenu",
322
+ /**
323
+ * Declarative adjustment configuration for adjustable widgets.
324
+ *
325
+ * Works with Scale, Scrollbar, ScaleButton, SpinButton, and ListBox.
326
+ *
327
+ * @example
328
+ * ```tsx
329
+ * <GtkScale>
330
+ * <x.Adjustment
331
+ * value={50}
332
+ * lower={0}
333
+ * upper={100}
334
+ * onValueChanged={(v) => console.log(v)}
335
+ * />
336
+ * </GtkScale>
337
+ * ```
338
+ */
339
+ Adjustment: "Adjustment",
322
340
  /**
323
341
  * A mark to display on a GtkScale slider.
324
342
  *
@@ -332,6 +350,38 @@ export const x = {
332
350
  * ```
333
351
  */
334
352
  ScaleMark: "ScaleMark",
353
+ /**
354
+ * Declarative text buffer for a GtkTextView.
355
+ *
356
+ * @example
357
+ * ```tsx
358
+ * <GtkTextView>
359
+ * <x.TextBuffer
360
+ * text="Hello!"
361
+ * enableUndo
362
+ * onTextChanged={(text) => console.log(text)}
363
+ * />
364
+ * </GtkTextView>
365
+ * ```
366
+ */
367
+ TextBuffer: "TextBuffer",
368
+ /**
369
+ * Declarative source buffer for a GtkSourceView with syntax highlighting.
370
+ *
371
+ * @example
372
+ * ```tsx
373
+ * <GtkSourceView>
374
+ * <x.SourceBuffer
375
+ * text={code}
376
+ * language="typescript"
377
+ * styleScheme="Adwaita-dark"
378
+ * highlightMatchingBrackets
379
+ * onTextChanged={(text) => console.log(text)}
380
+ * />
381
+ * </GtkSourceView>
382
+ * ```
383
+ */
384
+ SourceBuffer: "SourceBuffer",
335
385
  /**
336
386
  * A day mark on a GtkCalendar.
337
387
  *
@@ -398,20 +448,61 @@ export const x = {
398
448
  */
399
449
  ExpanderRowAction: "ExpanderRowAction",
400
450
  /**
401
- * A page within an AdwNavigationView.
451
+ * Type-safe page component for AdwNavigationView or AdwNavigationSplitView.
452
+ *
453
+ * The `for` prop is required and determines valid `id` values:
454
+ * - `AdwNavigationView`: any string (page tags for navigation history)
455
+ * - `AdwNavigationSplitView`: `"content"` or `"sidebar"` (slot positions)
402
456
  *
403
457
  * @example
404
458
  * ```tsx
459
+ * // In NavigationView - id can be any string
405
460
  * <AdwNavigationView history={["home"]}>
406
- * <x.NavigationPage id="home" title="Home">
461
+ * <x.NavigationPage for={AdwNavigationView} id="home" title="Home">
407
462
  * <GtkLabel label="Welcome!" />
408
463
  * </x.NavigationPage>
409
- * <x.NavigationPage id="settings" title="Settings">
410
- * <GtkLabel label="Settings page" />
411
- * </x.NavigationPage>
412
464
  * </AdwNavigationView>
465
+ *
466
+ * // In NavigationSplitView - id is narrowed to "content" | "sidebar"
467
+ * <AdwNavigationSplitView>
468
+ * <x.NavigationPage for={AdwNavigationSplitView} id="sidebar" title="Sidebar">
469
+ * <GtkLabel label="Sidebar" />
470
+ * </x.NavigationPage>
471
+ * <x.NavigationPage for={AdwNavigationSplitView} id="content" title="Content">
472
+ * <GtkLabel label="Content" />
473
+ * </x.NavigationPage>
474
+ * </AdwNavigationSplitView>
413
475
  * ```
414
476
  */
415
477
  NavigationPage: "NavigationPage",
478
+ /**
479
+ * Declarative keyboard shortcut controller.
480
+ *
481
+ * Attach keyboard shortcuts to a widget. Must contain `x.Shortcut` children.
482
+ *
483
+ * @example
484
+ * ```tsx
485
+ * <GtkBox>
486
+ * <x.ShortcutController scope={Gtk.ShortcutScope.GLOBAL}>
487
+ * <x.Shortcut trigger="<Control>f" onActivate={() => setSearchMode(s => !s)} />
488
+ * <x.Shortcut trigger="<Control>q" onActivate={quit} />
489
+ * </x.ShortcutController>
490
+ * </GtkBox>
491
+ * ```
492
+ */
493
+ ShortcutController: "ShortcutController",
494
+ /**
495
+ * A keyboard shortcut definition.
496
+ *
497
+ * Must be a child of `x.ShortcutController`.
498
+ *
499
+ * @example
500
+ * ```tsx
501
+ * <x.Shortcut trigger="<Control>s" onActivate={save} />
502
+ * <x.Shortcut trigger={["F5", "<Control>r"]} onActivate={refresh} />
503
+ * <x.Shortcut trigger="Escape" onActivate={cancel} disabled={!canCancel} />
504
+ * ```
505
+ */
506
+ Shortcut: "Shortcut",
416
507
  };
417
508
  export * from "./generated/jsx.js";
@@ -0,0 +1,48 @@
1
+ import type { AdjustableWidget } from "./internal/predicates.js";
2
+ import { VirtualNode } from "./virtual.js";
3
+ /**
4
+ * Props for the Adjustment virtual element.
5
+ *
6
+ * Used to declaratively configure the adjustment for adjustable widgets
7
+ * such as Scale, Scrollbar, ScaleButton, SpinButton, and ListBox.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * <GtkScale>
12
+ * <x.Adjustment
13
+ * value={50}
14
+ * lower={0}
15
+ * upper={100}
16
+ * stepIncrement={1}
17
+ * onValueChanged={(v) => console.log("Value:", v)}
18
+ * />
19
+ * </GtkScale>
20
+ * ```
21
+ */
22
+ export type AdjustmentProps = {
23
+ /** The current value */
24
+ value?: number;
25
+ /** The minimum value */
26
+ lower?: number;
27
+ /** The maximum value */
28
+ upper?: number;
29
+ /** The increment for arrow keys */
30
+ stepIncrement?: number;
31
+ /** The increment for page up/down */
32
+ pageIncrement?: number;
33
+ /** The page size (usually 0 for scales) */
34
+ pageSize?: number;
35
+ /** Callback when the value changes */
36
+ onValueChanged?: (value: number) => void;
37
+ };
38
+ export declare class AdjustmentNode extends VirtualNode<AdjustmentProps> {
39
+ static priority: number;
40
+ private widget?;
41
+ private adjustment?;
42
+ static matches(type: string): boolean;
43
+ setWidget(widget: AdjustableWidget): void;
44
+ private setupAdjustment;
45
+ private updateSignalHandler;
46
+ updateProps(oldProps: AdjustmentProps | null, newProps: AdjustmentProps): void;
47
+ unmount(): void;
48
+ }
@@ -0,0 +1,70 @@
1
+ import * as Gtk from "@gtkx/ffi/gtk";
2
+ import { registerNodeClass } from "../registry.js";
3
+ import { signalStore } from "./internal/signal-store.js";
4
+ import { VirtualNode } from "./virtual.js";
5
+ export class AdjustmentNode extends VirtualNode {
6
+ static priority = 1;
7
+ widget;
8
+ adjustment;
9
+ static matches(type) {
10
+ return type === "Adjustment";
11
+ }
12
+ setWidget(widget) {
13
+ this.widget = widget;
14
+ this.setupAdjustment();
15
+ }
16
+ setupAdjustment() {
17
+ if (!this.widget)
18
+ return;
19
+ const { value = 0, lower = 0, upper = 100, stepIncrement = 1, pageIncrement = 10, pageSize = 0 } = this.props;
20
+ this.adjustment = new Gtk.Adjustment(value, lower, upper, stepIncrement, pageIncrement, pageSize);
21
+ this.widget.setAdjustment(this.adjustment);
22
+ this.updateSignalHandler();
23
+ }
24
+ updateSignalHandler() {
25
+ if (!this.adjustment)
26
+ return;
27
+ const { onValueChanged } = this.props;
28
+ if (onValueChanged) {
29
+ const adjustment = this.adjustment;
30
+ signalStore.set(this, adjustment, "value-changed", () => onValueChanged(adjustment.getValue()));
31
+ }
32
+ else {
33
+ signalStore.set(this, this.adjustment, "value-changed", null);
34
+ }
35
+ }
36
+ updateProps(oldProps, newProps) {
37
+ super.updateProps(oldProps, newProps);
38
+ if (!this.adjustment)
39
+ return;
40
+ if (!oldProps || oldProps.lower !== newProps.lower) {
41
+ this.adjustment.setLower(newProps.lower ?? 0);
42
+ }
43
+ if (!oldProps || oldProps.upper !== newProps.upper) {
44
+ this.adjustment.setUpper(newProps.upper ?? 100);
45
+ }
46
+ if (!oldProps || oldProps.stepIncrement !== newProps.stepIncrement) {
47
+ this.adjustment.setStepIncrement(newProps.stepIncrement ?? 1);
48
+ }
49
+ if (!oldProps || oldProps.pageIncrement !== newProps.pageIncrement) {
50
+ this.adjustment.setPageIncrement(newProps.pageIncrement ?? 10);
51
+ }
52
+ if (!oldProps || oldProps.pageSize !== newProps.pageSize) {
53
+ this.adjustment.setPageSize(newProps.pageSize ?? 0);
54
+ }
55
+ if (!oldProps || oldProps.value !== newProps.value) {
56
+ if (newProps.value !== undefined) {
57
+ this.adjustment.setValue(newProps.value);
58
+ }
59
+ }
60
+ if (!oldProps || oldProps.onValueChanged !== newProps.onValueChanged) {
61
+ this.updateSignalHandler();
62
+ }
63
+ }
64
+ unmount() {
65
+ this.adjustment = undefined;
66
+ this.widget = undefined;
67
+ super.unmount();
68
+ }
69
+ }
70
+ registerNodeClass(AdjustmentNode);
@@ -23,20 +23,20 @@ class ApplicationNode extends Node {
23
23
  this.container.setMenubar(this.menu.getMenu());
24
24
  return;
25
25
  }
26
- if (child instanceof WindowNode) {
26
+ if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
27
27
  return;
28
28
  }
29
- throw new Error(`Cannot append '${child.typeName}' to 'Application': expected Window or MenuItem`);
29
+ throw new Error(`Cannot append '${child.typeName}' to 'Application': expected ApplicationWindow or MenuItem`);
30
30
  }
31
31
  insertBefore(child, before) {
32
32
  if (child instanceof MenuNode) {
33
33
  this.menu.insertBefore(child, before);
34
34
  return;
35
35
  }
36
- if (child instanceof WindowNode) {
36
+ if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
37
37
  return;
38
38
  }
39
- throw new Error(`Cannot insert '${child.typeName}' into 'Application': expected Window or MenuItem`);
39
+ throw new Error(`Cannot insert '${child.typeName}' into 'Application': expected ApplicationWindow or MenuItem`);
40
40
  }
41
41
  removeChild(child) {
42
42
  if (child instanceof MenuNode) {
@@ -48,10 +48,10 @@ class ApplicationNode extends Node {
48
48
  }, CommitPriority.LOW);
49
49
  return;
50
50
  }
51
- if (child instanceof WindowNode) {
51
+ if (child instanceof WindowNode && child.container instanceof Gtk.ApplicationWindow) {
52
52
  return;
53
53
  }
54
- throw new Error(`Cannot remove '${child.typeName}' from 'Application': expected Window or MenuItem`);
54
+ throw new Error(`Cannot remove '${child.typeName}' from 'Application': expected ApplicationWindow or MenuItem`);
55
55
  }
56
56
  }
57
57
  registerNodeClass(ApplicationNode);