@gjsify/example-gtk-adwaita-storybook 0.53.0 → 0.55.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 (243) hide show
  1. package/dist/browser-main.js +8093 -3042
  2. package/dist/gjs.js +15 -10
  3. package/dist/gjs.node.mjs +10 -5
  4. package/package.json +5 -5
  5. package/src/browser/buttons/color-dialog-button.web.ts +42 -0
  6. package/src/browser/buttons/font-dialog-button.web.ts +42 -0
  7. package/src/browser/buttons/link-button.web.ts +37 -0
  8. package/src/browser/buttons/scale-button.web.ts +36 -0
  9. package/src/browser/buttons/toggle-button.web.ts +35 -0
  10. package/src/browser/controls/check-button.web.ts +38 -0
  11. package/src/browser/controls/gtk-spinner.web.ts +39 -0
  12. package/src/browser/controls/level-bar.web.ts +43 -0
  13. package/src/browser/controls/password-entry.web.ts +36 -0
  14. package/src/browser/controls/progress-bar.web.ts +39 -0
  15. package/src/browser/controls/scale.web.ts +44 -0
  16. package/src/browser/controls/search-entry.web.ts +49 -0
  17. package/src/browser/controls/spin-button.web.ts +40 -0
  18. package/src/browser/controls/switch.web.ts +38 -0
  19. package/src/browser/drawing/drag-icon.web.ts +112 -0
  20. package/src/browser/drawing/drawing-area.web.ts +66 -0
  21. package/src/browser/drawing/gl-area.web.ts +162 -0
  22. package/src/browser/drawing/graphics-offload.web.ts +74 -0
  23. package/src/browser/feedback/dialog.web.ts +76 -0
  24. package/src/browser/feedback/emoji-chooser.web.ts +93 -0
  25. package/src/browser/feedback/gtk-about-dialog.web.ts +105 -0
  26. package/src/browser/feedback/page-setup-unix-dialog.web.ts +93 -0
  27. package/src/browser/feedback/print-unix-dialog.web.ts +111 -0
  28. package/src/browser/feedback/shortcuts-dialog.web.ts +90 -0
  29. package/src/browser/layout/application-window.web.ts +94 -0
  30. package/src/browser/layout/aspect-frame.web.ts +49 -0
  31. package/src/browser/layout/bin.web.ts +41 -0
  32. package/src/browser/layout/breakpoint-bin.web.ts +61 -0
  33. package/src/browser/layout/center-box.web.ts +45 -0
  34. package/src/browser/layout/clamp-scrollable.web.ts +47 -0
  35. package/src/browser/layout/expander.web.ts +52 -0
  36. package/src/browser/layout/fixed.web.ts +51 -0
  37. package/src/browser/layout/frame.web.ts +40 -0
  38. package/src/browser/layout/grid.web.ts +46 -0
  39. package/src/browser/layout/layout-slot.web.ts +60 -0
  40. package/src/browser/layout/multi-layout-view.web.ts +94 -0
  41. package/src/browser/layout/overlay.web.ts +57 -0
  42. package/src/browser/layout/paned.web.ts +69 -0
  43. package/src/browser/layout/popover-bin.web.ts +54 -0
  44. package/src/browser/layout/popover-menu.web.ts +48 -0
  45. package/src/browser/layout/popover.web.ts +61 -0
  46. package/src/browser/layout/revealer.web.ts +53 -0
  47. package/src/browser/layout/scrollbar.web.ts +54 -0
  48. package/src/browser/layout/scrolled-window.web.ts +52 -0
  49. package/src/browser/layout/separator.web.ts +47 -0
  50. package/src/browser/layout/viewport.web.ts +51 -0
  51. package/src/browser/layout/window.web.ts +60 -0
  52. package/src/browser/media/image.web.ts +39 -0
  53. package/src/browser/media/inscription.web.ts +52 -0
  54. package/src/browser/media/media-controls.web.ts +65 -0
  55. package/src/browser/media/picture.web.ts +56 -0
  56. package/src/browser/media/video.web.ts +56 -0
  57. package/src/browser/navigation/popover-menu-bar.web.ts +40 -0
  58. package/src/browser/presentation/calendar.web.ts +49 -0
  59. package/src/browser/presentation/column-view.web.ts +45 -0
  60. package/src/browser/presentation/flow-box.web.ts +52 -0
  61. package/src/browser/presentation/grid-view.web.ts +37 -0
  62. package/src/browser/presentation/list-box.web.ts +48 -0
  63. package/src/browser/presentation/list-view.web.ts +36 -0
  64. package/src/browser/presentation/tree-expander.web.ts +68 -0
  65. package/src/browser/presentation/window-handle.web.ts +42 -0
  66. package/src/browser/rows/preferences-row.web.ts +43 -0
  67. package/src/browser/stories.ts +158 -0
  68. package/src/browser/text/editable-label.web.ts +45 -0
  69. package/src/browser/text/search-bar.web.ts +45 -0
  70. package/src/browser/text/text-view.web.ts +54 -0
  71. package/src/browser/text/text.web.ts +48 -0
  72. package/src/browser/view-switching/notebook.web.ts +67 -0
  73. package/src/browser/view-switching/stack-sidebar.web.ts +68 -0
  74. package/src/browser/view-switching/stack-switcher.web.ts +70 -0
  75. package/src/browser/view-switching/stack.web.ts +72 -0
  76. package/src/browser/view-switching/tab-bar.web.ts +105 -0
  77. package/src/browser/view-switching/tab-button.web.ts +52 -0
  78. package/src/browser/view-switching/tab-overview.web.ts +87 -0
  79. package/src/browser/view-switching/view-switcher-sidebar.web.ts +77 -0
  80. package/src/browser/windows/action-bar.web.ts +66 -0
  81. package/src/browser/windows/gtk-application-window.web.ts +67 -0
  82. package/src/browser/windows/gtk-header-bar.web.ts +61 -0
  83. package/src/browser/windows/gtk-window.web.ts +58 -0
  84. package/src/browser/windows/window-controls.web.ts +54 -0
  85. package/src/buttons/color-dialog-button.meta.ts +16 -0
  86. package/src/buttons/color-dialog-button.story.ts +49 -0
  87. package/src/buttons/font-dialog-button.meta.ts +29 -0
  88. package/src/buttons/font-dialog-button.story.ts +52 -0
  89. package/src/buttons/link-button.meta.ts +18 -0
  90. package/src/buttons/link-button.story.ts +48 -0
  91. package/src/buttons/scale-button.meta.ts +34 -0
  92. package/src/buttons/scale-button.story.ts +50 -0
  93. package/src/buttons/toggle-button.meta.ts +17 -0
  94. package/src/buttons/toggle-button.story.ts +46 -0
  95. package/src/controls/check-button.meta.ts +19 -0
  96. package/src/controls/check-button.story.ts +56 -0
  97. package/src/controls/gtk-spinner.meta.ts +24 -0
  98. package/src/controls/gtk-spinner.story.ts +53 -0
  99. package/src/controls/level-bar.meta.ts +39 -0
  100. package/src/controls/level-bar.story.ts +58 -0
  101. package/src/controls/password-entry.meta.ts +18 -0
  102. package/src/controls/password-entry.story.ts +54 -0
  103. package/src/controls/progress-bar.meta.ts +20 -0
  104. package/src/controls/progress-bar.story.ts +53 -0
  105. package/src/controls/scale.meta.ts +47 -0
  106. package/src/controls/scale.story.ts +66 -0
  107. package/src/controls/search-entry.meta.ts +18 -0
  108. package/src/controls/search-entry.story.ts +57 -0
  109. package/src/controls/spin-button.meta.ts +40 -0
  110. package/src/controls/spin-button.story.ts +55 -0
  111. package/src/controls/switch.meta.ts +18 -0
  112. package/src/controls/switch.story.ts +50 -0
  113. package/src/drawing/drag-icon.meta.ts +39 -0
  114. package/src/drawing/drag-icon.story.ts +117 -0
  115. package/src/drawing/drawing-area.meta.ts +45 -0
  116. package/src/drawing/drawing-area.story.ts +78 -0
  117. package/src/drawing/gl-area.meta.ts +30 -0
  118. package/src/drawing/gl-area.story.ts +113 -0
  119. package/src/drawing/graphics-offload.meta.ts +39 -0
  120. package/src/drawing/graphics-offload.story.ts +73 -0
  121. package/src/feedback/dialog.meta.ts +25 -0
  122. package/src/feedback/dialog.story.ts +78 -0
  123. package/src/feedback/emoji-chooser.meta.ts +10 -0
  124. package/src/feedback/emoji-chooser.story.ts +98 -0
  125. package/src/feedback/gtk-about-dialog.meta.ts +29 -0
  126. package/src/feedback/gtk-about-dialog.story.ts +90 -0
  127. package/src/feedback/page-setup-unix-dialog.meta.ts +37 -0
  128. package/src/feedback/page-setup-unix-dialog.story.ts +70 -0
  129. package/src/feedback/print-unix-dialog.meta.ts +30 -0
  130. package/src/feedback/print-unix-dialog.story.ts +93 -0
  131. package/src/feedback/shortcuts-dialog.meta.ts +12 -0
  132. package/src/feedback/shortcuts-dialog.story.ts +79 -0
  133. package/src/layout/application-window.meta.ts +16 -0
  134. package/src/layout/application-window.story.ts +97 -0
  135. package/src/layout/aspect-frame.meta.ts +19 -0
  136. package/src/layout/aspect-frame.story.ts +62 -0
  137. package/src/layout/bin.meta.ts +15 -0
  138. package/src/layout/bin.story.ts +56 -0
  139. package/src/layout/breakpoint-bin.meta.ts +38 -0
  140. package/src/layout/breakpoint-bin.story.ts +62 -0
  141. package/src/layout/center-box.meta.ts +26 -0
  142. package/src/layout/center-box.story.ts +54 -0
  143. package/src/layout/clamp-scrollable.meta.ts +30 -0
  144. package/src/layout/clamp-scrollable.story.ts +51 -0
  145. package/src/layout/expander.meta.ts +30 -0
  146. package/src/layout/expander.story.ts +62 -0
  147. package/src/layout/fixed.meta.ts +16 -0
  148. package/src/layout/fixed.story.ts +54 -0
  149. package/src/layout/frame.meta.ts +24 -0
  150. package/src/layout/frame.story.ts +51 -0
  151. package/src/layout/grid.meta.ts +45 -0
  152. package/src/layout/grid.story.ts +80 -0
  153. package/src/layout/layout-slot.meta.ts +22 -0
  154. package/src/layout/layout-slot.story.ts +68 -0
  155. package/src/layout/multi-layout-view.meta.ts +31 -0
  156. package/src/layout/multi-layout-view.story.ts +101 -0
  157. package/src/layout/overlay.meta.ts +42 -0
  158. package/src/layout/overlay.story.ts +72 -0
  159. package/src/layout/paned.meta.ts +45 -0
  160. package/src/layout/paned.story.ts +70 -0
  161. package/src/layout/popover-bin.meta.ts +29 -0
  162. package/src/layout/popover-bin.story.ts +66 -0
  163. package/src/layout/popover-menu.meta.ts +54 -0
  164. package/src/layout/popover-menu.story.ts +119 -0
  165. package/src/layout/popover.meta.ts +38 -0
  166. package/src/layout/popover.story.ts +66 -0
  167. package/src/layout/revealer.meta.ts +44 -0
  168. package/src/layout/revealer.story.ts +79 -0
  169. package/src/layout/scrollbar.meta.ts +33 -0
  170. package/src/layout/scrollbar.story.ts +61 -0
  171. package/src/layout/scrolled-window.meta.ts +57 -0
  172. package/src/layout/scrolled-window.story.ts +74 -0
  173. package/src/layout/separator.meta.ts +25 -0
  174. package/src/layout/separator.story.ts +53 -0
  175. package/src/layout/viewport.meta.ts +19 -0
  176. package/src/layout/viewport.story.ts +53 -0
  177. package/src/layout/window.meta.ts +13 -0
  178. package/src/layout/window.story.ts +66 -0
  179. package/src/media/image.meta.ts +24 -0
  180. package/src/media/image.story.ts +48 -0
  181. package/src/media/inscription.meta.ts +45 -0
  182. package/src/media/inscription.story.ts +64 -0
  183. package/src/media/media-controls.meta.ts +30 -0
  184. package/src/media/media-controls.story.ts +58 -0
  185. package/src/media/picture.meta.ts +42 -0
  186. package/src/media/picture.story.ts +81 -0
  187. package/src/media/video.meta.ts +32 -0
  188. package/src/media/video.story.ts +57 -0
  189. package/src/metas.ts +79 -0
  190. package/src/navigation/popover-menu-bar.meta.ts +51 -0
  191. package/src/navigation/popover-menu-bar.story.ts +72 -0
  192. package/src/presentation/calendar.meta.ts +28 -0
  193. package/src/presentation/calendar.story.ts +64 -0
  194. package/src/presentation/column-view.meta.ts +30 -0
  195. package/src/presentation/column-view.story.ts +73 -0
  196. package/src/presentation/flow-box.meta.ts +51 -0
  197. package/src/presentation/flow-box.story.ts +72 -0
  198. package/src/presentation/grid-view.meta.ts +28 -0
  199. package/src/presentation/grid-view.story.ts +64 -0
  200. package/src/presentation/list-box.meta.ts +55 -0
  201. package/src/presentation/list-box.story.ts +68 -0
  202. package/src/presentation/list-view.meta.ts +38 -0
  203. package/src/presentation/list-view.story.ts +73 -0
  204. package/src/presentation/tree-expander.meta.ts +24 -0
  205. package/src/presentation/tree-expander.story.ts +105 -0
  206. package/src/presentation/window-handle.meta.ts +27 -0
  207. package/src/presentation/window-handle.story.ts +53 -0
  208. package/src/rows/preferences-row.meta.ts +15 -0
  209. package/src/rows/preferences-row.story.ts +50 -0
  210. package/src/text/editable-label.meta.ts +17 -0
  211. package/src/text/editable-label.story.ts +47 -0
  212. package/src/text/search-bar.meta.ts +17 -0
  213. package/src/text/search-bar.story.ts +48 -0
  214. package/src/text/text-view.meta.ts +49 -0
  215. package/src/text/text-view.story.ts +69 -0
  216. package/src/text/text.meta.ts +21 -0
  217. package/src/text/text.story.ts +50 -0
  218. package/src/view-switching/notebook.meta.ts +44 -0
  219. package/src/view-switching/notebook.story.ts +77 -0
  220. package/src/view-switching/stack-sidebar.meta.ts +50 -0
  221. package/src/view-switching/stack-sidebar.story.ts +85 -0
  222. package/src/view-switching/stack-switcher.meta.ts +53 -0
  223. package/src/view-switching/stack-switcher.story.ts +95 -0
  224. package/src/view-switching/stack.meta.ts +53 -0
  225. package/src/view-switching/stack.story.ts +95 -0
  226. package/src/view-switching/tab-bar.meta.ts +22 -0
  227. package/src/view-switching/tab-bar.story.ts +85 -0
  228. package/src/view-switching/tab-button.meta.ts +14 -0
  229. package/src/view-switching/tab-button.story.ts +52 -0
  230. package/src/view-switching/tab-overview.meta.ts +21 -0
  231. package/src/view-switching/tab-overview.story.ts +86 -0
  232. package/src/view-switching/view-switcher-sidebar.meta.ts +42 -0
  233. package/src/view-switching/view-switcher-sidebar.story.ts +73 -0
  234. package/src/windows/action-bar.meta.ts +27 -0
  235. package/src/windows/action-bar.story.ts +65 -0
  236. package/src/windows/gtk-application-window.meta.ts +27 -0
  237. package/src/windows/gtk-application-window.story.ts +89 -0
  238. package/src/windows/gtk-header-bar.meta.ts +39 -0
  239. package/src/windows/gtk-header-bar.story.ts +76 -0
  240. package/src/windows/gtk-window.meta.ts +30 -0
  241. package/src/windows/gtk-window.story.ts +64 -0
  242. package/src/windows/window-controls.meta.ts +42 -0
  243. package/src/windows/window-controls.story.ts +61 -0
