turbo_boost-elements 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,7 +22,6 @@ class TurboBoost::Elements::ToggleCommand < TurboBoost::Elements::ApplicationCom
22
22
  end
23
23
 
24
24
  def toggle
25
- validate_element!
26
25
  element.aria.expanded? ? hide : show
27
26
  end
28
27
 
@@ -84,29 +84,37 @@ export default class TooltipElement extends HTMLElement {
84
84
  display: block;
85
85
  font-size: 0.8rem;
86
86
  font-weight: lighter;
87
- margin-bottom: 8px;
88
- margin-top: 4px;
87
+ margin-bottom: 12px;
88
+ margin-top: 8px;
89
89
  padding-bottom: 4px;
90
90
  padding-top: 4px;
91
91
  width: 100%;
92
92
  }
93
93
 
94
+ slot[name="content-top"],
95
+ slot[name="content"],
96
+ slot[name="content-bottom"] {
97
+ display: block;
98
+ font-weight: normal;
99
+ }
100
+
94
101
  slot[name="content-top"] {
95
102
  color: ${this.color};
96
- font-weight: normal;
103
+ margin-bottom: 8px;
104
+ }
105
+
106
+ slot[name="content"],
107
+ slot[name="content-bottom"] {
97
108
  opacity: 0.7;
109
+ padding-left: 12px;
98
110
  }
99
111
 
100
112
  slot[name="content"] {
101
113
  color: ${this.color};
102
- font-weight: normal;
103
- opacity: 0.7;
104
114
  }
105
115
 
106
116
  slot[name="content-bottom"] {
107
117
  color: red;
108
- font-weight: normal;
109
- opacity: 0.7;
110
118
  }
