@psytask/core 1.1.4 → 1.2.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/index.d.ts +61 -36
- package/dist/index.js +33 -15
- package/dist/index.min.js +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -100,9 +100,9 @@ type Component<P extends LooseObject = any, D extends LooseObject = LooseObject
|
|
|
100
100
|
data: () => D;
|
|
101
101
|
};
|
|
102
102
|
};
|
|
103
|
-
type
|
|
104
|
-
/**
|
|
105
|
-
|
|
103
|
+
type GenericComponent<P extends LooseObject = LooseObject, D extends LooseObject = LooseObject & ForbiddenData> = (patchProps?: Partial<P>,
|
|
104
|
+
/** NOTE: only for type hint */
|
|
105
|
+
__rawProps?: P) => Promise<Merge<D, BuiltinData>>;
|
|
106
106
|
/**
|
|
107
107
|
* Provide type infer for generic component, do nothing in runtime.
|
|
108
108
|
*
|
|
@@ -124,12 +124,40 @@ declare const generic: {
|
|
|
124
124
|
};
|
|
125
125
|
/** @ignore */
|
|
126
126
|
type MaybeGenericComponent<P extends LooseObject = any, D extends LooseObject & ForbiddenData = {}> = Component<P, D> | GenericComponent<P, D>;
|
|
127
|
+
/**
|
|
128
|
+
* @example
|
|
129
|
+
*
|
|
130
|
+
* Must be called on the top scope of component
|
|
131
|
+
*
|
|
132
|
+
* ```ts
|
|
133
|
+
* const Component = (props: {}) => {
|
|
134
|
+
* const ctx = getCurrentScene();
|
|
135
|
+
* return '';
|
|
136
|
+
* };
|
|
137
|
+
* ```
|
|
138
|
+
*
|
|
139
|
+
* DO NOT call on other place
|
|
140
|
+
*
|
|
141
|
+
* ```ts
|
|
142
|
+
* const Component = (props: {}) => {
|
|
143
|
+
* const fn = () => {
|
|
144
|
+
* const ctx = getCurrentScene(); // WRONG!
|
|
145
|
+
* };
|
|
146
|
+
* return '';
|
|
147
|
+
* };
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
declare const getCurrentScene: () => Scene<MaybeGenericComponent<any, {}>>;
|
|
151
|
+
declare const ReactiveFn: unique symbol;
|
|
152
|
+
type ComponentFlags = {
|
|
153
|
+
[ReactiveFn]?: <T extends LooseObject>(obj: T) => T;
|
|
154
|
+
};
|
|
127
155
|
type ComponentAdapter = {
|
|
128
|
-
/**
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
render: <T extends Component>(component: T, defaultProps: Parameters<T>[0],
|
|
132
|
-
/** If not provided,
|
|
156
|
+
/** Mark a component with reactive function */
|
|
157
|
+
mark: <T extends Component>(component: T & ComponentFlags) => T;
|
|
158
|
+
/** Call a component with default props and provided scene */
|
|
159
|
+
render: <T extends Component>(component: T & ComponentFlags, defaultProps: Parameters<T>[0],
|
|
160
|
+
/** If not provided, use current scene */
|
|
133
161
|
ctx?: Scene<Component>) => {
|
|
134
162
|
props: Parameters<T>[0];
|
|
135
163
|
} & (ReturnType<T> extends infer R ? R extends {
|
|
@@ -143,6 +171,24 @@ type ComponentAdapter = {
|
|
|
143
171
|
data: undefined;
|
|
144
172
|
} : never);
|
|
145
173
|
};
|
|
174
|
+
/**
|
|
175
|
+
* Adapte third-part reactive systems
|
|
176
|
+
*
|
|
177
|
+
* @example
|
|
178
|
+
*
|
|
179
|
+
* With Vue
|
|
180
|
+
*
|
|
181
|
+
* ```ts
|
|
182
|
+
* import { shallowReactive, effect } from '@vue/reactivity';
|
|
183
|
+
* const adapter = createComponentAdapter(shallowReactive);
|
|
184
|
+
* const VueComponent = (props: { text: string }) => {
|
|
185
|
+
* const node = document.createElement('div');
|
|
186
|
+
* effect(() => (node.textContent = props.text));
|
|
187
|
+
* return node;
|
|
188
|
+
* };
|
|
189
|
+
* const Component = adapter.mark(VueComponent);
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
146
192
|
declare const createComponentAdapter: (reactive: <T extends LooseObject>(obj: T) => T) => ComponentAdapter;
|
|
147
193
|
/**
|
|
148
194
|
* Lifecycle hooks.
|
|
@@ -158,36 +204,12 @@ type SceneEventMap = {
|
|
|
158
204
|
frame: number;
|
|
159
205
|
close: undefined;
|
|
160
206
|
};
|
|
161
|
-
/**
|
|
162
|
-
* @example
|
|
163
|
-
*
|
|
164
|
-
* Must be called on the top scope of component
|
|
165
|
-
*
|
|
166
|
-
* ```ts
|
|
167
|
-
* const Component = (props: {}) => {
|
|
168
|
-
* const ctx = getCurrentScene();
|
|
169
|
-
* return '';
|
|
170
|
-
* };
|
|
171
|
-
* ```
|
|
172
|
-
*
|
|
173
|
-
* DO NOT call on other place
|
|
174
|
-
*
|
|
175
|
-
* ```ts
|
|
176
|
-
* const Component = (props: {}) => {
|
|
177
|
-
* const fn = () => {
|
|
178
|
-
* const ctx = getCurrentScene(); // WRONG!
|
|
179
|
-
* };
|
|
180
|
-
* return '';
|
|
181
|
-
* };
|
|
182
|
-
* ```
|
|
183
|
-
*/
|
|
184
|
-
declare const getCurrentScene: () => Scene<MaybeGenericComponent<any, {}>>;
|
|
185
207
|
/** Scene options */
|
|
186
208
|
type SceneOptions<T extends MaybeGenericComponent> = {
|
|
187
209
|
/** Root element */
|
|
188
210
|
root: HTMLDivElement;
|
|
189
211
|
/** Default props */
|
|
190
|
-
defaultProps: Parameters<T>[
|
|
212
|
+
defaultProps: T extends Component<infer P, infer _> ? P : Parameters<T>[1] & {};
|
|
191
213
|
/** Control show timing */
|
|
192
214
|
timer: () => Timer;
|
|
193
215
|
/** Component adapter */
|
|
@@ -197,7 +219,7 @@ declare class Scene<T extends MaybeGenericComponent> extends EventEmitter<SceneE
|
|
|
197
219
|
#private;
|
|
198
220
|
readonly options: SceneOptions<T>;
|
|
199
221
|
readonly root: HTMLDivElement;
|
|
200
|
-
readonly data: T extends MaybeGenericComponent<infer
|
|
222
|
+
readonly data: T extends MaybeGenericComponent<infer _, infer D> ? () => D : undefined;
|
|
201
223
|
/**
|
|
202
224
|
* Show DOM and update props one-time
|
|
203
225
|
*
|
|
@@ -210,13 +232,16 @@ declare class Scene<T extends MaybeGenericComponent> extends EventEmitter<SceneE
|
|
|
210
232
|
* await scene.show(); // show with default props
|
|
211
233
|
* ```
|
|
212
234
|
*/
|
|
213
|
-
show: T extends Component<infer P, infer D> ?
|
|
235
|
+
show: T extends Component<infer P, infer D> ? (patchProps?: Partial<P>) => Promise<Merge<D, BuiltinData>> : T;
|
|
214
236
|
/**
|
|
215
237
|
* @param component - {@link Component}
|
|
216
238
|
* @param options - {@link SceneOptions}
|
|
217
239
|
*/
|
|
218
240
|
constructor(component: T, options: SceneOptions<T>);
|
|
219
|
-
/**
|
|
241
|
+
/**
|
|
242
|
+
* If called in frame, close in current frame (as microtask), else in next
|
|
243
|
+
* frame
|
|
244
|
+
*/
|
|
220
245
|
close(): void;
|
|
221
246
|
}
|
|
222
247
|
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @psytask/core v1.1
|
|
1
|
+
/** @psytask/core v1.2.1 cubxx MIT */
|
|
2
2
|
const symbol = Symbol.dispose ?? /* @__PURE__ */ Symbol.for("Symbol.dispose");
|
|
3
3
|
class EventEmitter {
|
|
4
4
|
listeners = {};
|
|
@@ -56,11 +56,19 @@ const createTimer = (shouldStop) => {
|
|
|
56
56
|
const timer = {
|
|
57
57
|
start: (cb) => new Promise((resolve) => {
|
|
58
58
|
const records = [];
|
|
59
|
-
|
|
59
|
+
if (currentFrameTime) {
|
|
60
|
+
records.push(currentFrameTime);
|
|
61
|
+
cb?.(currentFrameTime);
|
|
62
|
+
}
|
|
60
63
|
const frame = (time) => {
|
|
61
64
|
const is_stoped = shouldStop(time, records);
|
|
62
65
|
records.push(time);
|
|
63
|
-
|
|
66
|
+
if (is_stoped) {
|
|
67
|
+
timer.stop();
|
|
68
|
+
} else {
|
|
69
|
+
handle = rAF(frame);
|
|
70
|
+
cb?.(time);
|
|
71
|
+
}
|
|
64
72
|
};
|
|
65
73
|
let handle = rAF(frame);
|
|
66
74
|
timer.stop = () => {
|
|
@@ -78,23 +86,28 @@ const generic = (f) => (
|
|
|
78
86
|
//@ts-expect-error impl generic component
|
|
79
87
|
f
|
|
80
88
|
);
|
|
89
|
+
const sceneStack = [];
|
|
90
|
+
const getCurrentScene = () => sceneStack[sceneStack.length - 1] ?? ERR("Not found current scene");
|
|
91
|
+
const ReactiveFn = /* @__PURE__ */ Symbol();
|
|
81
92
|
const createComponentAdapter = (reactive) => ({
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
mark(component) {
|
|
94
|
+
component[ReactiveFn] = reactive;
|
|
95
|
+
return component;
|
|
96
|
+
},
|
|
97
|
+
render(component, defaultProps, ctx) {
|
|
98
|
+
const rprops = (component[ReactiveFn] ?? reactive)(defaultProps);
|
|
85
99
|
ctx && sceneStack.push(ctx);
|
|
86
|
-
const instanceOrNode = component(
|
|
100
|
+
const instanceOrNode = component(rprops);
|
|
87
101
|
ctx && sceneStack.pop();
|
|
88
102
|
let data;
|
|
89
103
|
const nodes = array_normalize(
|
|
90
104
|
typeof instanceOrNode !== "string" && "node" in instanceOrNode ? (data = instanceOrNode.data, instanceOrNode.node) : instanceOrNode
|
|
91
105
|
);
|
|
92
|
-
return { props, nodes, data };
|
|
106
|
+
return { props: rprops, nodes, data };
|
|
93
107
|
}
|
|
94
108
|
});
|
|
95
|
-
const sceneStack = [];
|
|
96
|
-
const getCurrentScene = () => sceneStack[sceneStack.length - 1] ?? ERR("Not found current scene");
|
|
97
109
|
class Scene extends EventEmitter {
|
|
110
|
+
// use GenericComponent as Scene.show type
|
|
98
111
|
/**
|
|
99
112
|
* @param component - {@link Component}
|
|
100
113
|
* @param options - {@link SceneOptions}
|
|
@@ -106,12 +119,14 @@ class Scene extends EventEmitter {
|
|
|
106
119
|
(this.root = root).tabIndex = -1;
|
|
107
120
|
root.style.scale = "0";
|
|
108
121
|
const { props, nodes, data } = adapter.render(
|
|
122
|
+
//@ts-expect-error impl generic component
|
|
109
123
|
component,
|
|
110
124
|
{ ...defaultProps },
|
|
111
125
|
this.on("dispose", () => root.remove())
|
|
112
126
|
);
|
|
113
127
|
this.#timer = timer();
|
|
114
|
-
this.#props = props
|
|
128
|
+
this.#props = props;
|
|
129
|
+
this.data = data;
|
|
115
130
|
root.append(...nodes);
|
|
116
131
|
}
|
|
117
132
|
root;
|
|
@@ -130,12 +145,15 @@ class Scene extends EventEmitter {
|
|
|
130
145
|
* await scene.show(); // show with default props
|
|
131
146
|
* ```
|
|
132
147
|
*/
|
|
133
|
-
//@ts-expect-error impl generic
|
|
148
|
+
//@ts-expect-error impl generic show
|
|
134
149
|
show = this.#show;
|
|
135
|
-
/**
|
|
150
|
+
/**
|
|
151
|
+
* If called in frame, close in current frame (as microtask), else in next
|
|
152
|
+
* frame
|
|
153
|
+
*/
|
|
136
154
|
close() {
|
|
137
|
-
const
|
|
138
|
-
(currentFrameTime ? queueMicrotask : rAF)(() =>
|
|
155
|
+
const ref = this.#timer;
|
|
156
|
+
(currentFrameTime ? queueMicrotask : rAF)(() => ref.stop());
|
|
139
157
|
}
|
|
140
158
|
async #show(patchProps) {
|
|
141
159
|
const { root, defaultProps } = this.options;
|
package/dist/index.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const y=Symbol.dispose??Symbol.for("Symbol.dispose");class p{listeners={};[y](){this.emit("dispose")}on(t,e){return(this.listeners[t]??=new Set).add(e),this}off(t,e){const s=this.listeners[t];return s&&(s.delete(e),s.size||delete this.listeners[t]),this}once(t,e){const s=r=>(this.off(t,s),e(r));return this.on(t,s),this}emit(t,...[e]){const s=this.listeners[t];if(s)for(const r of[...s])r(e);return this}}const w=o=>{throw Error(o)},d=requestAnimationFrame,b=Object,S=(o,t)=>b.assign(o,t),g=document;new Proxy({},{get:(o,t)=>e=>S(g.createElement(t),e)});const A=o=>Array.isArray(o)?o:[o];let c;const m=o=>(c=o,setTimeout(()=>c=0),d(m)),F=o=>{c??m(0);const t={start:e=>new Promise(s=>{const r=[];c&&(r.push(c),e?.(c));const n=a=>{const h=o(a,r);r.push(a),h?t.stop():(i=d(n),e?.(a))};let i=d(n);t.stop=()=>{r.pop(),cancelAnimationFrame(i),s(r)}}),stop(){}};return t},k=o=>o,l=[],E=()=>l[l.length-1]??w("Not found current scene"),u=Symbol(),P=o=>({mark(t){return t[u]=o,t},render(t,e,s){const r=(t[u]??o)(e);s&&l.push(s);const n=t(r);s&&l.pop();let i;const a=A(typeof n!="string"&&"node"in n?(i=n.data,n.node):n);return{props:r,nodes:a,data:i}}});class O extends p{constructor(t,e){super(),this.options=e;const{root:s,adapter:r,defaultProps:n,timer:i}=e;(this.root=s).tabIndex=-1,s.style.scale="0";const{props:a,nodes:h,data:f}=r.render(t,{...n},this.on("dispose",()=>s.remove()));this.#t=i(),this.#s=a,this.data=f,s.append(...h)}root;#t;#s;data;show=this.#e;close(){const t=this.#t;(c?queueMicrotask:d)(()=>t.stop())}async#e(t){const{root:e,defaultProps:s}=this.options,r={...s,...t};for(const i of Object.keys({...this.#s,...r}))this.#s[i]=r[i];this.emit("show"),e.style.scale="1",e.focus();const n=await this.#t.start(i=>this.emit("frame",i));return e.style.scale="0",{...this.emit("close").data?.(),frame_times:n,duration:c-n[0]}}}export{p as EventEmitter,O as Scene,P as createComponentAdapter,F as createTimer,k as generic,E as getCurrentScene};
|