w-flow-vue 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 (144) hide show
  1. package/.editorconfig +9 -0
  2. package/.eslintignore +3 -0
  3. package/.eslintrc.js +55 -0
  4. package/.jsdoc +25 -0
  5. package/AGENT.md +223 -0
  6. package/LICENSE +21 -0
  7. package/README.md +37 -0
  8. package/SECURITY.md +5 -0
  9. package/babel.config.js +16 -0
  10. package/dist/w-flow-vue.umd.js +15 -0
  11. package/dist/w-flow-vue.umd.js.map +1 -0
  12. package/docs/components_WFlowVue.vue.html +1214 -0
  13. package/docs/examples/app.html +62 -0
  14. package/docs/examples/app.umd.js +20 -0
  15. package/docs/examples/app.umd.js.map +1 -0
  16. package/docs/examples/ex-AppBasic.html +440 -0
  17. package/docs/examples/ex-AppConnectivity.html +131 -0
  18. package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
  19. package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
  20. package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
  21. package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
  22. package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
  23. package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
  24. package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
  25. package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
  26. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
  27. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
  28. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
  29. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
  30. package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
  31. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
  32. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
  33. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
  34. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
  35. package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
  36. package/docs/global.html +1919 -0
  37. package/docs/index.html +84 -0
  38. package/docs/js_defaults.mjs.html +105 -0
  39. package/docs/js_edge-path.mjs.html +237 -0
  40. package/docs/js_geometry.mjs.html +298 -0
  41. package/docs/js_graph.mjs.html +103 -0
  42. package/docs/js_step-routing.mjs.html +346 -0
  43. package/docs/module-WFlowVue.html +2790 -0
  44. package/docs/scripts/collapse.js +39 -0
  45. package/docs/scripts/commonNav.js +28 -0
  46. package/docs/scripts/linenumber.js +25 -0
  47. package/docs/scripts/nav.js +12 -0
  48. package/docs/scripts/polyfill.js +4 -0
  49. package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  50. package/docs/scripts/prettify/lang-css.js +2 -0
  51. package/docs/scripts/prettify/prettify.js +28 -0
  52. package/docs/scripts/search.js +99 -0
  53. package/docs/styles/jsdoc.css +776 -0
  54. package/docs/styles/prettify.css +80 -0
  55. package/jest.config.js +20 -0
  56. package/package.json +80 -0
  57. package/public/index.html +38 -0
  58. package/script.txt +22 -0
  59. package/src/App.vue +326 -0
  60. package/src/AppBasic.vue +125 -0
  61. package/src/AppConnectivity.vue +186 -0
  62. package/src/components/WFlowVue.vue +1142 -0
  63. package/src/components/canvas/BackgroundLayer.vue +78 -0
  64. package/src/components/canvas/FlowCanvas.vue +64 -0
  65. package/src/components/canvas/SelectionBox.vue +36 -0
  66. package/src/components/canvas/ViewportTransform.vue +35 -0
  67. package/src/components/edges/ConnectionLine.vue +65 -0
  68. package/src/components/edges/EdgeMarkerDefs.vue +76 -0
  69. package/src/components/edges/EdgeRenderer.vue +120 -0
  70. package/src/components/edges/EdgeWrapper.vue +379 -0
  71. package/src/components/nodes/DefaultNode.vue +276 -0
  72. package/src/components/nodes/Handle.vue +101 -0
  73. package/src/components/nodes/InputNode.vue +47 -0
  74. package/src/components/nodes/NodeBody.vue +103 -0
  75. package/src/components/nodes/NodeFace.vue +128 -0
  76. package/src/components/nodes/NodeRenderer.vue +95 -0
  77. package/src/components/nodes/NodeWrapper.vue +475 -0
  78. package/src/components/nodes/OutputNode.vue +47 -0
  79. package/src/components/ui/ConnSettingsForm.vue +158 -0
  80. package/src/components/ui/Controls.vue +83 -0
  81. package/src/components/ui/NodeSettingsForm.vue +185 -0
  82. package/src/js/defaults.mjs +33 -0
  83. package/src/js/edge-path.mjs +165 -0
  84. package/src/js/geometry.mjs +226 -0
  85. package/src/js/graph.mjs +31 -0
  86. package/src/js/step-routing.mjs +274 -0
  87. package/src/main.js +22 -0
  88. package/test/WFlowVue-features.test.mjs +760 -0
  89. package/test/WFlowVue.test.mjs +421 -0
  90. package/test/components-canvas.test.mjs +102 -0
  91. package/test/components-edge.test.mjs +147 -0
  92. package/test/components-node.test.mjs +174 -0
  93. package/test/components-ui.test.mjs +69 -0
  94. package/test/defaults.test.mjs +86 -0
  95. package/test/edge-path.test.mjs +102 -0
  96. package/test/generate-routing-snapshots.mjs +77 -0
  97. package/test/generate-visual-baselines.mjs +206 -0
  98. package/test/geometry.test.mjs +236 -0
  99. package/test/graph.test.mjs +72 -0
  100. package/test/jsons/routing-snapshots.json +24994 -0
  101. package/test/pics/_check2.png +0 -0
  102. package/test/pics/_check3.png +0 -0
  103. package/test/pics/_check4.png +0 -0
  104. package/test/pics/_check5.png +0 -0
  105. package/test/pics/_v1.png +0 -0
  106. package/test/pics/_v2.png +0 -0
  107. package/test/pics/_v3.png +0 -0
  108. package/test/pics/_v4.png +0 -0
  109. package/test/pics/_v5.png +0 -0
  110. package/test/pics/_v6.png +0 -0
  111. package/test/pics/_v7.png +0 -0
  112. package/test/pics/vb-edge-hovered.png +0 -0
  113. package/test/pics/vb-edges-normal.png +0 -0
  114. package/test/pics/vb-locked-edge-hovered.png +0 -0
  115. package/test/pics/vb-locked-node-hovered.png +0 -0
  116. package/test/pics/vb-locked-node-selected.png +0 -0
  117. package/test/pics/vb-locked-overview.png +0 -0
  118. package/test/pics/vb-node-1.png +0 -0
  119. package/test/pics/vb-node-10.png +0 -0
  120. package/test/pics/vb-node-11.png +0 -0
  121. package/test/pics/vb-node-12.png +0 -0
  122. package/test/pics/vb-node-2.png +0 -0
  123. package/test/pics/vb-node-3.png +0 -0
  124. package/test/pics/vb-node-4.png +0 -0
  125. package/test/pics/vb-node-5.png +0 -0
  126. package/test/pics/vb-node-6.png +0 -0
  127. package/test/pics/vb-node-7.png +0 -0
  128. package/test/pics/vb-node-8.png +0 -0
  129. package/test/pics/vb-node-9.png +0 -0
  130. package/test/pics/vb-node-hovered.png +0 -0
  131. package/test/pics/vb-node-selected.png +0 -0
  132. package/test/pics/vb-overview.png +0 -0
  133. package/test/step-routing-connectivity.test.mjs +78 -0
  134. package/test/step-routing.test.mjs +88 -0
  135. package/test/visual-regression.test.mjs +274 -0
  136. package/toolg/addVersion.mjs +4 -0
  137. package/toolg/cleanFolder.mjs +4 -0
  138. package/toolg/gDistApp.mjs +34 -0
  139. package/toolg/gDistRollupComps.mjs +22 -0
  140. package/toolg/gDocExams.mjs +47 -0
  141. package/toolg/gExtractHtml.mjs +179 -0
  142. package/toolg/modifyReadme.mjs +4 -0
  143. package/vue.config.js +9 -0
  144. package/vue2/344/271/213foreignObject/345/205/247/346/270/262/346/237/223/345/225/217/351/241/214/350/210/207/344/277/256/346/255/243.md +151 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Validate a potential connection.
