onelaraveljs 1.0.0

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.
Files changed (67) hide show
  1. package/README.md +87 -0
  2. package/docs/integration_analysis.md +116 -0
  3. package/docs/onejs_analysis.md +108 -0
  4. package/docs/optimization_implementation_group2.md +458 -0
  5. package/docs/optimization_plan.md +130 -0
  6. package/index.js +16 -0
  7. package/package.json +13 -0
  8. package/src/app.js +61 -0
  9. package/src/core/API.js +72 -0
  10. package/src/core/ChildrenRegistry.js +410 -0
  11. package/src/core/DOMBatcher.js +207 -0
  12. package/src/core/ErrorBoundary.js +226 -0
  13. package/src/core/EventDelegator.js +416 -0
  14. package/src/core/Helper.js +817 -0
  15. package/src/core/LoopContext.js +97 -0
  16. package/src/core/OneDOM.js +246 -0
  17. package/src/core/OneMarkup.js +444 -0
  18. package/src/core/Router.js +996 -0
  19. package/src/core/SEOConfig.js +321 -0
  20. package/src/core/SectionEngine.js +75 -0
  21. package/src/core/TemplateEngine.js +83 -0
  22. package/src/core/View.js +273 -0
  23. package/src/core/ViewConfig.js +229 -0
  24. package/src/core/ViewController.js +1410 -0
  25. package/src/core/ViewControllerOptimized.js +164 -0
  26. package/src/core/ViewIdentifier.js +361 -0
  27. package/src/core/ViewLoader.js +272 -0
  28. package/src/core/ViewManager.js +1962 -0
  29. package/src/core/ViewState.js +761 -0
  30. package/src/core/ViewSystem.js +301 -0
  31. package/src/core/ViewTemplate.js +4 -0
  32. package/src/core/helpers/BindingHelper.js +239 -0
  33. package/src/core/helpers/ConfigHelper.js +37 -0
  34. package/src/core/helpers/EventHelper.js +172 -0
  35. package/src/core/helpers/LifecycleHelper.js +17 -0
  36. package/src/core/helpers/ReactiveHelper.js +169 -0
  37. package/src/core/helpers/RenderHelper.js +15 -0
  38. package/src/core/helpers/ResourceHelper.js +89 -0
  39. package/src/core/helpers/TemplateHelper.js +11 -0
  40. package/src/core/managers/BindingManager.js +671 -0
  41. package/src/core/managers/ConfigurationManager.js +136 -0
  42. package/src/core/managers/EventManager.js +309 -0
  43. package/src/core/managers/LifecycleManager.js +356 -0
  44. package/src/core/managers/ReactiveManager.js +334 -0
  45. package/src/core/managers/RenderEngine.js +292 -0
  46. package/src/core/managers/ResourceManager.js +441 -0
  47. package/src/core/managers/ViewHierarchyManager.js +258 -0
  48. package/src/core/managers/ViewTemplateManager.js +127 -0
  49. package/src/core/reactive/ReactiveComponent.js +592 -0
  50. package/src/core/services/EventService.js +418 -0
  51. package/src/core/services/HttpService.js +106 -0
  52. package/src/core/services/LoggerService.js +57 -0
  53. package/src/core/services/StateService.js +512 -0
  54. package/src/core/services/StorageService.js +856 -0
  55. package/src/core/services/StoreService.js +258 -0
  56. package/src/core/services/TemplateDetectorService.js +361 -0
  57. package/src/core/services/Test.js +18 -0
  58. package/src/helpers/devWarnings.js +205 -0
  59. package/src/helpers/performance.js +226 -0
  60. package/src/helpers/utils.js +287 -0
  61. package/src/init.js +343 -0
  62. package/src/plugins/auto-plugin.js +34 -0
  63. package/src/services/Test.js +18 -0
  64. package/src/types/index.js +193 -0
  65. package/src/utils/date-helper.js +51 -0
  66. package/src/utils/helpers.js +39 -0
  67. package/src/utils/validation.js +32 -0
