@gjsify/example-gtk-adwaita-storybook 0.26.1 → 0.27.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.
package/dist/gjs.js CHANGED
@@ -65,7 +65,7 @@ if(globalThis.__gjsifyBundleUrl??=import.meta.url,Symbol.dispose||(Symbol.dispos
65
65
  </method>${e.length>0?`\n${e.join(`
66
66
  `)}`:``}
67
67
  </interface>
68
- </node>`}var ht=r;function captureWidgetPng(e){let t=e.get_native()?.get_renderer();if(!t)return null;let n=e.get_width(),r=e.get_height();if(n<=0||r<=0)return null;let i=Y.WidgetPaintable.new(e),a=Y.Snapshot.new();i.snapshot(a,n,r);let o=a.to_node();if(!o)return null;let s=new ht.Rect;s.init(0,0,n,r);let c=t.render_texture(o,s).save_to_png_bytes().get_data();return c?new Uint8Array(c):null}var X=i;function dumpGSettings(e){let t=X.SettingsSchemaSource.get_default()?.lookup(e,!0);if(!t)throw Error(formatDbusErrorMessage(`not-found`,`GSettings schema '${e}' is not installed`));let n=new X.Settings({settings_schema:t}),r={};for(let e of t.list_keys())r[e]=n.get_value(e).recursiveUnpack();return r}function parseWidgetPath(e){let t=e.split(`/`).filter(e=>e.length>0);if(t.length===0)return null;let n=t[0].match(/^toplevel:(\d+)$/);if(!n)return null;let r=[];for(let e of t.slice(1)){let t=e.match(/^child:(\d+)$/);if(!t)return null;r.push(Number(t[1]))}return{toplevel:Number(n[1]),children:r}}function buildWidgetPath(e,t){return[`toplevel:${e}`,...t.map(e=>`child:${e}`)].join(`/`)}function widgetType(e){let t=e;return typeof t.$typeName==`string`&&t.$typeName.length>0?t.$typeName:t.constructor?.$gtype?.name??`GtkWidget`}function activateWidget(e){let t=e;if(typeof t.activate==`function`&&t.activate()===!0)return!0;let n=typeof t.get_parent==`function`?t.get_parent():null;if(n&&widgetType(n)===`GtkListBox`){let t=n,r=!1;return typeof t.select_row==`function`&&(t.select_row(e),r=!0),typeof t.emit==`function`&&(t.emit(`row-activated`,e),r=!0),r}return!1}function nthChild(e,t){let n=e.get_first_child(),r=0;for(;n&&r<t;)n=n.get_next_sibling(),r++;return r===t?n:null}function listToplevels(){let e=Y.Window.get_toplevels(),t=e.get_n_items(),n=[];for(let r=0;r<t;r++){let t=e.get_item(r);t&&n.push({path:`toplevel:${r}`,type:widgetType(t),title:t.get_title?.()??null,mapped:t.get_mapped(),focused:t.is_active??!1})}return n}function resolveWidgetPath(e){let t=parseWidgetPath(e);if(!t)return null;let n=Y.Window.get_toplevels().get_item(t.toplevel);if(!n)return null;for(let e of t.children)if(n=nthChild(n,e),!n)return null;return n}function dumpTree(e,t,n){let r={path:n,type:widgetType(e),name:e.get_name()||null,cssClasses:e.get_css_classes(),mapped:e.get_mapped(),visible:e.get_visible(),children:[]};if(t<=0)return r;let i=e.get_first_child(),a=0;for(;i;)r.children.push(dumpTree(i,t-1,`${n}/child:${a}`)),i=i.get_next_sibling(),a++;return r}function jsonSafe(e){let t=typeof e;return e==null||t===`string`||t===`number`||t===`boolean`?e??null:`[${t}]`}function getWidgetProperty(e,t){let n=e,r=t.replace(/-/g,`_`),i=t.replace(/[-_]([a-z])/g,(e,t)=>t.toUpperCase());for(let e of[t,r,i])if(e in n)return jsonSafe(n[e])}function childIndex(e,t){let n=e.get_first_child(),r=0;for(;n;){if(n===t)return r;n=n.get_next_sibling(),r++}return-1}function pathOfWidget(e){let t=[],n=e,r=n.get_parent();for(;r;){let e=childIndex(r,n);if(e<0)return null;t.unshift(e),n=r,r=n.get_parent()}let i=Y.Window.get_toplevels(),a=i.get_n_items();for(let e=0;e<a;e++)if(i.get_item(e)===n)return buildWidgetPath(e,t);return null}function frameDelay(e){return new Promise(t=>{y.timeout_add(y.PRIORITY_DEFAULT,e,()=>(t(),y.SOURCE_REMOVE))})}async function captureWidgetWhenRenderable(e,t=12,n=50){for(let r=0;r<t;r++){let t=captureWidgetPng(e);if(t)return t;await frameDelay(n)}return captureWidgetPng(e)}var DevtoolsService=class{constructor(e,t){this._app=e,this._options=t,this._exported=null,this._kinds=new Map,this._extensions=t.extend??[];for(let[e,t]of Object.entries(mt))this._kinds.set(e,t);for(let e of this._extensions){for(let[t,n]of Object.entries(e.methodKinds))this._kinds.set(t,n);for(let[t,n]of Object.entries(e.handlers)){let e=n;this[t]=(...n)=>(this._guard(t),e(...n))}}}export(e,t){if(this._exported)return;let n=buildDevtoolsIfaceXml(this._extensions.flatMap(e=>e.methodsXml??[])),r=X.DBusExportedObject.wrapJSObject(n,this);r.export(e,t),this._exported=r}unexport(){this._exported?.unexport(),this._exported=null}GetStatus(){let e=this._app.get_active_window(),t={appId:this._app.get_application_id()??`unknown`,instance:this._options.instance??`default`,activeWindow:e?{id:e.get_name()||`window`,title:e.get_title()??``,mapped:e.get_mapped()}:null,toplevelCount:Y.Window.get_toplevels().get_n_items(),focusedWidget:null,paused:this._isPaused()};for(let e of this._extensions){let n=e.contributeStatus?.();n&&Object.assign(t,n)}return JSON.stringify(t)}async Screenshot(e){let t=this._app.get_active_window();if(!t)return new Uint8Array;let n=captureWidgetPng(t);return n||=(t.present(),await captureWidgetWhenRenderable(t)),n??new Uint8Array}ListActions(){let e={app:describeActions(this._actionGroup(`app`)),win:describeActions(this._actionGroup(`win`))};return JSON.stringify(e)}ActivateAction(e,t,n){this._guard(`ActivateAction`);let r=this._scope(e);activateAction(this._requireGroup(r,t),t,this._parseValue(n))}ChangeActionState(e,t,n){this._guard(`ChangeActionState`);let r=this._scope(e);changeActionState(this._requireGroup(r,t),t,this._parseValue(n))}PresentWindow(){this._app.get_active_window()?.present()}ResizeWindow(e,t){this._guard(`ResizeWindow`);let n=this._app.get_active_window();if(!n)throw Error(formatDbusErrorMessage(`unavailable`,`no active window to resize`));let r=Math.max(1,Math.round(e)),i=Math.max(1,Math.round(t));return n.is_maximized()&&n.unmaximize(),n.is_fullscreen()&&n.unfullscreen(),n.set_default_size(r,i),[r,i]}ListToplevels(){return JSON.stringify(listToplevels())}DumpTree(e,t){let n=this._resolveRootWidget(e);if(!n)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e||`active window`}'`));return JSON.stringify(dumpTree(n.widget,t>0?t:8,n.path))}GetProperty(e,t){let n=this._resolveRootWidget(e);if(!n)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e}'`));let r=getWidgetProperty(n.widget,t);if(r===void 0)throw Error(formatDbusErrorMessage(`not-found`,`widget has no property '${t}'`));return JSON.stringify(r)}GetFocused(){let e=this._app.get_active_window(),t=e?e.get_focus():null;return JSON.stringify(t?{path:pathOfWidget(t),name:t.get_name()||null,type:widgetType(t)}:null)}ActivateWidget(e){this._guard(`ActivateWidget`);let t=this._resolveRootWidget(e);if(!t)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e}'`));return activateWidget(t.widget)}DumpGSettings(e){return JSON.stringify(dumpGSettings(e))}DumpCss(){return JSON.stringify(dumpCss())}SwapCss(e,t){return this._guard(`SwapCss`),swapCss(e,t)}_resolveRootWidget(e){if(!e||e===`window`||e===`active`){let e=this._app.get_active_window();return e?{widget:e,path:pathOfWidget(e)??`toplevel:0`}:null}let t=resolveWidgetPath(e);return t?{widget:t,path:e}:null}_isPaused(){return this._options.paused?.()??!1}_guard(e){let t=this._kinds.get(e);if(!t)throw Error(formatDbusErrorMessage(`internal`,`unclassified devtools method '${e}'`));if(t===`mutating`&&this._isPaused())throw Error(formatDbusErrorMessage(`paused`,`${e} rejected — external control is paused. Read-only methods keep working.`))}_scope(e){return e===`app`?`app`:`win`}_actionGroup(e){if(e===`app`)return this._app;if(this._options.winActionGroup)return this._options.winActionGroup;let t=this._app.get_active_window();return t instanceof Y.ApplicationWindow?t:null}_requireGroup(e,t){let n=this._actionGroup(e);if(!n)throw Error(formatDbusErrorMessage(`unavailable`,`no '${e}' action group`));if(!n.has_action(t))throw Error(formatDbusErrorMessage(`not-found`,`unknown action ${e}.${t}`));return n}_parseValue(e){if(!e||e===`null`)return null;try{return JSON.parse(e)}catch{throw Error(formatDbusErrorMessage(`invalid-params`,`value_json is not valid JSON: ${e}`))}}};const gt=new Set;function envEnabled(){let e=y.getenv(`GJSIFY_DEVTOOLS`);if(e==null)return!1;let t=e.toLowerCase();return t!==``&&t!==`0`&&t!==`false`}function envInstance(){let e=y.getenv(`GJSIFY_DEVTOOLS_INSTANCE`);return e&&e!==``?e:void 0}function installDevtools(e,t={}){if(!(t.enabled??envEnabled()))return null;let n=new DevtoolsService(e,{...t,instance:t.instance??envInstance()}),r=e.get_dbus_connection(),i=e.get_dbus_object_path();if(r&&i){let t=`${i}/devtools`;n.export(r,t),h.log(`[gjsify-devtools] exported ${pt} at ${t} (dest ${e.get_application_id()??`?`})`)}else h.error(`[gjsify-devtools] no session-bus connection yet — call installDevtools() from the GtkApplication "startup" handler`);return gt.add(n),n}const _t=[`AdwNavigationSplitView`,`GtkListBox`,`AdwOverlaySplitView`];function probeEnabled(){let e=y.getenv(`GJSIFY_STORYBOOK_PROBE`);if(e==null)return!1;let t=e.toLowerCase();return t!==``&&t!==`0`&&t!==`false`}function collectTypes(e,t){t.add(e.type);for(let n of e.children)collectTypes(n,t)}function installStorybookProbe(e,t,n={}){let r=n.requireChrome??_t,i=n.out??y.getenv(`GJSIFY_STORYBOOK_PROBE_OUT`)??void 0,a=n.timeoutMs??8e3,o=n.storyWidget??y.getenv(`GJSIFY_STORYBOOK_PROBE_STORY_WIDGET`)??void 0,s=t.controller.listStories(),c=[...new Set(s.map(e=>e.category))],l=n.story??y.getenv(`GJSIFY_STORYBOOK_PROBE_STORY`)??s[0]?.title,u=l?t.openStoryByTitle(l):!1,d=t.activeStory,f=new Set;collectTypes(dumpTree(t,60,`toplevel:0`),f);let p=r.filter(e=>!f.has(e)),m=new Set;d&&collectTypes(dumpTree(d,60,`story`),m);let g=m.size,ee=o?m.has(o):null,finish=t=>{let n=JSON.stringify(t);if(t.ok)h.log(`STORYBOOK PROBE: PASS ${n}`);else{h.error(`STORYBOOK PROBE: FAIL ${n}`);try{typeof process<`u`&&(process.exitCode=1)}catch{}}if(i)try{y.file_set_contents(i,JSON.stringify(t,null,2))}catch{}e.quit()},te=0;y.timeout_add(y.PRIORITY_DEFAULT,100,()=>{te+=100;let e=captureWidgetPng(t),n=t.get_width()>0&&t.get_height()>0;if(!e&&!(te>=a))return y.SOURCE_CONTINUE;let i=d?captureWidgetPng(d):null,f=s.length>=1&&c.length>=1&&p.length===0&&u&&d!=null&&g>1,h;return s.length<1?h=`no stories registered`:c.length<1?h=`no categories`:p.length>0?h=`chrome missing: ${p.join(`, `)}`:!u||d==null?h=`could not open story: ${l??`(none)`}`:g<=1&&(h=`opened story rendered an empty subtree`),f&&o&&!m.has(o)&&(f=!1,h=`story widget ${o} not found in the opened story subtree`),f&&n&&(!e||e.length===0)&&(f=!1,h=`window realized (${t.get_width()}x${t.get_height()}) but the GSK capture was empty`),finish({ok:f,reason:h,stories:s.length,categories:c,opened:u,activeStory:d?d.meta.title:null,requiredChrome:r,missingChrome:p,storySubtreeWidgets:g,storyWidgetPresent:ee,windowRealized:n,windowPngBytes:e?e.length:0,storyPngBytes:i?i.length:0}),y.SOURCE_REMOVE})}var Z=a,Q=o;function adwControlWidgetFactory(){return{text(e,t){let n=new Z.EntryRow({title:e});t&&n.set_tooltip_text(t);let r=null;return n.connect(`changed`,()=>r?.(n.get_text())),{node:n,get:()=>n.get_text(),set:e=>n.set_text(e),onChange:e=>{r=e}}},boolean(e,t){let n=new Z.SwitchRow({title:e,subtitle:t??``}),r=null;return n.connect(`notify::active`,()=>r?.(n.get_active())),{node:n,get:()=>n.get_active(),set:e=>n.set_active(e),onChange:e=>{r=e}}},number(e){let t=Z.SpinRow.new_with_range(e.min??0,e.max??100,e.step??1);t.set_title(e.label||e.name),e.description&&t.set_subtitle(e.description);let n=null;return t.connect(`changed`,()=>n?.(t.get_value())),{node:t,get:()=>t.get_value(),set:e=>t.set_value(e),onChange:e=>{n=e}}},range(e){return buildRangeWidget(e)},select(e){return buildSelectWidget(e)},color(e,t){return buildColorWidget(e,t)}}}function buildRangeWidget(e){let t=e.min??0,n=e.max??100,r=e.step??1,i=typeof e.min==`number`?e.min:0,a=Number.isInteger(r)&&Number.isInteger(i),o=new Y.Adjustment({lower:t,upper:n,step_increment:r,value:i});o.step_increment=r;let s=new Y.ListBoxRow({selectable:!1,activatable:!1});s.add_css_class(`story-range-row`);let c=new Y.Box({orientation:Y.Orientation.VERTICAL,spacing:6,margin_top:12,margin_bottom:12,margin_start:12,margin_end:12}),l=new Y.Box({orientation:Y.Orientation.HORIZONTAL,spacing:12}),u=new Y.Label({label:e.label||e.name,halign:Y.Align.START,hexpand:!0,ellipsize:3});u.add_css_class(`heading`);let formatValue=e=>a?String(Math.round(e)):e.toFixed(2),d=new Y.Label({label:formatValue(i),halign:Y.Align.END});if(d.add_css_class(`numeric`),d.add_css_class(`dim-label`),l.append(u),l.append(d),c.append(l),e.description){let t=new Y.Label({label:e.description,halign:Y.Align.START,xalign:0,wrap:!0,max_width_chars:32});t.add_css_class(`caption`),t.add_css_class(`dim-label`),c.append(t)}let f=new Y.Scale({orientation:Y.Orientation.HORIZONTAL,adjustment:o,draw_value:!1,hexpand:!0}),p=null,m=!1;return f.connect(`value-changed`,()=>{if(m)return;let e=f.get_value();if(a){let t=Math.round(e);if(t!==e){f.set_value(t);return}e=t}d.set_label(formatValue(e)),p?.(e)}),c.append(f),s.set_child(c),{node:s,get:()=>f.get_value(),set:e=>{m=!0,f.set_value(e),m=!1,d.set_label(formatValue(e))},onChange:e=>{p=e}}}function buildSelectWidget(e){let t=e.options??[],n=Y.StringList.new(t.map(e=>e.label)),r=new Z.ComboRow({title:e.label||e.name,subtitle:e.description??``,model:n}),i=null;return r.connect(`notify::selected`,()=>i?.(r.get_selected())),{node:r,get:()=>r.get_selected(),set:e=>r.set_selected(e),onChange:e=>{i=e}}}function buildColorWidget(e,t){let n=new Z.ActionRow({title:e,subtitle:t??``}),r=new Y.ColorDialogButton({dialog:new Y.ColorDialog({title:e}),valign:Y.Align.CENTER});n.add_suffix(r),n.set_activatable_widget(r);let channel=e=>Math.round(Math.max(0,Math.min(1,e))*255).toString(16).padStart(2,`0`),rgbaToHex=e=>`#${channel(e.red)}${channel(e.green)}${channel(e.blue)}`,i=null,a=!1;return r.connect(`notify::rgba`,()=>{a||i?.(rgbaToHex(r.get_rgba()))}),{node:n,get:()=>rgbaToHex(r.get_rgba()),set:e=>{let t=new dt.RGBA;t.parse(e)&&(a=!0,r.set_rgba(t),a=!1)},onChange:e=>{i=e}}}var vt=class StorybookWindow extends Z.ApplicationWindow{static{Q.registerClass({GTypeName:`StorybookWindow`},StorybookWindow)}constructor(e){super(e),this._controlRows=[],this._rowByTitle=new Map,this._onSelect=null,this._suppressSelect=!1,this.set_default_size(1200,800),this.set_size_request(360,320),this.set_title(`Storybook`),this._buildUI(),this._controller=new StorybookController(this,e=>this._buildControls(e)),this._sidebar_list.connect(`row-selected`,this._onRowSelected.bind(this)),this._show_controls_button.connect(`toggled`,this._onToggleControls.bind(this)),this._controls_split_view.set_show_sidebar(!0)}_onRowSelected(e,t){if(this._suppressSelect||!t)return;let n=t;n.storyWidget&&this._onSelect?.(n.storyWidget)}get controller(){return this._controller}_buildControls(e){let t=e.meta.controls;if(!Array.isArray(t))return[];let n=adwControlWidgetFactory(),r=[];for(let i of t){if(!i?.name||!i?.type){h.warn(`Invalid control configuration:`,i);continue}let t=bindControl(e,i,n);t&&r.push(t)}return r}_buildUI(){this._sidebar_list=new Y.ListBox({selection_mode:Y.SelectionMode.SINGLE}),this._sidebar_list.add_css_class(`navigation-sidebar`);let e=new Y.ScrolledWindow({hexpand:!0,vexpand:!0,child:this._sidebar_list}),t=new Z.HeaderBar({title_widget:new Z.WindowTitle({title:`Stories`}),show_end_title_buttons:!1}),n=new Z.ToolbarView({content:e,top_bar_style:Z.ToolbarStyle.FLAT});n.add_top_bar(t);let r=new Z.NavigationPage({title:`Stories`,tag:`stories`,child:n});this._content_area=new Z.Bin({hexpand:!0,vexpand:!0});let i=new Y.ScrolledWindow({hexpand:!0,vexpand:!0,child:this._content_area});this._control_panel=new Z.PreferencesGroup({title:`Controls`});let a=new Z.PreferencesPage;a.add(this._control_panel);let o=new Y.ScrolledWindow({vexpand:!0,child:a});this._controls_split_view=new Z.OverlaySplitView({show_sidebar:!0,sidebar_position:Y.PackType.END,min_sidebar_width:280,max_sidebar_width:360,content:i,sidebar:o,css_classes:[`storybook-controls`]}),this._preview_title=new Z.WindowTitle({title:`Preview`}),this._show_controls_button=new Y.ToggleButton({icon_name:`sidebar-show-right-symbolic`,tooltip_text:`Toggle Controls`,active:!0});let s=new Z.HeaderBar({title_widget:this._preview_title});s.pack_end(this._show_controls_button);let c=new Z.ToolbarView({content:this._controls_split_view,top_bar_style:Z.ToolbarStyle.FLAT});c.add_top_bar(s);let l=new Z.NavigationPage({title:`Preview`,tag:`preview`,child:c});this._main_split_view=new Z.NavigationSplitView({min_sidebar_width:220,max_sidebar_width:320,sidebar:r,content:l}),this.set_content(this._main_split_view);let u=Z.BreakpointCondition.parse(`max-width: 720sp`);if(u){let e=new Z.Breakpoint({condition:u});e.connect(`apply`,()=>{this._main_split_view.collapsed=!0,this._controls_split_view.collapsed=!0}),e.connect(`unapply`,()=>{this._main_split_view.collapsed=!1,this._controls_split_view.collapsed=!1}),this.add_breakpoint(e)}}_onToggleControls(e){this._controls_split_view.set_show_sidebar(e.get_active())}populateSidebar(e){this._controller.mount(e,!0)}renderSidebar(e,t){this._onSelect=t,this._suppressSelect=!0,this._clearSidebar(),this._rowByTitle.clear();for(let t of e){this._addCategoryToSidebar(t.category);for(let{instance:e,name:n}of t.stories)this._addStoryToSidebar(e,n)}this._suppressSelect=!1}markSelected(e){let t=this._rowByTitle.get(e);t&&this._sidebar_list.get_selected_row()!==t&&(this._suppressSelect=!0,this._sidebar_list.select_row(t),this._suppressSelect=!1)}setPreviewTitle(e){this._preview_title.set_title(e)}showPreview(e){this._content_area.set_child(e),this._main_split_view.get_collapsed()&&this._main_split_view.set_show_content(!0)}renderControls(e){this._clearControlPanel();for(let t of e){let e=t.view;this._control_panel.add(e),this._controlRows.push(e)}this._show_controls_button.set_active(!0)}_clearSidebar(){let e=this._sidebar_list.get_first_child();for(;e;){let t=e.get_next_sibling();e.unparent(),e=t}}_addCategoryToSidebar(e){let t=new Y.ListBoxRow({selectable:!1}),n=new Y.Label({label:e,halign:Y.Align.START,margin_top:10,margin_bottom:4,margin_start:12,margin_end:12});n.add_css_class(`heading`),n.add_css_class(`dim-label`),t.set_child(n),this._sidebar_list.append(t)}_addStoryToSidebar(e,t){let n=new Y.ListBoxRow,r=new Y.Label({label:t||`Unnamed Story`,halign:Y.Align.START,margin_start:20,margin_top:6,margin_bottom:6});n.set_child(r),this._sidebar_list.append(n),n.storyWidget=e,this._rowByTitle.set(e.meta.title,n)}_clearControlPanel(){for(let e of this._controlRows)this._control_panel.remove(e);this._controlRows=[]}get activeStory(){return this._controller.activeStory}openStoryByTitle(e){return this._controller.openStoryByTitle(e)}setActiveArg(e,t){return this._controller.setActiveArg(e,t)}};Q.type_ensure(vt.$gtype);var yt=class StorybookApplication extends Z.Application{static{Q.registerClass({GTypeName:`StorybookApplication`},StorybookApplication)}constructor(e){super({application_id:e.applicationId,flags:X.ApplicationFlags.DEFAULT_FLAGS}),this._window=null,this._options=e,this.connect(`startup`,()=>this._initStyles()),this.connect(`activate`,()=>this._onActivate())}_initStyles(){let e=new Y.CssProvider;e.load_from_string(`
68
+ </node>`}var ht=r;function captureWidgetPng(e){let t=e.get_native()?.get_renderer();if(!t)return null;let n=e.get_width(),r=e.get_height();if(n<=0||r<=0)return null;let i=Y.WidgetPaintable.new(e),a=Y.Snapshot.new();i.snapshot(a,n,r);let o=a.to_node();if(!o)return null;let s=new ht.Rect;s.init(0,0,n,r);let c=t.render_texture(o,s).save_to_png_bytes().get_data();return c?new Uint8Array(c):null}var X=i;function dumpGSettings(e){let t=X.SettingsSchemaSource.get_default()?.lookup(e,!0);if(!t)throw Error(formatDbusErrorMessage(`not-found`,`GSettings schema '${e}' is not installed`));let n=new X.Settings({settings_schema:t}),r={};for(let e of t.list_keys())r[e]=n.get_value(e).recursiveUnpack();return r}function parseWidgetPath(e){let t=e.split(`/`).filter(e=>e.length>0);if(t.length===0)return null;let n=t[0].match(/^toplevel:(\d+)$/);if(!n)return null;let r=[];for(let e of t.slice(1)){let t=e.match(/^child:(\d+)$/);if(!t)return null;r.push(Number(t[1]))}return{toplevel:Number(n[1]),children:r}}function buildWidgetPath(e,t){return[`toplevel:${e}`,...t.map(e=>`child:${e}`)].join(`/`)}function widgetType(e){let t=e;return typeof t.$typeName==`string`&&t.$typeName.length>0?t.$typeName:t.constructor?.$gtype?.name??`GtkWidget`}function activateWidget(e){let t=e;if(typeof t.activate==`function`&&t.activate()===!0)return!0;let n=typeof t.get_parent==`function`?t.get_parent():null;if(n&&widgetType(n)===`GtkListBox`){let t=n,r=!1;return typeof t.select_row==`function`&&(t.select_row(e),r=!0),typeof t.emit==`function`&&(t.emit(`row-activated`,e),r=!0),r}return!1}function nthChild(e,t){let n=e.get_first_child(),r=0;for(;n&&r<t;)n=n.get_next_sibling(),r++;return r===t?n:null}function listToplevels(){let e=Y.Window.get_toplevels(),t=e.get_n_items(),n=[];for(let r=0;r<t;r++){let t=e.get_item(r);t&&n.push({path:`toplevel:${r}`,type:widgetType(t),title:t.get_title?.()??null,mapped:t.get_mapped(),focused:t.is_active??!1})}return n}function resolveWidgetPath(e){let t=parseWidgetPath(e);if(!t)return null;let n=Y.Window.get_toplevels().get_item(t.toplevel);if(!n)return null;for(let e of t.children)if(n=nthChild(n,e),!n)return null;return n}function dumpTree(e,t,n){let r={path:n,type:widgetType(e),name:e.get_name()||null,cssClasses:e.get_css_classes(),mapped:e.get_mapped(),visible:e.get_visible(),children:[]};if(t<=0)return r;let i=e.get_first_child(),a=0;for(;i;)r.children.push(dumpTree(i,t-1,`${n}/child:${a}`)),i=i.get_next_sibling(),a++;return r}function jsonSafe(e){let t=typeof e;return e==null||t===`string`||t===`number`||t===`boolean`?e??null:`[${t}]`}function getWidgetProperty(e,t){let n=e,r=t.replace(/-/g,`_`),i=t.replace(/[-_]([a-z])/g,(e,t)=>t.toUpperCase());for(let e of[t,r,i])if(e in n)return jsonSafe(n[e])}function childIndex(e,t){let n=e.get_first_child(),r=0;for(;n;){if(n===t)return r;n=n.get_next_sibling(),r++}return-1}function pathOfWidget(e){let t=[],n=e,r=n.get_parent();for(;r;){let e=childIndex(r,n);if(e<0)return null;t.unshift(e),n=r,r=n.get_parent()}let i=Y.Window.get_toplevels(),a=i.get_n_items();for(let e=0;e<a;e++)if(i.get_item(e)===n)return buildWidgetPath(e,t);return null}function frameDelay(e){return new Promise(t=>{y.timeout_add(y.PRIORITY_DEFAULT,e,()=>(t(),y.SOURCE_REMOVE))})}async function captureWidgetWhenRenderable(e,t=12,n=50){for(let r=0;r<t;r++){let t=captureWidgetPng(e);if(t)return t;await frameDelay(n)}return captureWidgetPng(e)}var DevtoolsService=class{constructor(e,t){this._app=e,this._options=t,this._exported=null,this._kinds=new Map,this._extensions=t.extend??[];for(let[e,t]of Object.entries(mt))this._kinds.set(e,t);for(let e of this._extensions){for(let[t,n]of Object.entries(e.methodKinds))this._kinds.set(t,n);for(let[t,n]of Object.entries(e.handlers)){let e=n;this[t]=(...n)=>(this._guard(t),e(...n))}}}export(e,t){if(this._exported)return;let n=buildDevtoolsIfaceXml(this._extensions.flatMap(e=>e.methodsXml??[])),r=X.DBusExportedObject.wrapJSObject(n,this);r.export(e,t),this._exported=r}unexport(){this._exported?.unexport(),this._exported=null}GetStatus(){let e=this._app.get_active_window(),t={appId:this._app.get_application_id()??`unknown`,instance:this._options.instance??`default`,activeWindow:e?{id:e.get_name()||`window`,title:e.get_title()??``,mapped:e.get_mapped()}:null,toplevelCount:Y.Window.get_toplevels().get_n_items(),focusedWidget:null,paused:this._isPaused()};for(let e of this._extensions){let n=e.contributeStatus?.();n&&Object.assign(t,n)}return JSON.stringify(t)}async ScreenshotAsync(e,t){try{let e=await this._captureActiveWindowPng();t.return_value(new y.Variant(`(ay)`,[e]))}catch(e){t.return_dbus_error(`org.gjsify.Devtools.Error.Screenshot`,e instanceof Error?e.message:String(e))}}async _captureActiveWindowPng(){let e=this._app.get_active_window();if(!e)return new Uint8Array;let t=captureWidgetPng(e);return t||=(e.present(),await captureWidgetWhenRenderable(e)),t??new Uint8Array}ListActions(){let e={app:describeActions(this._actionGroup(`app`)),win:describeActions(this._actionGroup(`win`))};return JSON.stringify(e)}ActivateAction(e,t,n){this._guard(`ActivateAction`);let r=this._scope(e);activateAction(this._requireGroup(r,t),t,this._parseValue(n))}ChangeActionState(e,t,n){this._guard(`ChangeActionState`);let r=this._scope(e);changeActionState(this._requireGroup(r,t),t,this._parseValue(n))}PresentWindow(){this._app.get_active_window()?.present()}ResizeWindow(e,t){this._guard(`ResizeWindow`);let n=this._app.get_active_window();if(!n)throw Error(formatDbusErrorMessage(`unavailable`,`no active window to resize`));let r=Math.max(1,Math.round(e)),i=Math.max(1,Math.round(t));return n.is_maximized()&&n.unmaximize(),n.is_fullscreen()&&n.unfullscreen(),n.set_default_size(r,i),[r,i]}ListToplevels(){return JSON.stringify(listToplevels())}DumpTree(e,t){let n=this._resolveRootWidget(e);if(!n)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e||`active window`}'`));return JSON.stringify(dumpTree(n.widget,t>0?t:8,n.path))}GetProperty(e,t){let n=this._resolveRootWidget(e);if(!n)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e}'`));let r=getWidgetProperty(n.widget,t);if(r===void 0)throw Error(formatDbusErrorMessage(`not-found`,`widget has no property '${t}'`));return JSON.stringify(r)}GetFocused(){let e=this._app.get_active_window(),t=e?e.get_focus():null;return JSON.stringify(t?{path:pathOfWidget(t),name:t.get_name()||null,type:widgetType(t)}:null)}ActivateWidget(e){this._guard(`ActivateWidget`);let t=this._resolveRootWidget(e);if(!t)throw Error(formatDbusErrorMessage(`not-found`,`no widget at '${e}'`));return activateWidget(t.widget)}DumpGSettings(e){return JSON.stringify(dumpGSettings(e))}DumpCss(){return JSON.stringify(dumpCss())}SwapCss(e,t){return this._guard(`SwapCss`),swapCss(e,t)}_resolveRootWidget(e){if(!e||e===`window`||e===`active`){let e=this._app.get_active_window();return e?{widget:e,path:pathOfWidget(e)??`toplevel:0`}:null}let t=resolveWidgetPath(e);return t?{widget:t,path:e}:null}_isPaused(){return this._options.paused?.()??!1}_guard(e){let t=this._kinds.get(e);if(!t)throw Error(formatDbusErrorMessage(`internal`,`unclassified devtools method '${e}'`));if(t===`mutating`&&this._isPaused())throw Error(formatDbusErrorMessage(`paused`,`${e} rejected — external control is paused. Read-only methods keep working.`))}_scope(e){return e===`app`?`app`:`win`}_actionGroup(e){if(e===`app`)return this._app;if(this._options.winActionGroup)return this._options.winActionGroup;let t=this._app.get_active_window();return t instanceof Y.ApplicationWindow?t:null}_requireGroup(e,t){let n=this._actionGroup(e);if(!n)throw Error(formatDbusErrorMessage(`unavailable`,`no '${e}' action group`));if(!n.has_action(t))throw Error(formatDbusErrorMessage(`not-found`,`unknown action ${e}.${t}`));return n}_parseValue(e){if(!e||e===`null`)return null;try{return JSON.parse(e)}catch{throw Error(formatDbusErrorMessage(`invalid-params`,`value_json is not valid JSON: ${e}`))}}};const gt=new Set;function envEnabled(){let e=y.getenv(`GJSIFY_DEVTOOLS`);if(e==null)return!1;let t=e.toLowerCase();return t!==``&&t!==`0`&&t!==`false`}function envInstance(){let e=y.getenv(`GJSIFY_DEVTOOLS_INSTANCE`);return e&&e!==``?e:void 0}function installDevtools(e,t={}){if(!(t.enabled??envEnabled()))return null;let n=new DevtoolsService(e,{...t,instance:t.instance??envInstance()}),r=e.get_dbus_connection(),i=e.get_dbus_object_path();if(r&&i){let t=`${i}/devtools`;n.export(r,t),h.log(`[gjsify-devtools] exported ${pt} at ${t} (dest ${e.get_application_id()??`?`})`)}else h.error(`[gjsify-devtools] no session-bus connection yet — call installDevtools() from the GtkApplication "startup" handler`);return gt.add(n),n}const _t=[`AdwNavigationSplitView`,`GtkListBox`,`AdwOverlaySplitView`];function probeEnabled(){let e=y.getenv(`GJSIFY_STORYBOOK_PROBE`);if(e==null)return!1;let t=e.toLowerCase();return t!==``&&t!==`0`&&t!==`false`}function collectTypes(e,t){t.add(e.type);for(let n of e.children)collectTypes(n,t)}function installStorybookProbe(e,t,n={}){let r=n.requireChrome??_t,i=n.out??y.getenv(`GJSIFY_STORYBOOK_PROBE_OUT`)??void 0,a=n.timeoutMs??8e3,o=n.storyWidget??y.getenv(`GJSIFY_STORYBOOK_PROBE_STORY_WIDGET`)??void 0,s=t.controller.listStories(),c=[...new Set(s.map(e=>e.category))],l=n.story??y.getenv(`GJSIFY_STORYBOOK_PROBE_STORY`)??s[0]?.title,u=l?t.openStoryByTitle(l):!1,d=t.activeStory,f=new Set;collectTypes(dumpTree(t,60,`toplevel:0`),f);let p=r.filter(e=>!f.has(e)),m=new Set;d&&collectTypes(dumpTree(d,60,`story`),m);let g=m.size,ee=o?m.has(o):null,finish=t=>{let n=JSON.stringify(t);if(t.ok)h.log(`STORYBOOK PROBE: PASS ${n}`);else{h.error(`STORYBOOK PROBE: FAIL ${n}`);try{typeof process<`u`&&(process.exitCode=1)}catch{}}if(i)try{y.file_set_contents(i,JSON.stringify(t,null,2))}catch{}e.quit()},te=0;y.timeout_add(y.PRIORITY_DEFAULT,100,()=>{te+=100;let e=captureWidgetPng(t),n=t.get_width()>0&&t.get_height()>0;if(!e&&!(te>=a))return y.SOURCE_CONTINUE;let i=d?captureWidgetPng(d):null,f=s.length>=1&&c.length>=1&&p.length===0&&u&&d!=null&&g>1,h;return s.length<1?h=`no stories registered`:c.length<1?h=`no categories`:p.length>0?h=`chrome missing: ${p.join(`, `)}`:!u||d==null?h=`could not open story: ${l??`(none)`}`:g<=1&&(h=`opened story rendered an empty subtree`),f&&o&&!m.has(o)&&(f=!1,h=`story widget ${o} not found in the opened story subtree`),f&&n&&(!e||e.length===0)&&(f=!1,h=`window realized (${t.get_width()}x${t.get_height()}) but the GSK capture was empty`),finish({ok:f,reason:h,stories:s.length,categories:c,opened:u,activeStory:d?d.meta.title:null,requiredChrome:r,missingChrome:p,storySubtreeWidgets:g,storyWidgetPresent:ee,windowRealized:n,windowPngBytes:e?e.length:0,storyPngBytes:i?i.length:0}),y.SOURCE_REMOVE})}var Z=a,Q=o;function adwControlWidgetFactory(){return{text(e,t){let n=new Z.EntryRow({title:e});t&&n.set_tooltip_text(t);let r=null;return n.connect(`changed`,()=>r?.(n.get_text())),{node:n,get:()=>n.get_text(),set:e=>n.set_text(e),onChange:e=>{r=e}}},boolean(e,t){let n=new Z.SwitchRow({title:e,subtitle:t??``}),r=null;return n.connect(`notify::active`,()=>r?.(n.get_active())),{node:n,get:()=>n.get_active(),set:e=>n.set_active(e),onChange:e=>{r=e}}},number(e){let t=Z.SpinRow.new_with_range(e.min??0,e.max??100,e.step??1);t.set_title(e.label||e.name),e.description&&t.set_subtitle(e.description);let n=null;return t.connect(`changed`,()=>n?.(t.get_value())),{node:t,get:()=>t.get_value(),set:e=>t.set_value(e),onChange:e=>{n=e}}},range(e){return buildRangeWidget(e)},select(e){return buildSelectWidget(e)},color(e,t){return buildColorWidget(e,t)}}}function buildRangeWidget(e){let t=e.min??0,n=e.max??100,r=e.step??1,i=typeof e.min==`number`?e.min:0,a=Number.isInteger(r)&&Number.isInteger(i),o=new Y.Adjustment({lower:t,upper:n,step_increment:r,value:i});o.step_increment=r;let s=new Y.ListBoxRow({selectable:!1,activatable:!1});s.add_css_class(`story-range-row`);let c=new Y.Box({orientation:Y.Orientation.VERTICAL,spacing:6,margin_top:12,margin_bottom:12,margin_start:12,margin_end:12}),l=new Y.Box({orientation:Y.Orientation.HORIZONTAL,spacing:12}),u=new Y.Label({label:e.label||e.name,halign:Y.Align.START,hexpand:!0,ellipsize:3});u.add_css_class(`heading`);let formatValue=e=>a?String(Math.round(e)):e.toFixed(2),d=new Y.Label({label:formatValue(i),halign:Y.Align.END});if(d.add_css_class(`numeric`),d.add_css_class(`dim-label`),l.append(u),l.append(d),c.append(l),e.description){let t=new Y.Label({label:e.description,halign:Y.Align.START,xalign:0,wrap:!0,max_width_chars:32});t.add_css_class(`caption`),t.add_css_class(`dim-label`),c.append(t)}let f=new Y.Scale({orientation:Y.Orientation.HORIZONTAL,adjustment:o,draw_value:!1,hexpand:!0}),p=null,m=!1;return f.connect(`value-changed`,()=>{if(m)return;let e=f.get_value();if(a){let t=Math.round(e);if(t!==e){f.set_value(t);return}e=t}d.set_label(formatValue(e)),p?.(e)}),c.append(f),s.set_child(c),{node:s,get:()=>f.get_value(),set:e=>{m=!0,f.set_value(e),m=!1,d.set_label(formatValue(e))},onChange:e=>{p=e}}}function buildSelectWidget(e){let t=e.options??[],n=Y.StringList.new(t.map(e=>e.label)),r=new Z.ComboRow({title:e.label||e.name,subtitle:e.description??``,model:n}),i=null;return r.connect(`notify::selected`,()=>i?.(r.get_selected())),{node:r,get:()=>r.get_selected(),set:e=>r.set_selected(e),onChange:e=>{i=e}}}function buildColorWidget(e,t){let n=new Z.ActionRow({title:e,subtitle:t??``}),r=new Y.ColorDialogButton({dialog:new Y.ColorDialog({title:e}),valign:Y.Align.CENTER});n.add_suffix(r),n.set_activatable_widget(r);let channel=e=>Math.round(Math.max(0,Math.min(1,e))*255).toString(16).padStart(2,`0`),rgbaToHex=e=>`#${channel(e.red)}${channel(e.green)}${channel(e.blue)}`,i=null,a=!1;return r.connect(`notify::rgba`,()=>{a||i?.(rgbaToHex(r.get_rgba()))}),{node:n,get:()=>rgbaToHex(r.get_rgba()),set:e=>{let t=new dt.RGBA;t.parse(e)&&(a=!0,r.set_rgba(t),a=!1)},onChange:e=>{i=e}}}var vt=class StorybookWindow extends Z.ApplicationWindow{static{Q.registerClass({GTypeName:`StorybookWindow`},StorybookWindow)}constructor(e){super(e),this._controlRows=[],this._rowByTitle=new Map,this._onSelect=null,this._suppressSelect=!1,this.set_default_size(1200,800),this.set_size_request(360,320),this.set_title(`Storybook`),this._buildUI(),this._controller=new StorybookController(this,e=>this._buildControls(e)),this._sidebar_list.connect(`row-selected`,this._onRowSelected.bind(this)),this._show_controls_button.connect(`toggled`,this._onToggleControls.bind(this)),this._controls_split_view.set_show_sidebar(!0)}_onRowSelected(e,t){if(this._suppressSelect||!t)return;let n=t;n.storyWidget&&this._onSelect?.(n.storyWidget)}get controller(){return this._controller}_buildControls(e){let t=e.meta.controls;if(!Array.isArray(t))return[];let n=adwControlWidgetFactory(),r=[];for(let i of t){if(!i?.name||!i?.type){h.warn(`Invalid control configuration:`,i);continue}let t=bindControl(e,i,n);t&&r.push(t)}return r}_buildUI(){this._sidebar_list=new Y.ListBox({selection_mode:Y.SelectionMode.SINGLE}),this._sidebar_list.add_css_class(`navigation-sidebar`);let e=new Y.ScrolledWindow({hexpand:!0,vexpand:!0,child:this._sidebar_list}),t=new Z.HeaderBar({title_widget:new Z.WindowTitle({title:`Stories`}),show_end_title_buttons:!1}),n=new Z.ToolbarView({content:e,top_bar_style:Z.ToolbarStyle.FLAT});n.add_top_bar(t);let r=new Z.NavigationPage({title:`Stories`,tag:`stories`,child:n});this._content_area=new Z.Bin({hexpand:!0,vexpand:!0});let i=new Y.ScrolledWindow({hexpand:!0,vexpand:!0,child:this._content_area});this._control_panel=new Z.PreferencesGroup({title:`Controls`});let a=new Z.PreferencesPage;a.add(this._control_panel);let o=new Y.ScrolledWindow({vexpand:!0,child:a});this._controls_split_view=new Z.OverlaySplitView({show_sidebar:!0,sidebar_position:Y.PackType.END,min_sidebar_width:280,max_sidebar_width:360,content:i,sidebar:o,css_classes:[`storybook-controls`]}),this._preview_title=new Z.WindowTitle({title:`Preview`}),this._show_controls_button=new Y.ToggleButton({icon_name:`sidebar-show-right-symbolic`,tooltip_text:`Toggle Controls`,active:!0});let s=new Z.HeaderBar({title_widget:this._preview_title});s.pack_end(this._show_controls_button);let c=new Z.ToolbarView({content:this._controls_split_view,top_bar_style:Z.ToolbarStyle.FLAT});c.add_top_bar(s);let l=new Z.NavigationPage({title:`Preview`,tag:`preview`,child:c});this._main_split_view=new Z.NavigationSplitView({min_sidebar_width:220,max_sidebar_width:320,sidebar:r,content:l}),this.set_content(this._main_split_view);let u=Z.BreakpointCondition.parse(`max-width: 720sp`);if(u){let e=new Z.Breakpoint({condition:u});e.connect(`apply`,()=>{this._main_split_view.collapsed=!0,this._controls_split_view.collapsed=!0}),e.connect(`unapply`,()=>{this._main_split_view.collapsed=!1,this._controls_split_view.collapsed=!1}),this.add_breakpoint(e)}}_onToggleControls(e){this._controls_split_view.set_show_sidebar(e.get_active())}populateSidebar(e){this._controller.mount(e,!0)}renderSidebar(e,t){this._onSelect=t,this._suppressSelect=!0,this._clearSidebar(),this._rowByTitle.clear();for(let t of e){this._addCategoryToSidebar(t.category);for(let{instance:e,name:n}of t.stories)this._addStoryToSidebar(e,n)}this._suppressSelect=!1}markSelected(e){let t=this._rowByTitle.get(e);t&&this._sidebar_list.get_selected_row()!==t&&(this._suppressSelect=!0,this._sidebar_list.select_row(t),this._suppressSelect=!1)}setPreviewTitle(e){this._preview_title.set_title(e)}showPreview(e){this._content_area.set_child(e),this._main_split_view.get_collapsed()&&this._main_split_view.set_show_content(!0)}renderControls(e){this._clearControlPanel();for(let t of e){let e=t.view;this._control_panel.add(e),this._controlRows.push(e)}this._show_controls_button.set_active(!0)}_clearSidebar(){let e=this._sidebar_list.get_first_child();for(;e;){let t=e.get_next_sibling();e.unparent(),e=t}}_addCategoryToSidebar(e){let t=new Y.ListBoxRow({selectable:!1}),n=new Y.Label({label:e,halign:Y.Align.START,margin_top:10,margin_bottom:4,margin_start:12,margin_end:12});n.add_css_class(`heading`),n.add_css_class(`dim-label`),t.set_child(n),this._sidebar_list.append(t)}_addStoryToSidebar(e,t){let n=new Y.ListBoxRow,r=new Y.Label({label:t||`Unnamed Story`,halign:Y.Align.START,margin_start:20,margin_top:6,margin_bottom:6});n.set_child(r),this._sidebar_list.append(n),n.storyWidget=e,this._rowByTitle.set(e.meta.title,n)}_clearControlPanel(){for(let e of this._controlRows)this._control_panel.remove(e);this._controlRows=[]}get activeStory(){return this._controller.activeStory}openStoryByTitle(e){return this._controller.openStoryByTitle(e)}setActiveArg(e,t){return this._controller.setActiveArg(e,t)}};Q.type_ensure(vt.$gtype);var yt=class StorybookApplication extends Z.Application{static{Q.registerClass({GTypeName:`StorybookApplication`},StorybookApplication)}constructor(e){super({application_id:e.applicationId,flags:X.ApplicationFlags.DEFAULT_FLAGS}),this._window=null,this._options=e,this.connect(`startup`,()=>this._initStyles()),this.connect(`activate`,()=>this._onActivate())}_initStyles(){let e=new Y.CssProvider;e.load_from_string(`
69
69
  /* Range-control card in the controls sidebar — keeps the label + description
70
70
  from being squashed into a single column when the sidebar is narrow. */
