@onetype/framework 2.0.45 → 2.0.46

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 (30) hide show
  1. package/addons/core/assets/back/functions/import.js +3 -3
  2. package/addons/core/commands/front/directives/run.js +1 -1
  3. package/addons/core/commands/front/directives/submit.js +1 -1
  4. package/addons/render/directives/front/items/self/100-if.js +25 -22
  5. package/addons/render/directives/front/items/self/1000-render.js +36 -33
  6. package/addons/render/directives/front/items/self/110-show.js +23 -20
  7. package/addons/render/directives/front/items/self/160-slot.js +33 -30
  8. package/addons/render/directives/front/items/self/200-for.js +71 -68
  9. package/addons/render/directives/front/items/self/2000-base.js +36 -33
  10. package/addons/render/directives/front/items/self/500-click-outside.js +37 -34
  11. package/addons/render/directives/front/items/self/500-events.js +1 -1
  12. package/addons/render/directives/front/items/self/500-mouse-enter.js +1 -1
  13. package/addons/render/directives/front/items/self/500-mouse-leave.js +1 -1
  14. package/addons/render/directives/front/items/self/650-fetch.js +150 -149
  15. package/addons/render/directives/front/items/self/660-form.js +217 -219
  16. package/addons/render/directives/front/items/self/700-text.js +42 -39
  17. package/addons/render/directives/front/items/self/750-html.js +38 -35
  18. package/addons/render/directives/front/items/self/750-node.js +1 -1
  19. package/addons/render/elements/front/items/directives/element.js +2 -2
  20. package/addons/render/pages/front/items/directives/change.js +1 -1
  21. package/addons/render/transforms/js/items/self/transform.js +1 -1
  22. package/lib/boot/load.js +105 -0
  23. package/lib/load.js +2 -1
  24. package/lib/src/classes/addon/classes/item/mixins/get.js +12 -1
  25. package/lib/src/classes/addon/classes/item/mixins/set.js +24 -2
  26. package/lib/src/classes/addon/mixins/items.js +48 -4
  27. package/lib/src/mixins/addons.js +27 -29
  28. package/lib/src/mixins/dependencies.js +24 -17
  29. package/package.json +1 -1
  30. package/lib/events.js +0 -106
