@jinntec/fore 1.5.0 → 1.7.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 (71) hide show
  1. package/dist/fore-dev.js +2 -36
  2. package/dist/fore-dev.js.map +1 -1
  3. package/dist/fore.js +2 -30
  4. package/dist/fore.js.map +1 -1
  5. package/index.js +13 -0
  6. package/package.json +9 -5
  7. package/resources/fore.css +178 -92
  8. package/src/DependencyNotifyingDomFacade.js +1 -2
  9. package/src/ForeElementMixin.js +31 -5
  10. package/src/actions/abstract-action.js +379 -297
  11. package/src/actions/fx-action.js +0 -1
  12. package/src/actions/fx-append.js +1 -2
  13. package/src/actions/fx-confirm.js +12 -0
  14. package/src/actions/fx-copy.js +0 -1
  15. package/src/actions/fx-delete.js +31 -9
  16. package/src/actions/fx-dispatch.js +19 -5
  17. package/src/actions/fx-hide.js +19 -0
  18. package/src/actions/fx-insert.js +72 -8
  19. package/src/actions/fx-load.js +253 -0
  20. package/src/actions/fx-message.js +22 -7
  21. package/src/actions/fx-refresh.js +11 -1
  22. package/src/actions/fx-reload.js +12 -2
  23. package/src/actions/fx-replace.js +5 -4
  24. package/src/actions/fx-reset.js +48 -0
  25. package/src/actions/fx-return.js +0 -1
  26. package/src/actions/fx-send.js +40 -2
  27. package/src/actions/fx-setfocus.js +25 -7
  28. package/src/actions/fx-setvalue.js +32 -4
  29. package/src/actions/fx-show.js +14 -2
  30. package/src/actions/fx-toggle.js +0 -1
  31. package/src/actions/fx-toggleboolean.js +58 -0
  32. package/src/actions/fx-update.js +9 -0
  33. package/src/events.js +0 -1
  34. package/src/fore.js +118 -63
  35. package/src/functions/common-function.js +28 -0
  36. package/src/fx-bind.js +9 -7
  37. package/src/fx-fore.js +153 -55
  38. package/src/fx-instance.js +55 -17
  39. package/src/fx-model.js +31 -33
  40. package/src/fx-submission.js +50 -47
  41. package/src/getInScopeContext.js +8 -10
  42. package/src/lab/fore-component.js +90 -0
  43. package/src/lab/instance-inspector.js +56 -0
  44. package/src/lab/template.html +16 -0
  45. package/src/relevance.js +27 -1
  46. package/src/tools/adi.js +1056 -0
  47. package/src/tools/fx-action-log.js +662 -0
  48. package/src/tools/fx-devtools.js +444 -0
  49. package/src/tools/fx-dom-inspector.js +609 -0
  50. package/src/tools/fx-json-instance.js +435 -0
  51. package/src/tools/fx-log-item.js +133 -0
  52. package/src/tools/fx-log-settings.js +474 -0
  53. package/src/tools/fx-minimap.js +194 -0
  54. package/src/tools/helpers.js +132 -0
  55. package/src/ui/abstract-control.js +41 -3
  56. package/src/ui/fx-alert.js +0 -1
  57. package/src/ui/fx-container.js +14 -3
  58. package/src/ui/fx-control.js +553 -474
  59. package/src/ui/fx-dialog.js +2 -0
  60. package/src/ui/fx-dom-inspector.js +1255 -0
  61. package/src/ui/fx-group.js +3 -4
  62. package/src/ui/fx-hint.js +2 -4
  63. package/src/ui/fx-inspector.js +5 -6
  64. package/src/ui/fx-items.js +55 -14
  65. package/src/ui/fx-output.js +36 -17
  66. package/src/ui/fx-repeat-attributes.js +10 -43
  67. package/src/ui/fx-repeat.js +5 -7
  68. package/src/ui/fx-switch.js +14 -3
  69. package/src/ui/fx-trigger.js +13 -1
  70. package/src/xpath-evaluation.js +109 -26
  71. package/src/xpath-util.js +55 -1