@@ -0,0 +1,97 @@
1
+ export class LoopContext {
2
+ constructor(parent = null) {
3
+ this.odd = true;
4
+ this.even = false;
5
+ this.first = false;
6
+ this.last = false;
7
+ this.iteration = 0;
8
+ this.index = 0;
9
+ this.remaining = null;
10
+ this.count = null;
11
+ this.depth = 0;
12
+ this.parent = parent;
13
+
14
+ this.type = 'increment';
15
+ }
16
+
17
+ setType(type) {
18
+ if(type === 'increment' || type === 'decrement') {
19
+ this.type = type;
20
+ }
21
+ }
22
+
23
+ reset() {
24
+ this.iteration = 0;
25
+ this.index = 0;
26
+ this.remaining = null;
27
+ this.count = null;
28
+ this.first = false;
29
+ this.last = false;
30
+ this.odd = true;
31
+ this.even = false;
32
+ }
33
+
34
+ increment() {
35
+ this.iteration++;
36
+ this.index++;
37
+ if (this.remaining !== null) {
38
+ this.remaining--;
39
+ }
40
+ this.first = this.iteration === 0;
41
+ this.last = this.iteration === this.count - 1;
42
+ }
43
+
44
+ decrement() {
45
+ this.iteration--;
46
+ this.index--;
47
+ if (this.remaining !== null) {
48
+ this.remaining++;
49
+ }
50
+ this.last = this.iteration === this.count - 1;
51
+ this.odd = !this.odd;
52
+ this.even = !this.even;
53
+ }
54
+ next() {
55
+ if (this.type === 'increment') {
56
+ this.increment();
57
+ } else {
58
+ this.decrement();
59
+ }
60
+ }
61
+
62
+ setCount(count) {
63
+ this.count = count;
64
+ this.remaining = count;
65
+ this.last = count === 1;
66
+ this.odd = false;
67
+ this.even = true;
68
+ }
69
+
70
+ /**
71
+ * Set the current times of the loop (iteration)
72
+ * @param {number} iteration iteration của vòng lặp hiện tại
73
+ */
74
+ setCurrentTimes(iteration) {
75
+ this.iteration = iteration;
76
+ if (this.remaining !== null) {
77
+ this.remaining--;
78
+ }
79
+ this.index = this.iteration;
80
+ this.first = this.iteration === 0;
81
+ this.last = this.iteration === this.count - 1;
82
+ this.odd = !this.odd;
83
+ this.even = !this.even;
84
+ }
85
+
86
+ setParent(parent) {
87
+ this.parent = parent;
88
+ }
89
+
90
+ getParent() {
91
+ return this.parent;
92
+ }
93
+
94
+ newChild() {
95
+ return new LoopContext(this);
96
+ }
97
+ }
@@ -0,0 +1,246 @@
1
+ export class OneDOM {
2
+ static validateElement(element) {
3
+ if (!(element instanceof Element || element instanceof Comment)) {
4
+ throw new Error('Provided value is not a valid DOM Element');
5
+ }
6
+ return true;
7
+ }
8
+ /**
9
+ * Convert various input types to a safe DocumentFragment
10
+ * Supports: string, Element, NodeList, Array<Element|string>
11
+ */
12
+ static toFragment(content) {
13
+ const fragment = document.createDocumentFragment();
14
+
15
+ const appendItem = (item) => {
16
+ if (!item) return;
17
+ if (typeof item === 'string') {
18
+ const template = document.createElement('template');
19
+ template.innerHTML = item.trim();
20
+ fragment.appendChild(template.content);
21
+ } else if (item instanceof Element || item instanceof DocumentFragment) {
22
+ fragment.appendChild(item);
23
+ } else if (Array.isArray(item) || item instanceof NodeList) {
24
+ item.forEach(appendItem);
25
+ }
26
+ else if (item instanceof Comment) {
27
+ fragment.appendChild(item);
28
+ }
29
+ else if (item instanceof Text) {
30
+ fragment.appendChild(item);
31
+ }
32
+ else {
33
+ console.warn('Unsupported content type:', item);
34
+ }
35
+ };
36
+
37
+ appendItem(content);
38
+ return fragment;
39
+ }
40
+
41
+ /**
42
+ * Chèn nội dung trước đối tượng tham chiếu trong DOM
43
+ * @param {Element|Comment} target đối tường dùng để tham chiếu
44
+ * @param {*} content nội dung thêm vào
45
+ */
46
+ static before(target, content) {
47
+ if (!(target instanceof Element || target instanceof Comment)) throw new Error('Target must be a DOM element');
48
+ target.parentNode.insertBefore(
49
+ this.toFragment(content),
50
+ target
51
+ );
52
+ }
53
+
54
+ /**
55
+ * Chèn nội dung sau đối tượng tham chiếu trong DOM
56
+ * @param {Element|Comment} target đối tường dùng để tham chiếu
57
+ * @param {*} content nội dung thêm vào
58
+ */
59
+ static after(target, content) {
60
+ if (!(target instanceof Element || target instanceof Comment)) throw new Error('Target must be a DOM element');
61
+ const frag = this.toFragment(content);
62
+ if (target.nextSibling) target.parentNode.insertBefore(frag, target.nextSibling);
63
+ else target.parentNode.appendChild(frag);
64
+ }
65
+
66
+ /**
67
+ * Thay thế đối tượng tham chiếu trong DOM bằng nội dung mới
68
+ * @param {Element|Comment} target đối tường dùng để tham chiếu
69
+ * @param {*} content nội dung thay thế
70
+ */
71
+ static replace(target, content) {
72
+ if (!(target instanceof Element || target instanceof Comment)) throw new Error('Target must be a DOM element');
73
+ target.replaceWith(this.toFragment(content));
74
+ }
75
+
76
+ /**
77
+ * Thêm nội dung vào cuối phần tử tham chiếu trong DOM
78
+ * @param {Element} target phần tử dùng để tham chiếu
79
+ * @param {*} content nội dung thêm vào
80
+ */
81
+ static append(target, content) {
82
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
83
+ target.appendChild(this.toFragment(content));
84
+ }
85
+
86
+ /**
87
+ * Thêm nội dung vào đầu phần tử tham chiếu trong DOM
88
+ * @param {Element} target phần tử dùng để tham chiếu
89
+ * @param {*} content nội dung thêm vào
90
+ */
91
+ static prepend(target, content) {
92
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
93
+ if (!target.firstChild) {
94
+ target.appendChild(this.toFragment(content));
95
+ return;
96
+ }
97
+ target.insertBefore(this.toFragment(content), target.firstChild);
98
+ }
99
+ /**
100
+ * Thiết lập nội dung HTML cho phần tử tham chiếu trong DOM
101
+ * @param {Element} target phần tử dùng để tham chiếu
102
+ * @param {*} content nội dung thiết lập
103
+ */
104
+ static setHTML(target, content) {
105
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
106
+ target.innerHTML = '';
107
+ target.appendChild(this.toFragment(content));
108
+ }
109
+
110
+ /**
111
+ * Thay thế toàn bộ nội dung của phần tử tham chiếu trong DOM
112
+ * @param {Element} target phần tử dùng để tham chiếu
113
+ * @param {*} content nội dung thay thế
114
+ */
115
+ static replaceContent(target, content) {
116
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
117
+ target.innerHTML = '';
118
+ target.appendChild(this.toFragment(content));
119
+ }
120
+
121
+ static content(target, content) {
122
+ if (content === undefined) {
123
+ // Lấy nội dung
124
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
125
+ return target.innerHTML;
126
+ } else {
127
+ // Thiết lập nội dung
128
+ this.setHTML(target, content);
129
+ }
130
+ }
131
+
132
+ static children(target, children = null) {
133
+ if (!(target instanceof Element)) throw new Error('Target must be a DOM element');
134
+ if (children === null || children === undefined) {
135
+ return Array.from(target.children);
136
+ } else {
137
+ target.innerHTML = '';
138
+ target.appendChild(this.toFragment(children));
139
+ }
140
+ }
141
+
142
+ static getInputValue(el) {
143
+ if (!el || !(el instanceof Element)) return null;
144
+
145
+ const tag = el.tagName.toLowerCase();
146
+ const type = (el.type || '').toLowerCase();
147
+
148
+ // Input
149
+ if (tag === 'input') {
150
+ switch (type) {
151
+ case 'checkbox':
152
+ return el.checked;
153
+ case 'radio':
154
+ return el.checked ? (el.value ? el.value : false) : null;
155
+ case 'file':
156
+ return el.multiple ? [...el.files] : el.files[0] || null;
157
+ case 'number':
158
+ case 'range':
159
+ return el.value === '' ? null : Number(el.value);
160
+ default:
161
+ return el.value;
162
+ }
163
+ }
164
+
165
+ // Select
166
+ if (tag === 'select') {
167
+ if (el.multiple) {
168
+ return [...el.selectedOptions].map(o => o.value);
169
+ }
170
+ return el.value;
171
+ }
172
+
173
+ // Textarea
174
+ if (tag === 'textarea') {
175
+ return el.value;
176
+ }
177
+
178
+ // Contenteditable
179
+ if (el.isContentEditable) {
180
+ return el.innerText;
181
+ }
182
+
183
+ return null;
184
+ }
185
+
186
+ static setInputValue(el, value) {
187
+ if (!el || !(el instanceof Element)) return;
188
+
189
+ const tag = el.tagName.toLowerCase();
190
+ const type = (el.type || '').toLowerCase();
191
+
192
+ // Input
193
+ if (tag === 'input') {
194
+ switch (type) {
195
+ case 'checkbox':
196
+ el.checked = Boolean(value);
197
+ return;
198
+
199
+ case 'radio':
200
+ el.checked = el.value === value;
201
+ return;
202
+
203
+ case 'file':
204
+ // Không thể set file programmatically (security)
205
+ return;
206
+
207
+ case 'number':
208
+ case 'range':
209
+ el.value = value ?? '';
210
+ return;
211
+
212
+ default:
213
+ el.value = value ?? '';
214
+ return;
215
+ }
216
+ }
217
+
218
+ // Select
219
+ if (tag === 'select') {
220
+ if (el.multiple && Array.isArray(value)) {
221
+ [...el.options].forEach(opt => {
222
+ opt.selected = value.includes(opt.value);
223
+ });
224
+ } else {
225
+ el.value = value ?? '';
226
+ }
227
+ return;
228
+ }
229
+
230
+ // Textarea
231
+ if (tag === 'textarea') {
232
+ el.value = value ?? '';
233
+ return;
234
+ }
235
+
236
+ // Contenteditable
237
+ if (el.isContentEditable) {
238
+ el.innerText = value ?? '';
239
+ return;
240
+ }
241
+ }
242
+
243
+
244
+ }
245
+
246
+ export default OneDOM;