71
71
  .story-range-row {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/example-gtk-adwaita-storybook",
3
- "version": "0.26.1",
3
+ "version": "0.27.0",
4
4
  "description": "Interactive component browser for Libadwaita widgets — a native Adwaita storybook built on @gjsify/storybook, debuggable over DBus/MCP via @gjsify/devtools",
5
5
  "type": "module",
6
6
  "main": "dist/gjs.js",
@@ -14,14 +14,14 @@
14
14
  "./package.json": "./package.json"
15
15
  },
16
16
  "scripts": {
17
- "clear": "rm -rf dist tsconfig.tsbuildinfo node_modules/.cache/gjsify-storybook",
17
+ "clear": "gjsify clear dist tsconfig.tsbuildinfo node_modules/.cache/gjsify-storybook",
18
18
  "check": "gjsify tsc --noEmit",
19
19
  "start": "gjsify storybook",
20
20
  "start:watch": "gjsify storybook --watch",
21
21
  "start:browser": "http-server dist -o -c-1",
22
22
  "build": "gjsify storybook --build-only --out dist/gjs.js",
23
23
  "build:browser": "gjsify build src/browser/main.ts --app browser --outfile dist/browser-main.js",
24
- "build:assets": "mkdir -p dist && cp -f src/browser/index.html dist/index.html",
24
+ "build:assets": "gjsify copy src/browser/index.html dist/",
25
25
  "build:web": "gjsify run build:browser && gjsify run build:assets",
26
26
  "debug": "gjsify debug --profile storybook"
27
27
  },
