@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,64 @@
1
+ // Gtk.GridView — the list view's model and factory, reflowed into columns.
2
+ // original implementation.
3
+
4
+ import Gtk from 'gi://Gtk?version=4.0';
5
+ import GObject from 'gi://GObject?version=2.0';
6
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
7
+ import { GRID_VIEW_ITEMS, gridViewMeta } from './grid-view.meta.js';
8
+
9
+ /** Story: a Gtk.GridView over a Gtk.StringList, with both column bounds as args. */
10
+ export class GridViewStory extends StoryWidget {
11
+ private _view: Gtk.GridView | null = null;
12
+ private _model: Gtk.StringList | null = null;
13
+
14
+ static {
15
+ GObject.registerClass({ GTypeName: 'AdwStorybookGridView' }, GridViewStory);
16
+ }
17
+
18
+ constructor() {
19
+ super(StoryWidget.fromMeta(GridViewStory.getMetadata(), 'Default'));
20
+ }
21
+
22
+ static getMetadata(): StoryMeta {
23
+ return { ...gridViewMeta, component: Gtk.GridView.$gtype };
24
+ }
25
+
26
+ initialize(): void {
27
+ this._model = Gtk.StringList.new([...GRID_VIEW_ITEMS]);
28
+
29
+ const factory = new Gtk.SignalListItemFactory();
30
+ factory.connect('setup', (_factory, item: GObject.Object) => {
31
+ (item as Gtk.ListItem).child = new Gtk.Label({ xalign: 0.5 });
32
+ });
33
+ factory.connect('bind', (_factory, item: GObject.Object) => {
34
+ const listItem = item as Gtk.ListItem;
35
+ const label = listItem.child as Gtk.Label;
36
+ label.label = (listItem.item as Gtk.StringObject).string;
37
+ });
38
+
39
+ this._view = new Gtk.GridView({ factory, vexpand: true });
40
+ const scroller = new Gtk.ScrolledWindow({ child: this._view, heightRequest: 200, hexpand: true });
41
+ this._apply();
42
+ this.addContent(scroller);
43
+ }
44
+
45
+ updateArgs(_args: StoryArgs): void {
46
+ this._apply();
47
+ }
48
+
49
+ private _apply(): void {
50
+ if (!this._view || !this._model) return;
51
+ this._view.model =
52
+ (this.args.selectionMode as string) === 'multiple'
53
+ ? Gtk.MultiSelection.new(this._model)
54
+ : (this.args.selectionMode as string) === 'none'
55
+ ? Gtk.NoSelection.new(this._model)
56
+ : Gtk.SingleSelection.new(this._model);
57
+ this._view.minColumns = Math.max(1, this.args.minColumns as number);
58
+ this._view.maxColumns = Math.max(this._view.minColumns, this.args.maxColumns as number);
59
+ }
60
+ }
61
+
62
+ GObject.type_ensure(GridViewStory.$gtype);
63
+
64
+ export const GridViewStories: StoryModule = { stories: [GridViewStory] };
@@ -0,0 +1,55 @@
1
+ // Shared, renderer-agnostic metadata for the List Box story. Imported by the GTK renderer
2
+ // (list-box.story.ts) and the browser renderer (browser/presentation/list-box.web.ts), so
3
+ // both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ /** The rows both renderings build, so a selected position means the same thing everywhere. */
8
+ export const LIST_BOX_ROWS = ['Documents', 'Downloads', 'Music', 'Pictures', 'Videos'] as const;
9
+
10
+ /**
11
+ * All four `Gtk.SelectionMode` values, under the same nicks the attribute and the shared
12
+ * selection module use — `browse` included, which is the mode the model-driven views have no
13
+ * word for because they wrap a selection MODEL and this one does not.
14
+ */
15
+ export const LIST_BOX_SELECTION_MODES = [
16
+ { label: 'Single', value: 'single' },
17
+ { label: 'Multiple', value: 'multiple' },
18
+ { label: 'Browse', value: 'browse' },
19
+ { label: 'None', value: 'none' },
20
+ ];
21
+
22
+ export const listBoxMeta: StoryMeta = {
23
+ title: 'Presentation/List Box',
24
+ description:
25
+ 'Gtk.ListBox — one row per child you append, with GTK’s four selection modes. Ctrl toggles and ' +
26
+ 'Shift extends from the anchor the last Shift-click left behind; activate-on-single-click defaults ' +
27
+ 'to TRUE here, unlike Gtk.ListView’s single-click-activate.',
28
+ controls: [
29
+ {
30
+ name: 'selectionMode',
31
+ label: 'Selection',
32
+ type: ControlType.SELECT,
33
+ options: LIST_BOX_SELECTION_MODES,
34
+ defaultValue: 'single',
35
+ },
36
+ { name: 'showSeparators', label: 'Separators', type: ControlType.BOOLEAN, defaultValue: true },
37
+ {
38
+ name: 'activateOnSingleClick',
39
+ label: 'Activate on single click',
40
+ type: ControlType.BOOLEAN,
41
+ defaultValue: true,
42
+ },
43
+ {
44
+ name: 'tabBehavior',
45
+ label: 'Tab behaviour',
46
+ type: ControlType.SELECT,
47
+ options: [
48
+ { label: 'All', value: 'all' },
49
+ { label: 'Item', value: 'item' },
50
+ { label: 'Cell', value: 'cell' },
51
+ ],
52
+ defaultValue: 'all',
53
+ },
54
+ ],
55
+ };
@@ -0,0 +1,68 @@
1
+ // Gtk.ListBox — one row per child you append, with GTK's four selection modes.
2
+ // original implementation.
3
+
4
+ import Gtk from 'gi://Gtk?version=4.0';
5
+ import GObject from 'gi://GObject?version=2.0';
6
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
7
+ import { LIST_BOX_ROWS, listBoxMeta } from './list-box.meta.js';
8
+
9
+ /** Story: a Gtk.ListBox of GtkListBoxRow children, the selection mode chosen by an arg. */
10
+ export class ListBoxStory extends StoryWidget {
11
+ private _box: Gtk.ListBox | null = null;
12
+
13
+ static {
14
+ GObject.registerClass({ GTypeName: 'AdwStorybookListBox' }, ListBoxStory);
15
+ }
16
+
17
+ constructor() {
18
+ super(StoryWidget.fromMeta(ListBoxStory.getMetadata(), 'Default'));
19
+ }
20
+
21
+ static getMetadata(): StoryMeta {
22
+ return { ...listBoxMeta, component: Gtk.ListBox.$gtype };
23
+ }
24
+
25
+ initialize(): void {
26
+ this._box = new Gtk.ListBox({ hexpand: true });
27
+ // `gtk_list_box_append()` WRAPS whatever it is given in a GtkListBoxRow, so the rows
28
+ // are built here — the one thing the markup form has to spell and this cannot.
29
+ for (const title of LIST_BOX_ROWS) {
30
+ this._box.append(new Gtk.ListBoxRow({ child: new Gtk.Label({ label: title, xalign: 0 }) }));
31
+ }
32
+ this._apply();
33
+ const scroller = new Gtk.ScrolledWindow({ child: this._box, heightRequest: 200 });
34
+ this.addContent(scroller);
35
+ }
36
+
37
+ updateArgs(_args: StoryArgs): void {
38
+ this._apply();
39
+ }
40
+
41
+ private _apply(): void {
42
+ if (!this._box) return;
43
+ this._box.selection_mode = this._selectionMode();
44
+ this._box.show_separators = this.args.showSeparators as boolean;
45
+ // The ParamSpec default is TRUE (gtklistbox.c:543) — the opposite of GtkListView's
46
+ // `single-click-activate` — so a false arg is the only thing that changes it.
47
+ this._box.activate_on_single_click = this.args.activateOnSingleClick as boolean;
48
+ this._box.tab_behavior = this.args.tabBehavior as Gtk.ListTabBehavior;
49
+ }
50
+
51
+ /** The four `Gtk.SelectionMode` values, under the nicks the shared metadata spells. */
52
+ private _selectionMode(): Gtk.SelectionMode {
53
+ switch (this.args.selectionMode as string) {
54
+ case 'multiple':
55
+ return Gtk.SelectionMode.MULTIPLE;
56
+ case 'browse':
57
+ return Gtk.SelectionMode.BROWSE;
58
+ case 'none':
59
+ return Gtk.SelectionMode.NONE;
60
+ default:
61
+ return Gtk.SelectionMode.SINGLE;
62
+ }
63
+ }
64
+ }
65
+
66
+ GObject.type_ensure(ListBoxStory.$gtype);
67
+
68
+ export const ListBoxStories: StoryModule = { stories: [ListBoxStory] };
@@ -0,0 +1,38 @@
1
+ // Shared, renderer-agnostic metadata for the List View story. Imported by the GTK
2
+ // renderer (list-view.story.ts) and the browser renderer
3
+ // (browser/presentation/list-view.web.ts), so both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ /** The one model all renderings drive, so a selected position means the same thing everywhere. */
8
+ export const LIST_VIEW_ITEMS = ['Documents', 'Downloads', 'Music', 'Pictures', 'Videos'] as const;
9
+
10
+ /** The three selection models a view may wrap its model in, under their portable nicks. */
11
+ export const LIST_VIEW_SELECTION_MODES = [
12
+ { label: 'Single', value: 'single' },
13
+ { label: 'Multiple', value: 'multiple' },
14
+ { label: 'None', value: 'none' },
15
+ ];
16
+
17
+ export const listViewMeta: StoryMeta = {
18
+ title: 'Presentation/List View',
19
+ description:
20
+ 'Gtk.ListView — one row per item of a list model, each built by a factory. The model is the ' +
21
+ 'portable list (ADR 0046); which Gtk.SelectionModel would have wrapped it is the selection mode.',
22
+ controls: [
23
+ {
24
+ name: 'selectionMode',
25
+ label: 'Selection',
26
+ type: ControlType.SELECT,
27
+ options: LIST_VIEW_SELECTION_MODES,
28
+ defaultValue: 'single',
29
+ },
30
+ { name: 'showSeparators', label: 'Separators', type: ControlType.BOOLEAN, defaultValue: true },
31
+ {
32
+ name: 'singleClickActivate',
33
+ label: 'Activate on single click',
34
+ type: ControlType.BOOLEAN,
35
+ defaultValue: false,
36
+ },
37
+ ],
38
+ };
@@ -0,0 +1,73 @@
1
+ // Gtk.ListView — one row per model item, each built by a factory.
2
+ // original implementation.
3
+
4
+ import Gtk from 'gi://Gtk?version=4.0';
5
+ import GObject from 'gi://GObject?version=2.0';
6
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
7
+ import { LIST_VIEW_ITEMS, listViewMeta } from './list-view.meta.js';
8
+
9
+ /** Story: a Gtk.ListView over a Gtk.StringList, with the selection model chosen by an arg. */
10
+ export class ListViewStory extends StoryWidget {
11
+ private _view: Gtk.ListView | null = null;
12
+ private _model: Gtk.StringList | null = null;
13
+
14
+ static {
15
+ GObject.registerClass({ GTypeName: 'AdwStorybookListView' }, ListViewStory);
16
+ }
17
+
18
+ constructor() {
19
+ super(StoryWidget.fromMeta(ListViewStory.getMetadata(), 'Default'));
20
+ }
21
+
22
+ static getMetadata(): StoryMeta {
23
+ return { ...listViewMeta, component: Gtk.ListView.$gtype };
24
+ }
25
+
26
+ initialize(): void {
27
+ this._model = Gtk.StringList.new([...LIST_VIEW_ITEMS]);
28
+
29
+ // `setup` builds the row widget and `bind` fills it — the pair GTK keeps apart so
30
+ // it can RECYCLE rows while scrolling.
31
+ const factory = new Gtk.SignalListItemFactory();
32
+ factory.connect('setup', (_factory, item: GObject.Object) => {
33
+ (item as Gtk.ListItem).child = new Gtk.Label({ xalign: 0 });
34
+ });
35
+ factory.connect('bind', (_factory, item: GObject.Object) => {
36
+ const listItem = item as Gtk.ListItem;
37
+ const label = listItem.child as Gtk.Label;
38
+ label.label = (listItem.item as Gtk.StringObject).string;
39
+ });
40
+
41
+ this._view = new Gtk.ListView({ factory, vexpand: true });
42
+ const scroller = new Gtk.ScrolledWindow({ child: this._view, heightRequest: 200, hexpand: true });
43
+ this._apply();
44
+ this.addContent(scroller);
45
+ }
46
+
47
+ updateArgs(_args: StoryArgs): void {
48
+ this._apply();
49
+ }
50
+
51
+ private _apply(): void {
52
+ if (!this._view || !this._model) return;
53
+ this._view.model = this._selectionModel(this._model);
54
+ this._view.showSeparators = this.args.showSeparators as boolean;
55
+ this._view.singleClickActivate = this.args.singleClickActivate as boolean;
56
+ }
57
+
58
+ /** The three models a `GtkListView:model` may be, under the nicks the story shares. */
59
+ private _selectionModel(model: Gtk.StringList): Gtk.SelectionModel {
60
+ switch (this.args.selectionMode as string) {
61
+ case 'multiple':
62
+ return Gtk.MultiSelection.new(model);
63
+ case 'none':
64
+ return Gtk.NoSelection.new(model);
65
+ default:
66
+ return Gtk.SingleSelection.new(model);
67
+ }
68
+ }
69
+ }
70
+
71
+ GObject.type_ensure(ListViewStory.$gtype);
72
+
73
+ export const ListViewStories: StoryModule = { stories: [ListViewStory] };
@@ -0,0 +1,24 @@
1
+ // Shared, renderer-agnostic metadata for the Tree Expander story. Imported by the GTK
2
+ // renderer (tree-expander.story.ts) and the browser renderer
3
+ // (browser/presentation/tree-expander.web.ts), so both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ /** One small tree, as parent labels to their children — enough for two levels of depth. */
8
+ export const TREE_EXPANDER_TREE: Readonly<Record<string, readonly string[]>> = {
9
+ Pictures: ['Holiday', 'Screenshots'],
10
+ Music: ['Albums'],
11
+ Notes: [],
12
+ };
13
+
14
+ export const treeExpanderMeta: StoryMeta = {
15
+ title: 'Presentation/Tree Expander',
16
+ description:
17
+ 'Gtk.TreeExpander — the indent and the disclosure arrow a tree row wears in front of its contents. ' +
18
+ 'A leaf takes one indent in place of the arrow, so its text lines up with its siblings.',
19
+ controls: [
20
+ { name: 'expanded', label: 'Expanded', type: ControlType.BOOLEAN, defaultValue: true },
21
+ { name: 'hideExpander', label: 'Hide the arrow', type: ControlType.BOOLEAN, defaultValue: false },
22
+ { name: 'indentForIcon', label: 'Indent leaves by an arrow', type: ControlType.BOOLEAN, defaultValue: true },
23
+ ],
24
+ };
@@ -0,0 +1,105 @@
1
+ // Gtk.TreeExpander — the indent and the arrow in front of a tree row's contents.
2
+ // original implementation.
3
+
4
+ import Gtk from 'gi://Gtk?version=4.0';
5
+ import type Gio from 'gi://Gio?version=2.0';
6
+ import GObject from 'gi://GObject?version=2.0';
7
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
8
+ import { TREE_EXPANDER_TREE, treeExpanderMeta } from './tree-expander.meta.js';
9
+
10
+ /**
11
+ * Story: a Gtk.ListView over a Gtk.TreeListModel, each row a Gtk.TreeExpander.
12
+ *
13
+ * The expander is only ever reachable this way — it watches a `GtkTreeListRow`, which
14
+ * only a `GtkTreeListModel` produces — so the story builds the model the widget needs
15
+ * rather than a standalone expander that would have nothing to expand.
16
+ */
17
+ export class TreeExpanderStory extends StoryWidget {
18
+ private _view: Gtk.ListView | null = null;
19
+ private _tree: Gtk.TreeListModel | null = null;
20
+ /** The expanders the factory has built, so an arg change reaches the live ones. */
21
+ private readonly _expanders = new Set<Gtk.TreeExpander>();
22
+
23
+ static {
24
+ GObject.registerClass({ GTypeName: 'AdwStorybookTreeExpander' }, TreeExpanderStory);
25
+ }
26
+
27
+ constructor() {
28
+ super(StoryWidget.fromMeta(TreeExpanderStory.getMetadata(), 'Default'));
29
+ }
30
+
31
+ static getMetadata(): StoryMeta {
32
+ return { ...treeExpanderMeta, component: Gtk.TreeExpander.$gtype };
33
+ }
34
+
35
+ initialize(): void {
36
+ const roots = Gtk.StringList.new(Object.keys(TREE_EXPANDER_TREE));
37
+ // `passthrough: false` is what makes the model hand out `GtkTreeListRow`s, which
38
+ // is what the expander watches; the C says so in the widget's own documentation.
39
+ this._tree = Gtk.TreeListModel.new(roots, false, false, (item: GObject.Object) => {
40
+ const children = TREE_EXPANDER_TREE[(item as Gtk.StringObject).string] ?? [];
41
+ return children.length === 0 ? null : (Gtk.StringList.new([...children]) as Gio.ListModel);
42
+ });
43
+
44
+ const factory = new Gtk.SignalListItemFactory();
45
+ factory.connect('setup', (_factory, item: GObject.Object) => {
46
+ const listItem = item as Gtk.ListItem;
47
+ // The expander owns the keyboard shortcuts, so focus belongs to it and not to
48
+ // the list item around it (gtktreeexpander.c, "Shortcuts and Gestures").
49
+ listItem.focusable = false;
50
+ const expander = new Gtk.TreeExpander();
51
+ expander.child = new Gtk.Label({ xalign: 0 });
52
+ listItem.child = expander;
53
+ this._expanders.add(expander);
54
+ });
55
+ factory.connect('teardown', (_factory, item: GObject.Object) => {
56
+ // Cleanup beside creation: a recycled row's expander is unparented here, and a
57
+ // set that kept it would hand a destroyed widget to the next arg change.
58
+ const child = (item as Gtk.ListItem).child;
59
+ if (child !== null) this._expanders.delete(child as Gtk.TreeExpander);
60
+ });
61
+ factory.connect('bind', (_factory, item: GObject.Object) => {
62
+ const listItem = item as Gtk.ListItem;
63
+ const expander = listItem.child as Gtk.TreeExpander;
64
+ const row = listItem.item as Gtk.TreeListRow;
65
+ expander.listRow = row;
66
+ (expander.child as Gtk.Label).label = (row.item as Gtk.StringObject).string;
67
+ this._applyTo(expander);
68
+ });
69
+
70
+ this._view = new Gtk.ListView({ model: Gtk.SingleSelection.new(this._tree), factory, vexpand: true });
71
+ const scroller = new Gtk.ScrolledWindow({ child: this._view, heightRequest: 200, hexpand: true });
72
+ this.addContent(scroller);
73
+ this._apply();
74
+ }
75
+
76
+ updateArgs(_args: StoryArgs): void {
77
+ this._apply();
78
+ }
79
+
80
+ /**
81
+ * Apply the args to the ROOT rows and to every expander currently bound.
82
+ *
83
+ * Two halves because the two properties live in two places: `expanded` is the tree
84
+ * row's and survives a row widget being recycled, while `hide-expander` and
85
+ * `indent-for-icon` are the WIDGET's and therefore have to be re-applied to each one
86
+ * the factory has built — which `bind` does for a row that arrives later.
87
+ */
88
+ private _apply(): void {
89
+ if (this._tree === null) return;
90
+ for (let position = 0; position < this._tree.get_n_items(); position++) {
91
+ const row = this._tree.get_row(position);
92
+ if (row !== null && row.depth === 0) row.expanded = this.args.expanded as boolean;
93
+ }
94
+ for (const expander of this._expanders) this._applyTo(expander);
95
+ }
96
+
97
+ private _applyTo(expander: Gtk.TreeExpander): void {
98
+ expander.hideExpander = this.args.hideExpander as boolean;
99
+ expander.indentForIcon = this.args.indentForIcon as boolean;
100
+ }
101
+ }
102
+
103
+ GObject.type_ensure(TreeExpanderStory.$gtype);
104
+
105
+ export const TreeExpanderStories: StoryModule = { stories: [TreeExpanderStory] };
@@ -0,0 +1,27 @@
1
+ // Shared, renderer-agnostic metadata for the Window Handle story. Imported by the GTK
2
+ // renderer (presentation/window-handle.story.ts) and the browser renderer
3
+ // (browser/presentation/window-handle.web.ts), so both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ export const windowHandleMeta: StoryMeta = {
8
+ title: 'Presentation/WindowHandle',
9
+ description:
10
+ 'Gtk.WindowHandle — the titlebar strip. Dragging it moves the window; a double click, ' +
11
+ 'a middle click and a right click raise the window actions the compositor (or, here, the ' +
12
+ 'titlebar settings) names.',
13
+ controls: [
14
+ {
15
+ name: 'action',
16
+ label: 'Double-click action',
17
+ type: ControlType.SELECT,
18
+ options: [
19
+ { label: 'Toggle maximize', value: 'toggle-maximize' },
20
+ { label: 'Minimize', value: 'minimize' },
21
+ { label: 'Menu', value: 'menu' },
22
+ { label: 'None', value: 'none' },
23
+ ],
24
+ defaultValue: 'toggle-maximize',
25
+ },
26
+ ],
27
+ };
@@ -0,0 +1,53 @@
1
+ // Gtk.WindowHandle — a header bar that can be dragged, and the three titlebar clicks.
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 { windowHandleMeta } from './window-handle.meta.js';
9
+
10
+ /**
11
+ * Story: a Gtk.WindowHandle around a header bar — the shape a window's titlebar takes.
12
+ */
13
+ export class WindowHandleStory extends StoryWidget {
14
+ private _handle: Gtk.WindowHandle | null = null;
15
+
16
+ static {
17
+ GObject.registerClass({ GTypeName: 'AdwStorybookWindowHandle' }, WindowHandleStory);
18
+ }
19
+
20
+ constructor() {
21
+ super(StoryWidget.fromMeta(WindowHandleStory.getMetadata(), 'Default'));
22
+ }
23
+
24
+ static getMetadata(): StoryMeta {
25
+ return { ...windowHandleMeta, component: Gtk.WindowHandle.$gtype };
26
+ }
27
+
28
+ initialize(): void {
29
+ const bar = new Adw.HeaderBar();
30
+ bar.set_title_widget(new Adw.WindowTitle({ title: 'Notes' }));
31
+ this._handle = new Gtk.WindowHandle({ child: bar, halign: Gtk.Align.CENTER });
32
+ this._apply();
33
+ this.addContent(this._handle);
34
+ }
35
+
36
+ updateArgs(_args: StoryArgs): void {
37
+ this._apply();
38
+ }
39
+
40
+ private _apply(): void {
41
+ // READ, and cannot be honoured: the action a double click performs is the
42
+ // `gtk-titlebar-double-click` SETTING, resolved by the compositor first
43
+ // (`gdk_toplevel_titlebar_gesture`) and by `Gtk.Settings` where there is no answer
44
+ // (gtkwindowhandle.c:282-333). A widget has no handle on either, so this story cannot
45
+ // set it per instance; the web renderer takes the same value as an attribute, which is
46
+ // the only door a document has.
47
+ void this.args.action;
48
+ }
49
+ }
50
+
51
+ GObject.type_ensure(WindowHandleStory.$gtype);
52
+
53
+ export const WindowHandleStories: StoryModule = { stories: [WindowHandleStory] };
@@ -0,0 +1,15 @@
1
+ // Shared, renderer-agnostic metadata for the Preferences Row story.
2
+
3
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
+
5
+ export const preferencesRowMeta: StoryMeta = {
6
+ title: 'Boxed Lists/Preferences Row',
7
+ description:
8
+ 'Adw.PreferencesRow — the base of every boxed-list row: a list row with a title that the preferences ' +
9
+ 'dialog searches. The title can carry Pango markup and be made selectable.',
10
+ controls: [
11
+ { name: 'title', label: 'Title', type: ControlType.TEXT, defaultValue: 'A <b>plain</b> preferences row' },
12
+ { name: 'useMarkup', label: 'Use markup', type: ControlType.BOOLEAN, defaultValue: true },
13
+ { name: 'titleSelectable', label: 'Title selectable', type: ControlType.BOOLEAN, defaultValue: false },
14
+ ],
15
+ };
@@ -0,0 +1,50 @@
1
+ // Adw.PreferencesRow — the base row, shown inside a boxed list.
2
+ // original implementation.
3
+
4
+ import Adw from 'gi://Adw?version=1';
5
+ import GObject from 'gi://GObject?version=2.0';
6
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
7
+ import { preferencesRowMeta } from './preferences-row.meta.js';
8
+
9
+ /** Story: a bare Adw.PreferencesRow inside an Adw.PreferencesGroup. */
10
+ export class PreferencesRowStory extends StoryWidget {
11
+ private _row: Adw.PreferencesRow | null = null;
12
+
13
+ static {
14
+ GObject.registerClass({ GTypeName: 'AdwStorybookPreferencesRow' }, PreferencesRowStory);
15
+ }
16
+
17
+ constructor() {
18
+ super(StoryWidget.fromMeta(PreferencesRowStory.getMetadata(), 'Default'));
19
+ }
20
+
21
+ static getMetadata(): StoryMeta {
22
+ return { ...preferencesRowMeta, component: Adw.PreferencesRow.$gtype };
23
+ }
24
+
25
+ initialize(): void {
26
+ this._row = new Adw.PreferencesRow();
27
+ this._apply();
28
+
29
+ const group = new Adw.PreferencesGroup();
30
+ group.add(this._row);
31
+
32
+ const clamp = new Adw.Clamp({ maximumSize: 400, child: group });
33
+ this.addContent(clamp);
34
+ }
35
+
36
+ updateArgs(_args: StoryArgs): void {
37
+ this._apply();
38
+ }
39
+
40
+ private _apply(): void {
41
+ if (!this._row) return;
42
+ this._row.title = this.args.title as string;
43
+ this._row.useMarkup = this.args.useMarkup as boolean;
44
+ this._row.titleSelectable = this.args.titleSelectable as boolean;
45
+ }
46
+ }
47
+
48
+ GObject.type_ensure(PreferencesRowStory.$gtype);
49
+
50
+ export const PreferencesRowStories: StoryModule = { stories: [PreferencesRowStory] };
@@ -0,0 +1,17 @@
1
+ // Shared, renderer-agnostic metadata for the Editable Label story. Imported by the GTK
2
+ // renderer (editable-label.story.ts) and the browser renderer
3
+ // (browser/text/editable-label.web.ts), so both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ export const editableLabelMeta: StoryMeta = {
8
+ title: 'Text/Editable Label',
9
+ description:
10
+ 'Gtk.EditableLabel — a label you click and edit in place. Enter starts editing, Enter commits, ' +
11
+ 'Escape discards, and editable=false leaves it a label; the draft lives in the entry, not in the label.',
12
+ controls: [
13
+ { name: 'text', label: 'Text', type: ControlType.TEXT, defaultValue: 'Ada Lovelace' },
14
+ { name: 'editable', label: 'Editable', type: ControlType.BOOLEAN, defaultValue: true },
15
+ { name: 'editing', label: 'Editing', type: ControlType.BOOLEAN, defaultValue: false },
16
+ ],
17
+ };
@@ -0,0 +1,47 @@
1
+ // Gtk.EditableLabel — a label you click and edit in place.
2
+ // original implementation.
3
+
4
+ import Gtk from 'gi://Gtk?version=4.0';
5
+ import GObject from 'gi://GObject?version=2.0';
6
+ import { type StoryArgs, type StoryMeta, type StoryModule, StoryWidget } from '@gjsify/storybook';
7
+ import { editableLabelMeta } from './editable-label.meta.js';
8
+
9
+ /** Story: a Gtk.EditableLabel with its text and both of its booleans bound to args. */
10
+ export class EditableLabelStory extends StoryWidget {
11
+ private _label: Gtk.EditableLabel | null = null;
12
+
13
+ static {
14
+ GObject.registerClass({ GTypeName: 'AdwStorybookEditableLabel' }, EditableLabelStory);
15
+ }
16
+
17
+ constructor() {
18
+ super(StoryWidget.fromMeta(EditableLabelStory.getMetadata(), 'Default'));
19
+ }
20
+
21
+ static getMetadata(): StoryMeta {
22
+ return { ...editableLabelMeta, component: Gtk.EditableLabel.$gtype };
23
+ }
24
+
25
+ initialize(): void {
26
+ this._label = new Gtk.EditableLabel({ halign: Gtk.Align.CENTER });
27
+ this._apply();
28
+ this.addContent(this._label);
29
+ }
30
+
31
+ updateArgs(_args: StoryArgs): void {
32
+ this._apply();
33
+ }
34
+
35
+ private _apply(): void {
36
+ if (!this._label) return;
37
+ // The draft lives in the entry, so the property is written only while nothing is being
38
+ // edited — which is the order the C keeps them in (gtkeditablelabel.c:237-248).
39
+ if (!this._label.editing) this._label.text = this.args.text as string;
40
+ this._label.editable = this.args.editable as boolean;
41
+ this._label.editing = this.args.editing as boolean;
42
+ }
43
+ }
44
+
45
+ GObject.type_ensure(EditableLabelStory.$gtype);
46
+
47
+ export const EditableLabelStories: StoryModule = { stories: [EditableLabelStory] };
@@ -0,0 +1,17 @@
1
+ // Shared, renderer-agnostic metadata for the Search Bar story. Imported by the GTK
2
+ // renderer (search-bar.story.ts) and the browser renderer (browser/text/search-bar.web.ts),
3
+ // so both expose identical controls.
4
+
5
+ import { ControlType, type StoryMeta } from '@gjsify/stories';
6
+
7
+ export const searchBarMeta: StoryMeta = {
8
+ title: 'Text/Search Bar',
9
+ description:
10
+ 'Gtk.SearchBar — the strip that reveals a search entry when search starts. The property IS the ' +
11
+ "revealer's reveal-child, so one boolean decides both whether the strip is shown and whether " +
12
+ 'the search is on; hiding it clears the entry.',
13
+ controls: [
14
+ { name: 'searchModeEnabled', label: 'Search mode', type: ControlType.BOOLEAN, defaultValue: false },
15
+ { name: 'showCloseButton', label: 'Close button', type: ControlType.BOOLEAN, defaultValue: true },
16
+ ],
17
+ };