111
119
  `
112
120
  }
@@ -81,6 +81,7 @@ addEventListener('turbo:load', autoRestart)
81
81
  addEventListener('turbo-frame:load', autoRestart)
82
82
  addEventListener(TurboBoost.Commands.events.success, autoRestart)
83
83
  addEventListener(TurboBoost.Commands.events.finish, autoRestart)
84
+ addEventListener('turbo-boost:devtools-connect', autoRestart)
84
85
  addEventListener('turbo-boost:devtools-close', stop)
85
86
 
86
87
  function register (name, label) {
@@ -1,5 +1,9 @@
1
- import ToggleTargetElement from './toggle_target_element'
2
- import ToggleTriggerElement from './toggle_trigger_element'
1
+ import TurboBoostElement from './turbo_boost_element'
2
+ import ToggleTargetElement from './toggle_elements/target_element'
3
+ import ToggleTriggerElement from './toggle_elements/trigger_element'
3
4
 
5
+ // Valid custom element names: https://html.spec.whatwg.org/#valid-custom-element-name
6
+
7
+ customElements.define('turbo-boost', TurboBoostElement)
4
8
  customElements.define('turbo-boost-toggle-target', ToggleTargetElement)
5
9
  customElements.define('turbo-boost-toggle-trigger', ToggleTriggerElement)
@@ -0,0 +1,138 @@
1
+ import ToggleElement from '../toggle_element'
2
+ import './focus'
3
+
4
+ export default class ToggleTargetElement extends ToggleElement {
5
+ connectedCallback () {
6
+ super.connectedCallback()
7
+
8
+ this.mouseenterHandler = this.onMouseenter.bind(this)
9
+ this.addEventListener('mouseenter', this.mouseenterHandler)
10
+
11
+ this.collapseHandler = this.collapse.bind(this)
12
+ this.collapseNowHandler = this.collapseNow.bind(this)
13
+
14
+ this.collapseOn.forEach(entry => {
15
+ const parts = entry.split('@')
16
+ const name = parts[0]
17
+
18
+ if (parts.length > 1) {
19
+ const target = parts[1].match(/^self|window$/) ? self : self[parts[1]]
20
+ target.addEventListener(name, this.collapseNowHandler)
21
+ } else {
22
+ this.addEventListener(name, this.collapseHandler)
23
+ }
24
+ })
25
+ }
26
+
27
+ disconnectedCallback () {
28
+ this.removeEventListener('mouseenter', this.mouseenterHandler)
29
+
30
+ this.collapseOn.forEach(entry => {
31
+ const parts = entry.split('@')
32
+ const name = parts[0]
33
+
34
+ if (parts.length > 1) {
35
+ const target = parts[1].match(/^self|window$/) ? self : self[parts[1]]
36
+ target.removeEventListener(name, this.collapseNowHandler)
37
+ } else {
38
+ this.removeEventListener(name, this.collapseHandler)
39
+ }
40
+ })
41
+ }
42
+
43
+ // TODO: get cached content working properly
44
+ // perhaps use a mechanic other than morph
45
+
46
+ // TODO: implement cache (similar to Turbo Drive restoration visit)
47
+ cacheHTML () {
48
+ // this.cachedHTML = this.innerHTML
49
+ }
50
+
51
+ // TODO: implement cache (similar to Turbo Drive restoration visit)
52
+ renderCachedHTML () {
53
+ // if (!this.cachedHTML) return
54
+ // this.innerHTML = this.cachedHTML
55
+ }
56
+
57
+ onMouseenter () {
58
+ clearTimeout(this.collapseTimeout)
59
+ }
60
+
61
+ collapse (delay = 250) {
62
+ clearTimeout(this.collapseTimeout)
63
+ if (typeof delay !== 'number') delay = 250
64
+
65
+ if (delay > 0)
66
+ return (this.collapseTimeout = setTimeout(() => this.collapse(0), delay))
67
+
68
+ this.innerHTML = ''
69
+ try {
70
+ this.expanded = false
71
+ this.triggerElement.hideDevtool()
72
+ } catch {}
73
+ }
74
+
75
+ collapseNow (event) {
76
+ if (event.target.closest('turbo-boost-devtool-tooltip')) return
77
+ this.collapse(0)
78
+ }
79
+
80
+ collapseMatches () {
81
+ document.querySelectorAll(this.collapseSelector).forEach(el => {
82
+ if (el === this) return
83
+ if (el.collapse) el.collapse(0)
84
+ })
85
+ }
86
+
87
+ get collapseSelector () {
88
+ return (
89
+ this.triggerElement.collapseSelector ||
90
+ this.getAttribute('collapse-selector')
91
+ )
92
+ }
93
+
94
+ focus () {
95
+ clearTimeout(this.focusTimeout)
96
+ this.focusTimeout = setTimeout(() => {
97
+ if (this.focusElement) this.focusElement.focus()
98
+ }, 50)
99
+ }
100
+
101
+ get focusSelector () {
102
+ let value = this.getAttribute('focus-selector')
103
+ if (this.triggerElement)
104
+ value = this.triggerElement.getAttribute('focus-selector') || value
105
+ return value
106
+ }
107
+
108
+ get focusElement () {
109
+ return this.querySelector(this.focusSelector)
110
+ }
111
+
112
+ get triggerElement () {
113
+ return (
114
+ document.getElementById(this.labeledBy) ||
115
+ document.querySelector(
116
+ `turbo-boost-toggle-trigger[aria-controls="${this.id}"]`
117
+ )
118
+ )
119
+ }
120
+
121
+ get labeledBy () {
122
+ return this.getAttribute('aria-labeledby')
123
+ }
124
+
125
+ get collapseOn () {
126
+ const value = this.getAttribute('collapse-on')
127
+ if (!value) return []
128
+ return JSON.parse(value)
129
+ }
130
+
131
+ get expanded () {
132
+ return this.triggerElement.expanded
133
+ }
134
+
135
+ set expanded (value) {
136
+ return (this.triggerElement.expanded = value)
137
+ }
138
+ }
@@ -0,0 +1,83 @@
1
+ import TurboBoostElement from '../../turbo_boost_element'
2
+
3
+ const html = `
4
+ <turbo-boost>
5
+ <slot name="busy" hidden></slot>
6
+ <slot></slot>
7
+ </turbo-boost>
8
+ `
9
+
10
+ export const busyDelay = 100 // milliseconds - time to wait before showing busy element
11
+ export const busyDuration = 400 // milliseconds - minimum time that busy element is shown
12
+
13
+ export default class ToggleElement extends TurboBoostElement {
14
+ constructor () {
15
+ super(html)
16
+ }
17
+
18
+ // TODO: Should we timeout after a theoretical max wait time?
19
+ // The idea being that a server error occurred and the toggle failed.
20
+ showBusyElement () {
21
+ clearTimeout(this.showBusyElementTimeout)
22
+ clearTimeout(this.hideBusyElementTimeout)
23
+
24
+ if (!this.busyElement) return
25
+
26
+ this.busyStartedAt = Date.now() + busyDelay
27
+ this.showBusyElementTimeout = setTimeout(() => {
28
+ this.busySlotElement.hidden = false
29
+ this.defaultSlotElement.hidden = true
30
+ }, busyDelay)
31
+ }
32
+
33
+ hideBusyElement () {
34
+ clearTimeout(this.showBusyElementTimeout)
35
+ clearTimeout(this.hideBusyElementTimeout)
36
+
37
+ if (!this.busyElement) return
38
+
39
+ let delay = busyDuration - (Date.now() - this.busyStartedAt)
40
+ if (delay < 0) delay = 0
41
+
42
+ delete this.busyStartedAt
43
+ this.hideBusyElementTimeout = setTimeout(() => {
44
+ this.busySlotElement.hidden = true
45
+ this.defaultSlotElement.hidden = false
46
+ }, delay)
47
+ }
48
+
49
+ get busyElement () {
50
+ return this.querySelector(':scope > [slot="busy"]')
51
+ }
52
+
53
+ get busySlotElement () {
54
+ return this.shadowRoot.querySelector('slot[name="busy"]')
55
+ }
56
+
57
+ get defaultSlotElement () {
58
+ return this.shadowRoot.querySelector('slot:not([name])')
59
+ }
60
+
61
+ // indicates if an rpc call is active/busy
62
+ get busy () {
63
+ return this.getAttribute('busy') === 'true'
64
+ }
65
+
66
+ // indicates if an rpc call is active/busy
67
+ set busy (value) {
68
+ value = !!value
69
+ if (this.busy === value) return
70
+ this.setAttribute('busy', value)
71
+ if (value) this.showBusyElement()
72
+ else this.hideBusyElement()
73
+ }
74
+
75
+ get busyStartedAt () {
76
+ if (!this.dataset.busyStartedAt) return 0
77
+ return Number(this.dataset.busyStartedAt)
78
+ }
79
+
80
+ set busyStartedAt (value) {
81
+ this.dataset.busyStartedAt = value
82
+ }
83
+ }
@@ -1,15 +1,17 @@
1
+ // Icons courtesy of https://feathericons.com/
1
2
  import {
2
3
  appendHTML,
3
4
  addHighlight,
5
+ attempt,
4
6
  coordinates,
5
7
  removeHighlight
6
- } from '../utils/dom'
7
- import supervisor from './supervisor'
8
+ } from '../../../utils/dom'
9
+ import supervisor from '../../../devtools/supervisor'
8
10
 
9
11
  let activeToggle
10
12
 
11
13
  document.addEventListener('turbo-boost:devtools-start', () =>
12
- supervisor.register('toggle', 'toggles<small>(trigger/target)</small>')
14
+ supervisor.register('toggle', 'toggles')
13
15
  )
14
16
 
15
17
  function appendTooltip (title, subtitle, content, options = {}) {
@@ -25,7 +27,7 @@ function appendTooltip (title, subtitle, content, options = {}) {
25
27
  `)