@@ -47,11 +47,11 @@
47
47
  "@girs/glib-2.0": "^4.1.0",
48
48
  "@girs/gobject-2.0": "^4.1.0",
49
49
  "@girs/gtk-4.0": "^4.1.0",
50
- "@gjsify/adwaita-web": "^0.26.1",
51
- "@gjsify/cli": "^0.26.1",
50
+ "@gjsify/adwaita-web": "^0.27.0",
51
+ "@gjsify/cli": "^0.27.0",
52
52
  "@gjsify/node-gi": "file:../../../packages/node-gi/node-gi",
53
- "@gjsify/storybook": "^0.26.1",
54
- "@gjsify/adwaita-storybook": "^0.26.1",
53
+ "@gjsify/storybook": "^0.27.0",
54
+ "@gjsify/adwaita-storybook": "^0.27.0",
55
55
  "@types/node": "^25.9.2",
56
56
  "typescript": "^6.0.3"
57
57
  },
@@ -22,8 +22,7 @@ export class ClampWebStory extends StoryElement {
22
22
  inner.style.width = '100%';
23
23
  inner.style.boxSizing = 'border-box';
24
24
  inner.style.padding = '18px';
25
- inner.textContent =
26
- 'This content is clamped — it stops growing past the maximum size and stays centred.';
25
+ inner.textContent = 'This content is clamped — it stops growing past the maximum size and stays centred.';
27
26
 
28
27
  this._clamp = document.createElement('adw-clamp');
29
28
  this._clamp.append(inner);
@@ -35,10 +35,7 @@ export class ToolbarViewWebStory extends StoryElement {
35
35
  const content = document.createElement('adw-status-page');
36
36
  content.setAttribute('icon', 'folder');
37
37
  content.setAttribute('title', 'Your library');
38
- content.setAttribute(
39
- 'description',
40
- 'Content sits between the toolbars and scrolls independently of them.',
41
- );
38
+ content.setAttribute('description', 'Content sits between the toolbars and scrolls independently of them.');
42
39
  view.appendChild(content);
43
40
 
44
41
  // Bottom action bar — flat start buttons, a centered label and an end button
@@ -27,10 +27,7 @@ export class NavigationViewWebStory extends StoryElement {
27
27
  this._view = document.createElement('adw-navigation-view') as AdwNavigationViewEl;
28
28
  this._view.style.width = '480px';
29
29
  this._view.style.height = '340px';
30
- this._view.setAttribute(
31
- 'animate-transitions',
32
- (this.args.animateTransitions as boolean) ? 'true' : 'false',
33
- );
30
+ this._view.setAttribute('animate-transitions', (this.args.animateTransitions as boolean) ? 'true' : 'false');
34
31
 
35
32
  // --- Detail page: a status page describing the contact. ---
36
33
  this._detailTitle = document.createElement('adw-window-title');
@@ -89,10 +86,7 @@ export class NavigationViewWebStory extends StoryElement {
89
86
 
90
87
  updateArgs(_args: StoryArgs): void {
91
88
  if (!this._view) return;
92
- this._view.setAttribute(
93
- 'animate-transitions',
94
- (this.args.animateTransitions as boolean) ? 'true' : 'false',
95
- );
89
+ this._view.setAttribute('animate-transitions', (this.args.animateTransitions as boolean) ? 'true' : 'false');
96
90
  this._rootTitle?.setAttribute('title', this.args.rootTitle as string);
97
91
  const detailTitle = this.args.detailTitle as string;
98
92
  this._detailTitle?.setAttribute('title', detailTitle);
@@ -7,7 +7,12 @@ export const aboutDialogMeta: StoryMeta = {
7
7
  description:
8
8
  'Adw.AboutDialog — the standard Adwaita about window with application name, version, credits and license.',
9
9
  controls: [
10
- { name: 'applicationName', label: 'Application name', type: ControlType.TEXT, defaultValue: 'Adwaita Storybook' },
10
+ {
11
+ name: 'applicationName',
12
+ label: 'Application name',
13
+ type: ControlType.TEXT,
14
+ defaultValue: 'Adwaita Storybook',
15
+ },
11
16
  { name: 'version', label: 'Version', type: ControlType.TEXT, defaultValue: '0.11.0' },
12
17
  ],
13
18
  };
@@ -4,8 +4,7 @@ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
4
 
5
5
  export const preferencesDialogMeta: StoryMeta = {
6
6
  title: 'Feedback/Preferences Dialog',
7
- description:
8
- 'Adw.PreferencesDialog — a preferences window with a page, a group and a handful of boxed-list rows.',
7
+ description: 'Adw.PreferencesDialog — a preferences window with a page, a group and a handful of boxed-list rows.',
9
8
  controls: [
10
9
  { name: 'pageTitle', label: 'Page title', type: ControlType.TEXT, defaultValue: 'General' },
11
10
  { name: 'groupTitle', label: 'Group title', type: ControlType.TEXT, defaultValue: 'Appearance' },
@@ -4,8 +4,7 @@ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
4
 
5
5
  export const wrapBoxMeta: StoryMeta = {
6
6
  title: 'Layout/Wrap Box',
7
- description:
8
- 'Adw.WrapBox flows its children horizontally and wraps them onto new lines when they run out of room.',
7
+ description: 'Adw.WrapBox flows its children horizontally and wraps them onto new lines when they run out of room.',
9
8
  controls: [
10
9
  {
11
10
  name: 'childSpacing',
@@ -4,8 +4,7 @@ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
4
 
5
5
  export const overlaySplitViewMeta: StoryMeta = {
6
6
  title: 'Navigation/Overlay Split View',
7
- description:
8
- 'Adw.OverlaySplitView — a sidebar shown beside the content, or overlaid on top of it when collapsed.',
7
+ description: 'Adw.OverlaySplitView — a sidebar shown beside the content, or overlaid on top of it when collapsed.',
9
8
  controls: [
10
9
  { name: 'showSidebar', label: 'Show sidebar', type: ControlType.BOOLEAN, defaultValue: true },
11
10
  { name: 'collapsed', label: 'Collapsed', type: ControlType.BOOLEAN, defaultValue: false },
@@ -4,8 +4,7 @@ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
4
 
5
5
  export const buttonRowMeta: StoryMeta = {
6
6
  title: 'Boxed Lists/Button Row',
7
- description:
8
- 'Adw.ButtonRow — a full-width row that acts as a button, with an optional icon and style class.',
7
+ description: 'Adw.ButtonRow — a full-width row that acts as a button, with an optional icon and style class.',
9
8
  controls: [
10
9
  { name: 'title', label: 'Title', type: ControlType.TEXT, defaultValue: 'Add account' },
11
10
  {
@@ -4,8 +4,7 @@ import { ControlType, type StoryMeta } from '@gjsify/stories';
4
4
 
5
5
  export const expanderRowMeta: StoryMeta = {
6
6
  title: 'Boxed Lists/Expander Row',
7
- description:
8
- 'Adw.ExpanderRow — a preferences row that discloses nested rows and can carry an enable switch.',
7
+ description: 'Adw.ExpanderRow — a preferences row that discloses nested rows and can carry an enable switch.',
9
8
  controls: [
10
9
  { name: 'title', label: 'Title', type: ControlType.TEXT, defaultValue: 'Proxy settings' },
11
10
  {