growing-panes 0.2.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.
@@ -0,0 +1,131 @@
1
+ type PaneSchema = Record<string, unknown>;
2
+ type PaneName<Schema extends PaneSchema> = Extract<keyof Schema, string>;
3
+ type Field<Definition, Name extends PropertyKey, Fallback> = Definition extends Record<Name, infer Value> ? Value : Fallback;
4
+ type PaneParams<Schema extends PaneSchema, Name extends PaneName<Schema>> = Field<Schema[Name], "params", undefined>;
5
+ type PaneData<Schema extends PaneSchema, Name extends PaneName<Schema>> = Field<Schema[Name], "data", undefined>;
6
+ type PaneMeta<Schema extends PaneSchema, Name extends PaneName<Schema>> = Field<Schema[Name], "meta", unknown>;
7
+ type InputProperty<Name extends PropertyKey, Value> = undefined extends Value ? {
8
+ [Key in Name]?: Value;
9
+ } : {
10
+ [Key in Name]: Value;
11
+ };
12
+ type PaneTargetFor<Schema extends PaneSchema, Name extends PaneName<Schema>> = {
13
+ readonly pane: Name;
14
+ readonly key?: string;
15
+ } & InputProperty<"params", PaneParams<Schema, Name>> & InputProperty<"data", PaneData<Schema, Name>>;
16
+ type PaneTarget<Schema extends PaneSchema> = {
17
+ [Name in PaneName<Schema>]: PaneTargetFor<Schema, Name>;
18
+ }[PaneName<Schema>];
19
+ type PaneEntryFor<Schema extends PaneSchema, Name extends PaneName<Schema>> = Readonly<{
20
+ key: string;
21
+ pane: Name;
22
+ params: PaneParams<Schema, Name>;
23
+ data: PaneData<Schema, Name>;
24
+ /** Zero-based position in the stack. */
25
+ depth: number;
26
+ }>;
27
+ type PaneEntry<Schema extends PaneSchema> = {
28
+ [Name in PaneName<Schema>]: PaneEntryFor<Schema, Name>;
29
+ }[PaneName<Schema>];
30
+ type PaneDefinition<Schema extends PaneSchema, Name extends PaneName<Schema>> = Readonly<{
31
+ canOpenFrom?: readonly PaneName<Schema>[];
32
+ display?: Readonly<{
33
+ maxVisible?: number;
34
+ }>;
35
+ meta?: PaneMeta<Schema, Name>;
36
+ }>;
37
+ type PaneDefinitions<Schema extends PaneSchema> = {
38
+ readonly [Name in PaneName<Schema>]: PaneDefinition<Schema, Name>;
39
+ };
40
+ interface PaneDisplayContext<Schema extends PaneSchema> {
41
+ readonly activeDefinition: PaneDefinition<Schema, PaneName<Schema>> | undefined;
42
+ readonly definitions: PaneDefinitions<Schema>;
43
+ }
44
+ interface PaneManagerConfig<Schema extends PaneSchema> {
45
+ readonly panes: PaneDefinitions<Schema>;
46
+ readonly initialStack?: readonly PaneTarget<Schema>[];
47
+ readonly display?: Readonly<{
48
+ maxVisible?: number;
49
+ }>;
50
+ /**
51
+ * Smallest stack depth reachable with back navigation. Defaults to one when
52
+ * an initial stack exists, and zero otherwise.
53
+ */
54
+ readonly minimumDepth?: number;
55
+ readonly selectVisiblePanes?: (stack: readonly PaneEntry<Schema>[], context: PaneDisplayContext<Schema>) => readonly PaneEntry<Schema>[];
56
+ }
57
+ interface DefinedPaneConfig<Schema extends PaneSchema> extends PaneManagerConfig<Schema> {
58
+ /** Carries the schema through inference without creating a runtime field. */
59
+ readonly __schema?: Schema;
60
+ }
61
+ interface PaneState<Schema extends PaneSchema> {
62
+ readonly stack: readonly PaneEntry<Schema>[];
63
+ readonly revision: number;
64
+ }
65
+ interface PaneSnapshot<Schema extends PaneSchema> extends PaneState<Schema> {
66
+ readonly visiblePanes: readonly PaneEntry<Schema>[];
67
+ readonly activePane: PaneEntry<Schema> | undefined;
68
+ readonly canGoBack: boolean;
69
+ }
70
+ type PaneBackToTarget<Schema extends PaneSchema> = Readonly<{
71
+ key: string;
72
+ pane?: never;
73
+ }> | Readonly<{
74
+ pane: PaneName<Schema>;
75
+ key?: never;
76
+ }>;
77
+ type PaneEvent<Schema extends PaneSchema> = Readonly<{
78
+ type: "navigate";
79
+ target: PaneTarget<Schema>;
80
+ }> | Readonly<{
81
+ type: "back";
82
+ steps?: number;
83
+ }> | Readonly<{
84
+ type: "back-to";
85
+ target: PaneBackToTarget<Schema>;
86
+ }> | Readonly<{
87
+ type: "replace";
88
+ target: PaneTarget<Schema>;
89
+ }> | Readonly<{
90
+ type: "reset";
91
+ stack?: readonly PaneTarget<Schema>[];
92
+ }>;
93
+ type PaneChange<Schema extends PaneSchema> = Readonly<{
94
+ type: "navigate";
95
+ added: PaneEntry<Schema>;
96
+ }> | Readonly<{
97
+ type: "back";
98
+ removed: readonly PaneEntry<Schema>[];
99
+ }> | Readonly<{
100
+ type: "back-to";
101
+ removed: readonly PaneEntry<Schema>[];
102
+ }> | Readonly<{
103
+ type: "replace";
104
+ added: PaneEntry<Schema>;
105
+ removed: PaneEntry<Schema>;
106
+ }> | Readonly<{
107
+ type: "reset";
108
+ added: readonly PaneEntry<Schema>[];
109
+ removed: readonly PaneEntry<Schema>[];
110
+ }>;
111
+ interface PaneTransition<Schema extends PaneSchema> {
112
+ readonly state: PaneState<Schema>;
113
+ readonly change: PaneChange<Schema> | undefined;
114
+ }
115
+ type PaneListener<Schema extends PaneSchema> = (snapshot: PaneSnapshot<Schema>, change: PaneChange<Schema>) => void;
116
+ interface PaneManager<Schema extends PaneSchema> {
117
+ getSnapshot(): PaneSnapshot<Schema>;
118
+ getDefinition<Name extends PaneName<Schema>>(pane: Name): PaneDefinition<Schema, Name>;
119
+ navigate<Name extends PaneName<Schema>>(target: PaneTargetFor<Schema, Name>): PaneSnapshot<Schema>;
120
+ back(options?: Readonly<{
121
+ steps?: number;
122
+ }>): PaneSnapshot<Schema>;
123
+ backTo(target: PaneBackToTarget<Schema>): PaneSnapshot<Schema>;
124
+ replace<Name extends PaneName<Schema>>(target: PaneTargetFor<Schema, Name>): PaneSnapshot<Schema>;
125
+ reset(stack?: readonly PaneTarget<Schema>[]): PaneSnapshot<Schema>;
126
+ canNavigate<Name extends PaneName<Schema>>(target: PaneTargetFor<Schema, Name>): boolean;
127
+ dispatch(event: PaneEvent<Schema>): PaneSnapshot<Schema>;
128
+ subscribe(listener: PaneListener<Schema>): () => void;
129
+ }
130
+
131
+ export type { DefinedPaneConfig as D, PaneSchema as P, PaneManagerConfig as a, PaneState as b, PaneSnapshot as c, PaneEvent as d, PaneTransition as e, PaneManager as f, PaneBackToTarget as g, PaneChange as h, PaneData as i, PaneDefinition as j, PaneDefinitions as k, PaneDisplayContext as l, PaneEntry as m, PaneEntryFor as n, PaneListener as o, PaneMeta as p, PaneName as q, PaneParams as r, PaneTarget as s, PaneTargetFor as t };
package/package.json ADDED
@@ -0,0 +1,97 @@
1
+ {
2
+ "name": "growing-panes",
3
+ "version": "0.2.0",
4
+ "description": "Headless stack-based pane navigation for JavaScript and TypeScript",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": {
12
+ "types": "./dist/index.d.ts",
13
+ "default": "./dist/index.js"
14
+ },
15
+ "require": {
16
+ "types": "./dist/index.d.cts",
17
+ "default": "./dist/index.cjs"
18
+ }
19
+ },
20
+ "./react": {
21
+ "import": {
22
+ "types": "./dist/react.d.ts",
23
+ "default": "./dist/react.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/react.d.cts",
27
+ "default": "./dist/react.cjs"
28
+ }
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "CHANGELOG.md",
35
+ "LICENSE"
36
+ ],
37
+ "sideEffects": false,
38
+ "scripts": {
39
+ "build": "tsup src/index.ts src/react.ts --format esm,cjs --dts --clean --external react",
40
+ "test": "vitest run",
41
+ "typecheck": "tsc --noEmit",
42
+ "check": "pnpm typecheck && pnpm test && pnpm build && pnpm site:build",
43
+ "site:dev": "vite --config vite.config.ts",
44
+ "site:build": "vite build --config vite.config.ts",
45
+ "site:preview": "vite preview --config vite.config.ts",
46
+ "changeset": "changeset",
47
+ "version": "changeset version",
48
+ "release": "pnpm build && changeset publish"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "git+https://github.com/jhsu/growing-panes.git"
53
+ },
54
+ "bugs": {
55
+ "url": "https://github.com/jhsu/growing-panes/issues"
56
+ },
57
+ "homepage": "https://jhsu.github.io/growing-panes/",
58
+ "keywords": [
59
+ "headless",
60
+ "navigation",
61
+ "panes",
62
+ "stack",
63
+ "state-machine"
64
+ ],
65
+ "author": "Joseph Hsu",
66
+ "license": "MIT",
67
+ "publishConfig": {
68
+ "access": "public",
69
+ "registry": "https://registry.npmjs.org/"
70
+ },
71
+ "engines": {
72
+ "node": ">=20"
73
+ },
74
+ "packageManager": "pnpm@11.3.0",
75
+ "peerDependencies": {
76
+ "react": ">=18"
77
+ },
78
+ "peerDependenciesMeta": {
79
+ "react": {
80
+ "optional": true
81
+ }
82
+ },
83
+ "devDependencies": {
84
+ "@changesets/cli": "^3.0.3",
85
+ "@testing-library/react": "^16.3.3",
86
+ "@types/node": "^26.6.3",
87
+ "@types/react": "^19.3.0",
88
+ "@types/react-dom": "^19.3.0",
89
+ "jsdom": "^30.1.1",
90
+ "react": "^19.3.0",
91
+ "react-dom": "^19.3.0",
92
+ "tsup": "^8.5.1",
93
+ "typescript": "^5.9.3",
94
+ "vite": "^8.3.1",
95
+ "vitest": "^5.0.2"
96
+ }
97
+ }