@gjsify/stories 0.7.5
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/README.md +38 -0
- package/lib/esm/_virtual/_rolldown/runtime.js +1 -0
- package/lib/esm/args.js +1 -0
- package/lib/esm/index.js +1 -0
- package/lib/esm/types.js +1 -0
- package/lib/types/args.d.ts +11 -0
- package/lib/types/args.spec.d.ts +2 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/types.d.ts +109 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# @gjsify/stories
|
|
2
|
+
|
|
3
|
+
The runtime-agnostic **story-authoring contract** for gjsify's storybook. It defines the vocabulary every renderer shares — control kinds, argument maps, and story metadata — with **zero platform imports**, so the GTK renderer ([`@gjsify/storybook`](../../framework/storybook)) and any future web / NativeScript renderer can consume one set of types.
|
|
4
|
+
|
|
5
|
+
## Exports
|
|
6
|
+
|
|
7
|
+
- `ControlType` — `TEXT | NUMBER | BOOLEAN | SELECT | RANGE | COLOR`
|
|
8
|
+
- `StoryControl` — discriminated union (per-kind fields type-checked: `min`/`max`/`step` only on `NUMBER`/`RANGE`, `options` only on `SELECT`)
|
|
9
|
+
- `StoryArgs` / `StoryArgValue` — the live argument map a story renders from
|
|
10
|
+
- `StoryMeta<TComponent>` — `title` (`"Category/Name"`), `description`, `component`, `tags`, `controls`
|
|
11
|
+
- `StoryModule<TWidget>` / `StoryComponentConstructor<TWidget>` — the registration shape a renderer fills with instances
|
|
12
|
+
- `StoryDecorator<TWidget>` — wraps a story's build step
|
|
13
|
+
- `argsFromControls(controls)` — derive initial args from control defaults (defaults spelled once)
|
|
14
|
+
- `isStoryModule(value)` — narrowing guard used by story auto-discovery
|
|
15
|
+
|
|
16
|
+
## Usage
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { ControlType, type StoryControl, argsFromControls } from '@gjsify/stories';
|
|
20
|
+
|
|
21
|
+
const controls: StoryControl[] = [
|
|
22
|
+
{ name: 'label', label: 'Label', type: ControlType.TEXT, defaultValue: 'Click me' },
|
|
23
|
+
{ name: 'size', label: 'Size', type: ControlType.RANGE, min: 16, max: 96, step: 2, defaultValue: 42 },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
const args = argsFromControls(controls); // { label: 'Click me', size: 42 }
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
You normally do not import this package directly to author a story — you import the **renderer** (`@gjsify/storybook`), which re-exports this contract alongside its `StoryWidget` base class. Import `@gjsify/stories` directly only when writing a new renderer or renderer-agnostic tooling.
|
|
30
|
+
|
|
31
|
+
## Build / test
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
gjsify workspace @gjsify/stories build
|
|
35
|
+
gjsify workspace @gjsify/stories test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The contract is pure TypeScript with no platform imports, so a future `@gjsify/storybook-web` / `-nativescript` renderer can reuse it. Today the only renderer is `@gjsify/storybook` (GTK), so the package is declared `gjs`-only (it lives on the framework axis); a cross-runtime renderer would bump the `gjsify.runtimes` slots and add a `src/test.browser.mts`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var e=Object.defineProperty,__name=(t,n)=>e(t,`name`,{value:n,configurable:!0});export{__name};
|
package/lib/esm/args.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";import"./types.js";function argsFromControls(e=[]){let t={};for(let n of e)t[n.name]=defaultFor(n);return t}function defaultFor(e){if(e.defaultValue!==void 0)return e.defaultValue;switch(e.type){case`text`:return``;case`color`:return`#000000`;case`boolean`:return!1;case`number`:case`range`:return e.min??0;case`select`:return e.options[0]?.value??null;default:return null}}export{argsFromControls};
|
package/lib/esm/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ControlType as e,isStoryModule as t}from"./types.js";import{argsFromControls as n}from"./args.js";export{e as ControlType,n as argsFromControls,t as isStoryModule};
|
package/lib/esm/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./_virtual/_rolldown/runtime.js";let e=function(e){return e.TEXT=`text`,e.NUMBER=`number`,e.BOOLEAN=`boolean`,e.SELECT=`select`,e.RANGE=`range`,e.COLOR=`color`,e}({});function isStoryModule(e){return typeof e==`object`&&!!e&&Array.isArray(e.stories)}export{e as ControlType,isStoryModule};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type StoryArgs, type StoryControl } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Derive the initial {@link StoryArgs} from a control list's `defaultValue`s so
|
|
4
|
+
* a story spells its defaults once (in `controls`) rather than duplicating them
|
|
5
|
+
* in a constructor.
|
|
6
|
+
*
|
|
7
|
+
* A control without an explicit `defaultValue` falls back to a kind-appropriate
|
|
8
|
+
* empty value: TEXT → `''`, COLOR → `'#000000'`, BOOLEAN → `false`,
|
|
9
|
+
* NUMBER/RANGE → `min ?? 0`, SELECT → first option's value (or `null`).
|
|
10
|
+
*/
|
|
11
|
+
export declare function argsFromControls(controls?: StoryControl[]): StoryArgs;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Value type for a single story argument — covers every {@link ControlType}.
|
|
3
|
+
* `null` represents "not set".
|
|
4
|
+
*/
|
|
5
|
+
export type StoryArgValue = string | number | boolean | null;
|
|
6
|
+
/** Map of story-argument name → current value. */
|
|
7
|
+
export type StoryArgs = Record<string, StoryArgValue>;
|
|
8
|
+
/** Control kinds a story can expose for live editing in the runner. */
|
|
9
|
+
export declare enum ControlType {
|
|
10
|
+
TEXT = "text",
|
|
11
|
+
NUMBER = "number",
|
|
12
|
+
BOOLEAN = "boolean",
|
|
13
|
+
SELECT = "select",
|
|
14
|
+
RANGE = "range",
|
|
15
|
+
COLOR = "color"
|
|
16
|
+
}
|
|
17
|
+
/** A single choice in a {@link ControlType.SELECT} control. */
|
|
18
|
+
export interface StorySelectOption {
|
|
19
|
+
label: string;
|
|
20
|
+
value: StoryArgValue;
|
|
21
|
+
}
|
|
22
|
+
interface StoryControlBase {
|
|
23
|
+
/** Argument key this control drives (matches a key in {@link StoryArgs}). */
|
|
24
|
+
name: string;
|
|
25
|
+
/** Human-readable label shown beside the control. */
|
|
26
|
+
label: string;
|
|
27
|
+
/** Optional help / tooltip text. */
|
|
28
|
+
description?: string;
|
|
29
|
+
}
|
|
30
|
+
/** Free-text control. */
|
|
31
|
+
export interface StoryTextControl extends StoryControlBase {
|
|
32
|
+
type: ControlType.TEXT;
|
|
33
|
+
defaultValue?: string;
|
|
34
|
+
}
|
|
35
|
+
/** Color picker — `defaultValue` is a `#rrggbb` hex string. */
|
|
36
|
+
export interface StoryColorControl extends StoryControlBase {
|
|
37
|
+
type: ControlType.COLOR;
|
|
38
|
+
defaultValue?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Toggle control. */
|
|
41
|
+
export interface StoryBooleanControl extends StoryControlBase {
|
|
42
|
+
type: ControlType.BOOLEAN;
|
|
43
|
+
defaultValue?: boolean;
|
|
44
|
+
}
|
|
45
|
+
/** Numeric spinner ({@link ControlType.NUMBER}) or slider ({@link ControlType.RANGE}). */
|
|
46
|
+
export interface StoryNumberControl extends StoryControlBase {
|
|
47
|
+
type: ControlType.NUMBER | ControlType.RANGE;
|
|
48
|
+
min?: number;
|
|
49
|
+
max?: number;
|
|
50
|
+
step?: number;
|
|
51
|
+
defaultValue?: number;
|
|
52
|
+
}
|
|
53
|
+
/** Single-choice dropdown. */
|
|
54
|
+
export interface StorySelectControl extends StoryControlBase {
|
|
55
|
+
type: ControlType.SELECT;
|
|
56
|
+
options: StorySelectOption[];
|
|
57
|
+
defaultValue?: StoryArgValue;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A control descriptor — a discriminated union on `type` so per-kind fields are
|
|
61
|
+
* compile-time-checked (`min`/`max`/`step` only on NUMBER/RANGE, `options` only
|
|
62
|
+
* on SELECT).
|
|
63
|
+
*/
|
|
64
|
+
export type StoryControl = StoryTextControl | StoryColorControl | StoryBooleanControl | StoryNumberControl | StorySelectControl;
|
|
65
|
+
/**
|
|
66
|
+
* Metadata describing one story (or a group of variants of one component).
|
|
67
|
+
*
|
|
68
|
+
* `TComponent` defaults to `unknown` to keep this contract platform-free — the
|
|
69
|
+
* GTK renderer passes a `GObject.GType`, a future web renderer might pass a tag
|
|
70
|
+
* name. It is display-only.
|
|
71
|
+
*/
|
|
72
|
+
export interface StoryMeta<TComponent = unknown> {
|
|
73
|
+
/** `"Category/Name"` — the slash-prefix groups the navigation sidebar. */
|
|
74
|
+
title: string;
|
|
75
|
+
/** What the story demonstrates. */
|
|
76
|
+
description?: string;
|
|
77
|
+
/** The component under test — a renderer-specific handle, display only. */
|
|
78
|
+
component?: TComponent;
|
|
79
|
+
/** Free-form tags (`'autodocs'` is reserved for generated docs). */
|
|
80
|
+
tags?: string[];
|
|
81
|
+
/** Editable controls that drive this story's {@link StoryArgs}. */
|
|
82
|
+
controls?: StoryControl[];
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* A renderer's story-widget contract: a zero-arg constructor that also exposes
|
|
86
|
+
* static metadata. Each renderer specializes `TWidget` with its own base class
|
|
87
|
+
* (the GTK renderer's `StoryWidget`, a future web renderer's element).
|
|
88
|
+
*/
|
|
89
|
+
export interface StoryComponentConstructor<TWidget = unknown> {
|
|
90
|
+
new (): TWidget;
|
|
91
|
+
getMetadata(): StoryMeta;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A group of related story constructors. `instances` is populated by a renderer
|
|
95
|
+
* registry once the widgets are constructed.
|
|
96
|
+
*/
|
|
97
|
+
export interface StoryModule<TWidget = unknown> {
|
|
98
|
+
stories: StoryComponentConstructor<TWidget>[];
|
|
99
|
+
instances?: TWidget[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Wraps a story's content-build step — e.g. to install a shared action group or
|
|
103
|
+
* a mock environment around every story in a module. Runs in the renderer's
|
|
104
|
+
* initialize path: call `build()` to perform the default construction.
|
|
105
|
+
*/
|
|
106
|
+
export type StoryDecorator<TWidget = unknown> = (build: () => void, widget: TWidget) => void;
|
|
107
|
+
/** Narrowing guard — `true` when `value` is a {@link StoryModule}. */
|
|
108
|
+
export declare function isStoryModule(value: unknown): value is StoryModule;
|
|
109
|
+
export {};
|
package/package.json
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@gjsify/stories",
|
|
3
|
+
"version": "0.7.5",
|
|
4
|
+
"description": "Runtime-agnostic story-authoring contract (controls, args, metadata) shared by every gjsify storybook renderer",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"module": "lib/esm/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/esm/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"lib"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"clear": "rm -rf lib tmp tsconfig.tsbuildinfo test.gjs.mjs || exit 0",
|
|
19
|
+
"check": "gjsify tsc --noEmit",
|
|
20
|
+
"build": "gjsify run build:gjsify && gjsify run build:types",
|
|
21
|
+
"build:gjsify": "gjsify build --library 'src/**/*.{ts,js}' --exclude 'src/**/*.spec.{mts,ts}' 'src/test.{mts,ts}'",
|
|
22
|
+
"build:types": "gjsify tsc",
|
|
23
|
+
"build:test": "gjsify run build:test:gjs",
|
|
24
|
+
"build:test:gjs": "gjsify build src/test.mts --app gjs --outfile test.gjs.mjs",
|
|
25
|
+
"test": "gjsify run build:gjsify && gjsify run build:test && gjsify run test:gjs",
|
|
26
|
+
"test:gjs": "gjsify run test.gjs.mjs"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [
|
|
29
|
+
"gjs",
|
|
30
|
+
"storybook",
|
|
31
|
+
"stories",
|
|
32
|
+
"gtk",
|
|
33
|
+
"adwaita"
|
|
34
|
+
],
|
|
35
|
+
"dependencies": {},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@gjsify/cli": "^0.7.5",
|
|
38
|
+
"@gjsify/unit": "^0.7.5",
|
|
39
|
+
"@types/node": "^25.9.2",
|
|
40
|
+
"typescript": "^6.0.3"
|
|
41
|
+
},
|
|
42
|
+
"gjsify": {
|
|
43
|
+
"runtimes": {
|
|
44
|
+
"gjs": "polyfill",
|
|
45
|
+
"node": "none",
|
|
46
|
+
"browser": "none",
|
|
47
|
+
"nativescript": "none"
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
"license": "MIT",
|
|
51
|
+
"repository": {
|
|
52
|
+
"type": "git",
|
|
53
|
+
"url": "git+https://github.com/gjsify/gjsify.git",
|
|
54
|
+
"directory": "packages/framework/stories"
|
|
55
|
+
},
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/gjsify/gjsify/issues"
|
|
58
|
+
},
|
|
59
|
+
"homepage": "https://github.com/gjsify/gjsify/tree/main/packages/framework/stories#readme"
|
|
60
|
+
}
|