Skip to content

Commit 677af59

Browse files
committed
feat(core): add new router component $useState method
1 parent 27887e8 commit 677af59

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed

src/core/modules/component/component-class.js

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,85 @@ import vdom from './vdom.js';
77
import patch from './patch.js';
88
import $jsx from './$jsx.js';
99

10+
/* eslint-disable no-shadow */
11+
/* eslint-disable no-return-assign */
12+
/* eslint-disable no-plusplus */
13+
/* eslint-disable no-param-reassign */
14+
/* eslint-disable no-sequences */
15+
const types = [
16+
{
17+
name: 'array',
18+
init: (i) => i,
19+
type: (i) => [i].find(Array.isArray),
20+
update: (i, o) => [o].filter(Array.isArray).find(() => ((i.length = 0), i.push(...o))),
21+
insert: (i, x, o = []) => i.splice(Math.max(x, 0), 0, ...[o].flat()),
22+
replace: (i, x, o = []) => i.splice(Math.max(x, 0), Math.min(++x, 1), ...[o].flat()),
23+
append: (i, o = []) => i.push(...[o].flat()),
24+
prepend: (i, o = []) => i.unshift(...[o].flat()),
25+
swap: (i, a, b) => {
26+
[i[a], i[b]] = [i[b], i[a]];
27+
},
28+
fromTo: (i, a, b = a) => i.splice(Math.max(b, 0), 0, ...i.splice(Math.max(a, 0), 1)),
29+
remove: (i, o, a = i.map((_, x) => x)) =>
30+
[o]
31+
.flat()
32+
.filter((i) => a.includes(i))
33+
.sort((a, b) => b - a)
34+
.forEach((x) => i.splice(x, 1)),
35+
clear: (i) => (i.length = 0),
36+
},
37+
{
38+
name: 'object',
39+
init: (i) => i,
40+
type: (i) =>
41+
[i]
42+
.filter((i) => [i !== null, i !== undefined].every((i) => i))
43+
.find((i) => Object.getPrototypeOf(i) === Object.prototype),
44+
update: (i, o) => Object.assign(i, o),
45+
insert: () => {},
46+
replace: () => {},
47+
append: () => {},
48+
prepend: () => {},
49+
swap: () => ({}), // N/A
50+
fromTo: () => ({}), // N/A
51+
remove: (i, o) => [o].flat().forEach((k) => delete i[k]),
52+
clear: (i) => Object.keys(i).forEach((k) => delete i[k]),
53+
},
54+
{
55+
name: 'atoms',
56+
type: () => true,
57+
init: (i, o = {}) => (
58+
Object.defineProperty(o, 'value', {
59+
get: () => i,
60+
set: (v) => {
61+
// eslint-disable-next-line
62+
i = v;
63+
},
64+
}),
65+
o
66+
),
67+
update: (i, v = i.value) => {
68+
i.value = v;
69+
},
70+
insert: () => ({}), // N/A
71+
replace: () => ({}), // N/A
72+
append: () => ({}), // N/A
73+
prepend: () => ({}), // N/A
74+
swap: () => ({}), // N/A
75+
fromTo: () => ({}), // N/A
76+
remove: () => ({}), // N/A
77+
clear: (i) => {
78+
i.value = undefined;
79+
},
80+
},
81+
];
82+
83+
/* eslint-enable no-shadow */
84+
/* eslint-enable no-return-assign */
85+
/* eslint-enable no-plusplus */
86+
/* eslint-enable no-param-reassign */
87+
/* eslint-enable no-sequences */
88+
1089
class Component {
1190
constructor(app, component, props = {}, { el, context, children } = {}) {
1291
const document = getDocument();
@@ -157,6 +236,50 @@ class Component {
157236
return $store;
158237
}
159238

239+
/* eslint-disable no-sequences */
240+
getUseState() {
241+
return (o) =>
242+
[o].reduce(
243+
(t, _i, _x, _a, i = t.init(_i)) => ({
244+
state: i,
245+
update: (v) => (t.update(i, v), this.update()),
246+
remove: (v) => (t.remove(i, v), this.update()),
247+
clear: () => (t.clear(i), this.update()),
248+
insert: (x, v) => (t.insert(i, x, v), this.update()),
249+
replace: (x, v) => (t.replace(i, x, v), this.update()),
250+
append: (v) => (t.append(i, v), this.update()),
251+
prepend: (v) => (t.prepend(i, v), this.update()),
252+
swap: (a, b) => (t.swap(i, a, b), this.update()),
253+
fromTo: (a, b) => (t.fromTo(i, a, b), this.update()),
254+
method: (f = () => ({})) => (f(i), this.update()),
255+
async: (f = () => Promise.reject(i)) => f(i).then(() => this.update()),
256+
}),
257+
types.find((i) => i.type(o)),
258+
);
259+
}
260+
261+
_getUseState() {
262+
return (o) =>
263+
[o].reduce(
264+
(t, _i, _x, _a, i = t.init(_i)) => [
265+
i, // state
266+
(v) => (t.update(i, v), this.update()), // update
267+
(v) => (t.remove(i, v), this.update()), // remove
268+
() => (t.clear(i), this.update()), // clear
269+
(x, v) => (t.insert(i, x, v), this.update()), // insert
270+
(x, v) => (t.replace(i, x, v), this.update()), // replace
271+
(v) => (t.append(i, v), this.update()), // append
272+
(v) => (t.prepend(i, v), this.update()), // prepend
273+
(a, b) => (t.swap(i, a, b), this.update()), // swap
274+
(a, b) => (t.fromTo(i, a, b), this.update()), // fromTo
275+
(f = () => ({})) => (f(i), this.update()), // method
276+
(f = () => Promise.reject(i)) => f(i).then(() => this.update()), // async
277+
],
278+
types.find((i) => i.type(o)),
279+
);
280+
}
281+
/* eslint-enable no-sequences */
282+
160283
getComponentContext(includeHooks) {
161284
const ctx = {
162285
$f7route: this.context.f7route,
@@ -173,6 +296,8 @@ class Component {
173296
$store: this.getComponentStore(),
174297
$ref: this.getComponentRef(),
175298
$el: {},
299+
$useState: this.getUseState(),
300+
$_useState: this._getUseState(),
176301
};
177302
Object.defineProperty(ctx.$el, 'value', {
178303
get: () => {

src/core/modules/component/component.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,22 @@ export interface ComponentContext {
3434
/** Create reactive variable */
3535
$ref: (initialValue: any) => { value: any };
3636

37+
/** Create reactive state */
38+
$useState: (initialValue: any) => {
39+
state: any;
40+
update: (value: any) => void;
41+
remove: (pos: any) => void;
42+
clear: () => void;
43+
insert: (pos: any, value: any) => void;
44+
replace: (pos: any, value: any) => void;
45+
append: (value: any) => void;
46+
prepend: (value: any) => void;
47+
swap: (a: any, b: any) => void;
48+
fromTo: (a: any, b: any) => void;
49+
method: (f: any) => void;
50+
async: (f: any) => void;
51+
};
52+
3753
/** Defer the callback to be executed after the next DOM update cycle. Use it immediately after you’ve changed some data to wait for the DOM update. */
3854
$tick: (callback?: () => void) => Promise<any>;
3955
/** Update/rerender component when state/data changed */

src/core/modules/component/parse-component.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ function parseComponent(componentString) {
6161
var $update = $$ctx.$update;
6262
var $store = $$ctx.$store;
6363
var $ref = $$ctx.$ref;
64+
var $useState = $$ctx.$useState;
6465
6566
return $h\`${template}\`
6667
}

0 commit comments

Comments
 (0)