@modalogue/core 0.1.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/README.md +95 -0
- package/dist/index.d.mts +39 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +70 -0
- package/dist/index.mjs +68 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# @modalogue/core
|
|
2
|
+
|
|
3
|
+
Headless state management for multi-step dialogs. Framework-agnostic with zero dependencies.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @modalogue/core
|
|
9
|
+
# or
|
|
10
|
+
pnpm add @modalogue/core
|
|
11
|
+
# or
|
|
12
|
+
yarn add @modalogue/core
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Usage
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import Modalogue from '@modalogue/core';
|
|
19
|
+
|
|
20
|
+
// Create a new instance
|
|
21
|
+
const modalogue = new Modalogue();
|
|
22
|
+
|
|
23
|
+
// Subscribe to state changes
|
|
24
|
+
const unsubscribe = modalogue.subscribe((state) => {
|
|
25
|
+
console.log('Modal state:', state);
|
|
26
|
+
// state.isOpen - boolean
|
|
27
|
+
// state.activeView - { id, element }
|
|
28
|
+
// state.hasHistory - boolean
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// Open a modal with content
|
|
32
|
+
modalogue.open(<YourContent />);
|
|
33
|
+
|
|
34
|
+
// Navigate to a new view (adds to history)
|
|
35
|
+
modalogue.navigate(<NextView />);
|
|
36
|
+
|
|
37
|
+
// Go back to previous view
|
|
38
|
+
modalogue.back();
|
|
39
|
+
|
|
40
|
+
// Close modal and clear history
|
|
41
|
+
modalogue.close();
|
|
42
|
+
|
|
43
|
+
// Hide modal without clearing history
|
|
44
|
+
modalogue.hide();
|
|
45
|
+
|
|
46
|
+
// Show hidden modal
|
|
47
|
+
modalogue.show();
|
|
48
|
+
|
|
49
|
+
// Clean up subscription
|
|
50
|
+
unsubscribe();
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## API
|
|
54
|
+
|
|
55
|
+
### `new Modalogue()`
|
|
56
|
+
|
|
57
|
+
Creates a new Modalogue instance.
|
|
58
|
+
|
|
59
|
+
### `modalogue.subscribe(callback): () => void`
|
|
60
|
+
|
|
61
|
+
Subscribe to state changes. Returns an unsubscribe function.
|
|
62
|
+
|
|
63
|
+
### `modalogue.open(content): void`
|
|
64
|
+
|
|
65
|
+
Opens the modal with the given content. Clears any existing history.
|
|
66
|
+
|
|
67
|
+
### `modalogue.navigate(content): void`
|
|
68
|
+
|
|
69
|
+
Navigates to new content, preserving history for back navigation.
|
|
70
|
+
|
|
71
|
+
### `modalogue.back(): void`
|
|
72
|
+
|
|
73
|
+
Goes back to the previous view. If on the first view, closes the modal.
|
|
74
|
+
|
|
75
|
+
### `modalogue.close(): void`
|
|
76
|
+
|
|
77
|
+
Closes the modal and clears all history.
|
|
78
|
+
|
|
79
|
+
### `modalogue.hide(): void`
|
|
80
|
+
|
|
81
|
+
Hides the modal without clearing history (can be shown again).
|
|
82
|
+
|
|
83
|
+
### `modalogue.show(): void`
|
|
84
|
+
|
|
85
|
+
Shows a previously hidden modal.
|
|
86
|
+
|
|
87
|
+
## Types
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import type { ModalState, ModalContent, ActiveView, Subscriber, ModalAPI } from '@modalogue/core';
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## License
|
|
94
|
+
|
|
95
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type ModalContent<T = any> = T;
|
|
2
|
+
type ActiveView = {
|
|
3
|
+
element: ModalContent | null;
|
|
4
|
+
id: number | null;
|
|
5
|
+
};
|
|
6
|
+
type ModalState = {
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
activeView: ActiveView;
|
|
9
|
+
hasHistory: boolean;
|
|
10
|
+
};
|
|
11
|
+
type Subscriber = (state: ModalState) => void;
|
|
12
|
+
interface ModalAPI {
|
|
13
|
+
open: (content: ModalContent) => void;
|
|
14
|
+
navigate: (content: ModalContent) => void;
|
|
15
|
+
back: () => void;
|
|
16
|
+
close: () => void;
|
|
17
|
+
hide: () => void;
|
|
18
|
+
show: () => void;
|
|
19
|
+
subscribe: (callback: Subscriber) => () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class Modalogue {
|
|
23
|
+
private subscribers;
|
|
24
|
+
private isOpen;
|
|
25
|
+
private viewHistory;
|
|
26
|
+
constructor();
|
|
27
|
+
subscribe: (callback: Subscriber) => (() => void);
|
|
28
|
+
private notify;
|
|
29
|
+
private getActiveView;
|
|
30
|
+
open: (content: ModalContent) => void;
|
|
31
|
+
navigate: (content: ModalContent) => void;
|
|
32
|
+
back: () => void;
|
|
33
|
+
close: () => void;
|
|
34
|
+
hide: () => void;
|
|
35
|
+
show: () => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { Modalogue as default };
|
|
39
|
+
export type { ActiveView, ModalAPI, ModalContent, ModalState, Subscriber };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
type ModalContent<T = any> = T;
|
|
2
|
+
type ActiveView = {
|
|
3
|
+
element: ModalContent | null;
|
|
4
|
+
id: number | null;
|
|
5
|
+
};
|
|
6
|
+
type ModalState = {
|
|
7
|
+
isOpen: boolean;
|
|
8
|
+
activeView: ActiveView;
|
|
9
|
+
hasHistory: boolean;
|
|
10
|
+
};
|
|
11
|
+
type Subscriber = (state: ModalState) => void;
|
|
12
|
+
interface ModalAPI {
|
|
13
|
+
open: (content: ModalContent) => void;
|
|
14
|
+
navigate: (content: ModalContent) => void;
|
|
15
|
+
back: () => void;
|
|
16
|
+
close: () => void;
|
|
17
|
+
hide: () => void;
|
|
18
|
+
show: () => void;
|
|
19
|
+
subscribe: (callback: Subscriber) => () => void;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
declare class Modalogue {
|
|
23
|
+
private subscribers;
|
|
24
|
+
private isOpen;
|
|
25
|
+
private viewHistory;
|
|
26
|
+
constructor();
|
|
27
|
+
subscribe: (callback: Subscriber) => (() => void);
|
|
28
|
+
private notify;
|
|
29
|
+
private getActiveView;
|
|
30
|
+
open: (content: ModalContent) => void;
|
|
31
|
+
navigate: (content: ModalContent) => void;
|
|
32
|
+
back: () => void;
|
|
33
|
+
close: () => void;
|
|
34
|
+
hide: () => void;
|
|
35
|
+
show: () => void;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export { Modalogue as default };
|
|
39
|
+
export type { ActiveView, ModalAPI, ModalContent, ModalState, Subscriber };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
2
|
+
|
|
3
|
+
class Modalogue {
|
|
4
|
+
constructor(){
|
|
5
|
+
this.subscribers = new Set();
|
|
6
|
+
this.isOpen = false;
|
|
7
|
+
this.viewHistory = [];
|
|
8
|
+
this.subscribe = (callback)=>{
|
|
9
|
+
this.subscribers.add(callback);
|
|
10
|
+
return ()=>this.subscribers.delete(callback);
|
|
11
|
+
};
|
|
12
|
+
this.notify = ()=>{
|
|
13
|
+
const state = {
|
|
14
|
+
isOpen: this.isOpen,
|
|
15
|
+
activeView: this.getActiveView(),
|
|
16
|
+
hasHistory: this.viewHistory.length > 1
|
|
17
|
+
};
|
|
18
|
+
this.subscribers.forEach((subscriber)=>subscriber(state));
|
|
19
|
+
};
|
|
20
|
+
this.getActiveView = ()=>{
|
|
21
|
+
return this.viewHistory[this.viewHistory.length - 1] || {
|
|
22
|
+
id: null,
|
|
23
|
+
element: null
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
this.open = (content)=>{
|
|
27
|
+
this.viewHistory = [
|
|
28
|
+
{
|
|
29
|
+
id: 0,
|
|
30
|
+
element: content
|
|
31
|
+
}
|
|
32
|
+
];
|
|
33
|
+
this.isOpen = true;
|
|
34
|
+
this.notify();
|
|
35
|
+
};
|
|
36
|
+
this.navigate = (content)=>{
|
|
37
|
+
this.viewHistory.push({
|
|
38
|
+
id: this.viewHistory.length,
|
|
39
|
+
element: content
|
|
40
|
+
});
|
|
41
|
+
this.notify();
|
|
42
|
+
};
|
|
43
|
+
this.back = ()=>{
|
|
44
|
+
if (this.viewHistory.length > 1) {
|
|
45
|
+
this.viewHistory.pop();
|
|
46
|
+
this.notify();
|
|
47
|
+
} else {
|
|
48
|
+
this.close();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
this.close = ()=>{
|
|
52
|
+
this.isOpen = false;
|
|
53
|
+
this.viewHistory = [];
|
|
54
|
+
this.notify();
|
|
55
|
+
};
|
|
56
|
+
this.hide = ()=>{
|
|
57
|
+
this.isOpen = false;
|
|
58
|
+
this.notify();
|
|
59
|
+
};
|
|
60
|
+
this.show = ()=>{
|
|
61
|
+
this.isOpen = true;
|
|
62
|
+
this.notify();
|
|
63
|
+
};
|
|
64
|
+
// if (!Modalogue.instance) {
|
|
65
|
+
// Modalogue.instance = new Modalogue();
|
|
66
|
+
// }
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
exports.default = Modalogue;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
class Modalogue {
|
|
2
|
+
constructor(){
|
|
3
|
+
this.subscribers = new Set();
|
|
4
|
+
this.isOpen = false;
|
|
5
|
+
this.viewHistory = [];
|
|
6
|
+
this.subscribe = (callback)=>{
|
|
7
|
+
this.subscribers.add(callback);
|
|
8
|
+
return ()=>this.subscribers.delete(callback);
|
|
9
|
+
};
|
|
10
|
+
this.notify = ()=>{
|
|
11
|
+
const state = {
|
|
12
|
+
isOpen: this.isOpen,
|
|
13
|
+
activeView: this.getActiveView(),
|
|
14
|
+
hasHistory: this.viewHistory.length > 1
|
|
15
|
+
};
|
|
16
|
+
this.subscribers.forEach((subscriber)=>subscriber(state));
|
|
17
|
+
};
|
|
18
|
+
this.getActiveView = ()=>{
|
|
19
|
+
return this.viewHistory[this.viewHistory.length - 1] || {
|
|
20
|
+
id: null,
|
|
21
|
+
element: null
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
this.open = (content)=>{
|
|
25
|
+
this.viewHistory = [
|
|
26
|
+
{
|
|
27
|
+
id: 0,
|
|
28
|
+
element: content
|
|
29
|
+
}
|
|
30
|
+
];
|
|
31
|
+
this.isOpen = true;
|
|
32
|
+
this.notify();
|
|
33
|
+
};
|
|
34
|
+
this.navigate = (content)=>{
|
|
35
|
+
this.viewHistory.push({
|
|
36
|
+
id: this.viewHistory.length,
|
|
37
|
+
element: content
|
|
38
|
+
});
|
|
39
|
+
this.notify();
|
|
40
|
+
};
|
|
41
|
+
this.back = ()=>{
|
|
42
|
+
if (this.viewHistory.length > 1) {
|
|
43
|
+
this.viewHistory.pop();
|
|
44
|
+
this.notify();
|
|
45
|
+
} else {
|
|
46
|
+
this.close();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
this.close = ()=>{
|
|
50
|
+
this.isOpen = false;
|
|
51
|
+
this.viewHistory = [];
|
|
52
|
+
this.notify();
|
|
53
|
+
};
|
|
54
|
+
this.hide = ()=>{
|
|
55
|
+
this.isOpen = false;
|
|
56
|
+
this.notify();
|
|
57
|
+
};
|
|
58
|
+
this.show = ()=>{
|
|
59
|
+
this.isOpen = true;
|
|
60
|
+
this.notify();
|
|
61
|
+
};
|
|
62
|
+
// if (!Modalogue.instance) {
|
|
63
|
+
// Modalogue.instance = new Modalogue();
|
|
64
|
+
// }
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { Modalogue as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@modalogue/core",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Headless state management for multi-step dialogs",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": {
|
|
8
|
+
"types": "./dist/index.d.mts",
|
|
9
|
+
"default": "./dist/index.mjs"
|
|
10
|
+
},
|
|
11
|
+
"require": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"main": "./dist/index.js",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"sideEffects": false,
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "bunchee",
|
|
25
|
+
"dev": "bunchee --watch",
|
|
26
|
+
"type-check": "tsc --noEmit",
|
|
27
|
+
"test:unit": "vitest",
|
|
28
|
+
"test:unit:run": "vitest run",
|
|
29
|
+
"test:unit:coverage": "vitest run --coverage"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"modal",
|
|
33
|
+
"dialog",
|
|
34
|
+
"multi-step",
|
|
35
|
+
"headless",
|
|
36
|
+
"state-management"
|
|
37
|
+
],
|
|
38
|
+
"author": "Edoardo Guido <ciao@edoardoguido.com>",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "https://github.com/edoardoguido/modalogue",
|
|
43
|
+
"directory": "packages/core"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://modalogue.dev",
|
|
46
|
+
"peerDependencies": {},
|
|
47
|
+
"dependencies": {},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
50
|
+
"bunchee": "^6.5.2",
|
|
51
|
+
"jsdom": "^26.1.0",
|
|
52
|
+
"typescript": "^5.8.3",
|
|
53
|
+
"vitest": "^2.1.8"
|
|
54
|
+
}
|
|
55
|
+
}
|