@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,72 @@
1
+ // Browser port of the Stack story. Shares metadata with stack.story.ts.
2
+
3
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
4
+ // TYPE-ONLY: the pages are declared in markup and driven through attributes, so nothing
5
+ // here needs the element's own API surface — and a hand-written structural type would be
6
+ // a second copy of it that nothing keeps in step. The import erases.
7
+ import type { Gtk } from '@gjsify/adwaita-web';
8
+ import { STACK_PAGES, stackMeta } from '../../view-switching/stack.meta.js';
9
+
10
+ export class StackWebStory extends StoryElement {
11
+ private _stack: Gtk.Stack | null = null;
12
+
13
+ constructor() {
14
+ super(StackWebStory.getMetadata(), 'Default');
15
+ }
16
+
17
+ static getMetadata(): StoryMeta {
18
+ return stackMeta;
19
+ }
20
+
21
+ initialize(): void {
22
+ const stack = document.createElement('gtk-stack') as Gtk.Stack;
23
+ stack.style.flex = '1';
24
+
25
+ // A GtkStackPage is a GObject, not a widget: its properties are ATTRIBUTES on the
26
+ // page element, which is the mapping `<gtk-stack>`'s header records.
27
+ for (const page of STACK_PAGES) {
28
+ const child = document.createElement('div');
29
+ child.setAttribute('name', page.name);
30
+ child.setAttribute('title', page.title);
31
+ child.setAttribute('use-underline', '');
32
+ if (page.attn) child.setAttribute('needs-attention', '');
33
+ child.style.cssText =
34
+ 'display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;';
35
+ const heading = document.createElement('div');
36
+ heading.setAttribute('data-gtk-stack-story', 'heading');
37
+ heading.textContent = page.title;
38
+ const body = document.createElement('div');
39
+ body.setAttribute('data-gtk-stack-story', 'body');
40
+ body.textContent = page.body;
41
+ child.append(heading, body);
42
+ stack.appendChild(child);
43
+ }
44
+
45
+ const root = document.createElement('div');
46
+ root.style.cssText = 'display:flex;flex-direction:column;gap:12px;width:480px;height:320px;';
47
+ root.appendChild(stack);
48
+ this.addContent(root);
49
+
50
+ this._stack = stack;
51
+ this._apply();
52
+ }
53
+
54
+ updateArgs(_args: StoryArgs): void {
55
+ this._apply();
56
+ }
57
+
58
+ private _apply(): void {
59
+ if (!this._stack) return;
60
+ // The ORDER is the element's own: `transition-type` first, because a new type is
61
+ // what a page change resolves a two-way nick against (gtkstack.c:1546-1561).
62
+ this._stack.setAttribute('transition-type', this.args.transitionType as string);
63
+ this._stack.setAttribute('transition-duration', String(this.args.transitionDuration as number));
64
+ this._stack.toggleAttribute('interpolate-size', this.args.interpolateSize as boolean);
65
+ // `hhomogeneous` / `vhomogeneous` default TRUE (gtkstack.c:981-995), so the false
66
+ // case has to be spelled: an absent attribute already reads as true.
67
+ this._stack.setAttribute('hhomogeneous', (this.args.hhomogeneous as boolean) ? '' : 'false');
68
+ this._stack.setAttribute('vhomogeneous', (this.args.vhomogeneous as boolean) ? '' : 'false');
69
+ }
70
+ }
71
+
72
+ export const StackWebStories: WebStoryModule = { stories: [StackWebStory] };
@@ -0,0 +1,105 @@
1
+ // Browser port of the Tab Bar story — an <adw-tab-bar> bound by id to an
2
+ // <adw-tab-view>, with a slotted action widget on each side and the bar's five properties
3
+ // on the same controls. Shares its metadata with tab-bar.story.ts.
4
+
5
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
6
+ import type { Adw } from '@gjsify/adwaita-web';
7
+ import { tabBarMeta } from '../../view-switching/tab-bar.meta.js';
8
+
9
+ const TABS: ReadonlyArray<{ title: string; body: string }> = [
10
+ { title: 'Overview', body: 'A summary of everything at a glance.' },
11
+ { title: 'Details', body: 'The specifics, broken down line by line.' },
12
+ { title: 'History', body: 'A log of every change made so far.' },
13
+ ];
14
+
15
+ export class TabBarWebStory extends StoryElement {
16
+ private _bar: Adw.TabBar | null = null;
17
+ private _view: Adw.TabView | null = null;
18
+ private _startAction: HTMLButtonElement | null = null;
19
+ private _endAction: HTMLButtonElement | null = null;
20
+
21
+ constructor() {
22
+ super(TabBarWebStory.getMetadata(), 'Default');
23
+ }
24
+
25
+ static getMetadata(): StoryMeta {
26
+ return tabBarMeta;
27
+ }
28
+
29
+ initialize(): void {
30
+ const view = document.createElement('adw-tab-view') as Adw.TabView;
31
+ view.style.flex = '1';
32
+ for (const tab of TABS) {
33
+ const page = document.createElement('adw-tab-page');
34
+ page.setAttribute('title', tab.title);
35
+ page.appendChild(this._buildPageBody(tab.title, tab.body));
36
+ view.appendChild(page);
37
+ }
38
+ this._view = view;
39
+
40
+ const bar = document.createElement('adw-tab-bar') as Adw.TabBar;
41
+ // `view` is a widget REFERENCE upstream, and an id reference here — the same
42
+ // divergence `<adw-tab-button>` and `<adw-view-switcher-bar>` make. The setter
43
+ // takes the element directly, which is what `_apply` below uses for the rebinds.
44
+ bar.setAttribute('view', 'tab-bar-story-view');
45
+ view.id = 'tab-bar-story-view';
46
+ this._bar = bar;
47
+
48
+ // The two action widgets are widget-typed PROPERTIES, so a document spells them as
49
+ // `slot=` children rather than as children of their own.
50
+ this._startAction = this._actionButton('list-add-symbolic', 'New page');
51
+ this._startAction.slot = 'start-action-widget';
52
+ bar.appendChild(this._startAction);
53
+
54
+ this._endAction = this._actionButton('view-more-symbolic', 'Menu');
55
+ this._endAction.slot = 'end-action-widget';
56
+ bar.appendChild(this._endAction);
57
+
58
+ const root = document.createElement('div');
59
+ root.style.display = 'flex';
60
+ root.style.flexDirection = 'column';
61
+ root.style.width = '480px';
62
+ root.style.height = '320px';
63
+ root.append(bar, view);
64
+ this.addContent(root);
65
+ this._apply();
66
+ }
67
+
68
+ updateArgs(_args: StoryArgs): void {
69
+ this._apply();
70
+ }
71
+
72
+ private _actionButton(icon: string, tooltip: string): HTMLButtonElement {
73
+ const button = document.createElement('button') as HTMLButtonElement;
74
+ button.type = 'button';
75
+ button.className = 'adw-button flat image-button';
76
+ button.title = tooltip;
77
+ const image = document.createElement('gtk-image');
78
+ image.setAttribute('icon', icon);
79
+ button.appendChild(image);
80
+ return button;
81
+ }
82
+
83
+ private _buildPageBody(title: string, body: string): HTMLElement {
84
+ const status = document.createElement('adw-status-page');
85
+ status.setAttribute('icon', 'view-paged');
86
+ status.setAttribute('title', title);
87
+ status.setAttribute('description', body);
88
+ return status;
89
+ }
90
+
91
+ private _apply(): void {
92
+ const bar = this._bar;
93
+ const view = this._view;
94
+ if (bar === null || view === null) return;
95
+ bar.autohide = this.args.autohide as boolean;
96
+ bar.expandTabs = this.args.expandTabs as boolean;
97
+ bar.inverted = this.args.inverted as boolean;
98
+ // `view` through the PROPERTY, so the rebind does not depend on the id staying put.
99
+ if (bar.view !== view) bar.view = view;
100
+ bar.startActionWidget = (this.args.startAction as boolean) ? this._startAction : null;
101
+ bar.endActionWidget = (this.args.endAction as boolean) ? this._endAction : null;
102
+ }
103
+ }
104
+
105
+ export const TabBarWebStories: WebStoryModule = { stories: [TabBarWebStory] };
@@ -0,0 +1,52 @@
1
+ // Browser port of the Tab Button story. Shares metadata with tab-button.story.ts.
2
+
3
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
4
+ import type { Adw } from '@gjsify/adwaita-web';
5
+ import { tabButtonMeta } from '../../view-switching/tab-button.meta.js';
6
+
7
+ export class TabButtonWebStory extends StoryElement {
8
+ private _view: Adw.TabView | null = null;
9
+ private _serial = 0;
10
+
11
+ constructor() {
12
+ super(TabButtonWebStory.getMetadata(), 'Default');
13
+ }
14
+
15
+ static getMetadata(): StoryMeta {
16
+ return tabButtonMeta;
17
+ }
18
+
19
+ initialize(): void {
20
+ // The view is the counter's data source and is never shown.
21
+ this._view = document.createElement('adw-tab-view') as Adw.TabView;
22
+ this._view.hidden = true;
23
+ const button = document.createElement('adw-tab-button') as Adw.TabButton;
24
+ const stage = document.createElement('div');
25
+ stage.append(this._view, button);
26
+ this.addContent(stage);
27
+ button.view = this._view;
28
+ this._apply();
29
+ }
30
+
31
+ updateArgs(_args: StoryArgs): void {
32
+ this._apply();
33
+ }
34
+
35
+ private _apply(): void {
36
+ const view = this._view;
37
+ if (!view) return;
38
+ const wanted = this.args.pages as number;
39
+ // Pages added after the view connected go through its API.
40
+ while (view.nPages < wanted) {
41
+ this._serial += 1;
42
+ view.appendPage({ id: `page-${this._serial}`, title: `Page ${view.nPages}` });
43
+ }
44
+ while (view.nPages > wanted) view.closePage(view.pages[view.nPages - 1].id);
45
+ const last = view.nPages - 1;
46
+ view.pages.forEach((page, i) => {
47
+ view.setPageNeedsAttention(page.id, (this.args.needsAttention as boolean) && i === last);
48
+ });
49
+ }
50
+ }
51
+
52
+ export const TabButtonWebStories: WebStoryModule = { stories: [TabButtonWebStory] };
@@ -0,0 +1,87 @@
1
+ // Browser port of the Tab Overview story — an <adw-tab-overview> over an
2
+ // <adw-tab-view> with three pages, one of them pinned, plus the open / search /
3
+ // new-tab / inverted controls. Shares its metadata with tab-overview.story.ts.
4
+
5
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
6
+ import type { Adw } from '@gjsify/adwaita-web';
7
+ import { tabOverviewMeta } from '../../view-switching/tab-overview.meta.js';
8
+
9
+ const TABS: ReadonlyArray<{ title: string; body: string }> = [
10
+ { title: 'Overview', body: 'A summary of everything at a glance.' },
11
+ { title: 'Details', body: 'The specifics, broken down line by line.' },
12
+ { title: 'History', body: 'A log of every change made so far.' },
13
+ ];
14
+
15
+ export class TabOverviewWebStory extends StoryElement {
16
+ private _overview: Adw.TabOverview | null = null;
17
+ private _view: Adw.TabView | null = null;
18
+
19
+ constructor() {
20
+ super(TabOverviewWebStory.getMetadata(), 'Default');
21
+ }
22
+
23
+ static getMetadata(): StoryMeta {
24
+ return tabOverviewMeta;
25
+ }
26
+
27
+ initialize(): void {
28
+ const view = document.createElement('adw-tab-view') as Adw.TabView;
29
+ view.style.width = '480px';
30
+ view.style.height = '340px';
31
+
32
+ for (const [index, tab] of TABS.entries()) {
33
+ const page = document.createElement('adw-tab-page');
34
+ page.setAttribute('title', tab.title);
35
+ if (index === 0) page.setAttribute('pinned', '');
36
+ page.appendChild(this._buildPageBody(tab.title, tab.body));
37
+ view.appendChild(page);
38
+ }
39
+ this._view = view;
40
+
41
+ const overview = document.createElement('adw-tab-overview') as Adw.TabOverview;
42
+ overview.style.width = '480px';
43
+ overview.style.height = '340px';
44
+ overview.appendChild(view);
45
+
46
+ // `create-tab`'s handler returns the page; in the DOM that is `detail.page`.
47
+ overview.addEventListener('create-tab', (event) => {
48
+ // A declared `<adw-tab-page>` is adopted on connect only, so the new page
49
+ // goes in through the view's API — the rule the tab-button story follows.
50
+ // `appendPage` returns the POSITION, so the page itself is read back off the
51
+ // view: `create-tab`'s handler must hand over the page, not a number.
52
+ const position = view.appendPage({
53
+ id: `new-${view.nPages}`,
54
+ title: 'New Page',
55
+ content: this._buildPageBody('New Page', 'Just created.'),
56
+ });
57
+ (event as CustomEvent).detail.page = view.pages[position];
58
+ });
59
+
60
+ this._overview = overview;
61
+ this.addContent(overview);
62
+ this._apply();
63
+ }
64
+
65
+ updateArgs(_args: StoryArgs): void {
66
+ this._apply();
67
+ }
68
+
69
+ private _buildPageBody(title: string, body: string): HTMLElement {
70
+ const status = document.createElement('adw-status-page');
71
+ status.setAttribute('icon', 'view-paged');
72
+ status.setAttribute('title', title);
73
+ if (body !== '') status.setAttribute('description', body);
74
+ return status;
75
+ }
76
+
77
+ private _apply(): void {
78
+ const overview = this._overview;
79
+ if (overview === null) return;
80
+ overview.enableSearch = this.args.enableSearch as boolean;
81
+ overview.enableNewTab = this.args.enableNewTab as boolean;
82
+ overview.inverted = this.args.inverted as boolean;
83
+ overview.setOpen(this.args.open as boolean);
84
+ }
85
+ }
86
+
87
+ export const TabOverviewWebStories: WebStoryModule = { stories: [TabOverviewWebStory] };
@@ -0,0 +1,77 @@
1
+ // Browser port of the View Switcher Sidebar story — an <adw-view-switcher-sidebar> beside
2
+ // the <adw-view-stack> it drives, with the same sections, badge and unread dot as the GTK
3
+ // twin. Shares its metadata with view-switcher-sidebar.story.ts.
4
+
5
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
6
+ import type { Adw } from '@gjsify/adwaita-web';
7
+ import {
8
+ VIEW_SWITCHER_SIDEBAR_PAGES,
9
+ viewSwitcherSidebarMeta,
10
+ } from '../../view-switching/view-switcher-sidebar.meta.js';
11
+
12
+ export class ViewSwitcherSidebarWebStory extends StoryElement {
13
+ private _switcher: Adw.ViewSwitcherSidebar | null = null;
14
+
15
+ constructor() {
16
+ super(ViewSwitcherSidebarWebStory.getMetadata(), 'Default');
17
+ }
18
+
19
+ static getMetadata(): StoryMeta {
20
+ return viewSwitcherSidebarMeta;
21
+ }
22
+
23
+ initialize(): void {
24
+ const stack = document.createElement('adw-view-stack') as Adw.ViewStack;
25
+ stack.style.flex = '1';
26
+
27
+ for (const spec of VIEW_SWITCHER_SIDEBAR_PAGES) {
28
+ const page = document.createElement('adw-view-stack-page');
29
+ page.setAttribute('name', spec.name);
30
+ page.setAttribute('title', spec.title);
31
+ page.setAttribute('icon-name', spec.icon);
32
+ if (spec.sectionTitle) {
33
+ // The section opens ON this page, and the heading is its own.
34
+ page.setAttribute('starts-section', '');
35
+ page.setAttribute('section-title', spec.sectionTitle);
36
+ }
37
+ if (spec.badgeNumber) page.setAttribute('badge-number', String(spec.badgeNumber));
38
+ if (spec.needsAttention) page.setAttribute('needs-attention', '');
39
+ page.appendChild(this._buildContent(spec.icon, spec.title));
40
+ stack.appendChild(page);
41
+ }
42
+
43
+ const switcher = document.createElement('adw-view-switcher-sidebar') as Adw.ViewSwitcherSidebar;
44
+ switcher.style.width = '200px';
45
+ // The stack is the sibling declared right after the switcher, which is the
46
+ // nearest one the element can find when the attribute names no id.
47
+ this._switcher = switcher;
48
+
49
+ const stage = document.createElement('div');
50
+ stage.style.display = 'flex';
51
+ stage.style.flexDirection = 'row';
52
+ stage.style.width = '480px';
53
+ stage.style.height = '340px';
54
+ stage.append(switcher, stack);
55
+ this.addContent(stage);
56
+ this._apply();
57
+ }
58
+
59
+ updateArgs(_args: StoryArgs): void {
60
+ this._apply();
61
+ }
62
+
63
+ private _buildContent(icon: string, title: string): HTMLElement {
64
+ const status = document.createElement('adw-status-page');
65
+ status.setAttribute('icon', icon.replace(/-symbolic$/, ''));
66
+ status.setAttribute('title', title);
67
+ return status;
68
+ }
69
+
70
+ private _apply(): void {
71
+ const switcher = this._switcher;
72
+ if (switcher === null) return;
73
+ switcher.mode = (this.args.mode as boolean) ? 'page' : 'sidebar';
74
+ }
75
+ }
76
+
77
+ export const ViewSwitcherSidebarWebStories: WebStoryModule = { stories: [ViewSwitcherSidebarWebStory] };
@@ -0,0 +1,66 @@
1
+ // Browser port of the Action Bar story. Shares metadata with action-bar.story.ts.
2
+
3
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
4
+ import { actionBarMeta } from '../../windows/action-bar.meta.js';
5
+
6
+ export class ActionBarWebStory extends StoryElement {
7
+ private _bar: HTMLElement | null = null;
8
+
9
+ constructor() {
10
+ super(ActionBarWebStory.getMetadata(), 'Default');
11
+ }
12
+
13
+ static getMetadata(): StoryMeta {
14
+ return actionBarMeta;
15
+ }
16
+
17
+ initialize(): void {
18
+ this._bar = document.createElement('gtk-action-bar');
19
+ // The same three children in the same order as the GTK story — `pack_end` PREPENDS,
20
+ // so the button added LAST sits nearest the edge (gtkactionbar.c:262-277).
21
+ for (const [slot, icon] of [
22
+ ['end', 'document-save-symbolic'],
23
+ ['end', 'document-open-symbolic'],
24
+ ['start', 'document-print-symbolic'],
25
+ ] as const) {
26
+ const button = document.createElement('gtk-button');
27
+ button.setAttribute('slot', slot);
28
+ button.setAttribute('icon-name', icon);
29
+ button.setAttribute('flat', '');
30
+ this._bar.appendChild(button);
31
+ }
32
+
33
+ const column = document.createElement('div');
34
+ column.style.display = 'flex';
35
+ column.style.flexDirection = 'column';
36
+ column.style.gap = '8px';
37
+ column.style.width = '420px';
38
+ const note = document.createElement('span');
39
+ note.textContent = 'The bar below is Gtk.ActionBar.';
40
+ column.append(note, this._bar);
41
+
42
+ this.addContent(column);
43
+ this._apply();
44
+ }
45
+
46
+ updateArgs(_args: StoryArgs): void {
47
+ this._apply();
48
+ }
49
+
50
+ private _apply(): void {
51
+ if (!this._bar) return;
52
+ this._bar.setAttribute('revealed', String(this.args.revealed as boolean));
53
+ // `gtk_action_bar_set_center_widget` (:306-...) takes a widget or NULL, and NULL
54
+ // clears the centre rather than replacing it with an empty label.
55
+ const centre = this._bar.querySelector('[slot="center"]');
56
+ if ((this.args.center as string) === 'label' && centre === null) {
57
+ const label = document.createElement('span');
58
+ label.setAttribute('slot', 'center');
59
+ label.textContent = 'notes.md';
60
+ this._bar.appendChild(label);
61
+ }
62
+ centre?.remove();
63
+ }
64
+ }
65
+
66
+ export const ActionBarWebStories: WebStoryModule = { stories: [ActionBarWebStory] };
@@ -0,0 +1,67 @@
1
+ // Browser port of the GTK Application Window story. Shares metadata with gtk-application-window.story.ts.
2
+ //
3
+ // The menubar is a SLOT here, because GTK builds the bar from the application's menu model
4
+ // and no attribute can carry one — see `gtk-application-window.ts`. So the "the application has
5
+ // one" control adds and removes the SLOT rather than a `GMenuModel`.
6
+
7
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
8
+ import { gtkApplicationWindowMeta } from '../../windows/gtk-application-window.meta.js';
9
+
10
+ export class GtkApplicationWindowWebStory extends StoryElement {
11
+ private _window: HTMLElement | null = null;
12
+ private _menubar: HTMLElement | null = null;
13
+
14
+ constructor() {
15
+ super(GtkApplicationWindowWebStory.getMetadata(), 'Default');
16
+ }
17
+
18
+ static getMetadata(): StoryMeta {
19
+ return gtkApplicationWindowMeta;
20
+ }
21
+
22
+ initialize(): void {
23
+ this._window = document.createElement('gtk-application-window');
24
+ this._window.setAttribute('default-width', '460');
25
+ this._window.setAttribute('default-height', '260');
26
+
27
+ const bar = document.createElement('gtk-header-bar');
28
+ bar.setAttribute('slot', 'titlebar');
29
+ this._window.appendChild(bar);
30
+
31
+ const note = document.createElement('span');
32
+ note.textContent = 'The bar above the content is the application menubar.';
33
+ this._window.appendChild(note);
34
+
35
+ this._menubar = document.createElement('div');
36
+ for (const label of ['File', 'Edit']) {
37
+ const item = document.createElement('gtk-button');
38
+ item.setAttribute('label', label);
39
+ item.setAttribute('flat', '');
40
+ this._menubar.appendChild(item);
41
+ }
42
+
43
+ this.addContent(this._window);
44
+ this._apply();
45
+ }
46
+
47
+ updateArgs(_args: StoryArgs): void {
48
+ this._apply();
49
+ }
50
+
51
+ private _apply(): void {
52
+ if (!this._window) return;
53
+ this._window.setAttribute('title', this.args.title as string);
54
+ this._window.setAttribute('deletable', String(this.args.deletable as boolean));
55
+ this._window.setAttribute('show-menubar', String(this.args.showMenubar as boolean));
56
+ // The second half of `update_menubar`'s rule (gtkapplicationwindow.c:400-402): a
57
+ // window whose section has no items shows nothing, whatever the property says.
58
+ const present = this._window.querySelector('.adw-gtk-application-window-menubar')?.childElementCount ?? 0;
59
+ if (this.args.hasMenubar as boolean) {
60
+ if (present === 0) this._window.appendChild(this._menubar as HTMLElement);
61
+ } else if (present > 0) {
62
+ (this._menubar as HTMLElement).remove();
63
+ }
64
+ }
65
+ }
66
+
67
+ export const GtkApplicationWindowWebStories: WebStoryModule = { stories: [GtkApplicationWindowWebStory] };
@@ -0,0 +1,61 @@
1
+ // Browser port of the GTK Header Bar story. Shares metadata with gtk-header-bar.story.ts.
2
+
3
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
4
+ import { gtkHeaderBarMeta } from '../../windows/gtk-header-bar.meta.js';
5
+
6
+ export class GtkHeaderBarWebStory extends StoryElement {
7
+ private _bar: HTMLElement | null = null;
8
+ private _titleLabel: HTMLElement | null = null;
9
+
10
+ constructor() {
11
+ super(GtkHeaderBarWebStory.getMetadata(), 'Default');
12
+ }
13
+
14
+ static getMetadata(): StoryMeta {
15
+ return gtkHeaderBarMeta;
16
+ }
17
+
18
+ initialize(): void {
19
+ this._bar = document.createElement('gtk-header-bar');
20
+
21
+ // The same three children in the same order as the GTK story — `pack_end` PREPENDS,
22
+ // so the button added LAST sits nearest the edge (gtkheaderbar.c:843-861).
23
+ for (const [slot, icon] of [
24
+ ['end', 'open-menu-symbolic'],
25
+ ['end', 'system-search-symbolic'],
26
+ ['start', 'go-previous-symbolic'],
27
+ ] as const) {
28
+ const button = document.createElement('gtk-button');
29
+ button.setAttribute('slot', slot);
30
+ button.setAttribute('icon-name', icon);
31
+ button.setAttribute('flat', '');
32
+ this._bar.appendChild(button);
33
+ }
34
+
35
+ // `gtk_header_bar_set_title_widget` empties the centre bin for the widget and hands
36
+ // the derived label back on NULL (gtkheaderbar.c:319-336) — so this child is
37
+ // REMOVED rather than hidden, which is the only way the bar can rebuild the label.
38
+ this._titleLabel = document.createElement('span');
39
+ this._titleLabel.setAttribute('slot', 'title');
40
+ this._titleLabel.textContent = 'Mailboxes';
41
+
42
+ this.addContent(this._bar);
43
+ this._apply();
44
+ }
45
+
46
+ updateArgs(_args: StoryArgs): void {
47
+ this._apply();
48
+ }
49
+
50
+ private _apply(): void {
51
+ if (!this._bar) return;
52
+ this._bar.setAttribute('decoration-layout', this.args.decorationLayout as string);
53
+ this._bar.setAttribute('show-title-buttons', String(this.args.showTitleButtons as boolean));
54
+ const custom = (this.args.titleWidget as string) === 'custom';
55
+ const present = this._bar.querySelector('[slot="title"]') !== null;
56
+ if (custom && !present) this._bar.appendChild(this._titleLabel as HTMLElement);
57
+ if (!custom && present) (this._titleLabel as HTMLElement).remove();
58
+ }
59
+ }
60
+
61
+ export const GtkHeaderBarWebStories: WebStoryModule = { stories: [GtkHeaderBarWebStory] };
@@ -0,0 +1,58 @@
1
+ // Browser port of the GTK Window story. Shares metadata with gtk-window.story.ts.
2
+ //
3
+ // The replica is an IN-PAGE FRAME, not a toplevel — see `gtk-window.ts`. The one thing this
4
+ // story has to add for that to read is the `close-request` handler: GTK's default handler
5
+ // destroys the window unless `hide-on-close`, and an application that wants to keep it
6
+ // cancels the signal.
7
+
8
+ import { StoryElement, type StoryArgs, type StoryMeta, type WebStoryModule } from '@gjsify/adwaita-storybook';
9
+ import { gtkWindowMeta } from '../../windows/gtk-window.meta.js';
10
+
11
+ export class GtkWindowWebStory extends StoryElement {
12
+ private _window: HTMLElement | null = null;
13
+ private _bar: HTMLElement | null = null;
14
+
15
+ constructor() {
16
+ super(GtkWindowWebStory.getMetadata(), 'Default');
17
+ }
18
+
19
+ static getMetadata(): StoryMeta {
20
+ return gtkWindowMeta;
21
+ }
22
+
23
+ initialize(): void {
24
+ this._window = document.createElement('gtk-window');
25
+ this._window.setAttribute('default-width', '460');
26
+ this._window.setAttribute('default-height', '280');
27
+
28
+ // `decorated: false` DROPS the titlebar strip, so the story keeps the bar in the TREE
29
+ // and lets the property decide whether it is seen (gtkwindow.c:1014).
30
+ this._bar = document.createElement('gtk-header-bar');
31
+ this._bar.setAttribute('slot', 'titlebar');
32
+ this._window.appendChild(this._bar);
33
+
34
+ const note = document.createElement('span');
35
+ note.textContent = 'The frame above is a Gtk.HeaderBar.';
36
+ this._window.appendChild(note);
37
+
38
+ this.addContent(this._window);
39
+ this._apply();
40
+ }
41
+
42
+ updateArgs(_args: StoryArgs): void {
43
+ this._apply();
44
+ }
45
+
46
+ private _apply(): void {
47
+ if (!this._window) return;
48
+ this._window.setAttribute('title', this.args.title as string);
49
+ this._window.setAttribute('decorated', String(this.args.decorated as boolean));
50
+ this._window.setAttribute('deletable', String(this.args.deletable as boolean));
51
+ this._window.setAttribute('resizable', String(this.args.resizable as boolean));
52
+ this._window.setAttribute('maximized', String(this.args.maximized as boolean));
53
+ this._window.setAttribute('modal', String(this.args.modal as boolean));
54
+ this._window.setAttribute('hide-on-close', String(this.args.hideOnClose as boolean));
55
+ }
56
+ }
57
+
58
+ export const GtkWindowWebStories: WebStoryModule = { stories: [GtkWindowWebStory] };