rumious 2.0.0 → 2.0.2
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/component/component.d.ts +1 -0
- package/dist/component/element.d.ts +4 -2
- package/dist/index.js +26 -20
- package/dist/jsx/component.d.ts +1 -1
- package/dist/jsx/element.d.ts +1 -1
- package/package.json +5 -2
- package/rollup.config.js +0 -21
- package/src/app/app.ts +0 -45
- package/src/app/index.ts +0 -1
- package/src/component/component.ts +0 -69
- package/src/component/element.ts +0 -76
- package/src/component/index.ts +0 -2
- package/src/global.ts +0 -20
- package/src/index.ts +0 -13
- package/src/jsx/component.ts +0 -17
- package/src/jsx/dynamic.ts +0 -87
- package/src/jsx/element.ts +0 -70
- package/src/jsx/index.ts +0 -7
- package/src/jsx/template.ts +0 -377
- package/src/module/index.ts +0 -7
- package/src/ref/index.ts +0 -1
- package/src/ref/ref.ts +0 -178
- package/src/render/context.ts +0 -11
- package/src/render/index.ts +0 -4
- package/src/render/list.ts +0 -115
- package/src/render/render.ts +0 -31
- package/src/render/view.ts +0 -101
- package/src/state/index.ts +0 -2
- package/src/state/list.ts +0 -96
- package/src/state/reactor.ts +0 -65
- package/src/state/state.ts +0 -68
- package/src/types/component.ts +0 -6
- package/src/types/index.ts +0 -3
- package/src/types/state.ts +0 -16
- package/src/types/template.ts +0 -7
- package/src/utils/checker.ts +0 -5
- package/tsconfig.json +0 -20
package/src/jsx/template.ts
DELETED
@@ -1,377 +0,0 @@
|
|
1
|
-
import { RumiousRenderContext, renderFrag, RumiousViewControl } from '../render/index.js';
|
2
|
-
import { RumiousTemplate } from '../types/index.js';
|
3
|
-
import { RumiousRef } from '../ref/index.js';
|
4
|
-
import { RumiousState, RumiousListState } from '../state/index.js';
|
5
|
-
import { createEvent } from './element.js';
|
6
|
-
|
7
|
-
export function createTemplate(
|
8
|
-
fn: (root: HTMLElement | DocumentFragment, context: RumiousRenderContext) => HTMLElement
|
9
|
-
): RumiousTemplate {
|
10
|
-
return Object.assign(fn, {
|
11
|
-
__isTemplate: true as
|
12
|
-
const
|
13
|
-
});
|
14
|
-
}
|
15
|
-
|
16
|
-
|
17
|
-
export function html(
|
18
|
-
h: string
|
19
|
-
): Node {
|
20
|
-
let template = document.createElement('template');
|
21
|
-
template.innerHTML = h;
|
22
|
-
return template.content.cloneNode(true)
|
23
|
-
}
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
export const directives = {
|
28
|
-
ref(context: RumiousRenderContext, modifier: string, target: HTMLElement, value: RumiousRef) {
|
29
|
-
if (value instanceof RumiousRef) {
|
30
|
-
value.setTarget(target);
|
31
|
-
} else {
|
32
|
-
throw new Error("Cannot setup element reference for non-RumiousRef object !");
|
33
|
-
}
|
34
|
-
},
|
35
|
-
|
36
|
-
model(
|
37
|
-
context: RumiousRenderContext,
|
38
|
-
modifier: string,
|
39
|
-
element: HTMLElement,
|
40
|
-
state: RumiousState < any >
|
41
|
-
) {
|
42
|
-
const tag = element.tagName,
|
43
|
-
type = (element as HTMLInputElement).type;
|
44
|
-
|
45
|
-
if (tag === "TEXTAREA") {
|
46
|
-
element.addEventListener("input", () => state.set((element as HTMLTextAreaElement).value));
|
47
|
-
} else if (tag === "SELECT") {
|
48
|
-
element.addEventListener("change", () => {
|
49
|
-
const s = element as HTMLSelectElement;
|
50
|
-
state.set(s.multiple ? Array.from(s.selectedOptions).map(o => o.value) : s.value);
|
51
|
-
});
|
52
|
-
} else if (tag === "INPUT") {
|
53
|
-
if (type === "checkbox") {
|
54
|
-
element.addEventListener("change", () => state.set((element as HTMLInputElement).checked));
|
55
|
-
} else if (type === "radio") {
|
56
|
-
element.addEventListener("change", () => {
|
57
|
-
const i = element as HTMLInputElement;
|
58
|
-
if (i.checked) state.set(i.value);
|
59
|
-
});
|
60
|
-
} else if (type === "file") {
|
61
|
-
element.addEventListener("change", () => {
|
62
|
-
const f = (element as HTMLInputElement).files;
|
63
|
-
state.set(element.hasAttribute("multiple") ? f : f?.[0] ?? null);
|
64
|
-
});
|
65
|
-
} else {
|
66
|
-
element.addEventListener("input", () => {
|
67
|
-
const val = (element as HTMLInputElement).value;
|
68
|
-
state.set(type === "number" ? (val === "" ? null : +val) : val);
|
69
|
-
});
|
70
|
-
}
|
71
|
-
}
|
72
|
-
},
|
73
|
-
|
74
|
-
on(
|
75
|
-
context: RumiousRenderContext,
|
76
|
-
event: string,
|
77
|
-
element: HTMLElement,
|
78
|
-
callback: (e: Event) => void
|
79
|
-
) {
|
80
|
-
createEvent(
|
81
|
-
element,
|
82
|
-
event,
|
83
|
-
callback
|
84
|
-
);
|
85
|
-
},
|
86
|
-
|
87
|
-
bind(
|
88
|
-
context: RumiousRenderContext,
|
89
|
-
modifier: string,
|
90
|
-
element: HTMLElement,
|
91
|
-
state: RumiousState < any >
|
92
|
-
) {
|
93
|
-
let reactive: () => void = () => {};
|
94
|
-
|
95
|
-
switch (modifier) {
|
96
|
-
case 'text':
|
97
|
-
reactive = () => { element.textContent = String(state.get()) };
|
98
|
-
break;
|
99
|
-
|
100
|
-
case 'html':
|
101
|
-
reactive = () => { element.innerHTML = String(state.get()) };
|
102
|
-
break;
|
103
|
-
|
104
|
-
case 'style':
|
105
|
-
reactive = () => {
|
106
|
-
const styles = state.get();
|
107
|
-
if (typeof styles === 'string') {
|
108
|
-
element.setAttribute('style', styles);
|
109
|
-
} else if (typeof styles === 'object') {
|
110
|
-
Object.assign(element.style, styles);
|
111
|
-
}
|
112
|
-
};
|
113
|
-
break;
|
114
|
-
|
115
|
-
case 'class':
|
116
|
-
reactive = () => {
|
117
|
-
const cls = state.get();
|
118
|
-
if (typeof cls === 'string') element.className = cls;
|
119
|
-
else if (Array.isArray(cls)) element.className = cls.join(' ');
|
120
|
-
else if (typeof cls === 'object') {
|
121
|
-
element.className = Object.entries(cls)
|
122
|
-
.filter(([_, active]) => active)
|
123
|
-
.map(([name]) => name)
|
124
|
-
.join(' ');
|
125
|
-
}
|
126
|
-
};
|
127
|
-
break;
|
128
|
-
|
129
|
-
case 'disabled':
|
130
|
-
reactive = () => {
|
131
|
-
if ('disabled' in element)(element as any).disabled = Boolean(state.get());
|
132
|
-
};
|
133
|
-
break;
|
134
|
-
|
135
|
-
case 'checked':
|
136
|
-
reactive = () => {
|
137
|
-
if (element instanceof HTMLInputElement || element instanceof HTMLInputElement) {
|
138
|
-
element.checked = Boolean(state.get());
|
139
|
-
}
|
140
|
-
};
|
141
|
-
break;
|
142
|
-
|
143
|
-
case 'value':
|
144
|
-
reactive = () => {
|
145
|
-
if ('value' in element)(element as any).value = String(state.get());
|
146
|
-
};
|
147
|
-
break;
|
148
|
-
|
149
|
-
default:
|
150
|
-
throw new Error(`Unknown bind directive modifier: ${modifier}`);
|
151
|
-
}
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
function onStateChange(commit: any) {
|
156
|
-
if (!document.contains(element) && state.reactor) {
|
157
|
-
state.reactor.removeInternalBinding(onStateChange);
|
158
|
-
return;
|
159
|
-
}
|
160
|
-
reactive();
|
161
|
-
}
|
162
|
-
|
163
|
-
context.onRendered.push(() => {
|
164
|
-
reactive();
|
165
|
-
if (!state.reactor) return;
|
166
|
-
state.reactor.addInternalBinding(onStateChange);
|
167
|
-
});
|
168
|
-
},
|
169
|
-
|
170
|
-
attr(
|
171
|
-
context: RumiousRenderContext,
|
172
|
-
attrName: string,
|
173
|
-
element: HTMLElement,
|
174
|
-
state: RumiousState < any >
|
175
|
-
) {
|
176
|
-
|
177
|
-
function onStateChange(commit ? : any) {
|
178
|
-
if (!document.contains(element) && state.reactor) {
|
179
|
-
state.reactor.removeInternalBinding(onStateChange);
|
180
|
-
return;
|
181
|
-
}
|
182
|
-
element.setAttribute(attrName, String(state.get()));
|
183
|
-
}
|
184
|
-
|
185
|
-
context.onRendered.push(() => {
|
186
|
-
onStateChange();
|
187
|
-
if (!state.reactor) return;
|
188
|
-
state.reactor.addInternalBinding(onStateChange);
|
189
|
-
});
|
190
|
-
},
|
191
|
-
|
192
|
-
prop(
|
193
|
-
context: RumiousRenderContext,
|
194
|
-
name: string,
|
195
|
-
element: HTMLElement,
|
196
|
-
state: RumiousState < any >
|
197
|
-
) {
|
198
|
-
|
199
|
-
function onStateChange(commit ? : any) {
|
200
|
-
if (!document.contains(element) && state.reactor) {
|
201
|
-
state.reactor.removeInternalBinding(onStateChange);
|
202
|
-
return;
|
203
|
-
}
|
204
|
-
(element as any)[name] = state.get();
|
205
|
-
}
|
206
|
-
|
207
|
-
context.onRendered.push(() => {
|
208
|
-
onStateChange();
|
209
|
-
if (!state.reactor) return;
|
210
|
-
state.reactor.addInternalBinding(onStateChange);
|
211
|
-
});
|
212
|
-
},
|
213
|
-
|
214
|
-
html(
|
215
|
-
context: RumiousRenderContext,
|
216
|
-
modifier: string,
|
217
|
-
element: HTMLElement,
|
218
|
-
state: RumiousState < any >
|
219
|
-
) {
|
220
|
-
|
221
|
-
function onStateChange(commit ? : any) {
|
222
|
-
if (!document.contains(element) && state.reactor) {
|
223
|
-
state.reactor.removeInternalBinding(onStateChange);
|
224
|
-
return;
|
225
|
-
}
|
226
|
-
element.innerHTML = String(state.get());
|
227
|
-
}
|
228
|
-
|
229
|
-
context.onRendered.push(() => {
|
230
|
-
onStateChange();
|
231
|
-
if (!state.reactor) return;
|
232
|
-
state.reactor.addInternalBinding(onStateChange);
|
233
|
-
});
|
234
|
-
},
|
235
|
-
|
236
|
-
show(
|
237
|
-
context: RumiousRenderContext,
|
238
|
-
modifier: string,
|
239
|
-
element: HTMLElement,
|
240
|
-
state: RumiousState < any >
|
241
|
-
) {
|
242
|
-
|
243
|
-
function onStateChange(commit ? : any) {
|
244
|
-
if (!document.contains(element) && state.reactor) {
|
245
|
-
state.reactor.removeInternalBinding(onStateChange);
|
246
|
-
return;
|
247
|
-
}
|
248
|
-
element.style.display = Boolean(state.get()) ? 'block' : 'none';
|
249
|
-
}
|
250
|
-
|
251
|
-
context.onRendered.push(() => {
|
252
|
-
onStateChange();
|
253
|
-
if (!state.reactor) return;
|
254
|
-
state.reactor.addInternalBinding(onStateChange);
|
255
|
-
});
|
256
|
-
},
|
257
|
-
|
258
|
-
hide(
|
259
|
-
context: RumiousRenderContext,
|
260
|
-
modifier: string,
|
261
|
-
element: HTMLElement,
|
262
|
-
state: RumiousState < any >
|
263
|
-
) {
|
264
|
-
|
265
|
-
function onStateChange(commit ? : any) {
|
266
|
-
if (!document.contains(element) && state.reactor) {
|
267
|
-
state.reactor.removeInternalBinding(onStateChange);
|
268
|
-
return;
|
269
|
-
}
|
270
|
-
element.style.display = !Boolean(state.get()) ? 'block' : 'none';
|
271
|
-
}
|
272
|
-
|
273
|
-
context.onRendered.push(() => {
|
274
|
-
onStateChange();
|
275
|
-
if (!state.reactor) return;
|
276
|
-
state.reactor.addInternalBinding(onStateChange);
|
277
|
-
});
|
278
|
-
},
|
279
|
-
|
280
|
-
each < T > (
|
281
|
-
context: RumiousRenderContext,
|
282
|
-
modifier: string,
|
283
|
-
element: HTMLElement,
|
284
|
-
configs: EachDirectiveConfig < T >
|
285
|
-
) {
|
286
|
-
|
287
|
-
context = new RumiousRenderContext(
|
288
|
-
context.app,
|
289
|
-
context.target
|
290
|
-
);
|
291
|
-
|
292
|
-
const keyToNode = new Map < string,
|
293
|
-
Node > ();
|
294
|
-
const nodeOrder: string[] = [];
|
295
|
-
|
296
|
-
for (const item of configs.value.value) {
|
297
|
-
const key = configs.key(item);
|
298
|
-
const templ = renderFrag(configs.templ(item, key), context);
|
299
|
-
const dom = templ.childNodes[0] as Node;
|
300
|
-
keyToNode.set(key, dom);
|
301
|
-
nodeOrder.push(key);
|
302
|
-
element.appendChild(dom);
|
303
|
-
}
|
304
|
-
|
305
|
-
if (!configs.value.reactor) return;
|
306
|
-
|
307
|
-
configs.value.reactor.addInternalBinding((commit) => {
|
308
|
-
const value = commit.value;
|
309
|
-
const key = configs.key(value);
|
310
|
-
|
311
|
-
if (commit.type === 'remove') {
|
312
|
-
const oldDom = keyToNode.get(key);
|
313
|
-
if (oldDom) {
|
314
|
-
element.removeChild(oldDom);
|
315
|
-
keyToNode.delete(key);
|
316
|
-
const index = nodeOrder.indexOf(key);
|
317
|
-
if (index !== -1) nodeOrder.splice(index, 1);
|
318
|
-
}
|
319
|
-
return;
|
320
|
-
}
|
321
|
-
|
322
|
-
const templ = renderFrag(configs.templ(value, key), context);
|
323
|
-
const dom = templ.childNodes[0] as Node;
|
324
|
-
|
325
|
-
switch (commit.type) {
|
326
|
-
case 'append':
|
327
|
-
keyToNode.set(key, dom);
|
328
|
-
nodeOrder.push(key);
|
329
|
-
element.appendChild(dom);
|
330
|
-
break;
|
331
|
-
|
332
|
-
case 'prepend':
|
333
|
-
keyToNode.set(key, dom);
|
334
|
-
nodeOrder.unshift(key);
|
335
|
-
element.prepend(dom);
|
336
|
-
break;
|
337
|
-
|
338
|
-
case 'update': {
|
339
|
-
const oldDom = keyToNode.get(key);
|
340
|
-
if (oldDom) {
|
341
|
-
keyToNode.set(key, dom);
|
342
|
-
element.replaceChild(dom, oldDom);
|
343
|
-
}
|
344
|
-
break;
|
345
|
-
}
|
346
|
-
|
347
|
-
case 'insert': {
|
348
|
-
const index = commit.key!;
|
349
|
-
const anchorKey = nodeOrder[index];
|
350
|
-
const anchorNode = keyToNode.get(anchorKey) ?? null;
|
351
|
-
keyToNode.set(key, dom);
|
352
|
-
nodeOrder.splice(index, 0, key);
|
353
|
-
element.insertBefore(dom, anchorNode);
|
354
|
-
break;
|
355
|
-
}
|
356
|
-
}
|
357
|
-
});
|
358
|
-
},
|
359
|
-
|
360
|
-
view(
|
361
|
-
context: RumiousRenderContext,
|
362
|
-
modifier: string,
|
363
|
-
element: HTMLElement,
|
364
|
-
configs: RumiousViewControl
|
365
|
-
) {
|
366
|
-
configs.addTarget({
|
367
|
-
element,
|
368
|
-
context
|
369
|
-
});
|
370
|
-
}
|
371
|
-
}
|
372
|
-
|
373
|
-
interface EachDirectiveConfig < T > {
|
374
|
-
value: RumiousListState < T > ;
|
375
|
-
key: (item: T) => string;
|
376
|
-
templ: (item: T, key: string) => RumiousTemplate;
|
377
|
-
}
|
package/src/module/index.ts
DELETED
package/src/ref/index.ts
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
export * from './ref.js';
|
package/src/ref/ref.ts
DELETED
@@ -1,178 +0,0 @@
|
|
1
|
-
import {
|
2
|
-
RumiousComponent,
|
3
|
-
RumiousComponentElement
|
4
|
-
} from '../component/index.js';
|
5
|
-
|
6
|
-
export class RumiousRef {
|
7
|
-
public element!: HTMLElement;
|
8
|
-
private _mounted = false;
|
9
|
-
private _onMountCallbacks: ((el: HTMLElement) => void)[] = [];
|
10
|
-
private _onUnmountCallbacks: (() => void)[] = [];
|
11
|
-
|
12
|
-
constructor() {}
|
13
|
-
|
14
|
-
setTarget(element: HTMLElement) {
|
15
|
-
this.element = element;
|
16
|
-
this._mounted = true;
|
17
|
-
for (const cb of this._onMountCallbacks) {
|
18
|
-
cb(element);
|
19
|
-
}
|
20
|
-
}
|
21
|
-
|
22
|
-
reset() {
|
23
|
-
if (this._mounted) {
|
24
|
-
for (const cb of this._onUnmountCallbacks) {
|
25
|
-
cb();
|
26
|
-
}
|
27
|
-
}
|
28
|
-
this.element = undefined as any;
|
29
|
-
this._mounted = false;
|
30
|
-
}
|
31
|
-
|
32
|
-
get(): HTMLElement | undefined {
|
33
|
-
return this._mounted ? this.element : undefined;
|
34
|
-
}
|
35
|
-
|
36
|
-
isMounted(): boolean {
|
37
|
-
return this._mounted;
|
38
|
-
}
|
39
|
-
|
40
|
-
has(): boolean {
|
41
|
-
return this.isMounted();
|
42
|
-
}
|
43
|
-
|
44
|
-
onMount(cb: (el: HTMLElement) => void) {
|
45
|
-
this._onMountCallbacks.push(cb);
|
46
|
-
if (this._mounted) cb(this.element);
|
47
|
-
}
|
48
|
-
|
49
|
-
onUnmount(cb: () => void) {
|
50
|
-
this._onUnmountCallbacks.push(cb);
|
51
|
-
}
|
52
|
-
|
53
|
-
toString(): string {
|
54
|
-
return `[RumiousRef ${this._mounted ? "mounted" : "not mounted"}]`;
|
55
|
-
}
|
56
|
-
|
57
|
-
|
58
|
-
focus() {
|
59
|
-
this.assertMounted();
|
60
|
-
this.element.focus();
|
61
|
-
}
|
62
|
-
|
63
|
-
addClass(className: string) {
|
64
|
-
this.assertMounted();
|
65
|
-
this.element.classList.add(className);
|
66
|
-
}
|
67
|
-
|
68
|
-
removeClass(className: string) {
|
69
|
-
this.assertMounted();
|
70
|
-
this.element.classList.remove(className);
|
71
|
-
}
|
72
|
-
|
73
|
-
toggleClass(className: string) {
|
74
|
-
this.assertMounted();
|
75
|
-
this.element.classList.toggle(className);
|
76
|
-
}
|
77
|
-
|
78
|
-
setAttr(key: string, value: string) {
|
79
|
-
this.assertMounted();
|
80
|
-
this.element.setAttribute(key, value);
|
81
|
-
}
|
82
|
-
|
83
|
-
removeAttr(key: string) {
|
84
|
-
this.assertMounted();
|
85
|
-
this.element.removeAttribute(key);
|
86
|
-
}
|
87
|
-
|
88
|
-
query < T extends Element = Element > (selector: string): T | null {
|
89
|
-
this.assertMounted();
|
90
|
-
return this.element.querySelector < T > (selector);
|
91
|
-
}
|
92
|
-
|
93
|
-
queryAll < T extends Element = Element > (selector: string): NodeListOf < T > {
|
94
|
-
this.assertMounted();
|
95
|
-
return this.element.querySelectorAll < T > (selector);
|
96
|
-
}
|
97
|
-
|
98
|
-
get value(): string | undefined {
|
99
|
-
this.assertMounted();
|
100
|
-
return 'value' in this.element ? (this.element as any).value : undefined;
|
101
|
-
}
|
102
|
-
|
103
|
-
set value(val: string | undefined) {
|
104
|
-
this.assertMounted();
|
105
|
-
if ('value' in this.element) {
|
106
|
-
(this.element as any).value = val;
|
107
|
-
} else {
|
108
|
-
throw new Error("RumiousRefError: Element has no 'value' property.");
|
109
|
-
}
|
110
|
-
}
|
111
|
-
|
112
|
-
get text(): string | null {
|
113
|
-
this.assertMounted();
|
114
|
-
return this.element.textContent;
|
115
|
-
}
|
116
|
-
|
117
|
-
set text(val: string | null) {
|
118
|
-
this.assertMounted();
|
119
|
-
this.element.textContent = val;
|
120
|
-
}
|
121
|
-
|
122
|
-
get html(): string {
|
123
|
-
this.assertMounted();
|
124
|
-
return this.element.innerHTML;
|
125
|
-
}
|
126
|
-
|
127
|
-
set html(val: string) {
|
128
|
-
this.assertMounted();
|
129
|
-
this.element.innerHTML = val;
|
130
|
-
}
|
131
|
-
|
132
|
-
get checked(): boolean {
|
133
|
-
this.assertMounted();
|
134
|
-
return 'checked' in this.element ? Boolean((this.element as any).checked) : false;
|
135
|
-
}
|
136
|
-
|
137
|
-
set checked(val: boolean) {
|
138
|
-
this.assertMounted();
|
139
|
-
if ('checked' in this.element) {
|
140
|
-
(this.element as any).checked = val;
|
141
|
-
} else {
|
142
|
-
throw new Error("RumiousRefError: Element has no 'checked' property.");
|
143
|
-
}
|
144
|
-
}
|
145
|
-
|
146
|
-
get disabled(): boolean {
|
147
|
-
this.assertMounted();
|
148
|
-
return 'disabled' in this.element ? Boolean((this.element as any).disabled) : false;
|
149
|
-
}
|
150
|
-
|
151
|
-
set disabled(val: boolean) {
|
152
|
-
this.assertMounted();
|
153
|
-
if ('disabled' in this.element) {
|
154
|
-
(this.element as any).disabled = val;
|
155
|
-
} else {
|
156
|
-
throw new Error("RumiousRefError: Element has no 'disabled' property.");
|
157
|
-
}
|
158
|
-
}
|
159
|
-
|
160
|
-
get component():RumiousComponent | null{
|
161
|
-
if(this.element instanceof RumiousComponentElement){
|
162
|
-
return this.element.instance;
|
163
|
-
}else{
|
164
|
-
return null;
|
165
|
-
}
|
166
|
-
}
|
167
|
-
|
168
|
-
private assertMounted() {
|
169
|
-
if (!this._mounted) {
|
170
|
-
throw new Error("RumiousRefError: Element is not mounted.");
|
171
|
-
}
|
172
|
-
}
|
173
|
-
}
|
174
|
-
|
175
|
-
|
176
|
-
export function createRef(): RumiousRef {
|
177
|
-
return new RumiousRef();
|
178
|
-
}
|
package/src/render/context.ts
DELETED
package/src/render/index.ts
DELETED
package/src/render/list.ts
DELETED
@@ -1,115 +0,0 @@
|
|
1
|
-
import { RumiousViewControl } from './view.js';
|
2
|
-
import { RumiousListState, RumiousState } from '../state/index.js';
|
3
|
-
import { RumiousTemplate, RumiousChangeCommit } from '../types/index.js';
|
4
|
-
import { renderFrag } from '../render/index.js';
|
5
|
-
|
6
|
-
|
7
|
-
export class RumiousPagination < T > {
|
8
|
-
public currentPage = 0;
|
9
|
-
public limit = 50;
|
10
|
-
public pos = [0, 0];
|
11
|
-
constructor(
|
12
|
-
public view: RumiousViewControl,
|
13
|
-
public data: RumiousListState < T > ,
|
14
|
-
public templFn: (data: T) => RumiousTemplate,
|
15
|
-
public keyFn: (data: T) => string
|
16
|
-
) {}
|
17
|
-
|
18
|
-
show() {
|
19
|
-
|
20
|
-
let [start, end] = this.calcPos();
|
21
|
-
let list = this.data.value.slice(start, end);
|
22
|
-
this.pos = [start, end];
|
23
|
-
for (let data of list) {
|
24
|
-
let key = this.keyFn(data);
|
25
|
-
let templ = this.templFn(data);
|
26
|
-
this.view.addChild(templ);
|
27
|
-
}
|
28
|
-
|
29
|
-
if (!this.data.reactor) return;
|
30
|
-
this.data.reactor.addInternalBinding(this.onDataChange.bind(this));
|
31
|
-
}
|
32
|
-
|
33
|
-
calcPos(): [number, number] {
|
34
|
-
const size = this.data.value.length;
|
35
|
-
const totalPage = Math.ceil(size / this.limit);
|
36
|
-
const currentPage = Math.max(0, Math.min(this.currentPage, totalPage - 1));
|
37
|
-
const start = currentPage * this.limit;
|
38
|
-
const end = Math.min(start + this.limit, size);
|
39
|
-
return [start, end];
|
40
|
-
}
|
41
|
-
|
42
|
-
|
43
|
-
onDataChange(commit: RumiousChangeCommit < RumiousState < T[] >> ) {
|
44
|
-
const [start, end] = this.calcPos();
|
45
|
-
const total = this.data.value.length;
|
46
|
-
|
47
|
-
const { type, key, value } = commit;
|
48
|
-
|
49
|
-
if (type === 'set') {
|
50
|
-
this.view.emptyAll();
|
51
|
-
this.show();
|
52
|
-
return;
|
53
|
-
}
|
54
|
-
|
55
|
-
if (typeof key === 'number' && key < start) {
|
56
|
-
this.view.emptyAll();
|
57
|
-
this.show();
|
58
|
-
return;
|
59
|
-
}
|
60
|
-
|
61
|
-
if (typeof key === 'number' && key >= start && key < end) {
|
62
|
-
const indexInView = key - start;
|
63
|
-
|
64
|
-
switch (type) {
|
65
|
-
case 'update': {
|
66
|
-
const item = this.data.value[key];
|
67
|
-
const templ = this.templFn(item);
|
68
|
-
this.view.updateChild(indexInView, templ);
|
69
|
-
break;
|
70
|
-
}
|
71
|
-
|
72
|
-
case 'remove': {
|
73
|
-
this.view.removeChild(indexInView);
|
74
|
-
|
75
|
-
const extraIndex = end - 1;
|
76
|
-
if (extraIndex < total) {
|
77
|
-
const extraItem = this.data.value[extraIndex];
|
78
|
-
const extraTemplate = this.templFn(extraItem);
|
79
|
-
this.view.addChild(extraTemplate);
|
80
|
-
}
|
81
|
-
break;
|
82
|
-
}
|
83
|
-
|
84
|
-
case 'insert':
|
85
|
-
case 'prepend': {
|
86
|
-
const item = this.data.value[key];
|
87
|
-
const templ = this.templFn(item);
|
88
|
-
this.view.addChild(templ, true);
|
89
|
-
const currentViewSize = end - start + 1;
|
90
|
-
if (currentViewSize > this.limit) {
|
91
|
-
this.view.removeChild(this.limit);
|
92
|
-
}
|
93
|
-
break;
|
94
|
-
}
|
95
|
-
|
96
|
-
case 'append': {
|
97
|
-
if (key < start + this.limit) {
|
98
|
-
const item = this.data.value[key];
|
99
|
-
const templ = this.templFn(item);
|
100
|
-
this.view.addChild(templ);
|
101
|
-
|
102
|
-
const currentViewSize = end - start + 1;
|
103
|
-
if (currentViewSize > this.limit) {
|
104
|
-
this.view.removeChild(0);
|
105
|
-
}
|
106
|
-
}
|
107
|
-
break;
|
108
|
-
}
|
109
|
-
}
|
110
|
-
|
111
|
-
return;
|
112
|
-
}
|
113
|
-
|
114
|
-
}
|
115
|
-
}
|