@jinntec/fore 1.5.0 → 1.6.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 +12 -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-update.js +9 -0
  32. package/src/events.js +0 -1
  33. package/src/fore.js +118 -63
  34. package/src/functions/common-function.js +28 -0
  35. package/src/fx-bind.js +7 -7
  36. package/src/fx-fore.js +152 -55
  37. package/src/fx-instance.js +55 -17
  38. package/src/fx-model.js +31 -33
  39. package/src/fx-submission.js +50 -47
  40. package/src/getInScopeContext.js +8 -10
  41. package/src/lab/fore-component.js +90 -0
  42. package/src/lab/instance-inspector.js +56 -0
  43. package/src/lab/template.html +16 -0
  44. package/src/relevance.js +27 -1
  45. package/src/tools/adi.js +1056 -0
  46. package/src/tools/fx-action-log.js +662 -0
  47. package/src/tools/fx-devtools.js +444 -0
  48. package/src/tools/fx-dom-inspector.js +609 -0
  49. package/src/tools/fx-json-instance.js +435 -0
  50. package/src/tools/fx-log-item.js +133 -0
  51. package/src/tools/fx-log-settings.js +474 -0
  52. package/src/tools/fx-minimap.js +194 -0
  53. package/src/tools/helpers.js +132 -0
  54. package/src/ui/abstract-control.js +41 -3
  55. package/src/ui/fx-action-log.js +358 -0
  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
package/index.js CHANGED
@@ -23,6 +23,16 @@ import './src/ui/fx-inspector.js';
23
23
  import './src/ui/fx-dialog.js';
24
24
  import './src/ui/fx-items.js';
25
25
 
26
+ import './src/tools/fx-action-log.js';
27
+ import './src/tools/fx-log-settings.js';
28
+ import './src/tools/fx-log-item.js';
29
+ import './src/tools/fx-devtools.js';
30
+ import './src/tools/fx-dom-inspector.js';
31
+ import './src/lab/fore-component.js';
32
+ import './src/tools/fx-json-instance.js';
33
+ import './src/tools/fx-minimap.js';
34
+
35
+
26
36
  // import './src/ui/fx-checkbox-group.js';
27
37
 
28
38
  // action classes
@@ -43,6 +53,8 @@ import './src/actions/fx-confirm.js';
43
53
  import './src/actions/fx-show.js';
44
54
  import './src/actions/fx-hide.js';
45
55
  import './src/actions/fx-reload.js';
56
+ import './src/actions/fx-reset.js';
57
+ import './src/actions/fx-load.js';
46
58
 
47
59
  import './src/functions/fx-function.js';
48
60
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jinntec/fore",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
4
  "description": "Fore - declarative user interfaces in plain HTML",
5
5
  "module": "./index.js",
6
6
  "publishConfig": {
@@ -30,8 +30,8 @@
30
30
  "!.DS_Store"
31
31
  ],
32
32
  "dependencies": {
33
- "@jinntec/jinn-toast": "^1.0.4",
34
- "fontoxpath": "^3.27.1"
33
+ "@jinntec/jinn-toast": "^1.0.5",
34
+ "fontoxpath": "^3.29.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@babel/plugin-proposal-class-properties": "^7.17.12",
@@ -55,7 +55,7 @@
55
55
  "lint-staged": "^12.4.3",
56
56
  "lit-html": "^2.2.5",
57
57
  "mocha": "^10.0.0",
58
- "np": "^7.6.1",
58
+ "np": "^8.0.4",
59
59
  "rimraf": "^3.0.2",
60
60
  "rollup": "^2.75.4",
61
61
  "rollup-plugin-babel": "^4.4.0",
@@ -80,7 +80,8 @@
80
80
  "test:bs": "karma start karma.bs.config.js --coverage",
81
81
  "start:build": "cd dist && es-dev-server --open",
82
82
  "build": "rimraf dist && rollup -c rollup.config.js",
83
- "start": "es-dev-server --app-index doc/index.html --node-resolve --watch --open"
83
+ "start": "es-dev-server --app-index doc/index.html --node-resolve --watch --open",
84
+ "postinstall": "cd demo && npm i"
84
85
  },