@@ -1,283 +1,281 @@
1
- import directives from '#directives/addon.js';
2
-
3
- directives.ItemAdd({
4
- id: 'ot-form',
5
- icon: 'send',
6
- name: 'Form',
7
- description: 'Submit form data to endpoint and bind response to component data',
8
- category: 'data',
9
- trigger: 'node',
10
- order: 660,
11
- tag: 'ot-form',
12
- attributes: {
13
- 'post': ['string'],
14
- 'get': ['string'],
15
- 'endpoint': ['string'],
16
- 'url': ['string'],
17
- 'bind': ['string'],
18
- 'method': ['string'],
19
- 'redirect': ['string'],
20
- 'on-success': ['string'],
21
- 'on-error': ['string'],
22
- 'reset': ['boolean'],
23
- 'stop': ['boolean'],
24
- 'data': ['string']
25
- },
26
- code: function(data, item, compile, node, identifier)
27
- {
28
- const config = {};
29
- const methods = {};
30
-
31
- methods.init = () =>
32
- {
33
- methods.config();
34
- methods.state();
35
- methods.element();
36
- methods.compile();
37
- methods.handler();
38
- };
39
-
40
- methods.config = () =>
41
- {
42
- const post = data['post']?.value;
43
- const get = data['get']?.value;
44
-
45
- config.endpoint = post || get || data['endpoint']?.value || data['url']?.value || '';
46
- config.bind = data['bind']?.value || 'form';
47
- config.method = get ? 'GET' : (data['method']?.value || 'POST').toUpperCase();
48
- config.redirect = data['redirect']?.value;
49
- config.onSuccess = data['on-success']?.value;
50
- config.onError = data['on-error']?.value;
51
- config.reset = data['reset']?.value || false;
52
- config.stop = data['stop']?.value || false;
53
- config.data = methods.parseData();
54
- config.url = methods.normalizeUrl(config.endpoint);
55
- };
56
-
57
- methods.parseData = () =>
1
+ onetype.AddonReady('directives', function(directives)
2
+ {
3
+ directives.ItemAdd({
4
+ id: 'ot-form',
5
+ icon: 'send',
6
+ name: 'Form',
7
+ description: 'Submit form data to endpoint and bind response to component data',
8
+ category: 'data',
9
+ trigger: 'node',
10
+ order: 660,
11
+ tag: 'ot-form',
12
+ attributes: {
13
+ 'post': ['string'],
14
+ 'get': ['string'],
15
+ 'endpoint': ['string'],
16
+ 'url': ['string'],
17
+ 'bind': ['string'],
18
+ 'method': ['string'],
19
+ 'redirect': ['string'],
20
+ 'on-success': ['string'],
21
+ 'on-error': ['string'],
22
+ 'reset': ['boolean'],
23
+ 'stop': ['boolean'],
24
+ 'data': ['string']
25
+ },
26
+ code: function(data, item, compile, node, identifier)
58
27
  {
59
- const dataAttr = data['data']?.value;
28
+ const config = {};
29
+ const methods = {};
60
30
 
61
- if(!dataAttr)
31
+ methods.init = () =>
62
32
  {
63
- return {};
64
- }
33
+ methods.config();
34
+ methods.state();
35
+ methods.element();
36
+ methods.compile();
37
+ methods.handler();
38
+ };
65
39
 
66
- try
40
+ methods.config = () =>
67
41
  {
68
- return JSON.parse(dataAttr);
69
- }
70
- catch(e)
71
- {
72
- return onetype.Function(dataAttr, compile.data, false) || {};
73
- }
74
- };
42
+ const post = data['post']?.value;
43
+ const get = data['get']?.value;
44
+
45
+ config.endpoint = post || get || data['endpoint']?.value || data['url']?.value || '';
46
+ config.bind = data['bind']?.value || 'form';
47
+ config.method = get ? 'GET' : (data['method']?.value || 'POST').toUpperCase();
48
+ config.redirect = data['redirect']?.value;
49
+ config.onSuccess = data['on-success']?.value;
50
+ config.onError = data['on-error']?.value;
51
+ config.reset = data['reset']?.value || false;
52
+ config.stop = data['stop']?.value || false;
53
+ config.data = methods.parseData();
54
+ config.url = methods.normalizeUrl(config.endpoint);
55
+ };
75
56
 
76
- methods.normalizeUrl = (endpoint) =>
77
- {
78
- if(/^https?:\/\//.test(endpoint))
57
+ methods.parseData = () =>
79
58
  {
80
- return endpoint;
81
- }
59
+ const dataAttr = data['data']?.value;
82
60
 
83
- return endpoint.startsWith('/') ? endpoint : '/' + endpoint;
84
- };
61
+ if(!dataAttr)
62
+ {
63
+ return {};
64
+ }
85
65
 
86
- methods.state = () =>
87
- {
88
- if(!compile.data[config.bind])
89
- {
90
- compile.data[config.bind] = {
91
- response: null,
92
- error: null,
93
- loading: false
94
- };
95
- }
96
- };
66
+ try
67
+ {
68
+ return JSON.parse(dataAttr);
69
+ }
70
+ catch(e)
71
+ {
72
+ return onetype.Function(dataAttr, compile.data, false) || {};
73
+ }
74
+ };
97
75
 
98
- methods.element = () =>
99
- {
100
- config.html = node.innerHTML;
101
- config.form = document.createElement('form');
102
- config.form.setAttribute('autocomplete', 'off');
76
+ methods.normalizeUrl = (endpoint) =>
77
+ {
78
+ if(/^https?:\/\//.test(endpoint))
79
+ {
80
+ return endpoint;
81
+ }
103
82
 
104
- const reserved = ['endpoint', 'url', 'bind', 'method', 'on-success', 'on-error', 'reset', 'stop', 'data', 'redirect', 'post', 'get'];
83
+ return endpoint.startsWith('/') ? endpoint : '/' + endpoint;
84
+ };
105
85
 
106
- Array.from(node.attributes).forEach(attr =>
86
+ methods.state = () =>
107
87
  {
108
- if(!reserved.includes(attr.name))
88
+ if(!compile.data[config.bind])
109
89
  {
110
- config.form.setAttribute(attr.name, attr.value);
90
+ compile.data[config.bind] = {
91
+ response: null,
92
+ error: null,
93
+ loading: false
94
+ };
111
95
  }
112
- });
113
- };
114
-
115
- methods.compile = () =>
116
- {
117
- const compiled = item.Compile(config.html, compile.data);
96
+ };
118
97
 
119
- while(compiled.element.firstChild)
98
+ methods.element = () =>
120
99
  {
121
- config.form.appendChild(compiled.element.firstChild);
122
- }
100
+ config.html = node.innerHTML;
101
+ config.form = document.createElement('form');
102
+ config.form.setAttribute('autocomplete', 'off');
123
103
 
124
- node.replaceWith(config.form);
125
- compile.children = false;
126
- };
104
+ const reserved = ['endpoint', 'url', 'bind', 'method', 'on-success', 'on-error', 'reset', 'stop', 'data', 'redirect', 'post', 'get'];
127
105
 
128
- methods.handler = () =>
129
- {
130
- config.form.otForm = async (event) =>
106
+ Array.from(node.attributes).forEach(attr =>
107
+ {
108
+ if(!reserved.includes(attr.name))
109
+ {
110
+ config.form.setAttribute(attr.name, attr.value);
111
+ }
112
+ });
113
+ };
114
+
115
+ methods.compile = () =>
131
116
  {
132
- event.preventDefault();
117
+ const compiled = item.Compile(config.html, compile.data);
133
118
 
134
- if(config.stop)
119
+ while(compiled.element.firstChild)
135
120
  {
136
- event.stopPropagation();
121
+ config.form.appendChild(compiled.element.firstChild);
137
122
  }
138
123
 
139
- await methods.submit();
124
+ node.replaceWith(config.form);
125
+ compile.children = false;
140
126
  };
141
- };
142
-
143
- methods.submit = async () =>
144
- {
145
- const state = compile.data[config.bind];
146
- const formData = methods.extract();
147
-
148
- state.loading = true;
149
- state.error = null;
150
127
 
151
- try
128
+ methods.handler = () =>
152
129
  {
153
- const submitData = Object.assign({}, formData, config.data);
154
- const response = await methods.fetch(submitData);
130
+ config.form.otForm = async (event) =>
131
+ {
132
+ event.preventDefault();
155
133
 
156
- state.response = response.data !== undefined ? response.data : response;
157
- state.error = null;
158
- state.loading = false;
134
+ if(config.stop)
135
+ {
136
+ event.stopPropagation();
137
+ }
159
138
 
160
- methods.success();
161
- }
162
- catch(err)
163
- {
164
- state.response = null;
165
- state.error = err.message;
166
- state.loading = false;
139
+ await methods.submit();
140
+ };
141
+ };
167
142
 
168
- methods.error(err);
169
- }
170
- finally
143
+ methods.submit = async () =>
171
144
  {
172
- compile.data.Update();
173
- }
174
- };
175
-
176
- methods.extract = () =>
177
- {
178
- const formData = {};
179
- const inputs = config.form.querySelectorAll('input[name], textarea[name], select[name]');
145
+ const state = compile.data[config.bind];
146
+ const formData = methods.extract();
180
147
 
181
- inputs.forEach(input =>
182
- {
183
- const name = input.getAttribute('name');
148
+ state.loading = true;
149
+ state.error = null;
184
150
 
185
- if(!name)
151
+ try
186
152
  {
187
- return;
188
- }
153
+ const submitData = Object.assign({}, formData, config.data);
154
+ const response = await methods.fetch(submitData);
189
155
 
190
- if(input.type === 'checkbox')
191
- {
192
- formData[name] = input.checked;
156
+ state.response = response.data !== undefined ? response.data : response;
157
+ state.error = null;
158
+ state.loading = false;
159
+
160
+ methods.success();
193
161
  }
194
- else if(input.type === 'radio')
162
+ catch(err)
195
163
  {
196
- if(input.checked)
197
- {
198
- formData[name] = input.value;
199
- }
164
+ state.response = null;
165
+ state.error = err.message;
166
+ state.loading = false;
167
+
168
+ methods.error(err);
200
169
  }
201
- else
170
+ finally
202
171
  {
203
- formData[name] = input.value;
172
+ compile.data.Update();
204
173
  }
205
- });
174
+ };
206
175
 
207
- return formData;
208
- };
176
+ methods.extract = () =>
177
+ {
178
+ const formData = {};
179
+ const inputs = config.form.querySelectorAll('input[name], textarea[name], select[name]');
209
180
 
210
- methods.fetch = async (data) =>
211
- {
212
- const response = await fetch(config.url, {
213
- method: config.method,
214
- headers: { 'Content-Type': 'application/json' },
215
- body: JSON.stringify(data)
216
- });
181
+ inputs.forEach(input =>
182
+ {
183
+ const name = input.getAttribute('name');
217
184
 
218
- if(!response.ok)
219
- {
220
- throw onetype.Error(response.status, 'HTTP :status:.', {status: response.status});
221
- }
185
+ if(!name)
186
+ {
187
+ return;
188
+ }
222
189
 
223
- return response.json();
224
- };
190
+ if(input.type === 'checkbox')
191
+ {
192
+ formData[name] = input.checked;
193
+ }
194
+ else if(input.type === 'radio')
195
+ {
196
+ if(input.checked)
197
+ {
198
+ formData[name] = input.value;
199
+ }
200
+ }
201
+ else
202
+ {
203
+ formData[name] = input.value;
204
+ }
205
+ });
225
206
 
226
- methods.success = () =>
227
- {
228
- if(config.reset)
229
- {
230
- config.form.reset();
231
- }
207
+ return formData;
208
+ };
232
209
 
233
- if(config.redirect)
210
+ methods.fetch = async (data) =>
234
211
  {
235
- onetype.AddonGet('pages')?.Fn('change', null, config.redirect);
236
- return;
237
- }
212
+ const response = await fetch(config.url, {
213
+ method: config.method,
214
+ headers: { 'Content-Type': 'application/json' },
215
+ body: JSON.stringify(data)
216
+ });
238
217
 
239
- if(config.onSuccess)
218
+ if(!response.ok)
219
+ {
220
+ throw onetype.Error(response.status, 'HTTP :status:.', {status: response.status});
221
+ }
222
+
223
+ return response.json();
224
+ };
225
+
226
+ methods.success = () =>
240
227
  {
241
- const callback = onetype.Function(config.onSuccess, compile.data, false);
228
+ if(config.reset)
229
+ {
230
+ config.form.reset();
231
+ }
242
232
 
243
- if(typeof callback === 'function')
233
+ if(config.redirect)
244
234
  {
245
- callback(compile.data[config.bind].response);
235
+ onetype.AddonGet('pages')?.Fn('change', null, config.redirect);
236
+ return;
246
237
  }
247
- }
248
238
 
249
- onetype.Emit('@form.success', {
250
- bind: config.bind,
251
- response: compile.data[config.bind].response
252
- });
253
- };
239
+ if(config.onSuccess)
240
+ {
241
+ const callback = onetype.Function(config.onSuccess, compile.data, false);
254
242
 
255
- methods.error = (err) =>
256
- {
257
- onetype.Error(500, 'Form submit error.', {bind: config.bind});
243
+ if(typeof callback === 'function')
244
+ {
245
+ callback(compile.data[config.bind].response);
246
+ }
247
+ }
248
+
249
+ onetype.Emit('@form.success', {
250
+ bind: config.bind,
251
+ response: compile.data[config.bind].response
252
+ });
253
+ };
258
254
 
259
- if(config.onError)
255
+ methods.error = (err) =>
260
256
  {
261
- const callback = onetype.Function(config.onError, compile.data, false);
257
+ onetype.Error(500, 'Form submit error.', {bind: config.bind});
262
258
 
263
- if(typeof callback === 'function')
259
+ if(config.onError)
264
260
  {
265
- callback(err.message);
266
- }
267
- }
261
+ const callback = onetype.Function(config.onError, compile.data, false);
268
262
 
269
- onetype.Emit('@form.error', {
270
- bind: config.bind,
271
- error: err.message
272
- });
273
- };
263
+ if(typeof callback === 'function')
264
+ {
265
+ callback(err.message);
266
+ }
267
+ }
274
268
 