@@ -0,0 +1,98 @@
1
+ // Gtk.EmojiChooser — the emoji popover a text widget opens, with a search entry.
2
+ //
3
+ // The story shows the half that is easy to get wrong: the SEARCH. A term matches when it
4
+ // prefixes a word of the emoji's name or of one of its keywords, a section with no match at
5
+ // all disappears heading and all, and a search that empties every section shows the "No
6
+ // Results Found" page instead of the list.
7
+
8
+ import Gtk from 'gi://Gtk?version=4.0';
9
+ import GObject from 'gi://GObject?version=2.0';
10
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
11
+ import { emojiChooserMeta } from './emoji-chooser.meta.js';
12
+
13
+ /** Story: an entry with an emoji chooser attached to its prefix button. */
14
+ export class EmojiChooserStory extends StoryWidget {
15
+ private _button: Gtk.Button | null = null;
16
+ private _entry: Gtk.Entry | null = null;
17
+ private _chooser: Gtk.EmojiChooser | null = null;
18
+
19
+ static {
20
+ GObject.registerClass({ GTypeName: 'AdwStorybookEmojiChooser' }, EmojiChooserStory);
21
+ }
22
+
23
+ constructor() {
24
+ super(StoryWidget.fromMeta(EmojiChooserStory.getMetadata(), 'Default'));
25
+ }
26
+
27
+ static getMetadata(): StoryMeta {
28
+ return { ...emojiChooserMeta, component: Gtk.EmojiChooser.$gtype };
29
+ }
30
+
31
+ initialize(): void {
32
+ this._entry = new Gtk.Entry({
33
+ placeholderText: 'Type a message…',
34
+ halign: Gtk.Align.CENTER,
35
+ });
36
+ this._entry.add_css_class('card');
37
+ this._entry.hexpand = true;
38
+
39
+ this._chooser = Gtk.EmojiChooser.new();
40
+ this._chooser.connect('emoji-picked', (_chooser: Gtk.EmojiChooser, text: string) => {
41
+ if (this._entry === null) return;
42
+ // The signal carries the Unicode SEQUENCE, which is what an entry inserts.
43
+ this._entry.set_text(this._entry.get_text() + text);
44
+ });
45
+
46
+ this._button = new Gtk.Button({
47
+ iconName: 'face-smile-symbolic',
48
+ tooltipText: 'Insert an emoji',
49
+ valign: Gtk.Align.CENTER,
50
+ });
51
+ this._button.add_css_class('flat');
52
+ this._button.add_css_class('circular');
53
+ // The popover's anchor is the widget it is a child of, and the button is the entry's
54
+ // prefix — which is the arrangement GtkEntry's own emoji completion uses.
55
+ this._chooser.set_parent(this._button);
56
+ const row = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL, spacing: 6 });
57
+ row.append(this._button);
58
+ row.append(this._entry);
59
+
60
+ const box = new Gtk.Box({
61
+ orientation: Gtk.Orientation.VERTICAL,
62
+ spacing: 12,
63
+ halign: Gtk.Align.CENTER,
64
+ valign: Gtk.Align.CENTER,
65
+ });
66
+ box.append(row);
67
+ this.addContent(box);
68
+ this._applySearch(this.args.search as string);
69
+ }
70
+
71
+ /**
72
+ * The chooser's search entry.
73
+ *
74
+ * `GtkEmojiChooser` declares NO properties at all — the search is a `GtkSearchEntry`
75
+ * inside its template (`ui/gtkemojichooser.ui`), not a property of the widget — so the
76
+ * only way to drive it is to find it.
77
+ */
78
+ private _searchEntry(): Gtk.SearchEntry | null {
79
+ let child: Gtk.Widget | null = this._chooser?.get_first_child() ?? null;
80
+ while (child !== null) {
81
+ if (child instanceof Gtk.SearchEntry) return child;
82
+ child = child.get_first_child();
83
+ }
84
+ return null;
85
+ }
86
+
87
+ private _applySearch(text: string): void {
88
+ this._searchEntry()?.set_text(text);
89
+ }
90
+
91
+ updateArgs(args: StoryArgs): void {
92
+ if (typeof args.search === 'string') this._applySearch(args.search);
93
+ }
94
+ }
95
+
96
+ GObject.type_ensure(EmojiChooserStory.$gtype);
97
+
98
+ export const EmojiChooserStories: StoryModule = { stories: [EmojiChooserStory] };
@@ -0,0 +1,29 @@
1
+ // Shared, renderer-agnostic metadata for the Gtk.AboutDialog story.
2
+
3
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
+
5
+ export const gtkAboutDialogMeta: StoryMeta = {
6
+ title: 'Feedback/GTK About Dialog',
7
+ description:
8
+ "Gtk.AboutDialog — GTK's own about window: a dialog-size logo over the program name, with the Credits, License and System pages behind a stack switcher. NOT Adw.AboutDialog, which is a navigation view of preference rows.",
9
+ controls: [
10
+ { name: 'programName', label: 'Program name', type: ControlType.TEXT, defaultValue: 'Calculator' },
11
+ { name: 'version', label: 'Version', type: ControlType.TEXT, defaultValue: '48.1' },
12
+ {
13
+ name: 'licenseType',
14
+ label: 'License type',
15
+ type: ControlType.SELECT,
16
+ options: [
17
+ { label: 'Unknown', value: 'unknown' },
18
+ { label: 'Custom', value: 'custom' },
19
+ { label: 'GPL 3.0', value: 'gpl-3-0' },
20
+ { label: 'MIT', value: 'mit-x11' },
21
+ { label: 'BSD 3-Clause', value: 'bsd-3' },
22
+ { label: 'Apache 2.0', value: 'apache-2-0' },
23
+ { label: '0BSD', value: '0bsd' },
24
+ ],
25
+ defaultValue: 'gpl-3-0',
26
+ },
27
+ { name: 'withCredits', label: 'With credits', type: ControlType.BOOLEAN, defaultValue: true },
28
+ ],
29
+ };
@@ -0,0 +1,90 @@
1
+ // Gtk.AboutDialog — GTK's own about window, presented from a button.
2
+ //
3
+ // The page-visibility rules are the story's subject: `license-type` picks which licence
4
+ // text is on the main page and whether the License page exists at all, and `withCredits`
5
+ // decides the third page and the switcher.
6
+
7
+ import Gtk from 'gi://Gtk?version=4.0';
8
+ import GObject from 'gi://GObject?version=2.0';
9
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
10
+ import { gtkAboutDialogMeta } from './gtk-about-dialog.meta.js';
11
+
12
+ /** The `Gtk.License` nicks the control offers, in enum order. */
13
+ const LICENSES: Record<string, Gtk.License> = {
14
+ unknown: Gtk.License.UNKNOWN,
15
+ custom: Gtk.License.CUSTOM,
16
+ 'gpl-3-0': Gtk.License.GPL_3_0,
17
+ 'mit-x11': Gtk.License.MIT_X11,
18
+ 'bsd-3': Gtk.License.BSD_3,
19
+ 'apache-2-0': Gtk.License.APACHE_2_0,
20
+ '0bsd': Gtk.License['0BSD'],
21
+ };
22
+
23
+ /** Story: Gtk.AboutDialog presented from a button, with a licence type and credits. */
24
+ export class GtkAboutDialogStory extends StoryWidget {
25
+ private _button: Gtk.Button | null = null;
26
+
27
+ static {
28
+ GObject.registerClass({ GTypeName: 'AdwStorybookGtkAboutDialog' }, GtkAboutDialogStory);
29
+ }
30
+
31
+ constructor() {
32
+ super(StoryWidget.fromMeta(GtkAboutDialogStory.getMetadata(), 'Default'));
33
+ }
34
+
35
+ static getMetadata(): StoryMeta {
36
+ return { ...gtkAboutDialogMeta, component: Gtk.AboutDialog.$gtype };
37
+ }
38
+
39
+ initialize(): void {
40
+ this._button = new Gtk.Button({
41
+ label: 'Show dialog',
42
+ halign: Gtk.Align.CENTER,
43
+ valign: Gtk.Align.CENTER,
44
+ });
45
+ this._button.add_css_class('pill');
46
+ this._button.add_css_class('suggested-action');
47
+ this._button.connect('clicked', () => this._present());
48
+
49
+ this.addContent(this._button);
50
+ }
51
+
52
+ private _present(): void {
53
+ const dialog = new Gtk.AboutDialog({
54
+ programName: this.args.programName as string,
55
+ version: this.args.version as string,
56
+ logoIconName: 'application-x-executable-symbolic',
57
+ comments: 'An arithmetic calculator for the GNOME desktop.',
58
+ website: 'https://gitlab.gnome.org/World/gnome-calculator',
59
+ websiteLabel: 'GNOME Calculator',
60
+ copyright: '© 2026 The GNOME Project',
61
+ systemInformation: 'GTK 4.24.0\nglibc 2.42\nBuilt with meson 1.6',
62
+ });
63
+
64
+ const licenseType = LICENSES[this.args.licenseType as string] ?? Gtk.License.UNKNOWN;
65
+ if (licenseType === Gtk.License.CUSTOM) {
66
+ // A CUSTOM licence is the only one whose text the :license property supplies —
67
+ // set_license_type overwrites it for every other type (gtkaboutdialog.c:2259).
68
+ dialog.set_license('Permission is hereby granted, free of charge, to any person obtaining a copy…');
69
+ }
70
+ dialog.set_license_type(licenseType);
71
+
72
+ if (this.args.withCredits as boolean) {
73
+ dialog.set_authors(['Ada Lovelace <ada@example.org>', 'Grace Hopper']);
74
+ dialog.set_documenters(['Barbara Liskov']);
75
+ dialog.set_artists(['Margaret Hamilton']);
76
+ dialog.set_translator_credits('Alan Turing\nKatherine Johnson');
77
+ dialog.add_credit_section('Reviewed by', ['Tony Hoare <tony@example.org>']);
78
+ }
79
+
80
+ dialog.present();
81
+ }
82
+
83
+ updateArgs(_args: StoryArgs): void {
84
+ // The dialog reads the latest args each time it is presented; nothing to mutate live.
85
+ }
86
+ }
87
+
88
+ GObject.type_ensure(GtkAboutDialogStory.$gtype);
89
+
90
+ export const GtkAboutDialogStories: StoryModule = { stories: [GtkAboutDialogStory] };
@@ -0,0 +1,37 @@
1
+ // Shared, renderer-agnostic metadata for the Gtk.PageSetupUnixDialog story.
2
+
3
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
+
5
+ export const pageSetupUnixDialogMeta: StoryMeta = {
6
+ title: 'Feedback/Page Setup Dialog',
7
+ description:
8
+ "Gtk.PageSetupUnixDialog — the page setup dialog Unix platforms have instead of a native one: a printer and a paper size, the chosen sheet's size and margins, and four orientation buttons.",
9
+ controls: [
10
+ {
11
+ name: 'paperSize',
12
+ label: 'Paper size',
13
+ type: ControlType.SELECT,
14
+ options: [
15
+ { label: 'US Letter', value: 'na_letter' },
16
+ { label: 'US Legal', value: 'na_legal' },
17
+ { label: 'A4', value: 'iso_a4' },
18
+ { label: 'A5', value: 'iso_a5' },
19
+ { label: 'B5', value: 'iso_b5' },
20
+ { label: 'A3', value: 'iso_a3' },
21
+ ],
22
+ defaultValue: 'iso_a4',
23
+ },
24
+ {
25
+ name: 'orientation',
26
+ label: 'Orientation',
27
+ type: ControlType.SELECT,
28
+ options: [
29
+ { label: 'Portrait', value: 'portrait' },
30
+ { label: 'Landscape', value: 'landscape' },
31
+ { label: 'Reverse portrait', value: 'reverse-portrait' },
32
+ { label: 'Reverse landscape', value: 'reverse-landscape' },
33
+ ],
34
+ defaultValue: 'landscape',
35
+ },
36
+ ],
37
+ };
@@ -0,0 +1,70 @@
1
+ // Gtk.PageSetupUnixDialog — the Unix page setup dialog, presented from a button.
2
+ //
3
+ // The subject is what the dialog REPORTS: the chosen sheet's size in the user's unit, with
4
+ // the four margins in the label's tooltip, and the four orientation buttons that read back
5
+ // into the page setup.
6
+
7
+ import Gtk from 'gi://Gtk?version=4.0';
8
+ import GObject from 'gi://GObject?version=2.0';
9
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
10
+ import { pageSetupUnixDialogMeta } from './page-setup-unix-dialog.meta.js';
11
+
12
+ /** The `Gtk.PageOrientation` nicks the control offers, in enum order. */
13
+ const ORIENTATIONS: Record<string, Gtk.PageOrientation> = {
14
+ portrait: Gtk.PageOrientation.PORTRAIT,
15
+ landscape: Gtk.PageOrientation.LANDSCAPE,
16
+ 'reverse-portrait': Gtk.PageOrientation.REVERSE_PORTRAIT,
17
+ 'reverse-landscape': Gtk.PageOrientation.REVERSE_LANDSCAPE,
18
+ };
19
+
20
+ /** Story: the page setup dialog with a paper size and an orientation. */
21
+ export class PageSetupUnixDialogStory extends StoryWidget {
22
+ private _button: Gtk.Button | null = null;
23
+
24
+ static {
25
+ GObject.registerClass({ GTypeName: 'AdwStorybookPageSetupUnixDialog' }, PageSetupUnixDialogStory);
26
+ }
27
+
28
+ constructor() {
29
+ super(StoryWidget.fromMeta(PageSetupUnixDialogStory.getMetadata(), 'Default'));
30
+ }
31
+
32
+ static getMetadata(): StoryMeta {
33
+ return { ...pageSetupUnixDialogMeta, component: Gtk.PageSetupUnixDialog.$gtype };
34
+ }
35
+
36
+ initialize(): void {
37
+ this._button = new Gtk.Button({
38
+ label: 'Page Setup…',
39
+ halign: Gtk.Align.CENTER,
40
+ valign: Gtk.Align.CENTER,
41
+ });
42
+ this._button.add_css_class('pill');
43
+ this._button.add_css_class('suggested-action');
44
+ this._button.connect('clicked', () => this._present());
45
+
46
+ this.addContent(this._button);
47
+ }
48
+
49
+ private _present(): void {
50
+ const dialog = Gtk.PageSetupUnixDialog.new('Page Setup', null);
51
+ // A page setup the dialog takes its values from. `set_page_setup` selects the
52
+ // matching row — appending it when no row matches, which is why the margins come
53
+ // from the paper size's own defaults here.
54
+ const setup = new Gtk.PageSetup();
55
+ setup.set_paper_size_and_default_margins(Gtk.PaperSize.new(this.args.paperSize as string));
56
+ setup.set_orientation(ORIENTATIONS[this.args.orientation as string] ?? Gtk.PageOrientation.PORTRAIT);
57
+ dialog.set_page_setup(setup);
58
+ dialog.present();
59
+ }
60
+
61
+ updateArgs(_args: StoryArgs): void {
62
+ // The dialog reads the latest args each time it is presented; nothing to mutate live.
63
+ }
64
+ }
65
+
66
+ // Unix-only widget: GTK's Windows build has no page setup dialog, so the module contributes no story.
67
+ const available = 'PageSetupUnixDialog' in Gtk;
68
+ if (available) GObject.type_ensure(PageSetupUnixDialogStory.$gtype);
69
+
70
+ export const PageSetupUnixDialogStories: StoryModule = { stories: [PageSetupUnixDialogStory].filter(() => available) };
@@ -0,0 +1,30 @@
1
+ // Shared, renderer-agnostic metadata for the Gtk.PrintUnixDialog story.
2
+
3
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
+
5
+ export const printUnixDialogMeta: StoryMeta = {
6
+ title: 'Feedback/Print Dialog',
7
+ description:
8
+ 'Gtk.PrintUnixDialog — the Unix print dialog: seven notebook pages over a printer list, a Range and a Copies group on General, the sheet preview on Page Setup, and the Preview / Cancel / Print action area.',
9
+ controls: [
10
+ {
11
+ name: 'capabilities',
12
+ label: 'Capabilities',
13
+ type: ControlType.TEXT,
14
+ defaultValue: 'copies|collate|reverse|scale|preview|page-set',
15
+ },
16
+ {
17
+ name: 'range',
18
+ label: 'Range',
19
+ type: ControlType.SELECT,
20
+ options: [
21
+ { label: 'All Pages', value: 'all' },
22
+ { label: 'Current Page', value: 'current' },
23
+ { label: 'Selection', value: 'selection' },
24
+ { label: 'Pages', value: 'pages' },
25
+ ],
26
+ defaultValue: 'all',
27
+ },
28
+ { name: 'copies', label: 'Copies', type: ControlType.NUMBER, defaultValue: 2 },
29
+ ],
30
+ };
@@ -0,0 +1,93 @@
1
+ // Gtk.PrintUnixDialog — the Unix print dialog, presented from a button.
2
+ //
3
+ // The story is about the CAPABILITIES: `manual-capabilities` is the half of the mask the
4
+ // APPLICATION can handle, and every control on the General and Page Setup pages is gated on
5
+ // it — copies, collate (which also needs a count above one), reverse, scale, the two-sided
6
+ // sheet picker, and whether Preview appears at all. The printer list is empty here because
7
+ // GTK's comes from a print backend, and a story has none.
8
+
9
+ import Gtk from 'gi://Gtk?version=4.0';
10
+ import GObject from 'gi://GObject?version=2.0';
11
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
12
+ import { printUnixDialogMeta } from './print-unix-dialog.meta.js';
13
+
14
+ /**
15
+ * The nicks of `GtkPrintCapabilities`, in enum order. Read lazily: GTK compiles the Unix print
16
+ * dialog, and with it this enum, out of its Windows build, so the namespace has no
17
+ * `PrintCapabilities` there.
18
+ */
19
+ const capabilities = (): Record<string, Gtk.PrintCapabilities> => ({
20
+ collate: Gtk.PrintCapabilities.COLLATE,
21
+ copies: Gtk.PrintCapabilities.COPIES,
22
+ 'generate-pdf': Gtk.PrintCapabilities.GENERATE_PDF,
23
+ 'generate-ps': Gtk.PrintCapabilities.GENERATE_PS,
24
+ 'number-up': Gtk.PrintCapabilities.NUMBER_UP,
25
+ 'number-up-layout': Gtk.PrintCapabilities.NUMBER_UP_LAYOUT,
26
+ 'page-set': Gtk.PrintCapabilities.PAGE_SET,
27
+ preview: Gtk.PrintCapabilities.PREVIEW,
28
+ reverse: Gtk.PrintCapabilities.REVERSE,
29
+ scale: Gtk.PrintCapabilities.SCALE,
30
+ });
31
+
32
+ /** Story: the print dialog with the capabilities the application declares it can handle. */
33
+ export class PrintUnixDialogStory extends StoryWidget {
34
+ private _button: Gtk.Button | null = null;
35
+
36
+ static {
37
+ GObject.registerClass({ GTypeName: 'AdwStorybookPrintUnixDialog' }, PrintUnixDialogStory);
38
+ }
39
+
40
+ constructor() {
41
+ super(StoryWidget.fromMeta(PrintUnixDialogStory.getMetadata(), 'Default'));
42
+ }
43
+
44
+ static getMetadata(): StoryMeta {
45
+ return { ...printUnixDialogMeta, component: Gtk.PrintUnixDialog.$gtype };
46
+ }
47
+
48
+ initialize(): void {
49
+ this._button = new Gtk.Button({
50
+ label: 'Print…',
51
+ halign: Gtk.Align.CENTER,
52
+ valign: Gtk.Align.CENTER,
53
+ });
54
+ this._button.add_css_class('pill');
55
+ this._button.add_css_class('suggested-action');
56
+ this._button.connect('clicked', () => this._present());
57
+
58
+ this.addContent(this._button);
59
+ }
60
+
61
+ private _present(): void {
62
+ const dialog = Gtk.PrintUnixDialog.new('Print', null);
63
+ const nicks = capabilities();
64
+ const mask = String(this.args.capabilities)
65
+ .split('|')
66
+ .map((nick) => nicks[nick.trim()] ?? 0)
67
+ .reduce((caps, capability) => caps | capability, 0);
68
+ dialog.set_manual_capabilities(mask);
69
+
70
+ // The range group and the copies count, the two controls whose state decides what
71
+ // the dialog itself lets a user do (update_dialog_from_capabilities).
72
+ dialog.set_current_page(2);
73
+ dialog.set_support_selection(true);
74
+ dialog.set_has_selection(true);
75
+ const settings = new Gtk.PrintSettings();
76
+ settings.set_n_copies(Number(this.args.copies));
77
+ settings.set_collate(this.args.range === 'all');
78
+ settings.set_print_pages(this.args.range === 'current' ? Gtk.PrintPages.CURRENT : Gtk.PrintPages.ALL);
79
+ dialog.set_settings(settings);
80
+
81
+ dialog.present();
82
+ }
83
+
84
+ updateArgs(_args: StoryArgs): void {
85
+ // The dialog reads the latest args each time it is presented; nothing to mutate live.
86
+ }
87
+ }
88
+
89
+ // Unix-only widget: on Windows there is nothing to show, so the module contributes no story.
90
+ const available = 'PrintUnixDialog' in Gtk;
91
+ if (available) GObject.type_ensure(PrintUnixDialogStory.$gtype);
92
+
93
+ export const PrintUnixDialogStories: StoryModule = { stories: [PrintUnixDialogStory].filter(() => available) };
@@ -0,0 +1,12 @@
1
+ // Shared, renderer-agnostic metadata for the Shortcuts Dialog story. Imported by
2
+ // both the GTK renderer (shortcuts-dialog.story.ts) and the browser renderer
3
+ // (browser/feedback/shortcuts-dialog.web.ts) so the two expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ export const shortcutsDialogMeta: StoryMeta = {
8
+ title: 'Feedback/Shortcuts Dialog',
9
+ description:
10
+ 'Adw.ShortcutsDialog — the window that lists an application’s keyboard shortcuts, one titled section at a time.',
11
+ controls: [{ name: 'title', label: 'Title', type: ControlType.TEXT, defaultValue: 'Keyboard Shortcuts' }],
12
+ };
@@ -0,0 +1,79 @@
1
+ // Adw.ShortcutsDialog — the window that lists an application's shortcuts.
2
+ // original implementation.
3
+
4
+ import Adw from 'gi://Adw?version=1';
5
+ import Gtk from 'gi://Gtk?version=4.0';
6
+ import GObject from 'gi://GObject?version=2.0';
7
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
8
+ import { shortcutsDialogMeta } from './shortcuts-dialog.meta.js';
9
+
10
+ /** Story: Adw.ShortcutsDialog presented from a button, with two sections of shortcuts. */
11
+ export class ShortcutsDialogStory extends StoryWidget {
12
+ private _button: Gtk.Button | null = null;
13
+
14
+ static {
15
+ GObject.registerClass({ GTypeName: 'AdwStorybookShortcutsDialog' }, ShortcutsDialogStory);
16
+ }
17
+
18
+ constructor() {
19
+ super(StoryWidget.fromMeta(ShortcutsDialogStory.getMetadata(), 'Default'));
20
+ }
21
+
22
+ static getMetadata(): StoryMeta {
23
+ return { ...shortcutsDialogMeta, component: Adw.ShortcutsDialog.$gtype };
24
+ }
25
+
26
+ initialize(): void {
27
+ this._button = new Gtk.Button({
28
+ label: 'Show dialog',
29
+ halign: Gtk.Align.CENTER,
30
+ valign: Gtk.Align.CENTER,
31
+ });
32
+ this._button.add_css_class('pill');
33
+ this._button.add_css_class('suggested-action');
34
+ this._button.connect('clicked', () => this._present());
35
+
36
+ this.addContent(this._button);
37
+ }
38
+
39
+ private _present(): void {
40
+ // SECTIONS ARE GObjects, not widgets: each is added with `add(section)`, and an
41
+ // untitled one is the documented way to subdivide a section into groups.
42
+ const general = new Adw.ShortcutsSection({ title: 'General' });
43
+ general.add(new Adw.ShortcutsItem({ title: 'Open Menu', accelerator: 'F10' }));
44
+ general.add(new Adw.ShortcutsItem({ title: 'Preferences', action_name: 'app.preferences' }));
45
+ general.add(new Adw.ShortcutsItem({ title: 'Quit', accelerator: '<Control>q' }));
46
+
47
+ // No title: the section below is a continuation of the one above, which is what
48
+ // the class documents an untitled section for.
49
+ const navigation = new Adw.ShortcutsSection();
50
+ navigation.add(
51
+ new Adw.ShortcutsItem({
52
+ title: 'Move Tab Left',
53
+ accelerator: '<Shift><Control>Page_Up',
54
+ direction: Gtk.TextDirection.LTR,
55
+ }),
56
+ );
57
+ navigation.add(
58
+ new Adw.ShortcutsItem({
59
+ title: 'Move Tab Left',
60
+ accelerator: '<Shift><Control>Page_Up',
61
+ direction: Gtk.TextDirection.RTL,
62
+ }),
63
+ );
64
+
65
+ const dialog = new Adw.ShortcutsDialog({ title: this.args.title as string });
66
+ dialog.add(general);
67
+ dialog.add(navigation);
68
+
69
+ dialog.present(this);
70
+ }
71
+
72
+ updateArgs(_args: StoryArgs): void {
73
+ // The dialog reads the latest args each time it is presented; nothing to mutate live.
74
+ }
75
+ }
76
+
77
+ GObject.type_ensure(ShortcutsDialogStory.$gtype);
78
+
79
+ export const ShortcutsDialogStories: StoryModule = { stories: [ShortcutsDialogStory] };
@@ -0,0 +1,16 @@
1
+ // Shared, renderer-agnostic metadata for the Application Window story. Imported by
2
+ // both the GTK renderer (application-window.story.ts) and the browser renderer
3
+ // (browser/layout/application-window.web.ts) so the two expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ export const applicationWindowMeta: StoryMeta = {
8
+ title: 'Layout/Application Window',
9
+ description:
10
+ 'Adw.ApplicationWindow — an Adw.Window that belongs to a GtkApplication, plus that application’s menubar.',
11
+ controls: [
12
+ { name: 'title', label: 'Title', type: ControlType.TEXT, defaultValue: 'Text Editor' },
13
+ { name: 'subtitle', label: 'Subtitle', type: ControlType.TEXT, defaultValue: 'notes.md' },
14
+ { name: 'showMenubar', label: 'Show menubar', type: ControlType.BOOLEAN, defaultValue: true },
15
+ ],
16
+ };
@@ -0,0 +1,97 @@
1
+ // Adw.ApplicationWindow — an Adw.Window that belongs to a GtkApplication, and the
2
+ // menubar such an application installs.
3
+ // original implementation.
4
+
5
+ import Adw from 'gi://Adw?version=1';
6
+ import Gtk from 'gi://Gtk?version=4.0';
7
+ import Gio from 'gi://Gio?version=2.0';
8
+ import GObject from 'gi://GObject?version=2.0';
9
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
10
+ import { applicationWindowMeta } from './application-window.meta.js';
11
+
12
+ /** Story: Adw.ApplicationWindow with a menubar, a header bar and a status page. */
13
+ export class ApplicationWindowStory extends StoryWidget {
14
+ private _window: Adw.ApplicationWindow | null = null;
15
+ private _title: Adw.WindowTitle | null = null;
16
+ private _toolbarView: Adw.ToolbarView | null = null;
17
+ private _menubar: Gtk.PopoverMenuBar | null = null;
18
+
19
+ static {
20
+ GObject.registerClass({ GTypeName: 'AdwStorybookApplicationWindow' }, ApplicationWindowStory);
21
+ }
22
+
23
+ constructor() {
24
+ super(StoryWidget.fromMeta(ApplicationWindowStory.getMetadata(), 'Default'));
25
+ }
26
+
27
+ static getMetadata(): StoryMeta {
28
+ return { ...applicationWindowMeta, component: Adw.ApplicationWindow.$gtype };
29
+ }
30
+
31
+ initialize(): void {
32
+ this._title = new Adw.WindowTitle({
33
+ title: this.args.title as string,
34
+ subtitle: this.args.subtitle as string,
35
+ });
36
+
37
+ const headerBar = new Adw.HeaderBar({ titleWidget: this._title, widthRequest: 460 });
38
+
39
+ const backButton = new Gtk.Button({ iconName: 'go-previous-symbolic' });
40
+ backButton.add_css_class('flat');
41
+ headerBar.pack_start(backButton);
42
+
43
+ this._toolbarView = new Adw.ToolbarView();
44
+ this._toolbarView.add_top_bar(headerBar);
45
+ this._toolbarView.content = new Adw.StatusPage({
46
+ title: 'Your Library',
47
+ description: 'Content sits between the toolbars and scrolls independently of them.',
48
+ });
49
+
50
+ // The menubar is a row of LINKS, which is what `Gtk.Application:menubar` is
51
+ // documented to be — two sections, each opening into its own popover.
52
+ const menu = new Gio.Menu();
53
+ const fileSection = new Gio.Menu();
54
+ fileSection.append('New Window', 'app.new-window');
55
+ fileSection.append('Quit', 'app.quit');
56
+ menu.append_section(null, fileSection);
57
+ const helpSection = new Gio.Menu();
58
+ helpSection.append('Keyboard Shortcuts', 'app.shortcuts');
59
+ helpSection.append('About', 'app.about');
60
+ menu.append_section(null, helpSection);
61
+
62
+ // Gtk.MenuBar is gone from GTK 4, so the row is a Gtk.PopoverMenuBar — and it is
63
+ // the WIDGET an application window draws as its menubar. An app never adds it:
64
+ // `Gtk.Application` installs the menu model at construction, and the property
65
+ // this story toggles is what decides whether the window DRAWS it. A story has no
66
+ // GtkApplication to install one, so it adds the same widget by hand, as the
67
+ // toolbar view's second top bar, which is where the application window's own
68
+ // menubar sits.
69
+ this._menubar = new Gtk.PopoverMenuBar({ menu_model: menu });
70
+ if (this.args.showMenubar as boolean) this._toolbarView.add_top_bar(this._menubar);
71
+
72
+ this._window = new Adw.ApplicationWindow({
73
+ content: this._toolbarView,
74
+ show_menubar: this.args.showMenubar as boolean,
75
+ });
76
+ this._window.set_default_size(460, 260);
77
+
78
+ this.addContent(this._window);
79
+ }
80
+
81
+ updateArgs(_args: StoryArgs): void {
82
+ if (!this._title || !this._window || !this._toolbarView || !this._menubar) return;
83
+ this._title.title = this.args.title as string;
84
+ this._title.subtitle = this.args.subtitle as string;
85
+ this._window.show_menubar = this.args.showMenubar as boolean;
86
+
87
+ // The property and the bar are one decision, so the control moves both — which
88
+ // is what the application window does with the menubar its application installed.
89
+ const showing = this.args.showMenubar as boolean;
90
+ if (showing && this._menubar.get_parent() === null) this._toolbarView.add_top_bar(this._menubar);
91
+ if (!showing && this._menubar.get_parent() !== null) this._toolbarView.remove(this._menubar);
92
+ }
93
+ }
94
+
95
+ GObject.type_ensure(ApplicationWindowStory.$gtype);
96
+
97
+ export const ApplicationWindowStories: StoryModule = { stories: [ApplicationWindowStory] };