reflex_behaviors 0.0.6 → 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,53 @@
1
+ const added = []
2
+
3
+ const dependencies = {
4
+ LeaderLine: {
5
+ src:
6
+ 'https://cdnjs.cloudflare.com/ajax/libs/leader-line/1.0.7/leader-line.min.js',
7
+ integrity:
8
+ 'sha512-0dNdzMjpT6pJdFGF1DwybFCfm3K/lzHhxaMXC/92J9/DZujHlqYFqmhTOAoD0o+LkeEsVK2ar/ESs7/Q2B6wJg==',
9
+ global: 'LeaderLine'
10
+ },
11
+
12
+ PlainDraggable: {
13
+ src:
14
+ 'https://cdn.jsdelivr.net/npm/plain-draggable@2.5.14/plain-draggable.min.js',
15
+ global: 'PlainDraggable'
16
+ }
17
+ }
18
+
19
+ function exists (dependency) {
20
+ if (dependency.global && self[dependency.global]) return true
21
+ if (document.querySelector(`[src='${dependency.src}']`)) return true
22
+ return added.includes(dependency)
23
+ }
24
+
25
+ function add (dependency) {
26
+ if (exists(dependency)) return
27
+ added.push(dependency)
28
+
29
+ const { src, integrity } = dependency
30
+ const script = document.createElement('script')
31
+ script.setAttribute('src', src)
32
+ script.setAttribute('crossorigin', 'anonymous')
33
+ script.setAttribute('referrerpolicy', 'no-referrer')
34
+ if (integrity) script.setAttribute('integrity', integrity)
35
+ document.head.appendChild(script)
36
+ }
37
+
38
+ function remove (dependency) {
39
+ if (!added.includes(dependency)) return
40
+ added.splice(added.indexOf(dependency), 1)
41
+
42
+ const { src } = dependency
43
+ const el = document.querySelector(`script[src='${src}']`)
44
+ if (el) el.remove()
45
+ if (dependency.global && self[dependency.global])
46
+ self[dependency.global] = null
47
+ }
48
+
49
+ function removeAll () {
50
+ ;[...added].forEach(dependency => remove(dependency))
51
+ }
52
+
53
+ export default { ...dependencies, add, remove, removeAll }
@@ -6,9 +6,13 @@ export default class SupervisorElement extends HTMLElement {
6
6
  this.enabledDevtools = {}
7
7
  this.attachShadow({ mode: 'open' })
8
8
  this.shadowRoot.innerHTML = this.html
9
- this.shadowRoot
10
- .querySelector('button')
11
- .addEventListener('click', () => this.close())
9
+ this.shadowRoot.querySelector('button').addEventListener('click', () =>
10
+ this.dispatchEvent(
11
+ new CustomEvent('reflex-behaviors:devtools-close', {
12
+ bubbles: true
13
+ })
14
+ )
15
+ )
12
16
 
13
17
  this.addEventListener('change', event => {
14
18
  const devtoolElement = event.target
@@ -2,12 +2,7 @@ import { appendHTML } from '../utils/dom'
2
2
  import DevtoolElement from './elements/devtool_element'
3
3
  import SupervisorElement from './elements/supervisor_element'
4
4
  import TooltipElement from './elements/tooltip_element'
5
- import {
6
- addLeaderLineDependency,
7
- addPlainDraggableDependency,
8
- removeLeaderLineDependency,
9
- removePlainDraggableDependency
10
- } from './dependencies'
5
+ import dependencies from './dependencies'
11
6
 
12
7
  customElements.define('reflex-behaviors-devtool', DevtoolElement)
13
8
  customElements.define('reflex-behaviors-devtool-supervisor', SupervisorElement)
@@ -33,14 +28,13 @@ function stop () {
33
28
  })
34
29
  )
35
30
  supervisorElement = null
36
- removeLeaderLineDependency()
37
- removePlainDraggableDependency()
31
+ dependencies.removeAll()
38
32
  }
39
33
 