85
86
  "keywords": [
86
87
  "Fore",
@@ -128,6 +129,9 @@
128
129
  ]
129
130
  }
130
131
  },
132
+ "engines": {
133
+ "node": ">= 16.19.1"
134
+ },
131
135
  "prettier": "@open-wc/prettier-config",
132
136
  "main": "index.js"
133
137
  }
@@ -1,66 +1,124 @@
1
- @import 'toastify.css';
2
1
  @import 'vars.css';
2
+ @import 'toastify.css';
3
+ /*@import url('dev.css');*/
3
4
 
4
- html{
5
- --inspector-bg:var(--paper-grey-300);
6
- --inspector-pre-bg:var(--paper-grey-100);
7
- --inspector-color:var(--paper-grey-800);
8
- --inspector-instance-height:200px;
5
+ html {
6
+ --inspector-bg: var(--paper-grey-300);
7
+ --inspector-pre-bg: var(--paper-grey-100);
8
+ --inspector-color: var(--paper-grey-800);
9
+ --inspector-instance-height: 200px;
9
10
  --inspector-handle-bg: var(--paper-blue-500);
10
11
  --inspector-handle-width: 30px;
11
-
12
12
  }
13
- [unresolved]{
13
+
14
+ [unresolved] {
14
15
  display: none;
15
16
  }
17
+
16
18
  [disabled] {
17
19
  pointer-events: none;
18
20
  cursor: default;
19
21
  }
20
- [refresh-on-view]{
22
+
23
+ [refresh-on-view] {
21
24
  /*opacity: 0;*/
22
25
  }
23
- /*
24
- defaults for relevance
25
26
 
26
- You can overwrite these matchers to use transistions
27
+ /*
28
+ nonrelevant must always be hidden
27
29
  */
28
- [nonrelevant]{
29
- display: none;
30
+ [nonrelevant] {
31
+ display: none !important;
30
32
  }
31
- [relevant]{
33
+
34
+ [relevant] {
32
35
  display: block;
33
36
  }
34
37
 
35
- [required]:after {
38
+ fx-control[required]:after {
36
39
  content: "*";
37
40
  display: inline;
38
41
  color: red;
39
42
  }
40
43
 
41
- fx-alert{
42
- color:darkred;
44
+ [slot=messages] {
45
+ margin: 0 auto;
46
+ width: 100%;
47
+ padding: 2rem 0 1rem;
48
+ background: white;
49
+ border-radius: 0.5rem;
50
+ position: relative;
51
+ }
52
+
53
+ [slot=messages]::before {
54
+ content: attr(data-level);
55
+ padding: 0.5rem;
56
+ background: darkred;
57
+ color: white;
58
+ display: block;
59
+ }
60
+
61
+ [slot=messages] div {
62
+ color: black;
63
+ padding: 0.25rem;
64
+ border: thin solid #efefef;
65
+ }
66
+
67
+ [slot=messages] div::before {
68
+ width: 6rem;
69
+ display: inline-block;
70
+ }
71
+
72
+ [slot=messages] div:nth-child(1)::before {
73
+ content: 'Id:';
74
+ }
75
+
76
+ [slot=messages] div:nth-child(2)::before {
77
+ content: 'Path:';
78
+ }
79
+
80
+ [slot=messages] div:nth-child(3)::before {
81
+ content: 'Message:';
82
+ }
83
+
84
+ .fore-error {
85
+ height: 2rem;
86
+ background: darkred;
87
+ width: 100%;
88
+ display: block !important;
89
+ color: white;
90
+ }
91
+
92
+ .fore-error::before {
93
+ content: 'right-click to inspect';
94
+ display: flex;
95
+ flex-align: center;
96
+ }
97
+
98
+ fx-alert {
99
+ color: darkred;
43
100
  font-size: 0.9rem;
44
101
  display: none;
45
102
  }
46
- .visited[invalid] fx-alert{
103
+
104
+ .visited[invalid] fx-alert {
47
105
  display: block;
48
106
  }
49
107
 
50
108
  /* case not displayed by default - if you want e.g. apply transitions you have to overwrite this rule with display='inline' or similar */
51
- fx-case{
109
+ fx-case {
52
110
  display: none;
53
111
  }
54
112
 
55
- fx-output[readonly] img{
113
+ fx-output[readonly] img {
56
114
  background: inherit;
57
115
  }
58
116
 
59
- .error{
117
+ .error {
60
118
  background: var(--paper-red-500);
61
119
  }
62
120
 
63
- fx-control, fx-trigger , .fx-checkbox{
121
+ fx-control, fx-trigger, .fx-checkbox {
64
122
  white-space: nowrap;
65
123
  /* position: relative; */
66
124
  }
@@ -68,93 +126,81 @@ fx-control, fx-trigger , .fx-checkbox{
68
126
  /* ### FX-DIALOG STYLES ### */
69
127
  /* ### FX-DIALOG STYLES ### */
70
128
  /* ### FX-DIALOG STYLES ### */
71
- fx-dialog{
129
+ fx-dialog {
72
130
  display: none;
73
131
  opacity: 0;
74
- width:100vw;
132
+ width: 100vw;
75
133
  height: 100vh;
76
134
  transition: opacity 1s linear;
77
135
  z-index: -1;
78
136
  transition: none;
79
137
  }
80
- fx-dialog.show{
138
+
139
+ fx-dialog.show {
81
140
  display: block;
82
141
  min-height: 200px;
83
142
  border-radius: 0.5rem;
84
143
  opacity: 1;
85
- background:rgba(0,0,0,0.5);
144
+ background: rgba(0, 0, 0, 0.5);
86
145
  z-index: 10;
87
146
  transition: opacity 0.4s linear;
88
147
  }
89
148
 
90
- fx-dialog.show .dialog-content{
149
+ fx-dialog.show .dialog-content {
91
150
  padding: 1rem;
92
- width:fit-content;
93
- height:fit-content;
94
- border:thin solid;
151
+ width: fit-content;
152
+ height: fit-content;
153
+ border: thin solid;
95
154
  border-radius: 0.3rem;
96
155
  position: absolute;
97
- left:50%;
98
- top:50%;
99
- transform:translateX(-50%) translateY(-50%);
156
+ left: 50%;
157
+ top: 50%;
158
+ transform: translateX(-50%) translateY(-50%);
100
159
  background: white;
101
160
 
102
161
  }
103
- fx-dialog a.close-dialog{
162
+
163
+ fx-dialog a.close-dialog {
104
164
  position: absolute;
105
165
  right: 0.4rem;
106
- top:0.2rem;
107
- color:var(--paper-grey-900);
166
+ top: 0.2rem;
167
+ color: var(--paper-grey-900);
108
168
  text-decoration: none;
109
- font-size:1.2rem;
169
+ font-size: 1.2rem;
110
170
  }
111
- fx-dialog .action{
171
+
172
+ fx-dialog .action {
112
173
  width: 100%;
113
174
  text-align: center;
114
175
  display: block;
115
176
  }
116
177
 
117
- /* fx-fore{ */
118
- /* opacity: 0; */
119
- /* } */
120
- /* fx-fore.fx-ready{ */
121
- /* opacity: 1; */
122
- /* } */
123
-
124
-
125
- fx-group, fx-switch, fx-repeat, fx-dialog{
178
+ fx-group, fx-switch, fx-repeat, fx-dialog {
126
179
  display: block;
127
180
  }
128
181
 
129
- fx-hint{
182
+ fx-hint {
130
183
  display: none;
131
184
  }
132
185
 
133
186
  fx-model,
134
- fx-model *,
135
- fx-model ::slotted(fx-instance),
136
187
  fx-instance,
137
188
  fx-action,
138
- fx-setvalue{
139
- display:none;
189
+ fx-setvalue {
190
+ display: none;
140
191
  }
141
192
 
142
193
  fx-trigger a[disabled] {
143
- color:lightgrey;
144
- }
145
- fx-trigger img[disabled]{
146
- filter:blur(2px);
194
+ color: lightgrey;
147
195
  }
148
196
 
197
+ fx-trigger img[disabled] {
198
+ filter: blur(2px);
199
+ }
149
200
 
150
- fx-repeatitem{
151
- position:relative;
152
- opacity:1;
153
- /*
154
- -webkit-transition: opacity 3s;
155
- -moz-transition: opacity 3s;
156
- transition: opacity 3s;
157
- */
201
+ fx-repeatitem {
202
+ position: relative;
203
+ opacity: 1;
158
204
  }
159
205
 
160
206
  .hidden {
@@ -163,52 +209,92 @@ fx-repeatitem{
163
209
  transition: visibility 0s 2s, opacity 2s linear;
164
210
  }
165
211
 
166
- .isEmpty.visited .widget{
212
+ .isEmpty.visited .widget {
167
213
  background: lightpink;
168
214
  }
169
215
 
170
- .loaded{
216
+ .loaded {
171
217
  animation: fadein 0.3s forwards;
172
218
  }
219
+
173
220
  /* avoid flicker from nested lazily loaded elements */
174
- .loaded .loaded{
221
+ .loaded .loaded {
175
222
  animation: none;
176
223
  opacity: 1;
177
224
  }
178
225
 
179
- .logtree details{
180
- padding:0.1rem 1rem;
181
- margin:0;
226
+ .logtree details {
227
+ padding: 0.1rem 1rem;
228
+ margin: 0;
229
+ }
230
+ noscript{
231
+ display: block;
232
+ width: 100%;
233
+ padding: 1rem;
234
+ background: darkorange;
235
+ color:white;
236
+ position: absolute;
237
+ top:0;
238
+ left:0;
182
239
  }
183
- .logtree details summary{
184
240
 
241
+ .submit-validation-failed .isEmpty .widget {
242
+ background: lightpink;
185
243
  }
186
244
 
187
- /*
188
- .nonrelevant{
189
- opacity: 0;
190
- height: 0;
245
+ .vertical label {
191
246
  display: block;
192
- padding: 0;
193
- margin: 0;
194
- border: none;
195
- transition: opacity 0.4s;
196
247
  }
197
- */
198
248
 
249
+ /* fx-action-log styles */
199
250
 
200
- .submit-validation-failed .isEmpty .widget{
201
- background: lightpink;
251
+ fx-fore.action-log{
252
+ /*background: var(--paper-orange-500);*/
253
+ }
254
+ .action-log .action-log-debug {
255
+ display: block !important;
256
+ min-height: 3rem;
257
+ background: var(--paper-orange-500);
202
258
  }
203
- .vertical label{
259
+ .action-log fx-model{
204
260
  display: block;
261
+ min-height: 1rem;
262
+ }
263
+ .action-log fx-model::before{
264
+ content:'model';
265
+ }
266
+
267
+ .action-log fx-instance,
268
+ .action-log fx-bind,
269
+ .action-log fx-submission,
270
+ .action-log fx-function
271
+ {
272
+ display: block;
273
+ min-height: 2rem;
274
+ background: var(--paper-orange-500);
275
+ }
276
+
277
+ .action-log fx-bind::before{
278
+ content:'bind :: ' attr(ref);
279
+ }
280
+ .action-log fx-instance::before{
281
+ content:'instance :: ' attr(id);
282
+ }
283
+ .action-log fx-submission::before{
284
+ content:'submission ::' attr(id);
285
+ }
286
+
287
+ .action-log .action-log-debug::before{
288
+ content: attr(data-name);
289
+ }
290
+ .action-log .action-log-debug .targetd{
291
+ cursor: pointer;
292
+ }
293
+
294
+
295
+ /* ### toastify customizations #### */
296
+
297
+ .toastify.on.warning{
298
+ background: var(--paper-orange-500);
205
299
  }
206
300
 
207
- /* @keyframes fadein { */
208
- /* 0% { */
209
- /* opacity:0; */
210
- /* } */
211
- /* 100% { */
212
- /* opacity:1; */
213
- /* } */
214
- /* } */
@@ -128,8 +128,7 @@ export class DependencyNotifyingDomFacade {
128
128
  * Get the parent of this element.
129
129
  * An implementation of IDomFacade is free to interpret the bucket to skip returning nodes that do not match the bucket, or use this information to its advantage.
130
130
  *
131
- * @param node -
132
- * @param bucket - The bucket that matches the attribute that will be used.
131
+ * @param node - the starting node
133
132
  */
134
133
  // eslint-disable-next-line class-methods-use-this
135
134
  getParentNode(node) {
@@ -1,12 +1,12 @@
1
1
  import { XPathUtil } from './xpath-util.js';
2
2
  import { FxModel } from './fx-model.js';
3
- import { Fore } from './fore.js';
4
3
  import {
5
4
  evaluateXPath,
6
5
  evaluateXPathToFirstNode,
7
6
  evaluateXPathToString,
8
7
  } from './xpath-evaluation.js';
9
8
  import getInScopeContext from './getInScopeContext.js';
9
+ import {Fore} from './fore.js';
10
10
 
11
11
  /**
12
12
  * Mixin containing all general functions that are shared by all Fore element classes.
@@ -134,11 +134,13 @@ export const foreElementMixin = superclass =>
134
134
  }
135
135
  });
136
136
  */
137
- this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext[0], this);
137
+ // this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext[0], this);
138
+ this.nodeset = evaluateXPath(this.ref, inscopeContext[0], this);
138
139
  } else {
139
140
  // this.nodeset = fx.evaluateXPathToFirstNode(this.ref, inscopeContext, null, {namespaceResolver: this.namespaceResolver});
141
+ if(!inscopeContext) return;
140
142
  const { nodeType } = inscopeContext;
141
- if (nodeType) {
143
+ if (nodeType && !XPathUtil.isAbsolutePath(this.ref)) {
142
144
  this.nodeset = evaluateXPathToFirstNode(this.ref, inscopeContext, this);
143
145
  } else {
144
146
  [this.nodeset] = evaluateXPath(this.ref, inscopeContext, this);
@@ -147,6 +149,30 @@ export const foreElementMixin = superclass =>
147
149
  // console.log('UiElement evaluated to nodeset: ', this.nodeset);
148
150
  }
149
151
 
152
+ /**
153
+ * resolves template expressions for a single attribute
154
+ * @param expr an attribute value containing curly brackets containing XPath expressions to evaluate
155
+ * @param node the attribute node used for scoped resolution
156
+ * @returns {*}
157
+ * @private
158
+ */
159
+ evaluateAttributeTemplateExpression(expr, node) {
160
+ const matches = expr.match(/{[^}]*}/g);
161
+ if (matches) {
162
+ matches.forEach(match => {
163
+ // console.log('match ', match);
164
+ const naked = match.substring(1, match.length - 1);
165
+ const inscope = getInScopeContext(node, naked);
166
+ const result = evaluateXPathToString(naked, inscope, this);
167
+ const replaced = expr.replaceAll(match, result);
168
+ // console.log('replacing ', expr, ' with ', replaced);
169
+ expr = replaced;
170
+ });
171
+ }
172
+ return expr;
173
+ }
174
+
175
+
150
176
  isNotBound() {
151
177
  return !this.hasAttribute('ref');
152
178
  }
@@ -160,7 +186,7 @@ export const foreElementMixin = superclass =>
160
186
  return this.getAttribute('ref');
161
187
  }
162
188
  // try to get closest parent bind
163
- const parent = Fore.getClosest('[ref]', this.parentNode);
189
+ const parent = XPathUtil.getClosest('[ref]', this.parentNode);
164
190
  if (!parent) {
165
191
  return 'instance()'; // the default instance
166
192
  }
@@ -199,7 +225,7 @@ export const foreElementMixin = superclass =>
199
225
  this.modelItem = mi;
200
226
  }
201
227
 
202
- const repeated = Fore.getClosest('fx-repeatitem', this);
228
+ const repeated = XPathUtil.getClosest('fx-repeatitem', this);
203
229
  let existed;
204
230
  if (repeated) {
205
231
  const { index } = repeated;