reflex_behaviors 0.0.6 → 0.0.8

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.
@@ -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"