275
- methods.init();
276
- }
277
- });
269
+ onetype.Emit('@form.error', {
270
+ bind: config.bind,
271
+ error: err.message
272
+ });
273
+ };
278
274
 
279
- onetype.AddonReady('directives', function()
280
- {
275
+ methods.init();
276
+ }
277
+ });
278
+
281
279
  document.addEventListener('submit', function(event)
282
280
  {
283
281
  const node = event.target;
@@ -1,50 +1,53 @@
1
- directives.ItemAdd({
2
- id: 'ot-text',
3
- icon: 'text_fields',
4
- name: 'Text',
5
- description: 'Set element text content dynamically. Updates text nodes based on data expressions.',
6
- category: 'content',
7
- trigger: 'node',
8
- order: 700,
9
- type: '3',
10
- code: function(data, item, compile, node, identifier)
11
- {
12
- if (!/\{\{.*\}\}/.test(node.textContent))
1
+ onetype.AddonReady('directives', function(directives)
2
+ {
3
+ directives.ItemAdd({
4
+ id: 'ot-text',
5
+ icon: 'text_fields',
6
+ name: 'Text',
7
+ description: 'Set element text content dynamically. Updates text nodes based on data expressions.',
8
+ category: 'content',
9
+ trigger: 'node',
10
+ order: 700,
11
+ type: '3',
12
+ code: function(data, item, compile, node, identifier)
13
13
  {
14
- return;
15
- }
16
-
17
- node.textContent = node.textContent.replace(/\{\{\s*([^}]+)\s*\}\}/g, (_, expression) =>
18
- {
19
- try
14
+ if (!/\{\{.*\}\}/.test(node.textContent))
20
15
  {
21
- const result = onetype.Function(expression, compile.data, false);
16
+ return;
17
+ }
22
18
 
23
- if (result == null)
19
+ node.textContent = node.textContent.replace(/\{\{\s*([^}]+)\s*\}\}/g, (_, expression) =>
20
+ {
21
+ try
24
22
  {
25
- return '';
26
- }
23
+ const result = onetype.Function(expression, compile.data, false);
27
24
 
28
- const type = typeof result;
25
+ if (result == null)
26
+ {
27
+ return '';
28
+ }
29
29
 
30
- if (['boolean', 'number', 'string'].includes(type))
31
- {
32
- return result;
33
- }
30
+ const type = typeof result;
34
31
 
35
- const stringified = result.toString();
32
+ if (['boolean', 'number', 'string'].includes(type))
33
+ {
34
+ return result;
35
+ }
36
36
 
37
- if (stringified !== '[object Object]')
37
+ const stringified = result.toString();
38
+
39
+ if (stringified !== '[object Object]')
40
+ {
41
+ return stringified;
42
+ }
43
+
44
+ return `{{${type}}}`;
45
+ }
46
+ catch(error)
38
47
  {
39
- return stringified;
48
+ return `{{Error: ${error.message}}}`;
40
49
  }
41
-
42
- return `{{${type}}}`;
43
- }
44
- catch(error)
45
- {
46
- return `{{Error: ${error.message}}}`;
47
- }
48
- });
49
- }
50
+ });
51
+ }
52
+ });
50
53
  });
