@gtkx/storybook 0.0.1
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/actions-panel.d.ts +7 -0
- package/dist/actions-panel.d.ts.map +1 -0
- package/dist/actions-panel.js +11 -0
- package/dist/actions-panel.js.map +1 -0
- package/dist/actions.d.ts +35 -0
- package/dist/actions.d.ts.map +1 -0
- package/dist/actions.js +161 -0
- package/dist/actions.js.map +1 -0
- package/dist/catalog.d.ts +71 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +158 -0
- package/dist/catalog.js.map +1 -0
- package/dist/compose.d.ts +27 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +67 -0
- package/dist/compose.js.map +1 -0
- package/dist/config.d.ts +13 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +4 -0
- package/dist/config.js.map +1 -0
- package/dist/controls.d.ts +10 -0
- package/dist/controls.d.ts.map +1 -0
- package/dist/controls.js +94 -0
- package/dist/controls.js.map +1 -0
- package/dist/explorer-navigator.d.ts +11 -0
- package/dist/explorer-navigator.d.ts.map +1 -0
- package/dist/explorer-navigator.js +25 -0
- package/dist/explorer-navigator.js.map +1 -0
- package/dist/explorer-preview.d.ts +8 -0
- package/dist/explorer-preview.d.ts.map +1 -0
- package/dist/explorer-preview.js +89 -0
- package/dist/explorer-preview.js.map +1 -0
- package/dist/explorer-view.d.ts +15 -0
- package/dist/explorer-view.d.ts.map +1 -0
- package/dist/explorer-view.js +24 -0
- package/dist/explorer-view.js.map +1 -0
- package/dist/explorer.d.ts +22 -0
- package/dist/explorer.d.ts.map +1 -0
- package/dist/explorer.js +23 -0
- package/dist/explorer.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +143 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/upstream.d.ts +14 -0
- package/dist/upstream.d.ts.map +1 -0
- package/dist/upstream.js +5 -0
- package/dist/upstream.js.map +1 -0
- package/package.json +86 -0
- package/src/actions-panel.tsx +32 -0
- package/src/actions.ts +234 -0
- package/src/catalog.ts +263 -0
- package/src/compose.ts +94 -0
- package/src/config.ts +14 -0
- package/src/controls.tsx +206 -0
- package/src/explorer-navigator.tsx +120 -0
- package/src/explorer-preview.tsx +207 -0
- package/src/explorer-view.tsx +93 -0
- package/src/explorer.ts +44 -0
- package/src/index.ts +16 -0
- package/src/types.ts +205 -0
- package/src/upstream.ts +24 -0
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** Story discovery and preview configuration for the native explorer. */
|
|
2
|
+
type StorybookConfig = {
|
|
3
|
+
/** Project-relative globs; defaults to CSF story files under src. */
|
|
4
|
+
stories?: string[];
|
|
5
|
+
/** Additional project-relative globs excluded from discovery. */
|
|
6
|
+
exclude?: string[];
|
|
7
|
+
/** Project-relative preview module; defaults to a discovered .storybook/preview file. */
|
|
8
|
+
preview?: string;
|
|
9
|
+
};
|
|
10
|
+
/** Returns a typed explorer configuration without changing it or resolving its paths. */
|
|
11
|
+
declare const defineConfig: (config: StorybookConfig) => StorybookConfig;
|
|
12
|
+
export { defineConfig, type StorybookConfig };
|
|
13
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,KAAK,eAAe,GAAG;IACnB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,yFAAyF;AACzF,QAAA,MAAM,YAAY,GAAI,QAAQ,eAAe,KAAG,eAAyB,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAE,KAAK,eAAe,EAAE,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAUA,yFAAyF;AACzF,MAAM,YAAY,GAAG,CAAC,MAAuB,EAAmB,EAAE,CAAC,MAAM,CAAC;AAE1E,OAAO,EAAE,YAAY,EAAwB,CAAC","sourcesContent":["/** Story discovery and preview configuration for the native explorer. */\ntype StorybookConfig = {\n /** Project-relative globs; defaults to CSF story files under src. */\n stories?: string[];\n /** Additional project-relative globs excluded from discovery. */\n exclude?: string[];\n /** Project-relative preview module; defaults to a discovered .storybook/preview file. */\n preview?: string;\n};\n\n/** Returns a typed explorer configuration without changing it or resolving its paths. */\nconst defineConfig = (config: StorybookConfig): StorybookConfig => config;\n\nexport { defineConfig, type StorybookConfig };\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { Args, ArgTypes } from "./types.js";
|
|
3
|
+
type ControlsProps = {
|
|
4
|
+
argTypes: ArgTypes;
|
|
5
|
+
args: Args;
|
|
6
|
+
onChange: (update: Args) => void;
|
|
7
|
+
};
|
|
8
|
+
declare const Controls: ({ argTypes, args, onChange }: ControlsProps) => ReactNode;
|
|
9
|
+
export { Controls };
|
|
10
|
+
//# sourceMappingURL=controls.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controls.d.ts","sourceRoot":"","sources":["../src/controls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKvC,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEjD,KAAK,aAAa,GAAG;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,IAAI,KAAK,IAAI,CAAA;CAAE,CAAC;AAwK1F,QAAA,MAAM,QAAQ,GAAI,8BAA8B,aAAa,KAAG,SA4B/D,CAAC;AAEF,OAAO,EAAE,QAAQ,EAAE,CAAC"}
|
package/dist/controls.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ComboRow } from "@gtkx/components";
|
|
3
|
+
import { markupEscapeText } from "@gtkx/gi/glib";
|
|
4
|
+
import { AdwActionRow, AdwEntryRow, AdwPreferencesGroup, AdwSpinRow, AdwSwitchRow } from "@gtkx/jsx/adw";
|
|
5
|
+
import { GtkAdjustment } from "@gtkx/jsx/gtk";
|
|
6
|
+
const isObject = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
7
|
+
const isWithinBoundsOrAbsent = (value, min, max) => value === undefined || (typeof value === "number" && Number.isFinite(value) && value >= min && value <= max);
|
|
8
|
+
const controlTitle = (name, argument) => typeof name === "string" ? name : argument;
|
|
9
|
+
const numberDigits = (step) => {
|
|
10
|
+
const [coefficient = "", exponent = "0"] = String(step).split("e", 2);
|
|
11
|
+
const fraction = coefficient.split(".", 2)[1]?.length ?? 0;
|
|
12
|
+
const digits = Math.max(0, fraction - Number(exponent));
|
|
13
|
+
return Math.min(20, digits);
|
|
14
|
+
};
|
|
15
|
+
const UnsupportedControl = ({ title, description }) => (_jsx(AdwActionRow, { title: markupEscapeText(title, -1), subtitle: markupEscapeText(description, -1), sensitive: false }));
|
|
16
|
+
const NumberControl = ({ argument, title, value, settings, isDisabled, onChange, }) => {
|
|
17
|
+
const min = settings.min ?? -Number.MAX_SAFE_INTEGER;
|
|
18
|
+
const max = settings.max ?? Number.MAX_SAFE_INTEGER;
|
|
19
|
+
const step = settings.step ?? 1;
|
|
20
|
+
if (typeof min !== "number" || typeof max !== "number" || typeof step !== "number" ||
|
|
21
|
+
!Number.isFinite(min) || !Number.isFinite(max) || !Number.isFinite(step) ||
|
|
22
|
+
step <= 0 || min > max || !isWithinBoundsOrAbsent(value, min, max)) {
|
|
23
|
+
return _jsx(UnsupportedControl, { title: title, description: "Provide a finite number and valid bounds." });
|
|
24
|
+
}
|
|
25
|
+
const currentValue = typeof value === "number" ? value : Math.max(min, Math.min(0, max));
|
|
26
|
+
return (_jsx(AdwSpinRow, { name: `storybook-control-${argument}`, title: markupEscapeText(title, -1), sensitive: !isDisabled, value: currentValue, digits: numberDigits(step), numeric: true, widthChars: 8, adjustment: (_jsx(GtkAdjustment, { lower: min, upper: max, stepIncrement: step, pageIncrement: Math.min(Number.MAX_VALUE, step * 10), value: currentValue })), onNotifyValue: (next) => {
|
|
27
|
+
if (typeof next === "number" && Number.isFinite(next) &&
|
|
28
|
+
next >= min && next <= max && !Object.is(next, value)) {
|
|
29
|
+
onChange({ [argument]: next });
|
|
30
|
+
}
|
|
31
|
+
} }));
|
|
32
|
+
};
|
|
33
|
+
const SelectControl = (props) => {
|
|
34
|
+
const { argument, title, value, options, settings, isDisabled, onChange } = props;
|
|
35
|
+
if (!Array.isArray(options) || options.length === 0 || options.some((option) => option !== null && typeof option !== "string" && typeof option !== "number" && typeof option !== "boolean")) {
|
|
36
|
+
return _jsx(UnsupportedControl, { title: title, description: "Provide a list of text, number, or boolean options." });
|
|
37
|
+
}
|
|
38
|
+
const values = options;
|
|
39
|
+
const selected = values.findIndex((option) => Object.is(option, value));
|
|
40
|
+
const labels = isObject(settings.labels) ? settings.labels : {};
|
|
41
|
+
const items = values.map((option, index) => {
|
|
42
|
+
const label = labels[String(option)];
|
|
43
|
+
return { id: String(index), value: typeof label === "string" ? label : String(option) };
|
|
44
|
+
});
|
|
45
|
+
return (_jsx(ComboRow, { name: `storybook-control-${argument}`, title: markupEscapeText(title, -1), sensitive: !isDisabled, items: items, selectedId: selected === -1 ? null : String(selected), onSelectionChanged: (id) => {
|
|
46
|
+
const index = Number(id);
|
|
47
|
+
if (Number.isSafeInteger(index) && index >= 0 && index < values.length) {
|
|
48
|
+
onChange({ [argument]: values[index] });
|
|
49
|
+
}
|
|
50
|
+
} }));
|
|
51
|
+
};
|
|
52
|
+
const Control = (props) => {
|
|
53
|
+
const { argument, title, value, type, isDisabled, onChange } = props;
|
|
54
|
+
switch (type) {
|
|
55
|
+
case "boolean": {
|
|
56
|
+
return (_jsx(AdwSwitchRow, { name: `storybook-control-${argument}`, title: markupEscapeText(title, -1), sensitive: !isDisabled, active: value === true, onNotifyActive: (active) => {
|
|
57
|
+
if (typeof active === "boolean" && !Object.is(active, value)) {
|
|
58
|
+
onChange({ [argument]: active });
|
|
59
|
+
}
|
|
60
|
+
} }));
|
|
61
|
+
}
|
|
62
|
+
case "text": {
|
|
63
|
+
return (_jsx(AdwEntryRow, { name: `storybook-control-${argument}`, title: markupEscapeText(title, -1), sensitive: !isDisabled, text: typeof value === "string" ? value : "", onNotifyText: (text) => {
|
|
64
|
+
if (typeof text === "string" && !Object.is(text, value)) {
|
|
65
|
+
onChange({ [argument]: text });
|
|
66
|
+
}
|
|
67
|
+
} }));
|
|
68
|
+
}
|
|
69
|
+
case "number":
|
|
70
|
+
case "range": {
|
|
71
|
+
return _jsx(NumberControl, { ...props });
|
|
72
|
+
}
|
|
73
|
+
case "select":
|
|
74
|
+
case "radio":
|
|
75
|
+
case "inline-radio": {
|
|
76
|
+
return _jsx(SelectControl, { ...props });
|
|
77
|
+
}
|
|
78
|
+
default: {
|
|
79
|
+
return _jsx(UnsupportedControl, { title: title, description: `Unsupported control: ${type}` });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
const Controls = ({ argTypes, args, onChange }) => (_jsx(AdwPreferencesGroup, { title: "Controls", children: Object.entries(argTypes).map(([argument, annotation]) => {
|
|
84
|
+
const control = annotation?.control;
|
|
85
|
+
const table = annotation?.table;
|
|
86
|
+
if (control === undefined || control === false || (isObject(table) && table.disable === true)) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const settings = isObject(control) ? control : {};
|
|
90
|
+
const type = typeof control === "string" ? control : settings.type;
|
|
91
|
+
return (_jsx(Control, { argument: argument, title: controlTitle(annotation?.name, argument), value: args[argument], type: typeof type === "string" ? type : "unknown", settings: settings, options: annotation?.options, isDisabled: settings.disable === true, onChange: onChange }, argument));
|
|
92
|
+
}) }));
|
|
93
|
+
export { Controls };
|
|
94
|
+
//# sourceMappingURL=controls.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"controls.js","sourceRoot":"","sources":["../src/controls.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport { ComboRow } from \"@gtkx/components\";\nimport { markupEscapeText } from \"@gtkx/gi/glib\";\nimport { AdwActionRow, AdwEntryRow, AdwPreferencesGroup, AdwSpinRow, AdwSwitchRow } from \"@gtkx/jsx/adw\";\nimport { GtkAdjustment } from \"@gtkx/jsx/gtk\";\nimport type { Args, ArgTypes } from \"./types.js\";\n\ntype ControlsProps = { argTypes: ArgTypes; args: Args; onChange: (update: Args) => void };\n\ntype ControlProps = {\n argument: string;\n title: string;\n value: unknown;\n type: string;\n settings: Args;\n options: unknown;\n isDisabled: boolean;\n onChange: (update: Args) => void;\n};\n\nconst isObject = (value: unknown): value is Args =>\n value !== null && typeof value === \"object\" && !Array.isArray(value);\n\nconst isWithinBoundsOrAbsent = (value: unknown, min: number, max: number): boolean =>\n value === undefined || (typeof value === \"number\" && Number.isFinite(value) && value >= min && value <= max);\n\nconst controlTitle = (name: unknown, argument: string): string => typeof name === \"string\" ? name : argument;\n\nconst numberDigits = (step: number): number => {\n const [coefficient = \"\", exponent = \"0\"] = String(step).split(\"e\", 2);\n const fraction = coefficient.split(\".\", 2)[1]?.length ?? 0;\n const digits = Math.max(0, fraction - Number(exponent));\n\n return Math.min(20, digits);\n};\n\nconst UnsupportedControl = ({ title, description }: { title: string; description: string }): ReactNode => (\n <AdwActionRow title={markupEscapeText(title, -1)} subtitle={markupEscapeText(description, -1)} sensitive={false} />\n);\n\nconst NumberControl = ({\n argument,\n title,\n value,\n settings,\n isDisabled,\n onChange,\n}: Omit<ControlProps, \"type\" | \"options\">): ReactNode => {\n const min = settings.min ?? -Number.MAX_SAFE_INTEGER;\n const max = settings.max ?? Number.MAX_SAFE_INTEGER;\n const step = settings.step ?? 1;\n\n if (\n typeof min !== \"number\" || typeof max !== \"number\" || typeof step !== \"number\" ||\n !Number.isFinite(min) || !Number.isFinite(max) || !Number.isFinite(step) ||\n step <= 0 || min > max || !isWithinBoundsOrAbsent(value, min, max)\n ) {\n return <UnsupportedControl title={title} description=\"Provide a finite number and valid bounds.\" />;\n }\n\n const currentValue = typeof value === \"number\" ? value : Math.max(min, Math.min(0, max));\n\n return (\n <AdwSpinRow\n name={`storybook-control-${argument}`}\n title={markupEscapeText(title, -1)}\n sensitive={!isDisabled}\n value={currentValue}\n digits={numberDigits(step)}\n numeric\n widthChars={8}\n adjustment={(\n <GtkAdjustment\n lower={min}\n upper={max}\n stepIncrement={step}\n pageIncrement={Math.min(Number.MAX_VALUE, step * 10)}\n value={currentValue}\n />\n )}\n onNotifyValue={(next) => {\n if (\n typeof next === \"number\" && Number.isFinite(next) &&\n next >= min && next <= max && !Object.is(next, value)\n ) {\n onChange({ [argument]: next });\n }\n }}\n />\n );\n};\n\nconst SelectControl = (props: Omit<ControlProps, \"type\">): ReactNode => {\n const { argument, title, value, options, settings, isDisabled, onChange } = props;\n if (!Array.isArray(options) || options.length === 0 || options.some((option: unknown) =>\n option !== null && typeof option !== \"string\" && typeof option !== \"number\" && typeof option !== \"boolean\")) {\n return <UnsupportedControl title={title} description=\"Provide a list of text, number, or boolean options.\" />;\n }\n\n const values: unknown[] = options;\n const selected = values.findIndex((option) => Object.is(option, value));\n const labels = isObject(settings.labels) ? settings.labels : {};\n const items = values.map((option, index) => {\n const label = labels[String(option)];\n\n return { id: String(index), value: typeof label === \"string\" ? label : String(option) };\n });\n\n return (\n <ComboRow\n name={`storybook-control-${argument}`}\n title={markupEscapeText(title, -1)}\n sensitive={!isDisabled}\n items={items}\n selectedId={selected === -1 ? null : String(selected)}\n onSelectionChanged={(id) => {\n const index = Number(id);\n\n if (Number.isSafeInteger(index) && index >= 0 && index < values.length) {\n onChange({ [argument]: values[index] });\n }\n }}\n />\n );\n};\n\nconst Control = (props: ControlProps): ReactNode => {\n const { argument, title, value, type, isDisabled, onChange } = props;\n\n switch (type) {\n case \"boolean\": {\n return (\n <AdwSwitchRow\n name={`storybook-control-${argument}`}\n title={markupEscapeText(title, -1)}\n sensitive={!isDisabled}\n active={value === true}\n onNotifyActive={(active) => {\n if (typeof active === \"boolean\" && !Object.is(active, value)) {\n onChange({ [argument]: active });\n }\n }}\n />\n );\n }\n case \"text\": {\n return (\n <AdwEntryRow\n name={`storybook-control-${argument}`}\n title={markupEscapeText(title, -1)}\n sensitive={!isDisabled}\n text={typeof value === \"string\" ? value : \"\"}\n onNotifyText={(text) => {\n if (typeof text === \"string\" && !Object.is(text, value)) {\n onChange({ [argument]: text });\n }\n }}\n />\n );\n }\n case \"number\":\n case \"range\": {\n return <NumberControl {...props} />;\n }\n case \"select\":\n case \"radio\":\n case \"inline-radio\": {\n return <SelectControl {...props} />;\n }\n default: {\n return <UnsupportedControl title={title} description={`Unsupported control: ${type}`} />;\n }\n }\n};\n\nconst Controls = ({ argTypes, args, onChange }: ControlsProps): ReactNode => (\n <AdwPreferencesGroup title=\"Controls\">\n {Object.entries(argTypes).map(([argument, annotation]) => {\n const control: unknown = annotation?.control;\n const table: unknown = annotation?.table;\n\n if (control === undefined || control === false || (isObject(table) && table.disable === true)) {\n return null;\n }\n\n const settings = isObject(control) ? control : {};\n const type = typeof control === \"string\" ? control : settings.type;\n\n return (\n <Control\n key={argument}\n argument={argument}\n title={controlTitle(annotation?.name, argument)}\n value={args[argument]}\n type={typeof type === \"string\" ? type : \"unknown\"}\n settings={settings}\n options={annotation?.options}\n isDisabled={settings.disable === true}\n onChange={onChange}\n />\n );\n })}\n </AdwPreferencesGroup>\n);\n\nexport { Controls };\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { StoryEntry, StoryLoadError } from "./catalog.js";
|
|
3
|
+
type NavigatorProps = {
|
|
4
|
+
stories: StoryEntry[];
|
|
5
|
+
errors: StoryLoadError[];
|
|
6
|
+
selectedId: string | undefined;
|
|
7
|
+
onSelect: (id: string) => void;
|
|
8
|
+
};
|
|
9
|
+
declare const StoryNavigator: ({ stories, errors, selectedId, onSelect }: NavigatorProps) => ReactNode;
|
|
10
|
+
export { StoryNavigator };
|
|
11
|
+
//# sourceMappingURL=explorer-navigator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-navigator.d.ts","sourceRoot":"","sources":["../src/explorer-navigator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMvC,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE/D,KAAK,cAAc,GAAG;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC,CAAC;AA4DF,QAAA,MAAM,cAAc,GAAI,2CAA2C,cAAc,KAAG,SA4CnF,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { markupEscapeText } from "@gtkx/gi/glib";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import { AdwActionRow, AdwStatusPage } from "@gtkx/jsx/adw";
|
|
5
|
+
import { GtkBox, GtkLabel, GtkListBox, GtkScrolledWindow, GtkSearchEntry } from "@gtkx/jsx/gtk";
|
|
6
|
+
import { useState } from "react";
|
|
7
|
+
const StoryGroup = ({ title, entries, selectedId, onSelect }) => (_jsxs(GtkBox, { orientation: Gtk.Orientation.VERTICAL, spacing: 6, children: [_jsx(GtkLabel, { label: title, xalign: 0, marginStart: 18, marginEnd: 18, cssClasses: ["heading"], wrap: true }), _jsx(GtkListBox, { cssClasses: ["navigation-sidebar"], selectedIndex: entries.findIndex((entry) => entry.id === selectedId), onRowSelected: (row) => {
|
|
8
|
+
const entry = row === null ? undefined : entries[row.getIndex()];
|
|
9
|
+
if (entry) {
|
|
10
|
+
onSelect(entry.id);
|
|
11
|
+
}
|
|
12
|
+
}, children: entries.map((entry) => (_jsx(AdwActionRow, { name: `storybook-story-${entry.id}`, title: markupEscapeText(entry.name, -1), activatable: true, onActivated: () => {
|
|
13
|
+
onSelect(entry.id);
|
|
14
|
+
} }, entry.id))) })] }));
|
|
15
|
+
const LoadErrors = ({ errors }) => errors.length > 0 && (_jsx(GtkBox, { name: "storybook-load-errors", orientation: Gtk.Orientation.VERTICAL, spacing: 6, children: errors.map(({ source, error }, index) => (_jsx(GtkLabel, { label: `${source}\n${error.message.slice(0, 500)}`, cssClasses: ["error"], marginStart: 18, marginEnd: 18, wrap: true, selectable: true, xalign: 0 }, `${source}-${String(index)}`))) }));
|
|
16
|
+
const StoryNavigator = ({ stories, errors, selectedId, onSelect }) => {
|
|
17
|
+
const [search, setSearch] = useState("");
|
|
18
|
+
const query = search.trim().toLocaleLowerCase();
|
|
19
|
+
const groups = Map.groupBy(stories.filter((entry) => `${entry.title} ${entry.name}`.toLocaleLowerCase().includes(query)), (entry) => entry.title);
|
|
20
|
+
return (_jsxs(GtkBox, { orientation: Gtk.Orientation.VERTICAL, spacing: 12, children: [_jsx(GtkSearchEntry, { name: "storybook-search", placeholderText: "Search stories", text: search, marginStart: 12, marginEnd: 12, onChanged: (entry) => {
|
|
21
|
+
setSearch(entry.getText());
|
|
22
|
+
} }), _jsx(GtkScrolledWindow, { hscrollbarPolicy: Gtk.PolicyType.NEVER, vexpand: true, children: _jsxs(GtkBox, { orientation: Gtk.Orientation.VERTICAL, spacing: 18, marginBottom: 18, children: [[...groups].map(([title, entries]) => (_jsx(StoryGroup, { title: title, entries: entries, selectedId: selectedId, onSelect: onSelect }, title))), groups.size === 0 && (_jsx(AdwStatusPage, { name: "storybook-no-matches", title: query ? "No matching stories" : "No stories", iconName: "system-search-symbolic", cssClasses: ["compact"] })), _jsx(LoadErrors, { errors: errors })] }) })] }));
|
|
23
|
+
};
|
|
24
|
+
export { StoryNavigator };
|
|
25
|
+
//# sourceMappingURL=explorer-navigator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-navigator.js","sourceRoot":"","sources":["../src/explorer-navigator.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport { markupEscapeText } from \"@gtkx/gi/glib\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { AdwActionRow, AdwStatusPage } from \"@gtkx/jsx/adw\";\nimport { GtkBox, GtkLabel, GtkListBox, GtkScrolledWindow, GtkSearchEntry } from \"@gtkx/jsx/gtk\";\nimport { useState } from \"react\";\nimport type { StoryEntry, StoryLoadError } from \"./catalog.js\";\n\ntype NavigatorProps = {\n stories: StoryEntry[];\n errors: StoryLoadError[];\n selectedId: string | undefined;\n onSelect: (id: string) => void;\n};\n\ntype GroupProps = Pick<NavigatorProps, \"selectedId\" | \"onSelect\"> & {\n title: string;\n entries: StoryEntry[];\n};\n\nconst StoryGroup = ({ title, entries, selectedId, onSelect }: GroupProps): ReactNode => (\n <GtkBox orientation={Gtk.Orientation.VERTICAL} spacing={6}>\n <GtkLabel\n label={title}\n xalign={0}\n marginStart={18}\n marginEnd={18}\n cssClasses={[\"heading\"]}\n wrap\n />\n <GtkListBox\n cssClasses={[\"navigation-sidebar\"]}\n selectedIndex={entries.findIndex((entry) => entry.id === selectedId)}\n onRowSelected={(row) => {\n const entry = row === null ? undefined : entries[row.getIndex()];\n\n if (entry) {\n onSelect(entry.id);\n }\n }}\n >\n {entries.map((entry) => (\n <AdwActionRow\n key={entry.id}\n name={`storybook-story-${entry.id}`}\n title={markupEscapeText(entry.name, -1)}\n activatable\n onActivated={() => {\n onSelect(entry.id);\n }}\n />\n ))}\n </GtkListBox>\n </GtkBox>\n);\n\nconst LoadErrors = ({ errors }: Pick<NavigatorProps, \"errors\">): ReactNode => errors.length > 0 && (\n <GtkBox name=\"storybook-load-errors\" orientation={Gtk.Orientation.VERTICAL} spacing={6}>\n {errors.map(({ source, error }, index) => (\n <GtkLabel\n key={`${source}-${String(index)}`}\n label={`${source}\\n${error.message.slice(0, 500)}`}\n cssClasses={[\"error\"]}\n marginStart={18}\n marginEnd={18}\n wrap\n selectable\n xalign={0}\n />\n ))}\n </GtkBox>\n);\n\nconst StoryNavigator = ({ stories, errors, selectedId, onSelect }: NavigatorProps): ReactNode => {\n const [search, setSearch] = useState(\"\");\n const query = search.trim().toLocaleLowerCase();\n const groups = Map.groupBy(\n stories.filter((entry) => `${entry.title} ${entry.name}`.toLocaleLowerCase().includes(query)),\n (entry) => entry.title,\n );\n\n return (\n <GtkBox orientation={Gtk.Orientation.VERTICAL} spacing={12}>\n <GtkSearchEntry\n name=\"storybook-search\"\n placeholderText=\"Search stories\"\n text={search}\n marginStart={12}\n marginEnd={12}\n onChanged={(entry) => {\n setSearch(entry.getText());\n }}\n />\n <GtkScrolledWindow hscrollbarPolicy={Gtk.PolicyType.NEVER} vexpand>\n <GtkBox orientation={Gtk.Orientation.VERTICAL} spacing={18} marginBottom={18}>\n {[...groups].map(([title, entries]) => (\n <StoryGroup\n key={title}\n title={title}\n entries={entries}\n selectedId={selectedId}\n onSelect={onSelect}\n />\n ))}\n {groups.size === 0 && (\n <AdwStatusPage\n name=\"storybook-no-matches\"\n title={query ? \"No matching stories\" : \"No stories\"}\n iconName=\"system-search-symbolic\"\n cssClasses={[\"compact\"]}\n />\n )}\n <LoadErrors errors={errors} />\n </GtkBox>\n </GtkScrolledWindow>\n </GtkBox>\n );\n};\n\nexport { StoryNavigator };\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { StoryEntry } from "./catalog.js";
|
|
3
|
+
type PreviewProps = {
|
|
4
|
+
entry: StoryEntry;
|
|
5
|
+
};
|
|
6
|
+
declare const StorybookPreview: ({ entry }: PreviewProps) => ReactNode;
|
|
7
|
+
export { StorybookPreview };
|
|
8
|
+
//# sourceMappingURL=explorer-preview.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-preview.d.ts","sourceRoot":"","sources":["../src/explorer-preview.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAOvC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,KAAK,YAAY,GAAG;IAChB,KAAK,EAAE,UAAU,CAAC;CACrB,CAAC;AA2JF,QAAA,MAAM,gBAAgB,GAAI,WAAW,YAAY,KAAG,SAkCnD,CAAC;AAEF,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { markupEscapeText } from "@gtkx/gi/glib";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import { AdwHeaderBar, AdwStatusPage, AdwToolbarView, AdwWindowTitle } from "@gtkx/jsx/adw";
|
|
5
|
+
import { GtkBox, GtkButton, GtkScrolledWindow } from "@gtkx/jsx/gtk";
|
|
6
|
+
import { createPortal, rootElement } from "@gtkx/react";
|
|
7
|
+
import { Component, useCallback, useMemo, useState } from "react";
|
|
8
|
+
import { ActionsPanel } from "./actions-panel.js";
|
|
9
|
+
import { ActionStore, bindActions } from "./actions.js";
|
|
10
|
+
import { Controls } from "./controls.js";
|
|
11
|
+
class PreviewBoundary extends Component {
|
|
12
|
+
static getDerivedStateFromProps(props, state) {
|
|
13
|
+
return props.args === state.args ? null : { error: null, args: props.args };
|
|
14
|
+
}
|
|
15
|
+
static getDerivedStateFromError(error) {
|
|
16
|
+
return { error: error instanceof Error ? error : new Error(String(error)) };
|
|
17
|
+
}
|
|
18
|
+
state = { error: null, args: this.props.args };
|
|
19
|
+
render() {
|
|
20
|
+
return this.state.error === null
|
|
21
|
+
? this.props.children
|
|
22
|
+
: (_jsx(AdwStatusPage, { name: "storybook-preview-error", title: "Preview failed", iconName: "dialog-error-symbolic", description: markupEscapeText(this.state.error.message.slice(0, 500), -1) +
|
|
23
|
+
"\n\nAdjust controls, reset the preview, or select another story to continue." }));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const previewMode = (story) => {
|
|
27
|
+
const gtkx = story.parameters.gtkx;
|
|
28
|
+
const mode = typeof gtkx === "object" && gtkx !== null && "preview" in gtkx ? gtkx.preview : "content";
|
|
29
|
+
if (mode !== "content" && mode !== "window" && mode !== "dialog") {
|
|
30
|
+
throw new Error("Unsupported GTKX story preview mode");
|
|
31
|
+
}
|
|
32
|
+
return mode;
|
|
33
|
+
};
|
|
34
|
+
const PreviewContent = ({ story: Story, args }) => {
|
|
35
|
+
const mode = previewMode(Story);
|
|
36
|
+
if (mode !== "content") {
|
|
37
|
+
return (_jsxs(_Fragment, { children: [_jsx(AdwStatusPage, { title: mode === "window" ? "Window preview" : "Dialog preview", iconName: "window-new-symbolic", description: "The story owns its presentation. Reset to open it again." }), createPortal(_jsx(Story, { ...args }), rootElement)] }));
|
|
38
|
+
}
|
|
39
|
+
const margin = Story.parameters.layout === "fullscreen" ? 0 : 24;
|
|
40
|
+
const align = Story.parameters.layout === "centered" ? Gtk.Align.CENTER : Gtk.Align.FILL;
|
|
41
|
+
return (_jsx(GtkBox, { name: "storybook-canvas", orientation: Gtk.Orientation.VERTICAL, hexpand: true, vexpand: true, halign: align, valign: align, marginTop: margin, marginBottom: margin, marginStart: margin, marginEnd: margin, children: _jsx(Story, { ...args }) }));
|
|
42
|
+
};
|
|
43
|
+
const usePreviewState = ({ entry }) => {
|
|
44
|
+
const [state, setState] = useState(() => ({
|
|
45
|
+
story: entry.story,
|
|
46
|
+
args: { ...entry.story.args },
|
|
47
|
+
generation: 0,
|
|
48
|
+
error: null,
|
|
49
|
+
actions: new ActionStore(),
|
|
50
|
+
}));
|
|
51
|
+
const onError = useCallback((error) => {
|
|
52
|
+
setState((current) => current.story === state.story && current.generation === state.generation
|
|
53
|
+
? { ...current, error }
|
|
54
|
+
: current);
|
|
55
|
+
}, [state.story, state.generation]);
|
|
56
|
+
const boundArgs = useMemo(() => bindActions(state.args, state.story.argTypes, state.actions, onError), [state.args, state.story.argTypes, state.actions, onError]);
|
|
57
|
+
if (state.story !== entry.story) {
|
|
58
|
+
setState({
|
|
59
|
+
story: entry.story,
|
|
60
|
+
args: { ...entry.story.args },
|
|
61
|
+
generation: state.generation + 1,
|
|
62
|
+
error: null,
|
|
63
|
+
actions: new ActionStore(),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
const reset = () => {
|
|
67
|
+
setState((current) => ({
|
|
68
|
+
story: entry.story,
|
|
69
|
+
args: { ...entry.story.args },
|
|
70
|
+
generation: current.generation + 1,
|
|
71
|
+
error: null,
|
|
72
|
+
actions: new ActionStore(),
|
|
73
|
+
}));
|
|
74
|
+
};
|
|
75
|
+
const onChange = (args) => {
|
|
76
|
+
setState((current) => ({ ...current, args: { ...current.args, ...args } }));
|
|
77
|
+
};
|
|
78
|
+
return { state, boundArgs, reset, onChange };
|
|
79
|
+
};
|
|
80
|
+
const StoryInspector = ({ entry, actions, args, onChange }) => (_jsx(GtkScrolledWindow, { name: "storybook-inspector", widthRequest: 280, hscrollbarPolicy: Gtk.PolicyType.NEVER, vexpand: true, children: _jsxs(GtkBox, { orientation: Gtk.Orientation.VERTICAL, spacing: 24, marginTop: 18, marginBottom: 18, marginStart: 12, marginEnd: 12, children: [_jsx(Controls, { argTypes: entry.controls, args: args, onChange: onChange }), _jsx(ActionsPanel, { store: actions })] }) }));
|
|
81
|
+
const StorybookPreview = ({ entry }) => {
|
|
82
|
+
const { state, boundArgs, reset, onChange } = usePreviewState({ entry });
|
|
83
|
+
return (_jsx(AdwToolbarView, { hexpand: true, vexpand: true, topBar: (_jsx(AdwHeaderBar, { titleWidget: _jsx(AdwWindowTitle, { title: entry.name, subtitle: entry.title }), end: _jsx(GtkButton, { label: "Reset story", onClicked: reset }) })), children: _jsxs(GtkBox, { children: [_jsx(GtkBox, { orientation: Gtk.Orientation.VERTICAL, hexpand: true, vexpand: true, children: _jsx(PreviewBoundary, { args: state.args, children: state.error === null
|
|
84
|
+
? _jsx(PreviewContent, { story: entry.story, args: boundArgs })
|
|
85
|
+
: (_jsx(AdwStatusPage, { name: "storybook-preview-error", title: "Story action failed", iconName: "dialog-error-symbolic", description: markupEscapeText(state.error.message.slice(0, 500), -1) +
|
|
86
|
+
"\n\nReset the preview or select another story to continue." })) }, state.generation) }), _jsx(StoryInspector, { entry: entry, actions: state.actions, args: state.args, onChange: onChange })] }) }));
|
|
87
|
+
};
|
|
88
|
+
export { StorybookPreview };
|
|
89
|
+
//# sourceMappingURL=explorer-preview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-preview.js","sourceRoot":"","sources":["../src/explorer-preview.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport { markupEscapeText } from \"@gtkx/gi/glib\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport { AdwHeaderBar, AdwStatusPage, AdwToolbarView, AdwWindowTitle } from \"@gtkx/jsx/adw\";\nimport { GtkBox, GtkButton, GtkScrolledWindow } from \"@gtkx/jsx/gtk\";\nimport { createPortal, rootElement } from \"@gtkx/react\";\nimport { Component, useCallback, useMemo, useState } from \"react\";\nimport type { StoryEntry } from \"./catalog.js\";\nimport type { Args, ComposedStory } from \"./types.js\";\nimport { ActionsPanel } from \"./actions-panel.js\";\nimport { ActionStore, bindActions } from \"./actions.js\";\nimport { Controls } from \"./controls.js\";\n\ntype PreviewProps = {\n entry: StoryEntry;\n};\n\ntype PreviewState = {\n story: ComposedStory;\n args: Args;\n generation: number;\n error: Error | null;\n actions: ActionStore;\n};\n\ntype BoundaryProps = { children: ReactNode; args: Args };\ntype BoundaryState = { error: Error | null; args: Args };\n\nclass PreviewBoundary extends Component<BoundaryProps, BoundaryState> {\n static getDerivedStateFromProps(props: BoundaryProps, state: BoundaryState): BoundaryState | null {\n return props.args === state.args ? null : { error: null, args: props.args };\n }\n\n static getDerivedStateFromError(error: unknown): Pick<BoundaryState, \"error\"> {\n return { error: error instanceof Error ? error : new Error(String(error)) };\n }\n\n override state: BoundaryState = { error: null, args: this.props.args };\n\n override render(): ReactNode {\n return this.state.error === null\n ? this.props.children\n : (\n <AdwStatusPage\n name=\"storybook-preview-error\"\n title=\"Preview failed\"\n iconName=\"dialog-error-symbolic\"\n description={markupEscapeText(this.state.error.message.slice(0, 500), -1) +\n \"\\n\\nAdjust controls, reset the preview, or select another story to continue.\"}\n />\n );\n }\n}\n\nconst previewMode = (story: ComposedStory): \"content\" | \"window\" | \"dialog\" => {\n const gtkx = story.parameters.gtkx;\n const mode = typeof gtkx === \"object\" && gtkx !== null && \"preview\" in gtkx ? gtkx.preview : \"content\";\n\n if (mode !== \"content\" && mode !== \"window\" && mode !== \"dialog\") {\n throw new Error(\"Unsupported GTKX story preview mode\");\n }\n\n return mode;\n};\n\nconst PreviewContent = ({ story: Story, args }: { story: ComposedStory; args: Args }): ReactNode => {\n const mode = previewMode(Story);\n\n if (mode !== \"content\") {\n return (\n <>\n <AdwStatusPage\n title={mode === \"window\" ? \"Window preview\" : \"Dialog preview\"}\n iconName=\"window-new-symbolic\"\n description=\"The story owns its presentation. Reset to open it again.\"\n />\n {createPortal(<Story {...args} />, rootElement)}\n </>\n );\n }\n\n const margin = Story.parameters.layout === \"fullscreen\" ? 0 : 24;\n const align = Story.parameters.layout === \"centered\" ? Gtk.Align.CENTER : Gtk.Align.FILL;\n\n return (\n <GtkBox\n name=\"storybook-canvas\"\n orientation={Gtk.Orientation.VERTICAL}\n hexpand\n vexpand\n halign={align}\n valign={align}\n marginTop={margin}\n marginBottom={margin}\n marginStart={margin}\n marginEnd={margin}\n >\n <Story {...args} />\n </GtkBox>\n );\n};\n\nconst usePreviewState = ({ entry }: PreviewProps) => {\n const [state, setState] = useState<PreviewState>(() => ({\n story: entry.story,\n args: { ...entry.story.args },\n generation: 0,\n error: null,\n actions: new ActionStore(),\n }));\n const onError = useCallback((error: Error) => {\n setState((current) => current.story === state.story && current.generation === state.generation\n ? { ...current, error }\n : current);\n }, [state.story, state.generation]);\n const boundArgs = useMemo(\n () => bindActions(state.args, state.story.argTypes, state.actions, onError),\n [state.args, state.story.argTypes, state.actions, onError],\n );\n\n if (state.story !== entry.story) {\n setState({\n story: entry.story,\n args: { ...entry.story.args },\n generation: state.generation + 1,\n error: null,\n actions: new ActionStore(),\n });\n }\n\n const reset = (): void => {\n setState((current) => ({\n story: entry.story,\n args: { ...entry.story.args },\n generation: current.generation + 1,\n error: null,\n actions: new ActionStore(),\n }));\n };\n\n const onChange = (args: Args): void => {\n setState((current) => ({ ...current, args: { ...current.args, ...args } }));\n };\n\n return { state, boundArgs, reset, onChange };\n};\n\ntype InspectorProps = PreviewProps & { actions: ActionStore; args: Args; onChange: (args: Args) => void };\n\nconst StoryInspector = ({ entry, actions, args, onChange }: InspectorProps): ReactNode => (\n <GtkScrolledWindow\n name=\"storybook-inspector\"\n widthRequest={280}\n hscrollbarPolicy={Gtk.PolicyType.NEVER}\n vexpand\n >\n <GtkBox\n orientation={Gtk.Orientation.VERTICAL}\n spacing={24}\n marginTop={18}\n marginBottom={18}\n marginStart={12}\n marginEnd={12}\n >\n <Controls argTypes={entry.controls} args={args} onChange={onChange} />\n <ActionsPanel store={actions} />\n </GtkBox>\n </GtkScrolledWindow>\n);\n\nconst StorybookPreview = ({ entry }: PreviewProps): ReactNode => {\n const { state, boundArgs, reset, onChange } = usePreviewState({ entry });\n\n return (\n <AdwToolbarView\n hexpand\n vexpand\n topBar={(\n <AdwHeaderBar\n titleWidget={<AdwWindowTitle title={entry.name} subtitle={entry.title} />}\n end={<GtkButton label=\"Reset story\" onClicked={reset} />}\n />\n )}\n >\n <GtkBox>\n <GtkBox orientation={Gtk.Orientation.VERTICAL} hexpand vexpand>\n <PreviewBoundary key={state.generation} args={state.args}>\n {state.error === null\n ? <PreviewContent story={entry.story} args={boundArgs} />\n : (\n <AdwStatusPage\n name=\"storybook-preview-error\"\n title=\"Story action failed\"\n iconName=\"dialog-error-symbolic\"\n description={markupEscapeText(state.error.message.slice(0, 500), -1) +\n \"\\n\\nReset the preview or select another story to continue.\"}\n />\n )}\n </PreviewBoundary>\n </GtkBox>\n <StoryInspector entry={entry} actions={state.actions} args={state.args} onChange={onChange} />\n </GtkBox>\n </AdwToolbarView>\n );\n};\n\nexport { StorybookPreview };\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { StoryCatalog } from "./catalog.js";
|
|
3
|
+
/** Configuration for the native Storybook application shell. */
|
|
4
|
+
type StorybookProps = {
|
|
5
|
+
/** Source catalog whose stories and loading errors appear in the explorer. */
|
|
6
|
+
catalog: StoryCatalog;
|
|
7
|
+
/** Gio application identifier; defaults to org.gtkx.Storybook. */
|
|
8
|
+
applicationId?: string;
|
|
9
|
+
/** Explorer window and sidebar title; defaults to GTKX Storybook. */
|
|
10
|
+
title?: string;
|
|
11
|
+
};
|
|
12
|
+
/** Renders the Adwaita explorer application with navigation, story previews, controls, and actions. */
|
|
13
|
+
declare const Storybook: ({ catalog, applicationId, title, }: StorybookProps) => ReactNode;
|
|
14
|
+
export { Storybook };
|
|
15
|
+
//# sourceMappingURL=explorer-view.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-view.d.ts","sourceRoot":"","sources":["../src/explorer-view.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,gEAAgE;AAChE,KAAK,cAAc,GAAG;IAClB,8EAA8E;IAC9E,OAAO,EAAE,YAAY,CAAC;IACtB,kEAAkE;IAClE,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,qEAAqE;IACrE,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAsDF,uGAAuG;AACvG,QAAA,MAAM,SAAS,GAAI,oCAIhB,cAAc,KAAG,SAMnB,CAAC;AAEF,OAAO,EAAE,SAAS,EAAE,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as Gio from "@gtkx/gi/gio";
|
|
3
|
+
import { AdwApplication, AdwApplicationWindow, AdwHeaderBar, AdwOverlaySplitView, AdwStatusPage, AdwToolbarView, AdwWindowTitle, } from "@gtkx/jsx/adw";
|
|
4
|
+
import { quit } from "@gtkx/react";
|
|
5
|
+
import { useCallback, useState, useSyncExternalStore } from "react";
|
|
6
|
+
import { StoryNavigator } from "./explorer-navigator.js";
|
|
7
|
+
import { StorybookPreview } from "./explorer-preview.js";
|
|
8
|
+
const StorybookView = ({ catalog, title = "GTKX Storybook" }) => {
|
|
9
|
+
const subscribe = useCallback((listener) => catalog.subscribe(listener), [catalog]);
|
|
10
|
+
const getSnapshot = useCallback(() => catalog.getSnapshot(), [catalog]);
|
|
11
|
+
const snapshot = useSyncExternalStore(subscribe, getSnapshot);
|
|
12
|
+
const [selectedId, setSelectedId] = useState();
|
|
13
|
+
const selected = snapshot.stories.find((entry) => entry.id === selectedId) ?? snapshot.stories[0];
|
|
14
|
+
if (selectedId !== selected?.id) {
|
|
15
|
+
setSelectedId(selected?.id);
|
|
16
|
+
}
|
|
17
|
+
return (_jsx(AdwOverlaySplitView, { minSidebarWidth: 220, maxSidebarWidth: 300, sidebar: (_jsx(AdwToolbarView, { topBar: (_jsx(AdwHeaderBar, { titleWidget: (_jsx(AdwWindowTitle, { title: title, subtitle: `${String(snapshot.stories.length)} stories` })) })), children: _jsx(StoryNavigator, { stories: snapshot.stories, errors: snapshot.errors, selectedId: selected?.id, onSelect: setSelectedId }) })), children: selected
|
|
18
|
+
? _jsx(StorybookPreview, { entry: selected }, selected.id)
|
|
19
|
+
: (_jsx(AdwToolbarView, { topBar: _jsx(AdwHeaderBar, {}), children: _jsx(AdwStatusPage, { name: "storybook-empty", title: snapshot.isLoading ? "Loading stories" : "Choose a story", iconName: "applications-development-symbolic", description: "Stories from your project appear in the sidebar." }) })) }));
|
|
20
|
+
};
|
|
21
|
+
/** Renders the Adwaita explorer application with navigation, story previews, controls, and actions. */
|
|
22
|
+
const Storybook = ({ catalog, applicationId = "org.gtkx.Storybook", title = "GTKX Storybook", }) => (_jsx(AdwApplication, { applicationId: applicationId, flags: Gio.ApplicationFlags.NON_UNIQUE, children: _jsx(AdwApplicationWindow, { title: title, defaultWidth: 1200, defaultHeight: 800, onCloseRequest: quit, children: _jsx(StorybookView, { catalog: catalog, title: title }) }) }));
|
|
23
|
+
export { Storybook };
|
|
24
|
+
//# sourceMappingURL=explorer-view.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer-view.js","sourceRoot":"","sources":["../src/explorer-view.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { ReactNode } from \"react\";\nimport * as Gio from \"@gtkx/gi/gio\";\nimport {\n AdwApplication,\n AdwApplicationWindow,\n AdwHeaderBar,\n AdwOverlaySplitView,\n AdwStatusPage,\n AdwToolbarView,\n AdwWindowTitle,\n} from \"@gtkx/jsx/adw\";\nimport { quit } from \"@gtkx/react\";\nimport { useCallback, useState, useSyncExternalStore } from \"react\";\nimport type { StoryCatalog } from \"./catalog.js\";\nimport { StoryNavigator } from \"./explorer-navigator.js\";\nimport { StorybookPreview } from \"./explorer-preview.js\";\n\n/** Configuration for the native Storybook application shell. */\ntype StorybookProps = {\n /** Source catalog whose stories and loading errors appear in the explorer. */\n catalog: StoryCatalog;\n /** Gio application identifier; defaults to org.gtkx.Storybook. */\n applicationId?: string;\n /** Explorer window and sidebar title; defaults to GTKX Storybook. */\n title?: string;\n};\n\ntype StorybookViewProps = Pick<StorybookProps, \"catalog\" | \"title\">;\n\nconst StorybookView = ({ catalog, title = \"GTKX Storybook\" }: StorybookViewProps): ReactNode => {\n const subscribe = useCallback((listener: () => void) => catalog.subscribe(listener), [catalog]);\n const getSnapshot = useCallback(() => catalog.getSnapshot(), [catalog]);\n const snapshot = useSyncExternalStore(subscribe, getSnapshot);\n const [selectedId, setSelectedId] = useState<string>();\n const selected = snapshot.stories.find((entry) => entry.id === selectedId) ?? snapshot.stories[0];\n\n if (selectedId !== selected?.id) {\n setSelectedId(selected?.id);\n }\n\n return (\n <AdwOverlaySplitView\n minSidebarWidth={220}\n maxSidebarWidth={300}\n sidebar={(\n <AdwToolbarView\n topBar={(\n <AdwHeaderBar\n titleWidget={(\n <AdwWindowTitle title={title} subtitle={`${String(snapshot.stories.length)} stories`} />\n )}\n />\n )}\n >\n <StoryNavigator\n stories={snapshot.stories}\n errors={snapshot.errors}\n selectedId={selected?.id}\n onSelect={setSelectedId}\n />\n </AdwToolbarView>\n )}\n >\n {selected\n ? <StorybookPreview key={selected.id} entry={selected} />\n : (\n <AdwToolbarView topBar={<AdwHeaderBar />}>\n <AdwStatusPage\n name=\"storybook-empty\"\n title={snapshot.isLoading ? \"Loading stories\" : \"Choose a story\"}\n iconName=\"applications-development-symbolic\"\n description=\"Stories from your project appear in the sidebar.\"\n />\n </AdwToolbarView>\n )}\n </AdwOverlaySplitView>\n );\n};\n\n/** Renders the Adwaita explorer application with navigation, story previews, controls, and actions. */\nconst Storybook = ({\n catalog,\n applicationId = \"org.gtkx.Storybook\",\n title = \"GTKX Storybook\",\n}: StorybookProps): ReactNode => (\n <AdwApplication applicationId={applicationId} flags={Gio.ApplicationFlags.NON_UNIQUE}>\n <AdwApplicationWindow title={title} defaultWidth={1200} defaultHeight={800} onCloseRequest={quit}>\n <StorybookView catalog={catalog} title={title} />\n </AdwApplicationWindow>\n </AdwApplication>\n);\n\nexport { Storybook };\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StorySource } from "./catalog.js";
|
|
2
|
+
import type { Preview } from "./types.js";
|
|
3
|
+
/** Controls a running native Storybook explorer and its source catalog. */
|
|
4
|
+
type StorybookSession = {
|
|
5
|
+
/** Replaces discovered sources and preview annotations, rejecting if any source fails to load. */
|
|
6
|
+
updateStories: (sources: StorySource[], preview?: Preview) => Promise<void>;
|
|
7
|
+
/** Displays a session failure while keeping successfully loaded stories available. */
|
|
8
|
+
reportStorybookError: (cause: unknown) => void;
|
|
9
|
+
/** Unmounts the explorer and its story windows or dialogs. */
|
|
10
|
+
stop: () => void;
|
|
11
|
+
};
|
|
12
|
+
/** Starts a native explorer and returns the handle used to load stories and stop it. */
|
|
13
|
+
declare const startStorybook: (options: {
|
|
14
|
+
/** Gio application identifier assigned to the explorer application. */
|
|
15
|
+
applicationId: string;
|
|
16
|
+
}) => StorybookSession;
|
|
17
|
+
export { startStorybook };
|
|
18
|
+
export type { StorybookSession };
|
|
19
|
+
export type { StoryCatalogSnapshot, StoryEntry, StoryLoadError, StorySource } from "./catalog.js";
|
|
20
|
+
export { StoryCatalog } from "./catalog.js";
|
|
21
|
+
export { Storybook } from "./explorer-view.js";
|
|
22
|
+
//# sourceMappingURL=explorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer.d.ts","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAI1C,2EAA2E;AAC3E,KAAK,gBAAgB,GAAG;IACpB,kGAAkG;IAClG,aAAa,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5E,sFAAsF;IACtF,oBAAoB,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC/C,8DAA8D;IAC9D,IAAI,EAAE,MAAM,IAAI,CAAC;CACpB,CAAC;AAEF,wFAAwF;AACxF,QAAA,MAAM,cAAc,GAAI,SAAS;IAC7B,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;CACzB,KAAG,gBAcH,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,CAAC;AACjC,YAAY,EAAE,oBAAoB,EAAE,UAAU,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAElG,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/explorer.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { createRoot } from "@gtkx/react";
|
|
2
|
+
import { createElement } from "react";
|
|
3
|
+
import { StoryCatalog } from "./catalog.js";
|
|
4
|
+
import { Storybook } from "./explorer-view.js";
|
|
5
|
+
/** Starts a native explorer and returns the handle used to load stories and stop it. */
|
|
6
|
+
const startStorybook = (options) => {
|
|
7
|
+
const catalog = new StoryCatalog();
|
|
8
|
+
const root = createRoot(undefined, { onUncaughtError: catalog.reportError.bind(catalog) });
|
|
9
|
+
root.render(createElement(Storybook, { catalog, applicationId: options.applicationId }));
|
|
10
|
+
return {
|
|
11
|
+
updateStories: (sources, preview) => catalog.load(sources, preview),
|
|
12
|
+
reportStorybookError: (cause) => {
|
|
13
|
+
catalog.reportError(cause);
|
|
14
|
+
},
|
|
15
|
+
stop: () => {
|
|
16
|
+
root.unmount();
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
export { startStorybook };
|
|
21
|
+
export { StoryCatalog } from "./catalog.js";
|
|
22
|
+
export { Storybook } from "./explorer-view.js";
|
|
23
|
+
//# sourceMappingURL=explorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"explorer.js","sourceRoot":"","sources":["../src/explorer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAY/C,wFAAwF;AACxF,MAAM,cAAc,GAAG,CAAC,OAGvB,EAAoB,EAAE;IACnB,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,UAAU,CAAC,SAAS,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC3F,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;IAEzF,OAAO;QACH,aAAa,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;QACnE,oBAAoB,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5B,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;QACD,IAAI,EAAE,GAAG,EAAE;YACP,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;KACJ,CAAC;AACN,CAAC,CAAC;AAEF,OAAO,EAAE,cAAc,EAAE,CAAC;AAI1B,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC","sourcesContent":["import { createRoot } from \"@gtkx/react\";\nimport { createElement } from \"react\";\nimport type { StorySource } from \"./catalog.js\";\nimport type { Preview } from \"./types.js\";\nimport { StoryCatalog } from \"./catalog.js\";\nimport { Storybook } from \"./explorer-view.js\";\n\n/** Controls a running native Storybook explorer and its source catalog. */\ntype StorybookSession = {\n /** Replaces discovered sources and preview annotations, rejecting if any source fails to load. */\n updateStories: (sources: StorySource[], preview?: Preview) => Promise<void>;\n /** Displays a session failure while keeping successfully loaded stories available. */\n reportStorybookError: (cause: unknown) => void;\n /** Unmounts the explorer and its story windows or dialogs. */\n stop: () => void;\n};\n\n/** Starts a native explorer and returns the handle used to load stories and stop it. */\nconst startStorybook = (options: {\n /** Gio application identifier assigned to the explorer application. */\n applicationId: string;\n}): StorybookSession => {\n const catalog = new StoryCatalog();\n const root = createRoot(undefined, { onUncaughtError: catalog.reportError.bind(catalog) });\n root.render(createElement(Storybook, { catalog, applicationId: options.applicationId }));\n\n return {\n updateStories: (sources, preview) => catalog.load(sources, preview),\n reportStorybookError: (cause) => {\n catalog.reportError(cause);\n },\n stop: () => {\n root.unmount();\n },\n };\n};\n\nexport { startStorybook };\nexport type { StorybookSession };\nexport type { StoryCatalogSnapshot, StoryEntry, StoryLoadError, StorySource } from \"./catalog.js\";\n\nexport { StoryCatalog } from \"./catalog.js\";\n\nexport { Storybook } from \"./explorer-view.js\";\n"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { action } from "./actions.js";
|
|
2
|
+
export type { ActionCallback } from "./actions.js";
|
|
3
|
+
export { composeStories, composeStory } from "./compose.js";
|
|
4
|
+
export type { Args, ArgTypes, ComposedStories, ComposedStory, Decorator, Meta, Preview, StoryContext, StoryContextUpdate, StoryObj, StoryRender, } from "./types.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5D,YAAY,EACR,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,aAAa,EACb,SAAS,EACT,IAAI,EACJ,OAAO,EACP,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,WAAW,GACd,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC","sourcesContent":["export { action } from \"./actions.js\";\nexport type { ActionCallback } from \"./actions.js\";\nexport { composeStories, composeStory } from \"./compose.js\";\nexport type {\n Args,\n ArgTypes,\n ComposedStories,\n ComposedStory,\n Decorator,\n Meta,\n Preview,\n StoryContext,\n StoryContextUpdate,\n StoryObj,\n StoryRender,\n} from \"./types.js\";\n"]}
|