3
+ */
4
+ export function isValidConnection(connection, nodes, conns, validator) {
5
+ if (!connection.from || !connection.to) return false
6
+
7
+ // Self-connection not allowed by default
8
+ if (connection.from === connection.to) return false
9
+
10
+ // Check duplicate (same from→to path)
11
+ const duplicate = conns.find(
12
+ e => e.from === connection.from && e.to === connection.to
13
+ )
14
+ if (duplicate) return false
15
+
16
+ // Custom validator
17
+ if (validator && !validator(connection)) return false
18
+
19
+ return true
20
+ }
21
+
22
+ let _idCounter = 0
23
+
24
+ /**
25
+ * Generate a unique ID.
26
+ */
27
+ export function generateId() {
28
+ _idCounter++
29
+ return `${Date.now()}-${_idCounter}-${Math.random().toString(36).slice(2, 7)}`
30
+ }
31
+
@@ -0,0 +1,274 @@
1
+ // --- Step path routing using draw.io OrthConnector algorithm ---
2
+
3
+ let _cache = new Map()
4
+ let _cacheFrame = -1
5
+
6
+ export function clearStepCache() {
7
+ _cache.clear()
8
+ _cacheFrame = -1
9
+ }
10
+
11
+ export function calculateStepPoints(
12
+ sourceX, sourceY, sourcePosition,
13
+ targetX, targetY, targetPosition,
14
+ offset, allNodes, nodeInternals, connFromId, connToId
15
+ ) {
16
+ // --- Per-frame cache ---
17
+ let frame = Math.floor(Date.now() / 16)
18
+ if (frame !== _cacheFrame) {
19
+ _cache.clear(); _cacheFrame = frame
20
+ }
21
+ let ck = Math.round(sourceX / 10) + ',' + Math.round(sourceY / 10) + ',' +
22
+ Math.round(targetX / 10) + ',' + Math.round(targetY / 10) + ',' +
23
+ sourcePosition + ',' + targetPosition
24
+ let cached = _cache.get(ck)
25
+ if (cached) return cached
26
+
27
+ // Collect obstacles (bbox for all visible nodes)
28
+ let obs = []
29
+ if (allNodes && allNodes.length > 0) {
30
+ let ni = nodeInternals || {}
31
+ for (let i = 0; i < allNodes.length; i++) {
32
+ let n = allNodes[i]
33
+ if (n.hidden) continue
34
+ let w = (ni[n.id] && ni[n.id].width) || n.width || 100
35
+ let h = (ni[n.id] && ni[n.id].height) || n.height || 40
36
+ obs.push({ l: n.position.x, t: n.position.y, r: n.position.x + w, b: n.position.y + h })
37
+ }
38
+ }
39
+
40
+ let sObs = findObstacleAt(obs, sourceX, sourceY)
41
+ let tObs = findObstacleAt(obs, targetX, targetY)
42
+ let hOff = offset || 24
43
+
44
+ let result = lookupRoute(sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, sObs, tObs, hOff)
45
+ if (!result) {
46
+ result = segmentFallback(sourceX, sourceY, targetX, targetY, sObs, tObs)
47
+ }
48
+
49
+ if (_cache.size > 200) _cache.clear()
50
+ _cache.set(ck, result)
51
+ return result
52
+ }
53
+
54
+ // ==================== Helpers ====================
55
+
56
+ function findObstacleAt(obs, hx, hy) {
57
+ for (let i = 0; i < obs.length; i++) {
58
+ let o = obs[i]
59
+ if (hx >= o.l - 5 && hx <= o.r + 5 && hy >= o.t - 5 && hy <= o.b + 5) return o
60
+ }
61
+ return null
62
+ }
63
+
64
+ // === draw.io OrthConnector algorithm (adapted from mxEdgeStyle.js) ===
65
+ // Route patterns encode movement steps as bit-packed integers.
66
+ // Each step: direction(0-3) | side_mask(5-8) | center(9) | source(10) | target(11)
67
+ // The quad rotation normalizes geometry so a 4×4 table covers all 16 direction combos.
68
+ // Constants match draw.io: WEST=1, NORTH=2, SOUTH=4, EAST=8
69
+
70
+ let _W = 1; let _N = 2; let _S = 4; let _E = 8
71
+ let _SIDE = 480; let _CTR = 512; let _SRC = 1024; let _TGT = 2048
72
+ let _dirV = [[-1, 0], [0, -1], [1, 0], [0, 1], [-1, 0], [0, -1], [1, 0]]
73
+
74
+ let _rp = [
75
+ [[513, 2308, 2081, 2562], [513, 1090, 514, 2184, 2114, 2561], [513, 1090, 514, 2564, 2184, 2562], [513, 2308, 2561, 1090, 514, 2568, 2308]],
76
+ [[514, 1057, 513, 2308, 2081, 2562], [514, 2184, 2114, 2561], [514, 2184, 2562, 1057, 513, 2564, 2184], [514, 1057, 513, 2568, 2308, 2561]],
77
+ [[1090, 514, 1057, 513, 2308, 2081, 2562], [2114, 2561], [1090, 2562, 1057, 513, 2564, 2184], [1090, 514, 1057, 513, 2308, 2561, 2568]],
78
+ [[2081, 2562], [1057, 513, 1090, 514, 2184, 2114, 2561], [1057, 513, 1090, 514, 2184, 2562, 2564], [1057, 2561, 1090, 514, 2568, 2308]]
79
+ ]
80
+
81
+ function posToDirMask(pos) {
82
+ switch (pos) {
83
+ case 'left': return _W
84
+ case 'top': return _N
85
+ case 'right': return _E
86
+ case 'bottom': return _S
87
+ default: return _S
88
+ }
89
+ }
90
+
91
+ /**
92
+ * draw.io OrthConnector route generation.
93
+ * Uses bit-encoded route patterns + quad rotation + limits clamping.
94
+ * Returns waypoint array or null (fallback needed).
95
+ */
96
+ function lookupRoute(sourceX, sourceY, sourcePosition, targetX, targetY, targetPosition, sObs, tObs, buf) {
97
+ if (!sObs || !tObs) return null
98
+
99
+ let sDir = posToDirMask(sourcePosition)
100
+ let tDir = posToDirMask(targetPosition)
101
+
102
+ // Node geometry [x, y, width, height]
103
+ let geo = [
104
+ [sObs.l, sObs.t, sObs.r - sObs.l, sObs.b - sObs.t],
105
+ [tObs.l, tObs.t, tObs.r - tObs.l, tObs.b - tObs.t]
106
+ ]
107
+
108
+ // Too-close check: distance < 2*buf → fallback
109
+ let ddx = sourceX - targetX; let ddy = sourceY - targetY
110
+ let totalBuf = buf * 2
111
+ if (ddx * ddx + ddy * ddy < totalBuf * totalBuf) return null
112
+
113
+ // Limits: expanded bbox per node (prevents lines crossing nodes)
114
+ // draw.io hardcoded indices: [1]=left, [2]=top, [4]=right, [8]=bottom
115
+ let lim = [[], []]
116
+ for (let i = 0; i < 2; i++) {
117
+ lim[i][1] = geo[i][0] - buf
118
+ lim[i][2] = geo[i][1] - buf
119
+ lim[i][4] = geo[i][0] + geo[i][2] + buf
120
+ lim[i][8] = geo[i][1] + geo[i][3] + buf
121
+ }
122
+
123
+ // Constraint: handle position relative to node (0–1)
124
+ let con = [[0.5, 0.5], [0.5, 0.5]]
125
+ let gw0 = geo[0][2] || 1; let gh0 = geo[0][3] || 1
126
+ let gw1 = geo[1][2] || 1; let gh1 = geo[1][3] || 1
127
+ con[0][0] = (sourceX - geo[0][0]) / gw0
128
+ con[0][1] = (sourceY - geo[0][1]) / gh0
129
+ con[1][0] = (targetX - geo[1][0]) / gw1
130
+ con[1][1] = (targetY - geo[1][1]) / gh1
131
+
132
+ // Quad: which quadrant is target center relative to source center
133
+ // 0 | 1
134
+ // -----
135
+ // 3 | 2
136
+ let sCx = geo[0][0] + geo[0][2] / 2; let sCy = geo[0][1] + geo[0][3] / 2
137
+ let tCx = geo[1][0] + geo[1][2] / 2; let tCy = geo[1][1] + geo[1][3] / 2
138
+ let qx = sCx - tCx; let qy = sCy - tCy
139
+ let quad = 0
140
+ if (qx < 0) {
141
+ quad = qy < 0 ? 2 : 1
142
+ }
143
+ else if (qy <= 0) {
144
+ quad = qx === 0 ? 2 : 3
145
+ }
146
+
147
+ // Vertex separations (gap between nodes minus buffer, min 0)
148
+ let vs = []
149
+ vs[1] = Math.max(geo[0][0] - (geo[1][0] + geo[1][2]) - totalBuf, 0)
150
+ vs[2] = Math.max(geo[0][1] - (geo[1][1] + geo[1][3]) - totalBuf, 0)
151
+ vs[3] = Math.max(geo[1][0] - (geo[0][0] + geo[0][2]) - totalBuf, 0)
152
+ vs[4] = Math.max(geo[1][1] - (geo[0][1] + geo[0][3]) - totalBuf, 0)
153
+
154
+ // Route pattern lookup (with quad rotation)
155
+ // draw.io: only map EAST(8)→3, others are already in range 1-4
156
+ let si = sDir === _E ? 3 : sDir
157
+ let ti = tDir === _E ? 3 : tDir
158
+ si -= quad; ti -= quad
159
+ if (si < 1) si += 4
160
+ if (ti < 1) ti += 4
161
+ let rp = _rp[si - 1][ti - 1]
162
+
163
+ // Initial waypoint: handle position moved outward by buffer
164
+ let wp = []
165
+ for (let k = 0; k < 12; k++) wp[k] = [0, 0]
166
+ wp[0][0] = geo[0][0]
167
+ wp[0][1] = geo[0][1]
168
+ switch (sDir) {
169
+ case _W: wp[0][0] -= buf; wp[0][1] += con[0][1] * geo[0][3]; break
170
+ case _S: wp[0][0] += con[0][0] * geo[0][2]; wp[0][1] += geo[0][3] + buf; break
171
+ case _E: wp[0][0] += geo[0][2] + buf; wp[0][1] += con[0][1] * geo[0][3]; break
172
+ case _N: wp[0][0] += con[0][0] * geo[0][2]; wp[0][1] -= buf; break
173
+ }
174
+
175
+ // Waypoint generation loop
176
+ let ci = 0
177
+ let lastOr = (sDir & (_E | _W)) > 0 ? 0 : 1
178
+ let initOr = lastOr
179
+
180
+ for (let i = 0; i < rp.length; i++) {
181
+ let nd = rp[i] & 0xF
182
+ // draw.io: only map EAST(8)→3
183
+ let di = nd === _E ? 3 : nd
184
+ di += quad
185
+ if (di > 4) di -= 4
186
+ let dir = _dirV[di - 1]
187
+ let curOr = (di % 2 > 0) ? 0 : 1
188
+
189
+ if (curOr !== lastOr) {
190
+ ci++
191
+ wp[ci] = [wp[ci - 1][0], wp[ci - 1][1]]
192
+ }
193
+
194
+ let tar = (rp[i] & _TGT) > 0
195
+ let sou = (rp[i] & _SRC) > 0
196
+ let side = (rp[i] & _SIDE) >> 5
197
+ side = side << quad
198
+ if (side > 0xF) side = side >> 4
199
+ let ctr = (rp[i] & _CTR) > 0
200
+
201
+ if ((sou || tar) && side < 9) {
202
+ let st = sou ? 0 : 1
203
+ let limit
204
+ if (ctr && curOr === 0) {
205
+ limit = geo[st][0] + con[st][0] * geo[st][2]
206
+ }
207
+ else if (ctr) {
208
+ limit = geo[st][1] + con[st][1] * geo[st][3]
209
+ }
210
+ else {
211
+ limit = lim[st][side]
212
+ }
213
+ if (curOr === 0) {
214
+ let delta = (limit - wp[ci][0]) * dir[0]
215
+ if (delta > 0) wp[ci][0] += dir[0] * delta
216
+ }
217
+ else {
218
+ let delta = (limit - wp[ci][1]) * dir[1]
219
+ if (delta > 0) wp[ci][1] += dir[1] * delta
220
+ }
221
+ }
222
+ else if (ctr) {
223
+ wp[ci][0] += dir[0] * Math.abs(vs[di] / 2)
224
+ wp[ci][1] += dir[1] * Math.abs(vs[di] / 2)
225
+ }
226
+
227
+ // Collapse zero-length segments
228
+ if (ci > 0 && wp[ci][curOr] === wp[ci - 1][curOr]) {
229
+ ci--
230
+ }
231
+ else {
232
+ lastOr = curOr
233
+ }
234
+ }
235
+
236
+ // Build result: source handle → waypoints → target handle
237
+ let pts = [{ x: sourceX, y: sourceY }]
238
+ let tOr = (tDir & (_E | _W)) > 0 ? 0 : 1
239
+ let sameOr = tOr === initOr ? 0 : 1
240
+
241
+ for (let i = 0; i <= ci; i++) {
242
+ if (i === ci && sameOr !== (ci + 1) % 2) break
243
+ pts.push({ x: Math.round(wp[i][0] * 10) / 10, y: Math.round(wp[i][1] * 10) / 10 })
244
+ }
245
+ pts.push({ x: targetX, y: targetY })
246
+
247
+ // Remove consecutive duplicates
248
+ let result = [pts[0]]
249
+ for (let i = 1; i < pts.length; i++) {
250
+ if (Math.abs(pts[i].x - result[result.length - 1].x) > 0.5 ||
251
+ Math.abs(pts[i].y - result[result.length - 1].y) > 0.5) {
252
+ result.push(pts[i])
253
+ }
254
+ }
255
+ return result
256
+ }
257
+
258
+ /**
259
+ * SegmentConnector fallback (draw.io style).
260
+ * Used when nodes are too close for OrthConnector (tooShort).
261
+ */
262
+ function segmentFallback(sx, sy, tx, ty, sObs, tObs) {
263
+ let pts = [{ x: sx, y: sy }]
264
+ if (tObs && tx >= tObs.l && tx <= tObs.r && sy >= tObs.t && sy <= tObs.b) {
265
+ if (!(sObs && sx >= sObs.l && sx <= sObs.r && ty >= sObs.t && ty <= sObs.b)) {
266
+ pts.push({ x: sx, y: ty })
267
+ }
268
+ }
269
+ else if (sx !== tx && sy !== ty) {
270
+ pts.push({ x: tx, y: sy })
271
+ }
272
+ pts.push({ x: tx, y: ty })
273
+ return pts
274
+ }
package/src/main.js ADDED
@@ -0,0 +1,22 @@
1
+ import Vue from 'vue'
2
+ import App from './App.vue'
3
+
4
+ Vue.config.productionTip = false
5
+
6
+ // Fix Vue 2 bug #7330: components inside SVG foreignObject inherit
7
+ // SVG namespace, causing HTML elements to render as SVGElement (0x0).
8
+ Vue.mixin({
9
+ beforeCreate() {
10
+ if (this.$vnode && this.$vnode.ns === 'svg') this.$vnode.ns = undefined
11
+ },
12
+ beforeMount() {
13
+ if (this.$vnode && this.$vnode.ns === 'svg') this.$vnode.ns = undefined
14
+ },
15
+ beforeUpdate() {
16
+ if (this.$vnode && this.$vnode.ns === 'svg') this.$vnode.ns = undefined
17
+ },
18
+ })
19
+
20
+ new Vue({
21
+ render: h => h(App),
22
+ }).$mount('#app')