rumious 2.1.5 → 2.1.6

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.
@@ -1,281 +0,0 @@
1
- import { RumiousRenderContext, renderFrag } from '../render/index.js';
2
- import { RumiousRef } from '../ref/index.js';
3
- import { createEvent } from './element.js';
4
- export function createTemplate(fn) {
5
- return Object.assign(fn, {
6
- __isTemplate: true
7
- });
8
- }
9
- export function html(h) {
10
- let template = document.createElement('template');
11
- template.innerHTML = h;
12
- return template.content.cloneNode(true);
13
- }
14
- export const directives = {
15
- ref(context, modifier, target, value) {
16
- if (value instanceof RumiousRef) {
17
- value.setTarget(target);
18
- }
19
- else {
20
- throw new Error("Cannot setup element reference for non-RumiousRef object !");
21
- }
22
- },
23
- model(context, modifier, element, state) {
24
- const tag = element.tagName, type = element.type;
25
- if (tag === "TEXTAREA") {
26
- element.addEventListener("input", () => state.set(element.value));
27
- }
28
- else if (tag === "SELECT") {
29
- element.addEventListener("change", () => {
30
- const s = element;
31
- state.set(s.multiple ? Array.from(s.selectedOptions).map(o => o.value) : s.value);
32
- });
33
- }
34
- else if (tag === "INPUT") {
35
- if (type === "checkbox") {
36
- element.addEventListener("change", () => state.set(element.checked));
37
- }
38
- else if (type === "radio") {
39
- element.addEventListener("change", () => {
40
- const i = element;
41
- if (i.checked)
42
- state.set(i.value);
43
- });
44
- }
45
- else if (type === "file") {
46
- element.addEventListener("change", () => {
47
- const f = element.files;
48
- state.set(element.hasAttribute("multiple") ? f : f?.[0] ?? null);
49
- });
50
- }
51
- else {
52
- element.addEventListener("input", () => {
53
- const val = element.value;
54
- state.set(type === "number" ? (val === "" ? null : +val) : val);
55
- });
56
- }
57
- }
58
- },
59
- on(context, event, element, callback) {
60
- createEvent(element, event, callback);
61
- },
62
- bind(context, modifier, element, state) {
63
- let reactive = () => { };
64
- switch (modifier) {
65
- case 'text':
66
- reactive = () => { element.textContent = String(state.get()); };
67
- break;
68
- case 'html':
69
- reactive = () => { element.innerHTML = String(state.get()); };
70
- break;
71
- case 'style':
72
- reactive = () => {
73
- const styles = state.get();
74
- if (typeof styles === 'string') {
75
- element.setAttribute('style', styles);
76
- }
77
- else if (typeof styles === 'object') {
78
- Object.assign(element.style, styles);
79
- }
80
- };
81
- break;
82
- case 'class':
83
- reactive = () => {
84
- const cls = state.get();
85
- if (typeof cls === 'string')
86
- element.className = cls;
87
- else if (Array.isArray(cls))
88
- element.className = cls.join(' ');
89
- else if (typeof cls === 'object') {
90
- element.className = Object.entries(cls)
91
- .filter(([_, active]) => active)
92
- .map(([name]) => name)
93
- .join(' ');
94
- }
95
- };
96
- break;
97
- case 'disabled':
98
- reactive = () => {
99
- if ('disabled' in element)
100
- element.disabled = Boolean(state.get());
101
- };
102
- break;
103
- case 'checked':
104
- reactive = () => {
105
- if (element instanceof HTMLInputElement || element instanceof HTMLInputElement) {
106
- element.checked = Boolean(state.get());
107
- }
108
- };
109
- break;
110
- case 'value':
111
- reactive = () => {
112
- if ('value' in element)
113
- element.value = String(state.get());
114
- };
115
- break;
116
- case 'show':
117
- reactive = () => element.style.display = state.get() ? '' : 'none';
118
- break;
119
- case 'hide':
120
- reactive = () => element.style.display = state.get() ? 'none' : '';
121
- break;
122
- default:
123
- throw new Error(`Unknown bind directive modifier: ${modifier}`);
124
- }
125
- function onStateChange(commit) {
126
- if (!document.contains(element) && state.reactor) {
127
- state.reactor.removeInternalBinding(onStateChange);
128
- return;
129
- }
130
- reactive();
131
- }
132
- context.onRendered.push(() => {
133
- reactive();
134
- if (!state.reactor)
135
- return;
136
- state.reactor.addInternalBinding(onStateChange);
137
- });
138
- },
139
- attr(context, attrName, element, state) {
140
- function onStateChange(commit) {
141
- if (!document.contains(element) && state.reactor) {
142
- state.reactor.removeInternalBinding(onStateChange);
143
- return;
144
- }
145
- element.setAttribute(attrName, String(state.get()));
146
- }
147
- context.onRendered.push(() => {
148
- onStateChange();
149
- if (!state.reactor)
150
- return;
151
- state.reactor.addInternalBinding(onStateChange);
152
- });
153
- },
154
- prop(context, name, element, state) {
155
- function onStateChange(commit) {
156
- if (!document.contains(element) && state.reactor) {
157
- state.reactor.removeInternalBinding(onStateChange);
158
- return;
159
- }
160
- element[name] = state.get();
161
- }
162
- context.onRendered.push(() => {
163
- onStateChange();
164
- if (!state.reactor)
165
- return;
166
- state.reactor.addInternalBinding(onStateChange);
167
- });
168
- },
169
- html(context, modifier, element, state) {
170
- function onStateChange(commit) {
171
- if (!document.contains(element) && state.reactor) {
172
- state.reactor.removeInternalBinding(onStateChange);
173
- return;
174
- }
175
- element.innerHTML = String(state.get());
176
- }
177
- context.onRendered.push(() => {
178
- onStateChange();
179
- if (!state.reactor)
180
- return;
181
- state.reactor.addInternalBinding(onStateChange);
182
- });
183
- },
184
- show(context, modifier, element, state) {
185
- function onStateChange(commit) {
186
- if (!document.contains(element) && state.reactor) {
187
- state.reactor.removeInternalBinding(onStateChange);
188
- return;
189
- }
190
- element.style.display = Boolean(state.get()) ? 'block' : 'none';
191
- }
192
- context.onRendered.push(() => {
193
- onStateChange();
194
- if (!state.reactor)
195
- return;
196
- state.reactor.addInternalBinding(onStateChange);
197
- });
198
- },
199
- hide(context, modifier, element, state) {
200
- function onStateChange(commit) {
201
- if (!document.contains(element) && state.reactor) {
202
- state.reactor.removeInternalBinding(onStateChange);
203
- return;
204
- }
205
- element.style.display = !Boolean(state.get()) ? 'block' : 'none';
206
- }
207
- context.onRendered.push(() => {
208
- onStateChange();
209
- if (!state.reactor)
210
- return;
211
- state.reactor.addInternalBinding(onStateChange);
212
- });
213
- },
214
- each(context, modifier, element, configs) {
215
- context = new RumiousRenderContext(context.app, context.target);
216
- const keyToNode = new Map();
217
- const nodeOrder = [];
218
- for (const item of configs.value.value) {
219
- const key = configs.key(item);
220
- const templ = renderFrag(configs.templ(item, key), context);
221
- const dom = templ.childNodes[0];
222
- keyToNode.set(key, dom);
223
- nodeOrder.push(key);
224
- element.appendChild(dom);
225
- }
226
- if (!configs.value.reactor)
227
- return;
228
- configs.value.reactor.addInternalBinding((commit) => {
229
- const value = commit.value;
230
- const key = configs.key(value);
231
- if (commit.type === 'remove') {
232
- const oldDom = keyToNode.get(key);
233
- if (oldDom) {
234
- element.removeChild(oldDom);
235
- keyToNode.delete(key);
236
- const index = nodeOrder.indexOf(key);
237
- if (index !== -1)
238
- nodeOrder.splice(index, 1);
239
- }
240
- return;
241
- }
242
- const templ = renderFrag(configs.templ(value, key), context);
243
- const dom = templ.childNodes[0];
244
- switch (commit.type) {
245
- case 'append':
246
- keyToNode.set(key, dom);
247
- nodeOrder.push(key);
248
- element.appendChild(dom);
249
- break;
250
- case 'prepend':
251
- keyToNode.set(key, dom);
252
- nodeOrder.unshift(key);
253
- element.prepend(dom);
254
- break;
255
- case 'update': {
256
- const oldDom = keyToNode.get(key);
257
- if (oldDom) {
258
- keyToNode.set(key, dom);
259
- element.replaceChild(dom, oldDom);
260
- }
261
- break;
262
- }
263
- case 'insert': {
264
- const index = commit.key;
265
- const anchorKey = nodeOrder[index];
266
- const anchorNode = keyToNode.get(anchorKey) ?? null;
267
- keyToNode.set(key, dom);
268
- nodeOrder.splice(index, 0, key);
269
- element.insertBefore(dom, anchorNode);
270
- break;
271
- }
272
- }
273
- });
274
- },
275
- view(context, modifier, element, configs) {
276
- configs.addTarget({
277
- element,
278
- context
279
- });
280
- }
281
- };
@@ -1,2 +0,0 @@
1
- export class RumiousModule {
2
- }
package/dist/ref/index.js DELETED
@@ -1 +0,0 @@
1
- export * from './ref.js';
package/dist/ref/ref.js DELETED
@@ -1,147 +0,0 @@
1
- import { RumiousComponentElement } from '../component/index.js';
2
- export class RumiousRef {
3
- element;
4
- _mounted = false;
5
- _onMountCallbacks = [];
6
- _onUnmountCallbacks = [];
7
- constructor() { }
8
- setTarget(element) {
9
- this.element = element;
10
- this._mounted = true;
11
- for (const cb of this._onMountCallbacks) {
12
- cb(element);
13
- }
14
- }
15
- reset() {
16
- if (this._mounted) {
17
- for (const cb of this._onUnmountCallbacks) {
18
- cb();
19
- }
20
- }
21
- this.element = undefined;
22
- this._mounted = false;
23
- }
24
- get() {
25
- return this._mounted ? this.element : undefined;
26
- }
27
- isMounted() {
28
- return this._mounted;
29
- }
30
- has() {
31
- return this.isMounted();
32
- }
33
- onMount(cb) {
34
- this._onMountCallbacks.push(cb);
35
- if (this._mounted)
36
- cb(this.element);
37
- }
38
- onUnmount(cb) {
39
- this._onUnmountCallbacks.push(cb);
40
- }
41
- toString() {
42
- return `[RumiousRef ${this._mounted ? "mounted" : "not mounted"}]`;
43
- }
44
- focus() {
45
- this.assertMounted();
46
- this.element.focus();
47
- }
48
- addClass(className) {
49
- this.assertMounted();
50
- this.element.classList.add(className);
51
- }
52
- removeClass(className) {
53
- this.assertMounted();
54
- this.element.classList.remove(className);
55
- }
56
- toggleClass(className) {
57
- this.assertMounted();
58
- this.element.classList.toggle(className);
59
- }
60
- setAttr(key, value) {
61
- this.assertMounted();
62
- this.element.setAttribute(key, value);
63
- }
64
- removeAttr(key) {
65
- this.assertMounted();
66
- this.element.removeAttribute(key);
67
- }
68
- query(selector) {
69
- this.assertMounted();
70
- return this.element.querySelector(selector);
71
- }
72
- queryAll(selector) {
73
- this.assertMounted();
74
- return this.element.querySelectorAll(selector);
75
- }
76
- get value() {
77
- this.assertMounted();
78
- return 'value' in this.element ? this.element.value : undefined;
79
- }
80
- set value(val) {
81
- this.assertMounted();
82
- if ('value' in this.element) {
83
- this.element.value = val;
84
- }
85
- else {
86
- throw new Error("RumiousRefError: Element has no 'value' property.");
87
- }
88
- }
89
- get text() {
90
- this.assertMounted();
91
- return this.element.textContent;
92
- }
93
- set text(val) {
94
- this.assertMounted();
95
- this.element.textContent = val;
96
- }
97
- get html() {
98
- this.assertMounted();
99
- return this.element.innerHTML;
100
- }
101
- set html(val) {
102
- this.assertMounted();
103
- this.element.innerHTML = val;
104
- }
105
- get checked() {
106
- this.assertMounted();
107
- return 'checked' in this.element ? Boolean(this.element.checked) : false;
108
- }
109
- set checked(val) {
110
- this.assertMounted();
111
- if ('checked' in this.element) {
112
- this.element.checked = val;
113
- }
114
- else {
115
- throw new Error("RumiousRefError: Element has no 'checked' property.");
116
- }
117
- }
118
- get disabled() {
119
- this.assertMounted();
120
- return 'disabled' in this.element ? Boolean(this.element.disabled) : false;
121
- }
122
- set disabled(val) {
123
- this.assertMounted();
124
- if ('disabled' in this.element) {
125
- this.element.disabled = val;
126
- }
127
- else {
128
- throw new Error("RumiousRefError: Element has no 'disabled' property.");
129
- }
130
- }
131
- get component() {
132
- if (this.element instanceof RumiousComponentElement) {
133
- return this.element.instance;
134
- }
135
- else {
136
- return null;
137
- }
138
- }
139
- assertMounted() {
140
- if (!this._mounted) {
141
- throw new Error("RumiousRefError: Element is not mounted.");
142
- }
143
- }
144
- }
145
- export function createRef() {
146
- return new RumiousRef();
147
- }
@@ -1,9 +0,0 @@
1
- export class RumiousRenderContext {
2
- app;
3
- target;
4
- onRendered = [];
5
- constructor(app, target) {
6
- this.app = app;
7
- this.target = target;
8
- }
9
- }
@@ -1,4 +0,0 @@
1
- export * from './context.js';
2
- export * from './render.js';
3
- export * from './view.js';
4
- export * from './list.js';
@@ -1,96 +0,0 @@
1
- export class RumiousPagination {
2
- view;
3
- data;
4
- templFn;
5
- keyFn;
6
- currentPage = 0;
7
- limit = 50;
8
- pos = [0, 0];
9
- constructor(view, data, templFn, keyFn) {
10
- this.view = view;
11
- this.data = data;
12
- this.templFn = templFn;
13
- this.keyFn = keyFn;
14
- }
15
- show() {
16
- let [start, end] = this.calcPos();
17
- let list = this.data.value.slice(start, end);
18
- this.pos = [start, end];
19
- for (let data of list) {
20
- let key = this.keyFn(data);
21
- let templ = this.templFn(data);
22
- this.view.addChild(templ);
23
- }
24
- if (!this.data.reactor)
25
- return;
26
- this.data.reactor.addInternalBinding(this.onDataChange.bind(this));
27
- }
28
- calcPos() {
29
- const size = this.data.value.length;
30
- const totalPage = Math.ceil(size / this.limit);
31
- const currentPage = Math.max(0, Math.min(this.currentPage, totalPage - 1));
32
- const start = currentPage * this.limit;
33
- const end = Math.min(start + this.limit, size);
34
- return [start, end];
35
- }
36
- onDataChange(commit) {
37
- const [start, end] = this.calcPos();
38
- const total = this.data.value.length;
39
- const { type, key, value } = commit;
40
- if (type === 'set') {
41
- this.view.emptyAll();
42
- this.show();
43
- return;
44
- }
45
- if (typeof key === 'number' && key < start) {
46
- this.view.emptyAll();
47
- this.show();
48
- return;
49
- }
50
- if (typeof key === 'number' && key >= start && key < end) {
51
- const indexInView = key - start;
52
- switch (type) {
53
- case 'update': {
54
- const item = this.data.value[key];
55
- const templ = this.templFn(item);
56
- this.view.updateChild(indexInView, templ);
57
- break;
58
- }
59
- case 'remove': {
60
- this.view.removeChild(indexInView);
61
- const extraIndex = end - 1;
62
- if (extraIndex < total) {
63
- const extraItem = this.data.value[extraIndex];
64
- const extraTemplate = this.templFn(extraItem);
65
- this.view.addChild(extraTemplate);
66
- }
67
- break;
68
- }
69
- case 'insert':
70
- case 'prepend': {
71
- const item = this.data.value[key];
72
- const templ = this.templFn(item);
73
- this.view.addChild(templ, true);
74
- const currentViewSize = end - start + 1;
75
- if (currentViewSize > this.limit) {
76
- this.view.removeChild(this.limit);
77
- }
78
- break;
79
- }
80
- case 'append': {
81
- if (key < start + this.limit) {
82
- const item = this.data.value[key];
83
- const templ = this.templFn(item);
84
- this.view.addChild(templ);
85
- const currentViewSize = end - start + 1;
86
- if (currentViewSize > this.limit) {
87
- this.view.removeChild(0);
88
- }
89
- }
90
- break;
91
- }
92
- }
93
- return;
94
- }
95
- }
96
- }
@@ -1,17 +0,0 @@
1
- export function render(content, container, context) {
2
- context.onRendered = [];
3
- let result = content(container, context);
4
- for (var i = 0; i < context.onRendered.length; i++) {
5
- context.onRendered[i]();
6
- }
7
- return result;
8
- }
9
- export function renderFrag(content, context) {
10
- let container = document.createDocumentFragment();
11
- context.onRendered = [];
12
- let result = content(container, context);
13
- for (var i = 0; i < context.onRendered.length; i++) {
14
- context.onRendered[i]();
15
- }
16
- return result;
17
- }
@@ -1,76 +0,0 @@
1
- import { render, renderFrag } from './render.js';
2
- export class RumiousViewControl {
3
- targets = [];
4
- constructor() { }
5
- addTarget(target) {
6
- this.targets.push(target);
7
- }
8
- setView(template) {
9
- const targets = this.targets;
10
- if (targets.length === 0) {
11
- throw new Error(`RumiousRenderError: No target assigned to ViewControl`);
12
- }
13
- for (let i = 0; i < targets.length; i++) {
14
- render(template, targets[i].element, targets[i].context);
15
- }
16
- }
17
- removeChild(index) {
18
- for (let i = 0; i < this.targets.length; i++) {
19
- let parent = this.targets[i].element.parentElement;
20
- if (!parent)
21
- return;
22
- let element = parent.children[index];
23
- if (element)
24
- parent.removeChild(element);
25
- }
26
- }
27
- addChild(template, prepend = false) {
28
- const targets = this.targets;
29
- if (targets.length === 0) {
30
- throw new Error(`RumiousRenderError: No target assigned to ViewControl`);
31
- }
32
- for (let i = 0; i < targets.length; i++) {
33
- let templ = renderFrag(template, targets[i].context);
34
- if (!prepend)
35
- targets[i].element.appendChild(templ);
36
- else
37
- targets[i].element.prepend(templ);
38
- }
39
- }
40
- each(callback) {
41
- for (let target of this.targets) {
42
- callback(target);
43
- }
44
- }
45
- emptyAll() {
46
- const targets = this.targets;
47
- for (let i = 0; i < targets.length; i++) {
48
- targets[i].element.textContent = '';
49
- }
50
- }
51
- empty(target) {
52
- const targets = this.targets;
53
- for (let i = 0; i < targets.length; i++) {
54
- if (targets[i].element === target) {
55
- target.textContent = '';
56
- return;
57
- }
58
- }
59
- }
60
- updateChild(index, template) {
61
- for (let i = 0; i < this.targets.length; i++) {
62
- const { element, context } = this.targets[i];
63
- const parent = element.parentElement;
64
- if (!parent)
65
- continue;
66
- const oldChild = parent.children[index];
67
- const newNode = renderFrag(template, context);
68
- if (oldChild) {
69
- parent.replaceChild(newNode, oldChild);
70
- }
71
- }
72
- }
73
- }
74
- export function createViewControl() {
75
- return new RumiousViewControl();
76
- }
@@ -1,3 +0,0 @@
1
- export * from './state.js';
2
- export * from './list.js';
3
- export * from './store.js';