@gjsify/storybook-nativescript 0.36.0 → 0.38.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/lib/esm/app.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{createControlRow as e}from"./controls.js";import{StorybookController as t}from"@gjsify/storybook-core";import{AdwBreakpoint as n,AdwHeaderBar as r,AdwImageButton as i,AdwNavigationSplitView as a,AdwOverlaySplitView as o,AdwPreferencesGroup as s,AdwToolbarView as c,AdwWindowTitle as l,addBreakpoints as u,attachRowPressFeedback as d,setAdwaitaColorScheme as f}from"@gjsify/adwaita-nativescript";import{goPreviousSymbolic as p,sidebarShowRightSymbolic as m}from"@gjsify/adwaita-icons/actions";import{Label as h,Screen as g,ScrollView as _,StackLayout as v}from"@nativescript/core";var StorybookNativeApp=class{_controller=new t(this,e=>this._buildControls(e));_options;root;_listColumn;_previewSlot;_previewTitle;_controlsGroup;_controlsSplit;_backButton;_rowByTitle=new Map;_collapsed=!0;_disposeBreakpoint=null;constructor(e){this._options=e,this.root=new a,this._collapsed=!this._isWideWidth(g.mainScreen?.widthDIPs??0),this.root.collapsed=this._collapsed,this.root.className=`sb-window`}_isWideWidth(e){return e>=720}mount(){return this._buildUI(),this._controller.mount(this._options.stories,this._options.openFirst!==!1),this._wireColorScheme(),this._wireBreakpoint(),this.root}_wireBreakpoint(){let e=new n(`max-width: 720sp`,{onApply:()=>this._applyLayoutMode(!0),onUnapply:()=>this._applyLayoutMode(!1)});this._disposeBreakpoint=u(this.root,[e])}_applyLayoutMode(e){e===this._collapsed&&this.root.collapsed===e||(this._collapsed=e,this.root.collapsed=e,this._controlsSplit.collapsed=e,this.root.showSidebarPane(),this._backButton.visibility=e?`visible`:`collapse`)}get activeStory(){return this._controller.activeStory}listStories(){return this._controller.listStories()}openStoryByTitle(e){return this._controller.openStoryByTitle(e)}getCurrentStory(){return this._controller.getCurrentStory()}setActiveArg(e,t){return this._controller.setActiveArg(e,t)}get controller(){return this._controller}_wireColorScheme(){let e=this._options.application;e?.systemAppearance&&f(e.systemAppearance()===`dark`?`dark`:`light`)}renderSidebar(e,t){this._listColumn.removeChildren(),this._rowByTitle.clear();for(let{category:n,stories:r}of e){let e=new h;e.text=n,e.className=`sb-category`,this._listColumn.addChild(e);for(let{instance:e,name:n}of r){let r=new v;r.orientation=`vertical`,r.className=`sb-story-row`;let i=new h;i.text=n,i.className=`sb-story-row-label`,r.addChild(i),d(r),r.addEventListener(`tap`,()=>{t(e),this._collapsed&&this.root.hideSidebarPane()}),this._listColumn.addChild(r),this._rowByTitle.set(e.meta.title,r)}}}markSelected(e){for(let[t,n]of this._rowByTitle)n.className=t===e?`sb-story-row sb-story-row-selected`:`sb-story-row`}setPreviewTitle(e){this._previewTitle.title=e}showPreview(e){this._previewSlot.removeChildren(),this._previewSlot.addChild(e.view)}renderControls(e){this._controlsGroup.listbox.removeChildren();for(let t of e)this._controlsGroup.addRow(t.view)}_buildControls(t){let n=[],r=t.meta.controls;if(Array.isArray(r))for(let i of r){if(!i?.name||!i?.type){console.warn(`Invalid control configuration:`,i);continue}let r=e(t,i);r&&n.push(r)}return n}_buildUI(){let e=new c;e.className=`${e.className} sb-sidebar-pane`.trim();let t=new r;t.className=`${t.className} sb-sidebar-header`.trim();let n=new l;n.title=this._options.title??`Stories`,t.setTitleWidget(n),e.addTopBar(t),this._listColumn=new v,this._listColumn.orientation=`vertical`,this._listColumn.className=`sb-sidebar-list`;let a=new _;a.className=`sb-sidebar-scroll`,a.content=this._listColumn,e.setContent(a),this.root.setSidebar(e);let u=new c;u.className=`${u.className} sb-content-pane`.trim();let d=new r;d.className=`${d.className} sb-detail-header`.trim();let f=new i;f.icon=p,f.className=`${f.className} sb-back-button`.trim(),f.addEventListener(`tap`,()=>this.root.showSidebarPane()),f.visibility=this._collapsed?`visible`:`collapse`,this._backButton=f,d.packStart(f),this._previewTitle=new l,this._previewTitle.title=`Preview`,d.setTitleWidget(this._previewTitle);let h=new i;h.icon=m,h.className=`${h.className} sb-controls-toggle`.trim(),h.addEventListener(`tap`,()=>{this._controlsSplit.showSidebar=!this._controlsSplit.showSidebar}),d.packEnd(h),u.addTopBar(d),this._controlsSplit=new o,this._controlsSplit.collapsed=this._collapsed,this._controlsSplit.sidebarPosition=`end`,this._controlsSplit.sidebarWidth=320,this._controlsSplit.className=`${this._controlsSplit.className} sb-controls-split`.trim(),this._previewSlot=new v,this._previewSlot.orientation=`vertical`,this._previewSlot.className=`sb-preview-pane`;let g=new _;g.className=`sb-preview-scroll`,g.content=this._previewSlot,this._controlsSplit.setContent(g),this._controlsGroup=new s,this._controlsGroup.title=`Controls`,this._controlsGroup.className=`${this._controlsGroup.className} sb-controls-group`.trim();let y=new _;y.className=`sb-controls-scroll`,y.content=this._controlsGroup,this._controlsSplit.setSidebar(y),u.setContent(this._controlsSplit),this.root.setContent(u),this.root.showSidebarPane()}};function runStorybook(e){let t=new StorybookNativeApp(e);return t.mount(),t}export{StorybookNativeApp,runStorybook};
1
+ import"./_virtual/_rolldown/runtime.js";import{StorybookNsAppearance as e,buildAppearanceDialog as t,installAppearanceDialog as n}from"./appearance.js";import{createControlRow as r}from"./controls.js";import{StorybookController as i}from"@gjsify/storybook-core";import{AdwBreakpoint as a,AdwHeaderBar as o,AdwImageButton as s,AdwNavigationSplitView as c,AdwOverlaySplitView as l,AdwPreferencesGroup as u,AdwToolbarView as d,AdwWindowTitle as f,addBreakpoints as p,attachRowPressFeedback as m,setAdwaitaColorScheme as h}from"@gjsify/adwaita-nativescript";import{colorSelectSymbolic as g,goPreviousSymbolic as _,sidebarShowRightSymbolic as v}from"@gjsify/adwaita-icons/actions";import{Label as y,Screen as b,ScrollView as x,StackLayout as S}from"@nativescript/core";var StorybookNativeApp=class{_controller=new i(this,e=>this._buildControls(e));_options;root;_listColumn;_previewSlot;_previewTitle;_controlsGroup;_controlsSplit;_backButton;_appearance=new e;_appearanceDialog=null;_rowByTitle=new Map;_collapsed=!0;_disposeBreakpoint=null;constructor(e){this._options=e,this.root=new c,this._collapsed=!this._isWideWidth(b.mainScreen?.widthDIPs??0),this.root.collapsed=this._collapsed,this.root.className=`sb-window`}_isWideWidth(e){return e>=720}mount(){return this._buildUI(),this._controller.mount(this._options.stories,this._options.openFirst!==!1),this._wireColorScheme(),this._wireBreakpoint(),this._appearanceDialog||(this._appearanceDialog=t(this._appearance),n(this.root,this._appearanceDialog)),this.root}_presentAppearance(){this._appearanceDialog?.present()}_wireBreakpoint(){let e=new a(`max-width: 720sp`,{onApply:()=>this._applyLayoutMode(!0),onUnapply:()=>this._applyLayoutMode(!1)});this._disposeBreakpoint=p(this.root,[e])}_applyLayoutMode(e){e===this._collapsed&&this.root.collapsed===e||(this._collapsed=e,this.root.collapsed=e,this._controlsSplit.collapsed=e,this.root.showSidebarPane(),this._backButton.visibility=e?`visible`:`collapse`)}get activeStory(){return this._controller.activeStory}listStories(){return this._controller.listStories()}openStoryByTitle(e){return this._controller.openStoryByTitle(e)}getCurrentStory(){return this._controller.getCurrentStory()}setActiveArg(e,t){return this._controller.setActiveArg(e,t)}get controller(){return this._controller}_wireColorScheme(){let e=this._options.application;e?.systemAppearance&&h(e.systemAppearance()===`dark`?`dark`:`light`)}renderSidebar(e,t){this._listColumn.removeChildren(),this._rowByTitle.clear();for(let{category:n,stories:r}of e){let e=new y;e.text=n,e.className=`sb-category`,this._listColumn.addChild(e);for(let{instance:e,name:n}of r){let r=new S;r.orientation=`vertical`,r.className=`sb-story-row`;let i=new y;i.text=n,i.className=`sb-story-row-label`,r.addChild(i),m(r),r.addEventListener(`tap`,()=>{t(e),this._collapsed&&this.root.hideSidebarPane()}),this._listColumn.addChild(r),this._rowByTitle.set(e.meta.title,r)}}}markSelected(e){for(let[t,n]of this._rowByTitle)n.className=t===e?`sb-story-row sb-story-row-selected`:`sb-story-row`}setPreviewTitle(e){this._previewTitle.title=e}showPreview(e){this._previewSlot.removeChildren(),this._previewSlot.addChild(e.view)}renderControls(e){this._controlsGroup.listbox.removeChildren();for(let t of e)this._controlsGroup.addRow(t.view)}_buildControls(e){let t=[],n=e.meta.controls;if(Array.isArray(n))for(let i of n){if(!i?.name||!i?.type){console.warn(`Invalid control configuration:`,i);continue}let n=r(e,i);n&&t.push(n)}return t}_buildUI(){let e=new d;e.className=`${e.className} sb-sidebar-pane`.trim();let t=new o;t.className=`${t.className} sb-sidebar-header`.trim();let n=new f;n.title=this._options.title??`Stories`,t.setTitleWidget(n),e.addTopBar(t),this._listColumn=new S,this._listColumn.orientation=`vertical`,this._listColumn.className=`sb-sidebar-list`;let r=new x;r.className=`sb-sidebar-scroll`,r.content=this._listColumn,e.setContent(r),this.root.setSidebar(e);let i=new d;i.className=`${i.className} sb-content-pane`.trim();let a=new o;a.className=`${a.className} sb-detail-header`.trim();let c=new s;c.icon=_,c.className=`${c.className} sb-back-button`.trim(),c.addEventListener(`tap`,()=>this.root.showSidebarPane()),c.visibility=this._collapsed?`visible`:`collapse`,this._backButton=c,a.packStart(c),this._previewTitle=new f,this._previewTitle.title=`Preview`,a.setTitleWidget(this._previewTitle);let p=new s;p.icon=v,p.className=`${p.className} sb-controls-toggle`.trim(),p.addEventListener(`tap`,()=>{this._controlsSplit.showSidebar=!this._controlsSplit.showSidebar});let m=new s;m.icon=g,m.className=`${m.className} sb-appearance-button`.trim(),m.addEventListener(`tap`,()=>this._presentAppearance()),a.packEnd(m),a.packEnd(p),i.addTopBar(a),this._controlsSplit=new l,this._controlsSplit.collapsed=this._collapsed,this._controlsSplit.sidebarPosition=`end`,this._controlsSplit.sidebarWidth=320,this._controlsSplit.className=`${this._controlsSplit.className} sb-controls-split`.trim(),this._previewSlot=new S,this._previewSlot.orientation=`vertical`,this._previewSlot.className=`sb-preview-pane`;let h=new x;h.className=`sb-preview-scroll`,h.content=this._previewSlot,this._controlsSplit.setContent(h),this._controlsGroup=new u,this._controlsGroup.title=`Controls`,this._controlsGroup.className=`${this._controlsGroup.className} sb-controls-group`.trim();let y=new x;y.className=`sb-controls-scroll`,y.content=this._controlsGroup,this._controlsSplit.setSidebar(y),i.setContent(this._controlsSplit),this.root.setContent(i),this.root.showSidebarPane()}};function runStorybook(e){let t=new StorybookNativeApp(e);return t.mount(),t}export{StorybookNativeApp,runStorybook};
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{StorybookSettings as e}from"@gjsify/storybook-core";import{AdwPreferencesDialog as t,AdwPreferencesGroup as n,AdwPreferencesPage as r,AdwSwitchRow as i,NOTIFY_ACTIVE as a,applyAdwaitaNsAccent as o,clearAdwaitaNsAccent as s}from"@gjsify/adwaita-nativescript";import{GridLayout as c,WrapLayout as l}from"@nativescript/core";import{ADW_ACCENT_COLOR_NAMES as u,adwaitaAccentBgColor as d,adwaitaColorScheme as f}from"@gjsify/adwaita-core";const p=`sb-swatch`;var StorybookNsAppearance=class{settings;constructor(){this.settings=new e(()=>f()===`dark`),this.settings.subscribe(()=>this._apply()),this._apply()}_apply(){let e=this.settings.resolvedAccent;e?o(e):s()}};function buildSwatch(e){let t=new c;return t.className=p,t.backgroundColor=d(e),t}function buildAppearanceDialog(e){let o=e.settings,s=new t;s.title=`Appearance`;let c=new r,d=new n;d.title=`ACCENT COLOUR`;let f=new i;f.title=`Use a custom accent colour`,f.subtitle=`Off keeps the default Adwaita blue`,f.active=o.accentMode===`custom`,d.addRow(f);let m=new l;m.orientation=`horizontal`,m.className=`sb-swatch-row`;let h=new Map;for(let e of u){let t=buildSwatch(e);t.addEventListener(`tap`,()=>{o.accentMode===`custom`&&(o.accent=e)}),h.set(e,t),m.addChild(t)}d.addRow(m),c.addGroup(d),s.add(c);let sync=()=>{let e=o.accentMode===`custom`;f.active!==e&&(f.active=e),m.opacity=e?1:.4;for(let[e,t]of h)t.className=e===o.accent?`${p} selected`:p};return f.addEventListener(a,e=>{o.accentMode=e.active?`custom`:`system`}),o.subscribe(sync),sync(),s}function installAppearanceDialog(e,t){c.setColumn(t,0),c.setColumnSpan(t,3),c.setRow(t,0),c.setRowSpan(t,3),e.addChild(t)}export{StorybookNsAppearance,buildAppearanceDialog,installAppearanceDialog};
@@ -23,9 +23,8 @@ export interface StorybookNativeOptions {
23
23
  /** Auto-select the first story on mount (default true). */
24
24
  openFirst?: boolean;
25
25
  /**
26
- * The NativeScript `Application` (optional). When given, the storybook follows
27
- * the OS color scheme: NS already flips the `ns-dark` CSS class on the root view
28
- * (so backgrounds/text follow the system theme), and this keeps the symbolic
26
+ * The NativeScript `Application`. When given, the storybook follows the OS color
27
+ * scheme: NS already flips `ns-dark` on the root view, and this keeps the symbolic
29
28
  * ICON bitmaps recoloured to match (they are pre-coloured, outside CSS's reach).
30
29
  */
31
30
  application?: NsAppearanceSource;
@@ -44,6 +43,9 @@ export declare class StorybookNativeApp implements StorybookView<StoryView> {
44
43
  private _controlsSplit;
45
44
  /** Back button (visible only in collapsed/phone layout). */
46
45
  private _backButton;
46
+ /** Accent for the whole storybook, not for one story. */
47
+ private _appearance;
48
+ private _appearanceDialog;
47
49
  private _rowByTitle;
48
50
  /** Current layout mode — true = collapsed (phone), false = three-pane (wide). */
49
51
  private _collapsed;
@@ -54,17 +56,13 @@ export declare class StorybookNativeApp implements StorybookView<StoryView> {
54
56
  private _isWideWidth;
55
57
  /** Build the UI, instantiate stories, and select the first one. Returns the root view. */
56
58
  mount(): View;
57
- /**
58
- * Collapse to phone layout below 720sp, expand to three side-by-side panes at
59
- * or above it — the GTK storybook's `Adw.Breakpoint`, driven by the root
60
- * view's post-layout width. Seeds immediately so the first paint is correct.
61
- */
59
+ private _presentAppearance;
60
+ /** Driven by the root view's post-layout width; seeds immediately so the first paint is correct. */
62
61
  private _wireBreakpoint;
63
62
  /**
64
63
  * Switch between collapsed (phone) and expanded (wide) chrome. Collapsed: the
65
- * master/detail nav swaps panes, the controls are a tap-to-reveal overlay, and
66
- * the back button shows. Expanded: sidebar + preview + controls sit side by
67
- * side and the back button hides (no navigation needed).
64
+ * master/detail nav swaps panes, the controls are a tap-to-reveal overlay, and the
65
+ * back button shows. Expanded: three panes side by side, no back button.
68
66
  */
69
67
  private _applyLayoutMode;
70
68
  /** The currently-displayed story, or null. */
@@ -84,17 +82,13 @@ export declare class StorybookNativeApp implements StorybookView<StoryView> {
84
82
  /** The underlying controller (e.g. to build a devtools extension over it). */
85
83
  get controller(): StorybookController<StoryView>;
86
84
  /**
87
- * Match the OS color scheme at mount. NS applies the `ns-dark` CSS class to the
88
- * root BEFORE the first style pass (so backgrounds/text/borders follow the
89
- * system theme via `autoSystemAppearanceChanged`); the pre-coloured symbolic
90
- * ICON bitmaps are outside CSS's reach, so this sets the global icon scheme to
91
- * the matching fg (dark icons on light, near-white on dark). No-op without an
92
- * `application` option.
85
+ * Match the OS color scheme at mount. NS applies `ns-dark` before the first style
86
+ * pass; the pre-coloured symbolic ICON bitmaps are outside CSS's reach, so this sets
87
+ * the global icon scheme to the matching fg.
93
88
  *
94
- * Seed-only (mount-time): a clean launch is the dependable path because NS
95
- * 9.1-alpha does not reliably RE-APPLY the `.ns-dark` overrides at runtime, so a
96
- * live OS theme switch is picked up on the next launch rather than risking the
97
- * icons getting ahead of a CSS that didn't flip.
89
+ * SEED ONLY, deliberately: NS 9.1-alpha does not reliably RE-APPLY the `.ns-dark`
90
+ * overrides at runtime, so a live OS theme switch is picked up on the next launch
91
+ * rather than risking icons that are ahead of a CSS which did not flip.
98
92
  */
99
93
  private _wireColorScheme;
100
94
  renderSidebar(groups: Array<CategoryGroup<StoryView>>, onSelect: (instance: StoryView) => void): void;
@@ -0,0 +1,28 @@
1
+ import { AdwPreferencesDialog } from '@gjsify/adwaita-nativescript';
2
+ import { StorybookSettings } from '@gjsify/storybook-core';
3
+ import { GridLayout } from '@nativescript/core';
4
+ /** Owns the NativeScript side of {@link StorybookSettings}. */
5
+ export declare class StorybookNsAppearance {
6
+ readonly settings: StorybookSettings;
7
+ constructor();
8
+ private _apply;
9
+ }
10
+ /**
11
+ * The appearance dialog: the accent palette behind a switch.
12
+ *
13
+ * Returned unpresented; the caller adds it to a host cell and calls `present()`, the
14
+ * way every NS dialog in this tree is used.
15
+ */
16
+ export declare function buildAppearanceDialog(appearance: StorybookNsAppearance): AdwPreferencesDialog;
17
+ /**
18
+ * Put `dialog` into `root` so its scrim covers every pane.
19
+ *
20
+ * Added as a CHILD of the split view rather than by wrapping it: the split view is
21
+ * itself a `GridLayout`, and wrapping re-parents it — which crashes with
22
+ * "View already has a parent" the second time `mount()` runs, and `mount()` runs on
23
+ * every `onNavigatingTo`. Spanning the columns is what makes the scrim cover the
24
+ * content pane too; a child with no column lands in column 0, i.e. over the sidebar
25
+ * alone. The span is deliberately larger than the declared column count, which NS
26
+ * clamps — the count differs between the collapsed and expanded layouts.
27
+ */
28
+ export declare function installAppearanceDialog(root: GridLayout, dialog: AdwPreferencesDialog): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/storybook-nativescript",
3
- "version": "0.36.0",
3
+ "version": "0.38.0",
4
4
  "description": "NativeScript renderer for the @gjsify/stories contract — the NS counterpart of @gjsify/storybook (GTK) and @gjsify/adwaita-storybook (browser), built on @gjsify/adwaita-nativescript real native widgets",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -39,11 +39,12 @@
39
39
  "gnome"
40
40
  ],
41
41
  "dependencies": {
42
- "@gjsify/adwaita-icons": "^0.36.0",
43
- "@gjsify/adwaita-nativescript": "^0.36.0",
44
- "@gjsify/devtools-nativescript": "^0.36.0",
45
- "@gjsify/stories": "^0.36.0",
46
- "@gjsify/storybook-core": "^0.36.0"
42
+ "@gjsify/adwaita-icons": "^0.38.0",
43
+ "@gjsify/adwaita-core": "^0.38.0",
44
+ "@gjsify/adwaita-nativescript": "^0.38.0",
45
+ "@gjsify/devtools-nativescript": "^0.38.0",
46
+ "@gjsify/stories": "^0.38.0",
47
+ "@gjsify/storybook-core": "^0.38.0"
47
48
  },
48
49
  "peerDependencies": {
49
50
  "@nativescript/core": "*"
@@ -54,8 +55,8 @@
54
55
  }
55
56
  },
56
57
  "devDependencies": {
57
- "@gjsify/cli": "^0.36.0",
58
- "@gjsify/unit": "^0.36.0",
58
+ "@gjsify/cli": "^0.38.0",
59
+ "@gjsify/unit": "^0.38.0",
59
60
  "@nativescript/types": "~9.0.0",
60
61
  "@types/node": "^25.9.2",
61
62
  "typescript": "^6.0.3"
@@ -220,3 +220,34 @@
220
220
  .ns-dark .story-stage {
221
221
  border-color: rgba(255, 255, 255, 0.28);
222
222
  }
223
+
224
+ /* ===== Appearance dialog swatches =====
225
+ * Round accent swatches. NS has no radio input and no `:checked`, so selection is a
226
+ * class the dialog maintains and the ring is a border — `border-radius`,
227
+ * `border-width` and `opacity` are all in the NS CSS subset, which is what a circle
228
+ * with a ring needs. The unavailable state is the ROW's opacity, since the subset has
229
+ * no `:disabled` either. */
230
+ .sb-swatch-row {
231
+ margin: 12;
232
+ horizontal-align: center;
233
+ }
234
+
235
+ /* The ring is ALWAYS 3 wide and only its colour changes. Toggling `border-width`
236
+ * between 0 and 3 changes the box geometry, and NS then renders the rounded fill
237
+ * clipped — it looked like a circle with a bite taken out of it. */
238
+ .sb-swatch {
239
+ width: 28;
240
+ height: 28;
241
+ border-radius: 14;
242
+ margin: 4;
243
+ border-width: 3;
244
+ border-color: transparent;
245
+ }
246
+
247
+ .sb-swatch.selected {
248
+ border-color: rgba(0, 0, 0, 0.5);
249
+ }
250
+
251
+ .ns-dark .sb-swatch.selected {
252
+ border-color: #ffffff;
253
+ }