@@ -0,0 +1,435 @@
1
+
2
+ /**
3
+ * A simple collapsible treeview for showing JSON data.
4
+ *
5
+ */
6
+ class FxJsonInstance extends HTMLElement {
7
+ // constructor(container, options = {}) {
8
+ constructor() {
9
+ super();
10
+ const shadowRoot = this.attachShadow({mode: 'open'});
11
+ this.instanceElement = null;
12
+ this.foreSelector = null;
13
+ }
14
+
15
+ connectedCallback() {
16
+ this.container = this.querySelector('.json-path-picker-container');
17
+ this.foreSelector = this.hasAttribute('fore') ? this.getAttribute('fore') : 'fx-fore'; // default to first one in doc
18
+ this.render();
19
+ }
20
+
21
+ render() {
22
+ const style = `
23
+ @import '../../resources/fore.css';
24
+
25
+ :host {
26
+ display:block;
27
+ font-size:0.8em;
28
+ background:rgba(250, 250, 250, 0.9);
29
+ }
30
+ .container{
31
+ margin-left:1em;
32
+ }
33
+ .header{
34
+ margin-left:0;
35
+ }
36
+
37
+ ::slot[name='header']{
38
+ margin-left:-1em;
39
+ }
40
+ /* Syntax highlighting for JSON objects */
41
+ ul.json-dict, ol.json-array {
42
+ list-style-type: none;
43
+ margin: 0 0 0 1px;
44
+ border-left: 1px dotted #ccc;
45
+ padding-left: 2em;
46
+ }
47
+ .json-string {
48
+ // color: #0B7500;
49
+ }
50
+ .json-literal {
51
+ color: #1A01CC;
52
+ font-weight: bold;
53
+ }
54
+
55
+ /* Toggle button */
56
+ a.json-toggle {
57
+ position: relative;
58
+ color: inherit;
59
+ text-decoration: none;
60
+ }
61
+ a.json-toggle:focus {
62
+ outline: none;
63
+ }
64
+ a.json-toggle:before {
65
+ content: "\\25BC"; /* down arrow */
66
+ position: absolute;
67
+ display: inline-block;
68
+ width: 1em;
69
+ left: -1.2em;
70
+ font-size:0.8em;
71
+ }
72
+ a.json-toggle.collapsed:before {
73
+ content: "\\25B6"; /* left arrow */
74
+ }
75
+
76
+ /* Collapsable placeholder links */
77
+ a.json-placeholder {
78
+ color: #aaa;
79
+ padding: 0 1em;
80
+ text-decoration: none;
81
+ }
82
+ a.json-placeholder:hover {
83
+ text-decoration: underline;
84
+ }
85
+
86
+ /* Copy path icon */
87
+ .pick-path {
88
+ color: lightgray;
89
+ cursor: pointer;
90
+ margin-left: 3px;
91
+ }
92
+
93
+ .pick-path:hover {
94
+ color: darkgray;
95
+ }
96
+
97
+ `;
98
+
99
+ const instanceId = this.hasAttribute('instance') ? this.getAttribute('instance') : 'default';
100
+ const fore = document.querySelector(this.foreSelector);
101
+ if(!fore){
102
+ throw new Error(`this '${this.foreSelector}' does not match a fx-fore element`);
103
+ }
104
+
105
+ const html = `
106
+ <div class="container"></div>
107
+ `;
108
+
109
+ this.shadowRoot.innerHTML = `
110
+ <style>
111
+ ${style}
112
+ </style>
113
+ <slot name="header">
114
+ <header class="header">${instanceId}</header>
115
+ </slot>
116
+ <slot></slot>
117
+ ${html}
118
+ `;
119
+
120
+ // fore.addEventListener('ready', e => {
121
+
122
+ const instanceElement = document.querySelector(`#${instanceId}`);
123
+ if(!instanceElement || instanceElement.nodeName !== 'FX-INSTANCE' || instanceElement.getAttribute('type') !== 'json'){
124
+ throw new Error(`this '${instanceId}' does not match an fx-instance element or is not of type JSON`);
125
+ }
126
+ const container = this.shadowRoot.querySelector('.container');
127
+
128
+ const json = instanceElement.instanceData;
129
+ let tree = this.json2html(json,{"outputWithQuotes":true});
130
+ if (this.isCollapsable(json)) tree = "<a href='#' class=\"json-toggle\"></a>".concat(tree); // Insert HTML in target DOM element
131
+
132
+ container.innerHTML = tree;
133
+
134
+ const toggles = this.shadowRoot.querySelectorAll('.json-toggle');
135
+ toggles.forEach(toggle => {
136
+ toggle.addEventListener('click', this._handleToggleEvent.bind(this));
137
+ });
138
+ // container.addEventListener('click', (event) => this._handleToggleEvent);
139
+ // });
140
+ }
141
+
142
+
143
+ disconnectedCallback() {
144
+ }
145
+
146
+ _isHidden(elem) {
147
+ var width = elem.offsetWidth;
148
+ var height = elem.offsetHeight;
149
+ return width === 0 && height === 0 || window.getComputedStyle(elem).display === 'none';
150
+ }
151
+
152
+ _handleToggleEvent(event) {
153
+ // Change class
154
+ // event.preventDefault();
155
+ // event.stopPropagation();
156
+
157
+ const elm = event.target;
158
+ elm.classList.toggle('collapsed'); // Fetch every json-dict and json-array to toggle them
159
+
160
+ var subTarget = this._siblings(elm, 'ul.json-dict, ol.json-array', function (el) {
161
+ el.style.display = el.style.display === '' || el.style.display === 'block' ? 'none' : 'block';
162
+ }); // ForEach subtarget, previous siblings return array so we parse it
163
+
164
+ for (var i = 0; i < subTarget.length; i += 1) {
165
+ if (!this._isHidden(subTarget[i])) {
166
+ // Parse every siblings with '.json-placehoder' and remove them (previous add by else)
167
+ this._siblings(subTarget[i], '.json-placeholder', function (el) {
168
+ return el.parentNode.removeChild(el);
169
+ });
170
+ } else {
171
+ // count item in object / array
172
+ var childs = subTarget[i].children;
173
+ var count = 0;
174
+
175
+ for (var j = 0; j < childs.length; j += 1) {
176
+ if (childs[j].tagName === 'LI') {
177
+ count += 1;
178
+ }
179
+ }
180
+
181
+ var placeholder = count + (count > 1 ? ' items' : ' item'); // Append a placeholder
182
+ subTarget[i].insertAdjacentHTML('afterend', "<a href class=\"json-placeholder\">".concat(placeholder, "</a>"));
183
+ }
184
+ } // Prevent propagation
185
+
186
+
187
+ event.stopPropagation();
188
+ event.preventDefault();
189
+ }
190
+
191
+ _siblings(el, sel, callback) {
192
+ var sibs = [];
193
+
194
+ for (var i = 0; i < el.parentNode.children.length; i += 1) {
195
+ var child = el.parentNode.children[i];
196
+
197
+ if (child !== el && typeof sel === 'string' && child.matches(sel)) {
198
+ sibs.push(child);
199
+ }
200
+ } // If a callback is passed, call it on each sibs
201
+
202
+
203
+ if (callback && typeof callback === 'function') {
204
+ for (var _i = 0; _i < sibs.length; _i += 1) {
205
+ callback(sibs[_i]);
206
+ }
207
+ }
208
+
209
+ return sibs;
210
+ }
211
+
212
+ json2html(json, options) {
213
+ let html = '';
214
+
215
+ if (typeof json === 'string') {
216
+ // Escape tags
217
+ const tmp = json.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
218
+
219
+ if (this.isUrl(tmp)) {
220
+ html += "<a href=\"".concat(tmp, "\" class=\"json-string\">").concat(tmp, "</a>");
221
+ } else {
222
+ html += "<span class=\"json-string\">\"".concat(tmp, "\"</span>");
223
+ }
224
+ } else if (typeof json === 'number') {
225
+ html += "<span class=\"json-literal\">".concat(json, "</span>");
226
+ } else if (typeof json === 'boolean') {
227
+ html += "<span class=\"json-literal\">".concat(json, "</span>");
228
+ } else if (json === null) {
229
+ html += '<span class="json-literal">null</span>';
230
+ } else if (json instanceof Array) {
231
+ if (json.length > 0) {
232
+ html += '[<ol class="json-array">';
233
+
234
+ for (var i = 0; i < json.length; i += 1) {
235
+ html += "<li data-key-type=\"array\" data-key=\"".concat(i, "\">"); // Add toggle button if item is collapsable
236
+
237
+ if (this.isCollapsable(json[i])) {
238
+ html += '<a href="#" class="json-toggle"></a>';
239
+ }
240
+
241
+ html += this.json2html(json[i], options); // Add comma if item is not last
242
+
243
+ if (i < json.length - 1) {
244
+ html += ',';
245
+ }
246
+
247
+ html += '</li>';
248
+ }
249
+
250
+ html += '</ol>]';
251
+ } else {
252
+ html += '[]';
253
+ }
254
+ } else if (this._typeof(json) === 'object') {
255
+ let keyCount = Object.keys(json).length;
256
+
257
+ if (keyCount > 0) {
258
+ html += '{<ul class="json-dict">';
259
+
260
+ for (var key in json) {
261
+ if (json.hasOwnProperty(key)) {
262
+ html += "<li data-key-type=\"object\" data-key=\"".concat(key, "\">");
263
+ const keyRepr = options.outputWithQuotes ? "<span class=\"json-string\">\"".concat(key, "\"</span>") : key; // Add toggle button if item is collapsable
264
+
265
+ if (this.isCollapsable(json[key])) {
266
+ html += "<a href='#' class=\"json-toggle\">".concat(keyRepr, "</a>");
267
+ } else {
268
+ html += keyRepr;
269
+ }
270
+
271
+ // ### keep the following comment for later - pick path is a good idea but needs to be adapted to XPath syntax
272
+ // html += '<span class="pick-path" title="Pick path">&#10697;</span>';
273
+ html += ": ".concat(this.json2html(json[key], options)); // Add comma if item is not last
274
+
275
+ keyCount -= 1;
276
+
277
+ if (keyCount > 0) {
278
+ html += ',';
279
+ }
280
+
281
+ html += '</li>';
282
+ }
283
+ }
284
+
285
+ html += '</ul>}';
286
+ } else {
287
+ html += '{}';
288
+ }
289
+ }
290
+
291
+ return html;
292
+ }
293
+
294
+ isUrl(string) {
295
+ var regexp = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#:.?+=&%@!\-/]))?/;
296
+ return regexp.test(string);
297
+ }
298
+
299
+ _typeof(obj) {
300
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
301
+ this._typeof = function _typeof(obj) {
302
+ return typeof obj;
303
+ };
304
+ } else {
305
+ this._typeof = function _typeof(obj) {
306
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
307
+ };
308
+ }
309
+ return this._typeof(obj);
310
+ }
311
+
312
+ isCollapsable(arg) {
313
+ return arg instanceof Object && Object.keys(arg).length > 0;
314
+ }
315
+
316
+
317
+ /*
318
+ setup() {
319
+ // Create shadow DOM
320
+
321
+ // Add styles to shadow DOM
322
+ const style = document.createElement('style');
323
+ style.textContent = `
324
+ /!* add your CSS styles here *!/
325
+ `;
326
+ shadowRoot.appendChild(style);
327
+
328
+ // Move content to shadow DOM
329
+ const container = this.container.cloneNode(true);
330
+ shadowRoot.appendChild(container);
331
+ this.container.remove();
332
+ this.container = shadowRoot.querySelector('.json-path-picker-container');
333
+ this.clearBtn = shadowRoot.querySelector('.json-path-picker-clear-btn');
334
+ this.jsonTextarea = shadowRoot.querySelector('.json-path-picker-json');
335
+ this.treeView = shadowRoot.querySelector('.json-path-picker-tree');
336
+ this.resultView = shadowRoot.querySelector('.json-path-picker-result');
337
+
338
+ const data = {
339
+ "automobiles": [
340
+ {
341
+ "maker": "Nissan",
342
+ "model": "Teana",
343
+ "year": 2000
344
+ },
345
+ {
346
+ "maker": "Honda",
347
+ "model": "Jazz",
348
+ "year": 2023
349
+ },
350
+ {
351
+ "maker": "Honda",
352
+ "model": "Civic",
353
+ "year": 2007
354
+ },
355
+ {
356
+ "maker": "Toyota",
357
+ "model": "Yaris",
358
+ "year": 2008
359
+ },
360
+ {
361
+ "maker": "Honda",
362
+ "model": "Accord",
363
+ "year": 2011
364
+ }
365
+ ],
366
+ "motorcycles": [{
367
+ "maker": "Honda",
368
+ "model": "ST1300",
369
+ "year": 2012
370
+ }]
371
+ }
372
+
373
+ this.updateTree(JSON.stringify(data));
374
+
375
+ }
376
+ */
377
+
378
+
379
+ static get observedAttributes() {
380
+ return ['data'];
381
+ }
382
+
383
+ attributeChangedCallback(name, oldValue, newValue) {
384
+ if (name === 'data') {
385
+ this.jsonTextarea.value = newValue;
386
+ this.updateTree(newValue);
387
+ }
388
+ }
389
+
390
+
391
+ updateTree(jsonString) {
392
+ try {
393
+ this.data = JSON.parse(jsonString);
394
+ this.treeView.innerHTML = "";
395
+ this.treeView.appendChild(this.createTreeView(this.data, ""));
396
+ } catch (e) {
397
+ console.error(e);
398
+ alert("Invalid JSON");
399
+ }
400
+ }
401
+
402
+ createTreeView(data, path) {
403
+ let ul = document.createElement("ul");
404
+ ul.classList.add("jp-ul");
405
+ if (Array.isArray(data)) {
406
+ data.forEach((item, index) => {
407
+ let li = document.createElement("li");
408
+ li.classList.add("jp-li");
409
+ let newPath = path + "[" + index + "]";
410
+ li.appendChild(this.createItemView(newPath, item));
411
+ ul.appendChild(li);
412
+ });
413
+ } else if (typeof data === "object" && data !== null) {
414
+ Object.keys(data).forEach(key => {
415
+ let li = document.createElement("li");
416
+ li.classList.add("jp-li");
417
+ let newPath = path + "." + key;
418
+ li.appendChild(this.createItemView(newPath, data[key]));
419
+ ul.appendChild(li);
420
+ });
421
+ } else {
422
+ let li = document.createElement("li");
423
+ li.classList.add("jp-li");
424
+ li.appendChild(this.createItemView(path, data));
425
+ ul.appendChild(li);
426
+ }
427
+ return ul;
428
+ }
429
+
430
+ }
431
+
432
+
433
+ if (!customElements.get('fx-json-instance')) {
434
+ customElements.define('fx-json-instance', FxJsonInstance);
435
+ }
@@ -0,0 +1,133 @@
1
+
2
+ export class FxLogItem extends HTMLElement {
3
+
4
+ constructor() {
5
+ super();
6
+ this.attachShadow({ mode: 'open' });
7
+ this.eventName = '';
8
+ this.shortName = '';
9
+ this.shortInfo = '';
10
+ this.shortPath='';
11
+ this.xpath ='';
12
+ }
13
+
14
+
15
+ connectedCallback() {
16
+ const style = `
17
+ :host {
18
+ height: auto;
19
+ font-size: 0.8em;
20
+ font-weight: 400;
21
+
22
+ }
23
+
24
+ a,a:link,a:visited{
25
+ color:black;
26
+ }
27
+ a{
28
+ position:relative;
29
+ }
30
+ a[alt]:hover::after {
31
+ content:attr(alt);
32
+ position:absolute;
33
+ left:0;
34
+ top:1em;
35
+ border.thin solid;
36
+ padding:0.5em;
37
+ background:white;
38
+ z-index:1;
39
+ min-width:5em;
40
+ border:thin solid;
41
+ white-space:nowrap;
42
+ overflow-wrap:break-word;
43
+ }
44
+
45
+ .info{
46
+ padding:0 0.5em;
47
+ margin:0.1rem 0;
48
+ background:white;
49
+ position:relative;
50
+ border:1px solid #ddd;
51
+ border-radius:1em;
52
+ box-shadow: 1px 1px 5px 0px rgba(79, 136, 183, 0.8);
53
+ }
54
+ :host(.action) .info{
55
+ border-radius:0;
56
+ border-color:steelblue;
57
+ }
58
+
59
+ .info label{
60
+ grid-area:left;
61
+ overflow: hidden;
62
+ text-overflow: ellipsis;
63
+ }
64
+ .info a{
65
+ grid-area:right;
66
+ justify-self:end;
67
+ }
68
+ .info:hover{
69
+ outline:3px solid lightblue;
70
+ transition:height 0.4s;
71
+ }
72
+
73
+ summary{
74
+ padding:1em;
75
+ display:flex;
76
+ flex-wrap:wrap;
77
+ padding:0.5em 0;
78
+ cursor:pointer;
79
+ gap:0.25em;
80
+ }
81
+ /*
82
+ .log-name{
83
+ font-size:1.2em;
84
+ }
85
+ .log-name, .short-info{
86
+ width:10em;
87
+ }
88
+ */
89
+ .event-name{
90
+ width:12em;
91
+ text-align:right;
92
+ }
93
+ .short-info{
94
+ flex:3;
95
+ overflow:hidden;
96
+ white-space:nowrap;
97
+ text-overflow:ellipsis;
98
+ }
99
+ `;
100
+
101
+ this.eventName = this.getAttribute('event-name');
102
+ this.shortName = this.getAttribute('short-name');
103
+ this.shortInfo = this.hasAttribute('short-info') ? this.getAttribute('short-info'):'';
104
+ this.xpath = this.getAttribute('xpath');
105
+
106
+
107
+ const cut = this.xpath.substring(this.xpath.indexOf('/fx-fore'), this.xpath.length);;
108
+ const xpathCut = "/" + cut;
109
+ const shortPath = xpathCut.replaceAll('fx-','');
110
+
111
+ const html = `
112
+ <details class="info send">
113
+ <summary>
114
+ <span class="log-name"><a href="#" title="${shortPath}" data-path="${this.xpath}">${this.shortName}</a></span>
115
+ <span class="short-info">${this.shortInfo}</span>
116
+ <span class="event-name">${this.eventName}</span>
117
+ </summary>
118
+ <slot></slot>
119
+ </details>
120
+ `;
121
+
122
+ this.shadowRoot.innerHTML = `
123
+ <style>
124
+ ${style}
125
+ </style>
126
+ ${html}
127
+ `;
128
+ }
129
+
130
+ }
131
+ if (!customElements.get('fx-log-item')) {
132
+ customElements.define('fx-log-item', FxLogItem);
133
+ }