@jinntec/fore 1.0.0-4 → 1.0.0-5

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,4 +1,5 @@
1
1
  import { FxAction } from './fx-action.js';
2
+ import {AbstractAction} from "./abstract-action";
2
3
 
3
4
  /**
4
5
  * `fx-hide`
@@ -7,7 +8,7 @@ import { FxAction } from './fx-action.js';
7
8
  * @customElement
8
9
  * @demo demo/project.html
9
10
  */
10
- export class FxHide extends FxAction {
11
+ export class FxHide extends AbstractAction {
11
12
  connectedCallback() {
12
13
  this.dialog = this.getAttribute('dialog');
13
14
  if(!this.dialog){
@@ -85,32 +85,22 @@ export class FxInsert extends AbstractAction {
85
85
  console.log('this.nodeset', this.nodeset);
86
86
  */
87
87
 
88
- // ### obtaining targetSequence
89
- const inscope = getInScopeContext(this.getAttributeNode('ref'), this.ref);
90
-
91
- // @ts-ignore
92
- const targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
93
- // console.log('insert nodeset ', targetSequence);
88
+ let inscope;
89
+ // ### 'context' attribute takes precedence over 'ref'
90
+ let targetSequence;
91
+ if(this.hasAttribute('context')){
92
+ inscope = getInScopeContext(this.getAttributeNode('context'), this.getAttribute('context'));
93
+ targetSequence = evaluateXPathToNodes(this.getAttribute('context'), inscope, this.getOwnerForm());
94
+ }
94
95
 
95
- // ### obtaining originSequence
96
- /*
97
- let originSequence;
98
- if (this.origin) {
99
- // ### if there's an origin attribute use it
100
- const originTarget = evaluateXPathToFirstNode(this.origin, inscope, this.getOwnerForm());
101
- if(Array.isArray(originTarget) && originTarget.length === 0){
102
- console.warn('invalid origin for this insert action - ignoring...', this);
103
- return;
104
- }
105
- originSequence = originTarget.cloneNode(true);
106
- } else if (targetSequence) {
107
- // ### use last item of targetSequence
108
- originSequence = this._cloneTargetSequence(targetSequence);
109
- if(originSequence && !this.keepValues){
110
- this._clear(originSequence);
111
- }
112
- }
113
- */
96
+ if(this.hasAttribute('ref')){
97
+ if(inscope){
98
+ targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
99
+ }else{
100
+ inscope = getInScopeContext(this.getAttributeNode('ref'), this.ref);
101
+ targetSequence = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
102
+ }
103
+ }
114
104
  const originSequenceClone = this._cloneOriginSequence(inscope, targetSequence);
115
105
  if (!originSequenceClone) return; // if no origin back out without effect
116
106
 
@@ -127,13 +117,10 @@ export class FxInsert extends AbstractAction {
127
117
  index = 1;
128
118
  console.log('appended', inscope);
129
119
  } else {
130
- // todo: eval 'at'
131
120
 
132
- /*
133
- insert at position given by 'at' or use the last item in the targetSequence
134
- */
135
- // if (this.at) {
121
+ /* ### insert at position given by 'at' or use the last item in the targetSequence ### */
136
122
  if (this.hasAttribute('at')) {
123
+ // todo: eval 'at'
137
124
  // index = this.at;
138
125
  // insertLocationNode = targetSequence[this.at - 1];
139
126
 
@@ -165,7 +152,16 @@ export class FxInsert extends AbstractAction {
165
152
  // insertLocationNode.parentNode.append(originSequence);
166
153
  // const nextSibl = insertLocationNode.nextSibling;
167
154
  index += 1;
168
- insertLocationNode.insertAdjacentElement('afterend', originSequenceClone);
155
+ if(this.hasAttribute('context') && this.hasAttribute('ref')){
156
+ // index=1;
157
+ inscope.append(originSequenceClone);
158
+ }else if(this.hasAttribute('context')){
159
+ const contextAttr = this.getAttribute('context');
160
+ index=1;
161
+ insertLocationNode.prepend(originSequenceClone);
162
+ }else{
163
+ insertLocationNode.insertAdjacentElement('afterend', originSequenceClone);
164
+ }
169
165
  }
170
166
  }
171
167
 
@@ -173,16 +169,17 @@ export class FxInsert extends AbstractAction {
173
169
  // console.log('parent ', insertLocationNode.parentNode);
174
170
  // console.log('instance ', this.getModel().getDefaultContext());
175
171
 
176
- // console.log('<<<<<<< at', this.at);
177
- // console.log('<<<<<<< index', index);
172
+ console.log('<<<<<<< at', this.at);
173
+ console.log('<<<<<<< index', index);
178
174
  // todo: this actually should dispatch to respective instance
179
175
  document.dispatchEvent(
180
- new CustomEvent('insert', {
176
+ // new CustomEvent('insert', {
177
+ new CustomEvent('index-changed', {
181
178
  composed: true,
182
179
  bubbles: true,
183
180
  detail: {
184
181
  insertedNodes: originSequenceClone,
185
- position: index,
182
+ index,
186
183
  },
187
184
  }),
188
185
  );
@@ -17,7 +17,8 @@ class FxToggle extends FxAction {
17
17
  }
18
18
 
19
19
  */
20
- execute() {
20
+ perform() {
21
+ super.perform();
21
22
  console.log('### fx-toggle.execute ');
22
23
  if (this.case) {
23
24
  const ownerForm = this.getOwnerForm();
package/src/dep_graph.js CHANGED
@@ -91,7 +91,9 @@ function createDFS(edges, leavesOnly, result, circular) {
91
91
  // return;
92
92
  // console.log('‘circular path: ' + currentPath);
93
93
  // throw new DepGraphCycleError(currentPath);
94
- // throw new Error(currentPath);
94
+
95
+ // Stop all processing. This form is broken and we should not break the browser
96
+ throw new Error(`Cyclic at ${currentPath}`);
95
97
  }
96
98
 
97
99
  inCurrentPath[node] = true;
package/src/fore.js CHANGED
@@ -190,14 +190,16 @@ export class Fore {
190
190
  return fadeIn();
191
191
  }
192
192
 
193
- static fadeOutElement(element) {
194
- const duration = 2600;
193
+ static fadeOutElement(element, duration) {
194
+ // const duration = duration;
195
195
  let fadeOut = () => {
196
+
196
197
  // Stop all current animations
197
198
  if (element.getAnimations) {
198
199
  element.getAnimations().map(anim => anim.finish());
199
200
  }
200
201
 
202
+
201
203
  // Play the animation with the newly specified duration
202
204
  fadeOut = element.animate(
203
205
  {
@@ -220,6 +222,33 @@ export class Fore {
220
222
  target.dispatchEvent(event);
221
223
  }
222
224
 
225
+ static prettifyXml(source) {
226
+ const xmlDoc = new DOMParser().parseFromString(source, 'application/xml');
227
+ const xsltDoc = new DOMParser().parseFromString(
228
+ [
229
+ // describes how we want to modify the XML - indent everything
230
+ '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
231
+ ' <xsl:strip-space elements="*"/>',
232
+ ' <xsl:template match="para[content-style][not(text())]">', // change to just text() to strip space in text nodes
233
+ ' <xsl:value-of select="normalize-space(.)"/>',
234
+ ' </xsl:template>',
235
+ ' <xsl:template match="node()|@*">',
236
+ ' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>',
237
+ ' </xsl:template>',
238
+ ' <xsl:output indent="yes"/>',
239
+ '</xsl:stylesheet>',
240
+ ].join('\n'),
241
+ 'application/xml',
242
+ );
243
+
244
+ const xsltProcessor = new XSLTProcessor();
245
+ xsltProcessor.importStylesheet(xsltDoc);
246
+ const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
247
+ const resultXml = new XMLSerializer().serializeToString(resultDoc);
248
+ return resultXml;
249
+ }
250
+
251
+
223
252
  /**
224
253
  * clear all text nodes and attribute values to get a 'clean' template.
225
254
  * @param n
package/src/fx-bind.js CHANGED
@@ -251,7 +251,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
251
251
  // console.log('otherPath', otherPath)
252
252
 
253
253
  // todo: nasty hack to prevent duplicate pathes like 'a[1]' and 'a[1]/text()[1]' to end up as separate nodes in the graph
254
- if(!otherPath.endsWith('text()[1]')){
254
+ if (!otherPath.endsWith('text()[1]')) {
255
255
  if (!this.model.mainGraph.hasNode(otherPath)) {
256
256
  this.model.mainGraph.addNode(otherPath, ref);
257
257
  }
@@ -335,7 +335,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
335
335
  } else {
336
336
  // eslint-disable-next-line no-lonely-if
337
337
  if (this.ref) {
338
- const localResult = evaluateXPathToNodes(this.ref, n, this.getOwnerForm());
338
+ const localResult = evaluateXPathToNodes(this.ref, n, this);
339
339
  localResult.forEach(item => {
340
340
  this.nodeset.push(item);
341
341
  });
@@ -351,7 +351,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
351
351
  } else {
352
352
  const inst = this.getModel().getInstance(this.instanceId);
353
353
  if (inst.type === 'xml') {
354
- this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this.getOwnerForm());
354
+ this.nodeset = evaluateXPathToNodes(this.ref, inscopeContext, this);
355
355
  } else {
356
356
  this.nodeset = this.ref;
357
357
  }
@@ -517,7 +517,7 @@ export class FxBind extends foreElementMixin(HTMLElement) {
517
517
  const touchedNodes = new Set();
518
518
  const domFacade = new DependencyNotifyingDomFacade(otherNode => touchedNodes.add(otherNode));
519
519
  this.nodeset.forEach(node => {
520
- evaluateXPathToString(propertyExpr, node, this.getOwnerForm(), domFacade);
520
+ evaluateXPathToString(propertyExpr, node, this, domFacade);
521
521
  });
522
522
 
523
523
  return Array.from(touchedNodes.values());
package/src/fx-fore.js CHANGED
@@ -152,6 +152,7 @@ export class FxFore extends HTMLElement {
152
152
 
153
153
  const html = `
154
154
  <jinn-toast id="message" gravity="bottom" position="left"></jinn-toast>
155
+ <jinn-toast id="sticky" gravity="bottom" position="left" duration="-1" close="true" data-class="sticky-message"></jinn-toast>
155
156
  <jinn-toast id="error" text="error" duration="-1" data-class="error" close="true" position="left" gravity="bottom"></jinn-toast>
156
157
  <slot></slot>
157
158
  <div id="modalMessage" class="overlay">
@@ -676,6 +677,7 @@ export class FxFore extends HTMLElement {
676
677
  await this.refresh();
677
678
  // this.style.display='block'
678
679
  this.classList.add('fx-ready');
680
+ document.body.classList.add('fx-ready');
679
681
 
680
682
  this.ready = true;
681
683
  this.initialRun = false;
@@ -728,9 +730,9 @@ export class FxFore extends HTMLElement {
728
730
  this.shadowRoot.getElementById('messageContent').innerText = msg;
729
731
  // this.shadowRoot.getElementById('modalMessage').open();
730
732
  this.shadowRoot.getElementById('modalMessage').classList.add('show');
731
- } else if (level === 'modeless') {
733
+ } else if (level === 'sticky') {
732
734
  // const notification = this.$.modeless;
733
- this.shadowRoot.querySelector('#message').showToast(msg);
735
+ this.shadowRoot.querySelector('#sticky').showToast(msg);
734
736
  } else {
735
737
  const toast = this.shadowRoot.querySelector('#message');
736
738
  toast.showToast(msg);
@@ -2,12 +2,14 @@ import { evaluateXPathToFirstNode } from './xpath-evaluation.js';
2
2
 
3
3
  import { XPathUtil } from './xpath-util.js';
4
4
 
5
+
5
6
  function _getElement(node) {
6
- if (node.nodeType === Node.ATTRIBUTE_NODE) {
7
+ if (node && node.nodeType && node.nodeType === Node.ATTRIBUTE_NODE) {
7
8
  // The context of an attribute is the ref of the element it's defined on
8
9
  return node.ownerElement;
9
10
  }
10
11
 
12
+
11
13
  if (node.nodeType === Node.ELEMENT_NODE) {
12
14
  // The context of a query should be the element having a ref
13
15
  return node;
@@ -37,7 +39,10 @@ function _getInitialContext(node, ref) {
37
39
  const model = _getModelInContext(node);
38
40
  if (XPathUtil.isAbsolutePath(ref)) {
39
41
  const instanceId = XPathUtil.getInstanceId(ref);
40
- return model.getInstance(instanceId).getDefaultContext();
42
+ if(instanceId){
43
+ return model.getInstance(instanceId).getDefaultContext();
44
+ }
45
+ return model.getDefaultInstance().getDefaultContext();
41
46
  }
42
47
  if (model.getDefaultInstance() !== null && model.inited) {
43
48
  return model.getDefaultInstance().getDefaultContext();
@@ -55,9 +60,23 @@ export default function getInScopeContext(node, ref) {
55
60
 
56
61
  const repeatItem = parentElement.closest('fx-repeatitem');
57
62
  if (repeatItem) {
63
+ if(node.nodeName === 'context'){
64
+ return evaluateXPathToFirstNode(node.nodeValue, repeatItem.nodeset, _getForeContext(parentElement));
65
+ }
58
66
  return repeatItem.nodeset;
59
67
  }
60
68
 
69
+ if (parentElement.hasAttribute('context')) {
70
+ const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
71
+ const contextAttr = node.ownerElement.getAttribute('context');
72
+ return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
73
+ }
74
+
75
+ if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'context') {
76
+ const initialContext = _getInitialContext(node.ownerElement.parentNode, ref);
77
+ const contextAttr = node.ownerElement.getAttribute('context');
78
+ return evaluateXPathToFirstNode(contextAttr, initialContext, _getForeContext(parentElement));
79
+ }
61
80
  if (node.nodeType === Node.ATTRIBUTE_NODE && node.nodeName === 'ref') {
62
81
  // Note: do not consider the ref of the owner element since it should not be used to define the
63
82
  // context
@@ -44,6 +44,10 @@ export class FxContainer extends foreElementMixin(HTMLElement) {
44
44
  if (this.isBound()) {
45
45
  this.evalInContext();
46
46
  this.modelItem = this.getModelItem();
47
+ if(!this.modelItem.boundControls.includes(this)){
48
+ this.modelItem.boundControls.push(this);
49
+ }
50
+
47
51
  // this.value = this.modelItem.value;
48
52
  }
49
53
 
@@ -1,3 +1,4 @@
1
+ import {Fore} from '../fore.js';
1
2
  export class FxDialog extends HTMLElement {
2
3
 
3
4
  static get properties() {
@@ -14,7 +15,7 @@ export class FxDialog extends HTMLElement {
14
15
  connectedCallback() {
15
16
  const style = `
16
17
  :host {
17
- display: none;
18
+ display:none;
18
19
  height: 100vh;
19
20
  width:100vw;
20
21
  position:fixed;
@@ -22,7 +23,9 @@ export class FxDialog extends HTMLElement {
22
23
  top:0;
23
24
  right:0;
24
25
  bottom:0;
26
+ transition:opacity 0.4s linear;
25
27
  }
28
+
26
29
  `;
27
30
 
28
31
  this.shadowRoot.innerHTML = this.render(style);
@@ -37,6 +40,11 @@ export class FxDialog extends HTMLElement {
37
40
  });
38
41
  }
39
42
 
43
+ this.addEventListener('transitionend',()=>{
44
+ console.log('transitionend');
45
+ // this.style.display = 'none';
46
+ });
47
+
40
48
  this.focus();
41
49
  }
42
50
 
@@ -59,7 +67,8 @@ export class FxDialog extends HTMLElement {
59
67
  this.classList.add('show');
60
68
  }
61
69
 
62
- hide(){
70
+ async hide(){
71
+ await Fore.fadeOutElement(this,400);
63
72
  this.classList.remove('show');
64
73
  }
65
74
 
@@ -1,6 +1,4 @@
1
- import XfAbstractControl from './abstract-control.js';
2
1
  import { evaluateXPath, evaluateXPathToString, evaluateXPathToNodes } from '../xpath-evaluation.js';
3
- import getInScopeContext from '../getInScopeContext.js';
4
2
  import FxControl from './fx-control.js';
5
3
  import { Fore } from '../fore.js';
6
4
 
@@ -103,7 +101,7 @@ export class FxItems extends FxControl {
103
101
  // getting expr
104
102
  const expr = input.value;
105
103
  const cutted = expr.substring(1, expr.length - 1);
106
- const evaluated = evaluateXPath(cutted, node, newEntry);
104
+ const evaluated = evaluateXPathToString(cutted, node, newEntry);
107
105
 
108
106
  // adding space around value to allow matching of 'words'
109
107
  const spaced = ` ${evaluated} `;
@@ -4,7 +4,7 @@ import { Fore } from '../fore.js';
4
4
  import { foreElementMixin } from '../ForeElementMixin.js';
5
5
  import { evaluateXPath } from '../xpath-evaluation.js';
6
6
  import getInScopeContext from '../getInScopeContext.js';
7
- import {XPathUtil} from "../xpath-util";
7
+ import { XPathUtil } from '../xpath-util';
8
8
 
9
9
  /**
10
10
  * `fx-repeat`
@@ -100,41 +100,46 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
100
100
  this.index = idx + 1;
101
101
  });
102
102
  // todo: review - this is just used by append action - event consolidation ?
103
- this.addEventListener('index-changed', e => {
103
+ document.addEventListener('index-changed', e => {
104
104
  e.stopPropagation();
105
105
  if (!e.target === this) return;
106
106
  console.log('handle index event ', e);
107
107
  // const { item } = e.detail;
108
108
  // const idx = Array.from(this.children).indexOf(item);
109
109
  const { index } = e.detail;
110
- this.index = index;
110
+ this.index = Number(index);
111
111
  this.applyIndex(this.children[index - 1]);
112
112
  });
113
+ /*
113
114
  document.addEventListener('insert', e => {
114
115
  const nodes = e.detail.insertedNodes;
115
116
  this.index = e.detail.position;
116
117
  console.log('insert catched', nodes, this.index);
117
118
  });
119
+ */
118
120
 
119
121
  // if (this.getOwnerForm().lazyRefresh) {
120
- this.mutationObserver = new MutationObserver(mutations => {
121
- console.log('mutations', mutations);
122
-
123
- if(mutations[0].type === "childList"){
124
- const added = mutations[0].addedNodes[0];
125
- if(added){
126
- const path = XPathUtil.getPath(added);
127
- console.log('path mutated',path);
128
- // this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
129
- this.dispatch('path-mutated',{'path':path,'index': this.index});
130
- }
131
-
122
+ this.mutationObserver = new MutationObserver(mutations => {
123
+ console.log('mutations', mutations);
124
+
125
+ if (mutations[0].type === 'childList') {
126
+ const added = mutations[0].addedNodes[0];
127
+ if (added) {
128
+ const path = XPathUtil.getPath(added);
129
+ console.log('path mutated', path);
130
+ // this.dispatch('path-mutated',{'path':path,'nodeset':this.nodeset,'index': this.index});
131
+ // this.index = index;
132
+ // const prev = mutations[0].previousSibling.previousElementSibling;
133
+ // const index = prev.index();
134
+ // this.applyIndex(this.index -1);
135
+
136
+ this.dispatch('path-mutated', { path, index: this.index });
132
137
  }
133
- });
138
+ }
139
+ });
134
140
  // }
135
141
  this.getOwnerForm().registerLazyElement(this);
136
142
 
137
-
138
143
  const style = `
139
144
  :host{
140
145
  }
@@ -192,7 +197,7 @@ export class FxRepeat extends foreElementMixin(HTMLElement) {
192
197
  });
193
198
  }
194
199
 
195
- const seq = evaluateXPath(this.ref, inscope, this.getOwnerForm());
200
+ const seq = evaluateXPath(this.ref, inscope, this);
196
201
  // const seq = evaluateXPathToNodes(this.ref, inscope, this.getOwnerForm());
197
202
  if (seq === null) {
198
203
  // Empty sequence
@@ -10,38 +10,14 @@ import {
10
10
  registerCustomXPathFunction,
11
11
  registerXQueryModule,
12
12
  } from 'fontoxpath';
13
+ import { Fore } from './fore.js';
14
+
13
15
  import { XPathUtil } from './xpath-util.js';
14
16
 
15
17
  const XFORMS_NAMESPACE_URI = 'http://www.w3.org/2002/xforms';
16
18
 
17
19
  const createdNamespaceResolversByXPathQueryAndNode = new Map();
18
20
 
19
- function prettifyXml(source) {
20
- const xmlDoc = new DOMParser().parseFromString(source, 'application/xml');
21
- const xsltDoc = new DOMParser().parseFromString(
22
- [
23
- // describes how we want to modify the XML - indent everything
24
- '<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">',
25
- ' <xsl:strip-space elements="*"/>',
26
- ' <xsl:template match="para[content-style][not(text())]">', // change to just text() to strip space in text nodes
27
- ' <xsl:value-of select="normalize-space(.)"/>',
28
- ' </xsl:template>',
29
- ' <xsl:template match="node()|@*">',
30
- ' <xsl:copy><xsl:apply-templates select="node()|@*"/></xsl:copy>',
31
- ' </xsl:template>',
32
- ' <xsl:output indent="yes"/>',
33
- '</xsl:stylesheet>',
34
- ].join('\n'),
35
- 'application/xml',
36
- );
37
-
38
- const xsltProcessor = new XSLTProcessor();
39
- xsltProcessor.importStylesheet(xsltDoc);
40
- const resultDoc = xsltProcessor.transformToDocument(xmlDoc);
41
- const resultXml = new XMLSerializer().serializeToString(resultDoc);
42
- return resultXml;
43
- }
44
-
45
21
  function getCachedNamespaceResolver(xpath, node) {
46
22
  if (!createdNamespaceResolversByXPathQueryAndNode.has(xpath)) {
47
23
  return null;
@@ -236,9 +212,11 @@ function getVariablesInScope(formElement) {
236
212
  }
237
213
 
238
214
  const variables = {};
239
- for (const key of closestActualFormElement.inScopeVariables.keys()) {
240
- const varElement = closestActualFormElement.inScopeVariables.get(key);
241
- variables[key] = varElement.value;
215
+ if(closestActualFormElement.inScopeVariables){
216
+ for (const key of closestActualFormElement.inScopeVariables.keys()) {
217
+ const varElement = closestActualFormElement.inScopeVariables.get(key);
218
+ variables[key] = varElement.value;
219
+ }
242
220
  }
243
221
  return variables;
244
222
  }
@@ -599,7 +577,7 @@ registerCustomXPathFunction(
599
577
  // return JSON.stringify(instance.getDefaultContext());
600
578
  } else {
601
579
  const def = new XMLSerializer().serializeToString(instance.getDefaultContext());
602
- return prettifyXml(def);
580
+ return Fore.prettifyXml(def);
603
581
  }
604
582
  }
605
583
  return null;
package/src/xpath-util.js CHANGED
@@ -57,16 +57,27 @@ export class XPathUtil {
57
57
  throw new Error('no Fore element present');
58
58
  }
59
59
 
60
- // todo: this will need more work to look upward for instance() expr.
60
+ /**
61
+ * returns the instance id from a complete XPath using `instance()` function.
62
+ *
63
+ * Will return 'default' in case no ref is given at all or the `instance()` function is called without arg.
64
+ *
65
+ * Otherwise instance id is extracted from function and returned. If all fails null is returned.
66
+ * @param ref
67
+ * @returns {string}
68
+ */
61
69
  static getInstanceId(ref) {
62
70
  if (!ref) {
63
71
  return 'default';
64
72
  }
73
+ if (ref.startsWith('instance()')) {
74
+ return 'default';
75
+ }
65
76
  if (ref.startsWith('instance(')) {
66
77
  const result = ref.substring(ref.indexOf('(') + 1);
67
78
  return result.substring(1, result.indexOf(')') - 1);
68
79
  }
69
- return 'default';
80
+ return null;
70
81
  }
71
82
 
72
83
  // todo: certainly not ideal to rely on duplicating instance id on instance document - better way later ;)