26
28
  }
27
29
 
28
- export default class ToggleDevtool {
30
+ export default class Devtool {
29
31
  constructor (triggerElement) {
30
32
  this.name = 'toggle'
31
33
  this.command = triggerElement.dataset.turboCommand
@@ -33,47 +35,79 @@ export default class ToggleDevtool {
33
35
  this.targetElement = triggerElement.targetElement // SEE: app/javascript/elements/toggle_target_element.js
34
36
  this.morphElement = triggerElement.morphElement
35
37
 
36
- document.addEventListener('turbo-boost:devtool-enable', event => {
38
+ let hideTimeout
39
+ const debouncedHide = () => {
40
+ clearTimeout(hideTimeout)
41
+ hideTimeout = setTimeout(this.hide({ active: false }), 25)
42
+ }
43
+
44
+ this.eventListeners['turbo-boost:devtool-enable'] = event => {
45
+ // LeaderLine.positionByWindowResize = false
37
46
  const { name } = event.detail
38
- if (name === this.name) {
39
- addHighlight(this.triggerElement, {
40
- outline: '3px dashed blueviolet',
41
- outlineOffset: '2px'
42
- })
43
- }
44
- })
47
+ if (name !== this.name) return
48
+
49
+ addHighlight(this.triggerElement, {
50
+ outline: '3px dashed blueviolet',
51
+ outlineOffset: '2px'
52
+ })
45
53
 
46
- document.addEventListener('turbo-boost:devtool-disable', event => {
54
+ this.hide({ active: false })
55
+ if (this.active) this.show()
56
+ }
57
+
58
+ this.eventListeners['turbo-boost:devtool-disable'] = event => {
47
59
  const { name } = event.detail
48
60
  if (name === this.name) removeHighlight(this.triggerElement)
49
- })
50
-
51
- let hideTimeout
52
- const debouncedHide = () => {
53
- clearTimeout(hideTimeout)
54
- hideTimeout = setTimeout(this.hide(true), 25)
55
61
  }
56
62
 
57
- addEventListener('click', event => {
63
+ this.eventListeners['click'] = event => {
58
64
  if (event.target.closest('turbo-boost-devtool-tooltip')) return
59
65
  debouncedHide()
66
+ }
67
+
68
+ this.eventListeners['turbo:load'] = debouncedHide
69
+ this.eventListeners['turbo-frame:load'] = debouncedHide
70
+ this.eventListeners[TurboBoost.Commands.events.finish] = debouncedHide
71
+
72
+ this.registerEventListeners()
73
+ }
74
+
75
+ registerEventListeners () {
76
+ Object.entries(this.eventListeners).forEach(([type, listener]) => {
77
+ addEventListener(type, listener)
78
+ })
79
+ }
80
+
81
+ unregisterEventListeners () {
82
+ Object.entries(this.eventListeners).forEach(([type, listener]) => {
83
+ removeEventListener(type, listener)
60
84
  })
85
+ }
61
86
 
62
- addEventListener('turbo:load', debouncedHide)
63
- addEventListener('turbo-frame:load', debouncedHide)
64
- addEventListener(TurboBoost.Commands.events.success, debouncedHide)
65
- addEventListener(TurboBoost.Commands.events.finish, debouncedHide)
87
+ get eventListeners () {
88
+ return this._eventListeners || (this._eventListeners = {})
66
89
  }
67
90
 
68
91
  get enabled () {
69
92
  return supervisor.enabled(this.name)
70
93
  }
71
94
 
95
+ get active () {
96
+ return activeToggle === this
97
+ }
98
+
99
+ set active (value) {
100
+ if (value) activeToggle = this
101
+ else activeToggle = null
102
+ }
103
+
72
104
  show () {
73
105
  if (!this.enabled) return
74
- if (activeToggle === this) return
75
- activeToggle = this
76
- this.hide()
106
+
107
+ if (this.active) return
108
+ this.active = true
109
+
110
+ this.hide({ active: true })
77
111
 
78
112
  addHighlight(this.targetElement, {
79
113
  outline: '3px dashed darkcyan',
@@ -85,9 +119,12 @@ export default class ToggleDevtool {
85
119
  outlineOffset: '3px'
86
120
  })
87
121
 
88
- const morphTooltip = this.createMorphTooltip()
89
- const targetTooltip = this.createTargetTooltip()
90
- this.createTriggerTooltip(targetTooltip, morphTooltip)
122
+ this.renderingTooltip = this.createRenderingTooltip()
123
+ this.targetTooltip = this.createTargetTooltip()
124
+ this.triggerTooltip = this.createTriggerTooltip(
125
+ this.targetTooltip,
126
+ this.renderingTooltip
127
+ )
91
128
 
92
129
  document
93
130
  .querySelectorAll('.leader-line')
@@ -115,38 +152,55 @@ export default class ToggleDevtool {
115
152
  if (this.targetElement)
116
153
  data.target = {
117
154
  partial: this.targetElement.partial,
118
- id: this.targetElement.id,
155
+ dom_id: this.targetElement.id,
119
156
  status: 'OK'
120
157
  }
121
158
 
122
159
  console.table(data)
123
160
  }
124
161
 
125
- hide (clearActiveToggle) {
126
- document.querySelectorAll('.leader-line').forEach(el => el.remove())
162
+ hide ({ active: active = false }) {
127
163
  document
128
164
  .querySelectorAll('turbo-boost-devtool-tooltip')
129
- .forEach(el => el.remove())
165
+ .forEach(tooltip => {
166
+ attempt(() => tooltip.line.remove())
167
+ attempt(() => tooltip.drag.remove())
168
+ attempt(() => tooltip.lineToRendering.remove())
169
+ attempt(() => tooltip.lineToTarget.remove())
170
+ attempt(() => tooltip.remove())
171
+ })
130
172
 
131
173
  document.querySelectorAll('[data-turbo-boost-highlight]').forEach(el => {
132
174
  if (!el.tagName.match(/turbo-boost-toggle-trigger/i)) removeHighlight(el)
133
175
  })
134
176
 
135
- if (clearActiveToggle) activeToggle = null
177
+ this.active = active
136
178
  }
137
179
 
138
- createMorphTooltip () {
180
+ createRenderingTooltip () {
181
+ if (!this.triggerElement.renders)
182
+ return console.debug(
183
+ `Unable to create the rendering tooltip! The trigger element must set the 'renders' attribute.`
184
+ )
185
+
139
186
  if (!this.triggerElement.morphs)
140
187
  return console.debug(
141
- `Unable to create the morph tooltip! No element matches the DOM id: '${this.triggerElement.morphs}'`
188
+ `Unable to create the rendering tooltip! The trigger element specified the 'morphs' attrbiute but no element matches the DOM id: '${this.triggerElement.morphs}'`
142
189
  )
143
190
 
144
- const title = 'PARTIAL'
191
+ const title = `
192
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:inline-block;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19l7-7 3 3-7 7-3-3z"></path><path d="M18 13l-1.5-7.5L2 2l3.5 14.5L13 18l5-5z"></path><path d="M2 2l7.586 7.586"></path><circle cx="11" cy="11" r="2"></circle></svg>
193
+ RENDERING
194
+ `
145
195
  const subtitle = `
146
- id: ${this.triggerElement.morphs || 'unknown'}<br>
147
- partial: ${this.triggerElement.renders || 'unknown'}
196
+ <b>partial</b>: ${this.triggerElement.renders || 'unknown'}<br>
197
+ <b>morphs</b>: ${this.triggerElement.morphs || 'unknown'}<br>
198
+ `
199
+ const content = `
200
+ <div slot="content-top" style="font-size:85%; font-style:italic; font-weight:100;">
201
+ The <b>TRIGGER</b> toggles the <b>TARGET</b> then renders the partial &amp; morphs the element.<br>
202
+ </div>
148
203
  `
149
- const content = '<div slot="content"></div>'
150
204
  const tooltip = appendTooltip(title, subtitle, content, {
151
205
  backgroundColor: 'lightyellow',
152
206
  color: 'chocolate'
@@ -175,20 +229,31 @@ export default class ToggleDevtool {
175
229
  `Unable to create the target tooltip! No element matches the DOM id: '${this.triggerElement.controls}'`
176
230
  )
177
231
 
178
- const title = 'TARGET'
232
+ const title = `
233
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:inline-block;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"></circle><circle cx="12" cy="12" r="6"></circle><circle cx="12" cy="12" r="2"></circle></svg>
234
+ TARGET
235
+ `
179
236
  const subtitle = `
180
- id: ${this.targetElement.id}<br>
181
- labeled by: ${this.targetElement.labeledBy}
237
+ <b>id</b>: ${this.targetElement.id}<br>
238
+ <b>aria-labeled-by</b>: ${this.targetElement.labeledBy}<br>
182
239
  `
183
- const content = this.targetElement.viewStack
240
+ let content = this.targetElement.viewStack
184
241
  .reverse()
185
242
  .map((view, index) => {
186
243
  return this.triggerElement.sharedViews.includes(view)
187
- ? `<div slot="content-top">${index + 1}. ${view}</div>`
244
+ ? `<div slot="content">${index + 1}. ${view}</div>`
188
245
  : `<div slot="content-bottom">${index + 1}. ${view}</div>`
189
246
  }, this)
190
247
  .join('')
191
248
 
249
+ content = `
250
+ <div slot="content-top">
251
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:inline-block;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
252
+ <b>View Stack</b>
253
+ </div>
254
+ ${content}
255
+ `
256
+
192
257
  const tooltip = appendTooltip(title, subtitle, content, {
193
258
  backgroundColor: 'lightcyan',
194
259
  color: 'darkcyan',
@@ -210,22 +275,35 @@ export default class ToggleDevtool {
210
275
  return tooltip
211
276
  }
212
277
 
213
- createTriggerTooltip (targetTooltip, morphTooltip) {
278
+ createTriggerTooltip (targetTooltip, renderingTooltip) {
214
279
  if (!this.triggerElement) return
215
- const title = 'TRIGGER'
280
+ const title = `
281
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:inline;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>
282
+ TRIGGER
283
+ `
216
284
  const subtitle = `
217
- id: ${this.triggerElement.id}<br>
218
- controls: ${this.triggerElement.controls}
285
+ <b>id</b>: ${this.triggerElement.id}<br>
286
+ <b>aria-controls</b>: ${this.triggerElement.controls}<br>
287
+ <b>aria-expanded</b>: ${this.triggerElement.expanded}<br>
288
+ <b>remember</b>: ${this.triggerElement.remember}<br>
219
289
  `
220
- const content = this.triggerElement.viewStack
290
+ let content = this.triggerElement.viewStack
221
291
  .reverse()
222
292
  .map((view, index) => {
223
293
  return this.triggerElement.sharedViews.includes(view)
224
- ? `<div slot="content-top">${index + 1}. ${view}</div>`
294
+ ? `<div slot="content">${index + 1}. ${view}</div>`
225
295
  : `<div slot="content-bottom">${index + 1}. ${view}</div>`
226
296
  }, this)
227
297
  .join('')
228
298
 
299
+ content = `
300
+ <div slot="content-top">
301
+ <svg xmlns="http://www.w3.org/2000/svg" style="display:inline-block;" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><polygon points="12 2 2 7 12 12 22 7 12 2"></polygon><polyline points="2 17 12 22 22 17"></polyline><polyline points="2 12 12 17 22 12"></polyline></svg>
302
+ <b>View Stack</b>
303
+ </div>
304
+ ${content}
305
+ `
306
+
229
307
  const tooltip = appendTooltip(title, subtitle, content, {
230
308
  backgroundColor: 'lavender',
231
309
  color: 'blueviolet'
@@ -257,16 +335,16 @@ export default class ToggleDevtool {
257
335
  }
258
336
  }
259
337
 
260
- if (morphTooltip) {
261
- tooltip.lineToRendering = new LeaderLine(tooltip, morphTooltip, {
338
+ if (renderingTooltip) {
339
+ tooltip.lineToRendering = new LeaderLine(tooltip, renderingTooltip, {
262
340
  ...this.leaderLineOptions,
263
341
  color: 'blueviolet',
264
- middleLabel: 'renders and morphs',
342
+ middleLabel: 'renders & morphs',
265
343
  size: 2.1
266
344
  })
267
345
 
268
- morphTooltip.drag.onMove = () => {
269
- morphTooltip.line.position()
346
+ renderingTooltip.drag.onMove = () => {
347
+ renderingTooltip.line.position()
270
348
  if (tooltip.lineToTarget) tooltip.lineToTarget.position()
271
349
  tooltip.lineToRendering.position()
272
350
  }