@@ -1,44 +1,47 @@
1
- directives.ItemAdd({
2
- id: 'ot-html',
3
- icon: 'code',
4
- name: 'HTML',
5
- description: 'Set element innerHTML dynamically. Renders HTML content from data expressions.',
6
- category: 'content',
7
- trigger: 'node',
8
- order: 750,
9
- strict: true,
10
- type: '1',
11
- attributes: {
12
- 'ot-html': ['string']
13
- },
14
- code: function(data, item, compile, node, identifier)
15
- {
16
- const html = data['ot-html'].value;
17
-
18
- if(html)
1
+ onetype.AddonReady('directives', function(directives)
2
+ {
3
+ directives.ItemAdd({
4
+ id: 'ot-html',
5
+ icon: 'code',
6
+ name: 'HTML',
7
+ description: 'Set element innerHTML dynamically. Renders HTML content from data expressions.',
8
+ category: 'content',
9
+ trigger: 'node',
10
+ order: 750,
11
+ strict: true,
12
+ type: '1',
13
+ attributes: {
14
+ 'ot-html': ['string']
15
+ },
16
+ code: function(data, item, compile, node, identifier)
19
17
  {
20
- const results = onetype.Function(html, compile.data, false);
18
+ const html = data['ot-html'].value;
21
19
 
22
- if(typeof results === 'string' && results.trim())
20
+ if(html)
23
21
  {
24
- const originalChildren = compile.children;
25
- compile.children = false;
22
+ const results = onetype.Function(html, compile.data, false);
23
+
24
+ if(typeof results === 'string' && results.trim())
25
+ {
26
+ const originalChildren = compile.children;
27
+ compile.children = false;
28
+
29
+ const compiled = item.Compile(results, compile.data);
30
+ const fragment = document.createDocumentFragment();
26
31
 
27
- const compiled = item.Compile(results, compile.data);
28
- const fragment = document.createDocumentFragment();
32
+ while(compiled.element.firstChild)
33
+ {
34
+ fragment.appendChild(compiled.element.firstChild);
35
+ }
29
36
 
30
- while(compiled.element.firstChild)
37
+ node.replaceWith(fragment);
38
+ compile.children = originalChildren;
39
+ }
40
+ else
31
41
  {
32
- fragment.appendChild(compiled.element.firstChild);
42
+ node.remove();
33
43
  }
34
-
35
- node.replaceWith(fragment);
36
- compile.children = originalChildren;
37
- }
38
- else
39
- {
40
- node.remove();
41
44
  }
42
45
  }
43
- }
44
- });
46
+ });
47
+ });