40
34
  function start () {
41
35
  if (started()) return
42
- addLeaderLineDependency()
43
- addPlainDraggableDependency()
36
+ dependencies.add(dependencies.LeaderLine)
37
+ dependencies.add(dependencies.PlainDraggable)
44
38
  supervisorElement = appendHTML(
45
39
  '<reflex-behaviors-devtool-supervisor></reflex-behaviors-devtool-supervisor>'
46
40
  )
@@ -87,6 +81,7 @@ addEventListener('turbo:load', autoRestart)
87
81
  addEventListener('turbo-frame:load', autoRestart)
88
82
  addEventListener('turbo-reflex:success', autoRestart)
89
83
  addEventListener('turbo-reflex:finish', autoRestart)
84
+ addEventListener('reflex-behaviors:devtools-close', stop)
90
85
 
91
86
  function register (name, label) {
92
87
  if (!supervisorElement) return
@@ -46,11 +46,21 @@ export default class ToggleDevtool {
46
46
  if (name === this.name) removeHighlight(this.trigger)
47
47
  })
48
48
 
49
- document.addEventListener('click', event => {
49
+ let hideTimeout
50
+ const debouncedHide = () => {
51
+ clearTimeout(hideTimeout)
52
+ hideTimeout = setTimeout(this.hide(true), 25)
53
+ }
54
+
55
+ addEventListener('click', event => {
50
56
  if (event.target.closest('reflex-behaviors-devools-tooltip')) return
51
- activeToggle = null
52
- this.hide()
57
+ debouncedHide()
53
58
  })
59
+
60
+ addEventListener('turbo:load', debouncedHide)
61
+ addEventListener('turbo-frame:load', debouncedHide)
62
+ addEventListener('turbo-reflex:success', debouncedHide)
63
+ addEventListener('turbo-reflex:finish', debouncedHide)
54
64
  }
55
65
 
56
66
  get enabled () {
@@ -68,7 +78,7 @@ export default class ToggleDevtool {
68
78
  outlineOffset: '-2px'
69
79
  })
70
80
 
71
- addHighlight(this.renderingElement, {
81
+ addHighlight(this.trigger.renderingElement, {
72
82
  outline: '3px dashed chocolate',
73
83
  outlineOffset: '3px'
74
84
  })
@@ -82,26 +92,33 @@ export default class ToggleDevtool {
82
92
  .forEach(el => (el.style.zIndex = 100000))
83
93
 
84
94
  const data = {
85
- rendering: { partial: null, id: null },
86
- trigger: { partial: null, id: null },
87
- target: { partial: null, id: null }
95
+ rendering: {
96
+ partial: this.trigger.renderingPartial,
97
+ id: this.trigger.renderingInfo.id,
98
+ status: this.trigger.renderingElement ? 'OK' : 'Not Found'
99
+ },
100
+ trigger: { partial: null, id: null, status: 'Not Found' },
101
+ target: { partial: null, id: null, status: 'Not Found' }
88
102
  }
89
103
 
90
- if (this.renderingPartial) data.rendering.partial = this.renderingPartial
91
- if (this.renderingElement) data.rendering.id = this.renderingElement.id
92
-
93
104
  if (this.trigger)
94
- data.trigger = { partial: this.trigger.partial, id: this.trigger.id }
105
+ data.trigger = {
106
+ partial: this.trigger.partial,
107
+ id: this.trigger.id,
108
+ status: 'OK'
109
+ }
95
110
 
96
111
  if (this.target)
97
- data.target = { partial: this.target.partial, id: this.target.id }
98
- else if (this.trigger)
99
- data.target.id = `No element matches the targeted DOM id: ${this.trigger.controls}`
112
+ data.target = {
113
+ partial: this.target.partial,
114
+ id: this.target.id,
115
+ status: 'OK'
116
+ }
100
117
 
101
118
  console.table(data)
102
119
  }
103
120
 
104
- hide () {
121
+ hide (clearActiveToggle) {
105
122
  document.querySelectorAll('.leader-line').forEach(el => el.remove())
106
123
  document
107
124
  .querySelectorAll('reflex-behaviors-devools-tooltip')
@@ -112,18 +129,25 @@ export default class ToggleDevtool {
112
129
  .forEach(el => {
113
130
  if (!el.tagName.match(/toggle-trigger/i)) removeHighlight(el)
114
131
  })
132
+
133
+ if (clearActiveToggle) activeToggle = null
115
134
  }
116
135
 
117
136
  createRenderingTooltip () {
118
- if (!this.renderingElement) return
119
- const title = `RENDERING (id: ${this.renderingElement.id || 'unknown'})`
120
- const content = `<div slot="content">partial: ${this.renderingPartial}</div>`
137
+ if (!this.trigger.renderingElement)
138
+ return console.debug(
139
+ `Unable to create the rendering tooltip! No element matches the DOM id: '${this.trigger.renderingInfo.id}'`
140
+ )
141
+
142
+ const title = `RENDERING (id: ${this.trigger.renderingElement.id ||
143
+ 'unknown'})`
144
+ const content = `<div slot="content">partial: ${this.trigger.renderingPartial}</div>`
121
145
  const tooltip = appendTooltip(title, content, {
122
146
  backgroundColor: 'lightyellow',
123
147
  color: 'chocolate'
124
148
  })
125
149
 
126
- const coords = coordinates(this.renderingElement)
150
+ const coords = coordinates(this.trigger.renderingElement)
127
151
  const top = Math.ceil(
128
152
  coords.top + coords.height / 2 - tooltip.offsetHeight / 2
129
153
  )
@@ -131,7 +155,7 @@ export default class ToggleDevtool {
131
155
  tooltip.style.top = `${top}px`
132
156
  tooltip.style.left = `${left}px`
133
157
 
134
- tooltip.line = new LeaderLine(tooltip, this.renderingElement, {
158
+ tooltip.line = new LeaderLine(tooltip, this.trigger.renderingElement, {
135
159
  ...this.leaderLineOptions,
136
160
  color: 'chocolate'
137
161
  })
@@ -141,8 +165,10 @@ export default class ToggleDevtool {
141
165
  }
142
166
 
143
167
  createTargetTooltip () {
144
- if (!this.target) return
145
- if (!this.target.viewStack) return
168
+ if (!this.target)
169
+ return console.debug(
170
+ `Unable to create the target tooltip! No element matches the DOM id: '${this.trigger.controls}'`
171
+ )
146
172
 
147
173
  const title = `TARGET (id: ${this.target.id})`
148
174
  const content = this.target.viewStack
@@ -203,49 +229,44 @@ export default class ToggleDevtool {
203
229
  color: 'blueviolet'
204
230
  })
205
231
 
206
- tooltip.lineToTarget = new LeaderLine(tooltip, targetTooltip, {
207
- ...this.leaderLineOptions,
208
- color: 'blueviolet',
209
- middleLabel: 'toggles',
210
- size: 2.1
211
- })
232
+ if (targetTooltip) {
233
+ tooltip.lineToTarget = new LeaderLine(tooltip, targetTooltip, {
234
+ ...this.leaderLineOptions,
235
+ color: 'blueviolet',
236
+ middleLabel: 'toggles',
237
+ size: 2.1
238
+ })
212
239
 
213
- tooltip.lineToRendering = new LeaderLine(tooltip, renderingTooltip, {
214
- ...this.leaderLineOptions,
215
- color: 'blueviolet',
216
- middleLabel: 'renders',
217
- size: 2.1
218
- })
240
+ targetTooltip.drag.onMove = () => {
241
+ targetTooltip.line.position()
242
+ tooltip.lineToTarget.position()
243
+ tooltip.lineToRendering.position()
244
+ }
245
+ }
246
+
247
+ if (renderingTooltip) {
248
+ tooltip.lineToRendering = new LeaderLine(tooltip, renderingTooltip, {
249
+ ...this.leaderLineOptions,
250
+ color: 'blueviolet',
251
+ middleLabel: 'renders',
252
+ size: 2.1
253
+ })
254
+
255
+ renderingTooltip.drag.onMove = () => {
256
+ renderingTooltip.line.position()
257
+ if (tooltip.lineToTarget) tooltip.lineToTarget.position()
258
+ tooltip.lineToRendering.position()
259
+ }
260
+ }
219
261
 
220
262
  tooltip.drag = new PlainDraggable(tooltip)
221
263
  tooltip.drag.onMove = () => {
222
264
  tooltip.line.position()
223
- tooltip.lineToTarget.position()
224
- tooltip.lineToRendering.position()
225
- }
226
- targetTooltip.drag.onMove = () => {
227
- targetTooltip.line.position()
228
- tooltip.lineToTarget.position()
229
- tooltip.lineToRendering.position()
265
+ if (tooltip.lineToTarget) tooltip.lineToTarget.position()
266
+ if (tooltip.lineToRendering) tooltip.lineToRendering.position()
230
267
  }
231
- renderingTooltip.drag.onMove = () => {
232
- renderingTooltip.line.position()
233
- tooltip.lineToTarget.position()
234
- tooltip.lineToRendering.position()
235
- }
236
- return tooltip
237
- }
238
268
 
239
- get renderingPartial () {
240
- let partial = this.trigger ? this.trigger.renderingPartial : null
241
- partial = partial || (this.target ? this.target.renderingPartial : null)
242
- return partial
243
- }
244
-
245
- get renderingElement () {
246
- let element = this.trigger ? this.trigger.renderingElement : null
247
- element = element || (this.target ? this.target.renderingElement : null)
248
- return element
269
+ return tooltip
249
270
  }
250
271
 
251
272
  get leaderLineOptions () {
@@ -1,6 +1,3 @@
1
- import TurboReady from 'turbo_ready'
2
- TurboReady.initialize(Turbo.StreamActions)
3
-
4
1
  import 'turbo_reflex'
5
2
  import './elements'
6
3
  import devtools from './devtools'
@@ -52,6 +52,7 @@ export function removeHighlight (element) {
52
52
  }
53
53
 
54
54
  export function coordinates (element) {
55
+ if (!element) return {}
55
56
  const rect = element.getBoundingClientRect()
56
57
  return {
57
58
  left: rect.left + window.scrollX,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReflexBehaviors
4
- VERSION = "0.0.6"
4
+ VERSION = "0.0.8"
5
5
  end
data/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "reflex_behaviors",
3
- "version": "0.0.4",
3
+ "version": "0.0.7",
4
4
  "description": "Pre-built easy to use reactive TurboReflex behaviors for Rails/Hotwire apps.",
5
5
  "main": "app/javascript/index.js",
6
6
  "repository": "https://github.com/hopsoft/reflex_behaviors",
7
7
  "author": "Nate Hopkins (hopsoft) <natehop@gmail.com>",
8
8
  "license": "MIT",
9
9
  "dependencies": {
10
- "turbo_ready": ">= 0.1.2",
11
- "turbo_reflex": ">= 0.0.28"
10
+ "turbo_ready": ">= 0.1.3",
11
+ "turbo_reflex": ">= 0.0.29"
12
12
  },
13
13
  "peerDependencies": {
14
- "@hotwired/turbo": ">= 7.2",
15
14
  "@hotwired/turbo-rails": ">= 7.2"
16
15
  },
17
16
  "devDependencies": {
@@ -22,8 +22,8 @@ Gem::Specification.new do |s|
22
22
 
23
23
  s.add_dependency "rails", ">= 6.1"
24
24
  s.add_dependency "turbo-rails", ">= 1.1"
25
- s.add_dependency "turbo_ready", ">= 0.1.2"
26
- s.add_dependency "turbo_reflex", ">= 0.0.28"
25
+ s.add_dependency "turbo_ready", ">= 0.1.3"
26
+ s.add_dependency "turbo_reflex", ">= 0.0.29"
27
27
 
28
28
  s.add_development_dependency "magic_frozen_string_literal"
29
29
  s.add_development_dependency "minitest-reporters"