ziko 0.49.6 → 0.49.7
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/ziko.cjs +253 -209
- package/dist/ziko.js +257 -213
- package/dist/ziko.min.js +2 -2
- package/dist/ziko.mjs +251 -207
- package/package.json +1 -1
- package/src/hooks/index.js +9 -1
- package/src/hooks/use-channel.js +2 -19
- package/src/hooks/use-event-emitter.js +68 -0
- package/src/hooks/use-favicon.js +59 -0
- package/src/hooks/use-media-query.js +59 -0
- package/src/hooks/use-root.js +73 -0
- package/src/hooks/use-storage.js +72 -46
- package/src/hooks/use-thread.js +55 -0
- package/src/hooks/use-title.js +43 -0
- package/src/reactivity/hooks/head/useFavIcon.js +4 -4
- package/src/reactivity/hooks/head/useTitle.js +1 -1
- package/src/use/index.js +1 -1
- package/src/use/{use-event-emmiter.js → use-event-emmiter.js.txt} +3 -3
- package/types/hooks/index.d.ts +8 -1
- package/types/hooks/use-Thread.d.ts +33 -0
- package/types/hooks/use-event-emitter.d.ts +46 -0
- package/types/hooks/use-favicon.d.ts +41 -0
- package/types/hooks/use-media-query.d.ts +24 -0
- package/types/hooks/use-root.d.ts +15 -0
- package/types/hooks/use-storage.d.ts +47 -0
- package/types/hooks/use-title.d.ts +37 -0
package/src/hooks/index.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
// STATES
|
|
1
2
|
export * from './use-state.js';
|
|
2
3
|
export * from './use-derived.js';
|
|
3
4
|
export * from './use-reactive.js';
|
|
5
|
+
|
|
6
|
+
//
|
|
4
7
|
export * from './use-channel.js'
|
|
5
|
-
export * from './use-storage.js'
|
|
8
|
+
export * from './use-storage.js'
|
|
9
|
+
export * from './use-thread.js'
|
|
10
|
+
export * from './use-event-emitter.js'
|
|
11
|
+
export * from './use-media-query.js'
|
|
12
|
+
export * from './use-title.js'
|
|
13
|
+
export * from './use-root.js'
|
package/src/hooks/use-channel.js
CHANGED
|
@@ -1,36 +1,28 @@
|
|
|
1
1
|
import { Random } from "../math/random/index.js";
|
|
2
2
|
|
|
3
3
|
class UseChannel {
|
|
4
|
-
// private fields
|
|
5
4
|
#channel;
|
|
6
5
|
#eventData;
|
|
7
6
|
#handlers;
|
|
8
7
|
#uuid;
|
|
9
8
|
#subscribers;
|
|
10
|
-
#currentRooms;
|
|
11
|
-
|
|
9
|
+
#currentRooms;
|
|
12
10
|
constructor(name = "") {
|
|
13
11
|
this.#channel = new BroadcastChannel(name);
|
|
14
12
|
this.#eventData = new Map();
|
|
15
13
|
this.#handlers = new Map(); // Map<event, Array<{fn, rooms}>>
|
|
16
14
|
this.#uuid = "ziko-channel:" + Random.string(10);
|
|
17
15
|
this.#subscribers = new Set([this.#uuid]);
|
|
18
|
-
this.#currentRooms = new Set();
|
|
19
|
-
|
|
16
|
+
this.#currentRooms = new Set();
|
|
20
17
|
this.#channel.addEventListener("message", (e) => {
|
|
21
18
|
const { last_sent_event, userId, eventData, rooms } = e.data;
|
|
22
|
-
|
|
23
19
|
if (userId === this.#uuid) return; // ignore own messages
|
|
24
|
-
|
|
25
20
|
// broadcast if no rooms, else check intersection
|
|
26
21
|
if (rooms && rooms.length && !rooms.some(r => this.#currentRooms.has(r))) return;
|
|
27
|
-
|
|
28
22
|
this.#subscribers.add(userId);
|
|
29
23
|
this.#eventData = new Map(eventData);
|
|
30
|
-
|
|
31
24
|
const handlersList = this.#handlers.get(last_sent_event);
|
|
32
25
|
if (!handlersList) return;
|
|
33
|
-
|
|
34
26
|
handlersList.forEach(({ fn, rooms: handlerRooms }) => {
|
|
35
27
|
// trigger if listener has no room filter, or intersects subscriber rooms
|
|
36
28
|
if (!handlerRooms || handlerRooms.length === 0 ||
|
|
@@ -44,24 +36,20 @@ class UseChannel {
|
|
|
44
36
|
emit(event, data, rooms) {
|
|
45
37
|
this.#eventData.set(event, data);
|
|
46
38
|
if(typeof rooms === 'string') rooms = [rooms]
|
|
47
|
-
|
|
48
39
|
this.#channel.postMessage({
|
|
49
40
|
eventData: Array.from(this.#eventData.entries()),
|
|
50
41
|
last_sent_event: event,
|
|
51
42
|
userId: this.#uuid,
|
|
52
43
|
rooms: rooms && rooms.length ? rooms : undefined
|
|
53
44
|
});
|
|
54
|
-
|
|
55
45
|
return this;
|
|
56
46
|
}
|
|
57
|
-
|
|
58
47
|
on(event, handler = console.log, rooms) {
|
|
59
48
|
if (!this.#handlers.has(event)) this.#handlers.set(event, []);
|
|
60
49
|
if(typeof rooms === 'string') rooms = [rooms]
|
|
61
50
|
this.#handlers.get(event).push({ fn: handler, rooms });
|
|
62
51
|
return this;
|
|
63
52
|
}
|
|
64
|
-
|
|
65
53
|
off(event, handler) {
|
|
66
54
|
if (!this.#handlers.has(event)) return this;
|
|
67
55
|
this.#handlers.set(
|
|
@@ -70,7 +58,6 @@ class UseChannel {
|
|
|
70
58
|
);
|
|
71
59
|
return this;
|
|
72
60
|
}
|
|
73
|
-
|
|
74
61
|
once(event, handler, rooms) {
|
|
75
62
|
const wrapper = (data) => {
|
|
76
63
|
handler(data);
|
|
@@ -79,23 +66,19 @@ class UseChannel {
|
|
|
79
66
|
this.on(event, wrapper, rooms);
|
|
80
67
|
return this;
|
|
81
68
|
}
|
|
82
|
-
|
|
83
69
|
join(...rooms) {
|
|
84
70
|
rooms.forEach(r => this.#currentRooms.add(r));
|
|
85
71
|
return this;
|
|
86
72
|
}
|
|
87
|
-
|
|
88
73
|
leave(...rooms) {
|
|
89
74
|
if (!rooms.length) this.#currentRooms.clear();
|
|
90
75
|
else rooms.forEach(r => this.#currentRooms.delete(r));
|
|
91
76
|
return this;
|
|
92
77
|
}
|
|
93
|
-
|
|
94
78
|
close() {
|
|
95
79
|
this.#channel.close();
|
|
96
80
|
return this;
|
|
97
81
|
}
|
|
98
|
-
|
|
99
82
|
}
|
|
100
83
|
|
|
101
84
|
const useChannel = (name) => new UseChannel(name);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
class UseEventEmitter {
|
|
2
|
+
constructor(maxListeners = 10) {
|
|
3
|
+
this.events = {};
|
|
4
|
+
this.maxListeners = maxListeners;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
on(event, listener) {
|
|
8
|
+
if (!this.events[event]) this.events[event] = [];
|
|
9
|
+
this.events[event].push(listener);
|
|
10
|
+
if (this.events[event].length > this.maxListeners) {
|
|
11
|
+
console.warn(`Warning: Possible memory leak. Event '${event}' has more than ${this.maxListeners} listeners.`);
|
|
12
|
+
}
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
once(event, listener) {
|
|
17
|
+
const wrapper = (...args) => {
|
|
18
|
+
this.off(event, wrapper);
|
|
19
|
+
listener(...args);
|
|
20
|
+
};
|
|
21
|
+
return this.on(event, wrapper);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
off(event, listener) {
|
|
25
|
+
const listeners = this.events[event];
|
|
26
|
+
if (!listeners) return this;
|
|
27
|
+
|
|
28
|
+
const index = listeners.indexOf(listener);
|
|
29
|
+
if (index !== -1) {
|
|
30
|
+
listeners.splice(index, 1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return this;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
emit(event, data) {
|
|
37
|
+
const listeners = this.events[event];
|
|
38
|
+
if (!listeners) return false;
|
|
39
|
+
|
|
40
|
+
// Make a copy so removing listeners inside callbacks doesn't affect iteration
|
|
41
|
+
[...listeners].forEach(listener => {
|
|
42
|
+
try {
|
|
43
|
+
listener(data);
|
|
44
|
+
} catch (e) {
|
|
45
|
+
console.error(`Error in listener for '${event}':`, e);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
remove(event){
|
|
52
|
+
delete this.events[event];
|
|
53
|
+
return this;
|
|
54
|
+
}
|
|
55
|
+
clear() {
|
|
56
|
+
this.events = {};
|
|
57
|
+
return this;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
setMaxListeners(max) {
|
|
61
|
+
this.maxListeners = max;
|
|
62
|
+
return this;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const useEventEmitter = (maxListeners) => new UseEventEmitter(maxListeners);
|
|
67
|
+
|
|
68
|
+
export { useEventEmitter };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { useEventEmitter } from "./use-event-emitter.js";
|
|
2
|
+
|
|
3
|
+
class UseFavIcon {
|
|
4
|
+
constructor(FavIcon, withEmitter = true) {
|
|
5
|
+
this.#init();
|
|
6
|
+
this.cache = {
|
|
7
|
+
emitter: null
|
|
8
|
+
};
|
|
9
|
+
if (withEmitter) this.useEventEmitter();
|
|
10
|
+
if (FavIcon) this.set(FavIcon);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
#init() {
|
|
14
|
+
let link = document.querySelector("link[rel*='icon']");
|
|
15
|
+
let created = false;
|
|
16
|
+
|
|
17
|
+
if (!link) {
|
|
18
|
+
link = document.createElement("link");
|
|
19
|
+
created = true;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
link.type = "image/x-icon";
|
|
23
|
+
link.rel = "shortcut icon";
|
|
24
|
+
|
|
25
|
+
if (created) document.head.appendChild(link);
|
|
26
|
+
|
|
27
|
+
this.__FavIcon__ = link;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
setFavicon(href) {
|
|
31
|
+
if (href !== this.__FavIcon__.href) {
|
|
32
|
+
this.__FavIcon__.href = href;
|
|
33
|
+
|
|
34
|
+
if (this.cache.emitter)
|
|
35
|
+
this.cache.emitter.emit("ziko:favicon-changed", href);
|
|
36
|
+
}
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
get current() {
|
|
41
|
+
return this.__FavIcon__.href;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
onChange(callback) {
|
|
45
|
+
if (this.cache.emitter)
|
|
46
|
+
this.cache.emitter.on("ziko:favicon-changed", callback);
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
useEventEmitter() {
|
|
51
|
+
this.cache.emitter = useEventEmitter();
|
|
52
|
+
return this;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const useFavIcon = (FavIcon, withEmitter = true) => new UseFavIcon(FavIcon, withEmitter);
|
|
58
|
+
|
|
59
|
+
export { useFavIcon };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/*
|
|
2
|
+
[
|
|
3
|
+
{
|
|
4
|
+
query: '(min-width: 600px)',
|
|
5
|
+
callback: () => console.log(1)
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
query: '(max-width: 300px)',
|
|
9
|
+
callback: () => console.log(2)
|
|
10
|
+
}
|
|
11
|
+
]
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
class UseMediaQuery {
|
|
15
|
+
#mediaQueryRules;
|
|
16
|
+
#fallback;
|
|
17
|
+
#lastCalledCallback = null;
|
|
18
|
+
|
|
19
|
+
constructor(mediaQueryRules = [], fallback = () => {}) {
|
|
20
|
+
this.#mediaQueryRules = mediaQueryRules;
|
|
21
|
+
this.#fallback = fallback;
|
|
22
|
+
|
|
23
|
+
this.#init();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// PRIVATE: check if ANY rule matches
|
|
27
|
+
#checkAllRules() {
|
|
28
|
+
return this.#mediaQueryRules.some(
|
|
29
|
+
({ query }) => globalThis.matchMedia(query).matches
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// PRIVATE: installs listeners and initial checks
|
|
34
|
+
#init() {
|
|
35
|
+
this.#mediaQueryRules.forEach(({ query, callback }) => {
|
|
36
|
+
const mediaQueryList = globalThis.matchMedia(query);
|
|
37
|
+
|
|
38
|
+
const checkMatches = () => {
|
|
39
|
+
const anyMatch = this.#checkAllRules();
|
|
40
|
+
|
|
41
|
+
if (mediaQueryList.matches) {
|
|
42
|
+
callback();
|
|
43
|
+
this.#lastCalledCallback = callback;
|
|
44
|
+
} else if (!anyMatch && this.#lastCalledCallback !== this.#fallback) {
|
|
45
|
+
this.#fallback();
|
|
46
|
+
this.#lastCalledCallback = this.#fallback;
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
checkMatches();
|
|
51
|
+
mediaQueryList.addEventListener("change", checkMatches);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const useMediaQuery = (mediaQueryRules, fallback) =>
|
|
57
|
+
new UseMediaQuery(mediaQueryRules, fallback);
|
|
58
|
+
|
|
59
|
+
export { useMediaQuery };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
class UseRoot {
|
|
2
|
+
constructor(PropsMap, { namespace = 'Ziko', ValidateCssProps = false } = {}) {
|
|
3
|
+
this.currentPropsMap = PropsMap;
|
|
4
|
+
this.namespace = namespace;
|
|
5
|
+
this.ValidateCssProps = ValidateCssProps;
|
|
6
|
+
this.use(PropsMap);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
use(PropsMap) {
|
|
10
|
+
if (this.ValidateCssProps) ValidateCssPropsFn(PropsMap);
|
|
11
|
+
this.currentPropsMap = PropsMap;
|
|
12
|
+
this.#maintain();
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#maintain() {
|
|
17
|
+
const root = globalThis?.document?.documentElement?.style;
|
|
18
|
+
for (const prop in this.currentPropsMap) {
|
|
19
|
+
const cssProp = this.namespace ? `--${this.namespace}-${prop}` : `--${prop}`;
|
|
20
|
+
root.setProperty(cssProp, this.currentPropsMap[prop]);
|
|
21
|
+
|
|
22
|
+
Object.defineProperty(this, prop, {
|
|
23
|
+
value: `var(${cssProp})`,
|
|
24
|
+
writable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
enumerable: false
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function ValidateCssPropsFn(PropsMap) {
|
|
33
|
+
const validProps = new Set(Object.keys(document.documentElement.style));
|
|
34
|
+
for (const key in PropsMap) {
|
|
35
|
+
if (!validProps.has(key)) {
|
|
36
|
+
throw new Error(`Invalid CSS property: "${key}"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const useRoot = (PropsMap, options = {}) => new UseRoot(PropsMap, options);
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
UseRoot,
|
|
45
|
+
useRoot
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
// Usage
|
|
50
|
+
|
|
51
|
+
/*
|
|
52
|
+
const Styles = {
|
|
53
|
+
S1 : {
|
|
54
|
+
background : 'white',
|
|
55
|
+
color : 'darkblue'
|
|
56
|
+
border : '2px darkblue solid"'
|
|
57
|
+
},
|
|
58
|
+
S2 : {
|
|
59
|
+
background : 'darkblue',
|
|
60
|
+
color : 'white'
|
|
61
|
+
border : '2px green solid"'
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
const {use, border, background, color} = useRoot(Style.S1)
|
|
65
|
+
|
|
66
|
+
tags.p("Test useRoot ").style({
|
|
67
|
+
border,
|
|
68
|
+
color,
|
|
69
|
+
background,
|
|
70
|
+
padding : '10px'
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
*/
|
package/src/hooks/use-storage.js
CHANGED
|
@@ -1,73 +1,99 @@
|
|
|
1
|
-
// To do : remove old items
|
|
2
1
|
import { useChannel } from "./use-channel.js";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
|
|
3
|
+
class UseStorage {
|
|
4
|
+
constructor(storage, globalKey, initialValue, use_channel = true) {
|
|
5
|
+
this.cache = {
|
|
6
6
|
storage,
|
|
7
7
|
globalKey,
|
|
8
|
-
channel:useChannel(`Ziko:useStorage-${globalKey}`),
|
|
9
|
-
oldItemKeys:new Set()
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
this.#
|
|
8
|
+
channel: use_channel ? useChannel(`Ziko:useStorage-${globalKey}`) : null,
|
|
9
|
+
oldItemKeys: new Set()
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
this.#init(initialValue, use_channel);
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
|
|
15
|
+
get items() {
|
|
16
|
+
const raw = this.cache.storage.getItem(this.cache.globalKey);
|
|
17
|
+
if (!raw) return {};
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(raw);
|
|
20
|
+
} catch {
|
|
21
|
+
return {};
|
|
22
|
+
}
|
|
16
23
|
}
|
|
24
|
+
|
|
17
25
|
#maintain() {
|
|
18
|
-
|
|
26
|
+
const items = this.items;
|
|
27
|
+
this.cache.oldItemKeys.forEach(k => delete this[k]);
|
|
28
|
+
for (const key in items) {
|
|
29
|
+
this[key] = items[key];
|
|
30
|
+
this.cache.oldItemKeys.add(key);
|
|
31
|
+
}
|
|
19
32
|
}
|
|
20
|
-
#init(initialValue){
|
|
21
|
-
this.cache.channel
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
Object.keys(this.items).forEach(key=>this.cache.oldItemKeys.add(key));
|
|
26
|
-
// console.group("Ziko:useStorage")
|
|
27
|
-
// console.warn(`Storage key '${this.cache.globalKey}' already exists. we will not overwrite it.`);
|
|
28
|
-
// console.info(`%cWe'll keep the existing data.`,"background-color:#2222dd; color:gold;");
|
|
29
|
-
// console.group("")
|
|
33
|
+
#init(initialValue, use_channel) {
|
|
34
|
+
if (use_channel && this.cache.channel) this.cache.channel.on("Ziko-Storage-Updated", () => this.#maintain());
|
|
35
|
+
if (!initialValue) {
|
|
36
|
+
this.#maintain();
|
|
37
|
+
return;
|
|
30
38
|
}
|
|
39
|
+
if (this.cache.storage.getItem(this.cache.globalKey)) {
|
|
40
|
+
const existing = this.items;
|
|
41
|
+
Object.keys(existing).forEach(k => this.cache.oldItemKeys.add(k));
|
|
42
|
+
this.#maintain();
|
|
43
|
+
}
|
|
31
44
|
else this.set(initialValue);
|
|
32
45
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
this.cache.
|
|
36
|
-
|
|
46
|
+
|
|
47
|
+
set(data) {
|
|
48
|
+
this.cache.storage.setItem(this.cache.globalKey, JSON.stringify(data));
|
|
49
|
+
if (this.cache.channel) this.cache.channel.emit("Ziko-Storage-Updated", data);
|
|
37
50
|
this.#maintain();
|
|
38
|
-
return this
|
|
51
|
+
return this;
|
|
39
52
|
}
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
|
|
54
|
+
add(data) {
|
|
55
|
+
this.set({
|
|
42
56
|
...this.items,
|
|
43
57
|
...data
|
|
44
|
-
}
|
|
45
|
-
this.cache.storage.setItem(this.cache.globalKey,JSON.stringify(db));
|
|
46
|
-
this.#maintain();
|
|
58
|
+
});
|
|
47
59
|
return this;
|
|
48
60
|
}
|
|
49
|
-
remove(...keys){
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
delete
|
|
53
|
-
delete this[
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
remove(...keys) {
|
|
62
|
+
const items = { ...this.items };
|
|
63
|
+
keys.forEach(key => {
|
|
64
|
+
delete items[key];
|
|
65
|
+
delete this[key];
|
|
66
|
+
this.cache.oldItemKeys.delete(key);
|
|
67
|
+
});
|
|
68
|
+
this.set(items);
|
|
56
69
|
return this;
|
|
57
70
|
}
|
|
58
|
-
get(key){
|
|
71
|
+
get(key) {
|
|
59
72
|
return this.items[key];
|
|
60
73
|
}
|
|
61
|
-
clear(){
|
|
74
|
+
clear() {
|
|
62
75
|
this.cache.storage.removeItem(this.cache.globalKey);
|
|
76
|
+
this.cache.oldItemKeys.forEach(k => delete this[k]);
|
|
77
|
+
this.cache.oldItemKeys.clear();
|
|
63
78
|
this.#maintain();
|
|
64
79
|
return this;
|
|
65
80
|
}
|
|
66
|
-
|
|
81
|
+
onStorageUpdated(callback) {
|
|
82
|
+
if (this.cache.channel) {
|
|
83
|
+
this.cache.channel.on("Ziko-Storage-Updated", callback);
|
|
84
|
+
}
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
67
87
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
88
|
+
|
|
89
|
+
// factory functions
|
|
90
|
+
const useLocaleStorage = (key, initialValue, use_channel = true) =>
|
|
91
|
+
new UseStorage(localStorage, key, initialValue, use_channel);
|
|
92
|
+
|
|
93
|
+
const useSessionStorage = (key, initialValue, use_channel = true) =>
|
|
94
|
+
new UseStorage(sessionStorage, key, initialValue, use_channel);
|
|
95
|
+
|
|
96
|
+
export {
|
|
71
97
|
useLocaleStorage,
|
|
72
98
|
useSessionStorage
|
|
73
|
-
}
|
|
99
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
class UseThread {
|
|
2
|
+
#worker;
|
|
3
|
+
#callbacks = new Map();
|
|
4
|
+
#idCounter = 0;
|
|
5
|
+
|
|
6
|
+
constructor() {
|
|
7
|
+
const workerCode = `
|
|
8
|
+
this.onmessage = function(e) {
|
|
9
|
+
const { id, funStr, args, close } = e.data;
|
|
10
|
+
try {
|
|
11
|
+
const func = new Function("return " + funStr)();
|
|
12
|
+
const result = func(...args);
|
|
13
|
+
postMessage({ id, result });
|
|
14
|
+
} catch (error) {
|
|
15
|
+
postMessage({ id, error: error.message });
|
|
16
|
+
} finally {
|
|
17
|
+
if (close) self.close();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
`;
|
|
21
|
+
const blob = new Blob([workerCode], { type: "text/javascript" });
|
|
22
|
+
this.#worker = new Worker(URL.createObjectURL(blob));
|
|
23
|
+
|
|
24
|
+
this.#worker.addEventListener("message", (e) => {
|
|
25
|
+
const { id, result, error } = e.data;
|
|
26
|
+
const callback = this.#callbacks.get(id);
|
|
27
|
+
if (!callback) return;
|
|
28
|
+
|
|
29
|
+
callback(result, error);
|
|
30
|
+
this.#callbacks.delete(id);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
call(func, callback, args = [], close = true) {
|
|
34
|
+
if (typeof func !== "function") throw new TypeError("func must be a function");
|
|
35
|
+
const id = ++this.#idCounter;
|
|
36
|
+
this.#callbacks.set(id, callback);
|
|
37
|
+
|
|
38
|
+
this.#worker.postMessage({
|
|
39
|
+
id,
|
|
40
|
+
funStr: func.toString(),
|
|
41
|
+
args,
|
|
42
|
+
close
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return this;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
terminate() {
|
|
49
|
+
this.#worker.terminate();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const useThread = (func, callback, args = [], close = true) => new UseThread().call(func, callback, args, close);
|
|
54
|
+
|
|
55
|
+
export { UseThread, useThread };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useEventEmitter } from "./use-event-emitter.js";
|
|
2
|
+
|
|
3
|
+
class UseTitle {
|
|
4
|
+
constructor(title = document.title, withEmitter = true) {
|
|
5
|
+
this.cache = {
|
|
6
|
+
emitter: null
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
if (withEmitter) this.useEventEmitter();
|
|
10
|
+
this.set(title);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
useEventEmitter() {
|
|
14
|
+
this.cache.emitter = useEventEmitter();
|
|
15
|
+
return this;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
setTitle(title) {
|
|
19
|
+
if (title !== document.title) {
|
|
20
|
+
document.title = title;
|
|
21
|
+
|
|
22
|
+
if (this.cache.emitter) {
|
|
23
|
+
this.cache.emitter.emit("ziko:title-changed", title);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return this;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
get current() {
|
|
30
|
+
return document.title;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
onChange(callback) {
|
|
34
|
+
if (this.cache.emitter) {
|
|
35
|
+
this.cache.emitter.on("ziko:title-changed", callback);
|
|
36
|
+
}
|
|
37
|
+
return this;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const useTitle = (title, withEmitter = true) => new UseTitle(title, withEmitter);
|
|
42
|
+
|
|
43
|
+
export { useTitle };
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { useEventEmitter } from "../../../
|
|
1
|
+
import { useEventEmitter } from "../../../hooks/use-event-emitter.js";
|
|
2
2
|
class ZikoUseFavIcon{
|
|
3
|
-
constructor(FavIcon,
|
|
3
|
+
constructor(FavIcon,withEmitter=true){
|
|
4
4
|
this.#init();
|
|
5
5
|
this.cache={
|
|
6
6
|
Emitter:null
|
|
7
7
|
}
|
|
8
|
-
if(
|
|
8
|
+
if(withEmitter)this.useEventEmitter();
|
|
9
9
|
this.set(FavIcon);
|
|
10
10
|
}
|
|
11
11
|
#init(){
|
|
@@ -34,5 +34,5 @@ class ZikoUseFavIcon{
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
}
|
|
37
|
-
const useFavIcon=(FavIcon,
|
|
37
|
+
const useFavIcon=(FavIcon,withEmitter)=>new ZikoUseFavIcon(FavIcon,withEmitter);
|
|
38
38
|
export{ useFavIcon }
|
package/src/use/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
class UseEventEmitter {
|
|
2
|
-
constructor() {
|
|
2
|
+
constructor(maxListeners = 10) {
|
|
3
3
|
this.events = {};
|
|
4
|
-
this.maxListeners =
|
|
4
|
+
this.maxListeners = maxListeners;
|
|
5
5
|
}
|
|
6
6
|
on(event, listener) {
|
|
7
7
|
if (!this.events[event]) {
|
|
@@ -60,5 +60,5 @@ class UseEventEmitter {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
const useEventEmitter=()=>new UseEventEmitter()
|
|
63
|
+
const useEventEmitter=(maxListeners)=>new UseEventEmitter(maxListeners)
|
|
64
64
|
export{useEventEmitter}
|
package/types/hooks/index.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export type * from './use-channel.d.ts'
|
|
2
|
+
export type * from './use-storage.d.ts'
|
|
2
3
|
export type * from './use-state.d.ts'
|
|
3
4
|
export type * from './use-derived.d.ts'
|
|
4
|
-
export type * from './use-reactive.d.ts'
|
|
5
|
+
export type * from './use-reactive.d.ts'
|
|
6
|
+
export type * from './use-Thread.d.ts'
|
|
7
|
+
export type * from './use-event-emitter.d.ts'
|
|
8
|
+
export type * from './use-media-query.d.ts'
|
|
9
|
+
export type * from './use-title.d.ts'
|
|
10
|
+
export type * from './use-favicon.d.ts'
|
|
11
|
+
export type * from './use-root.d.ts'
|