reflex_behaviors 0.0.9 → 0.0.10

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,12 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require ReflexBehaviors::Engine.root.join("lib/reflex_behaviors/tag_builders")
3
+ require_relative "../../../lib/reflex_behaviors/tag_builders"
4
4
 
5
5
  module ReflexBehaviors::ApplicationHelper
6
- def idomatic_partial_path(partial_path)
7
- partial_path.to_s.gsub("/_", "/").split(".").first
8
- end
9
-
10
6
  def current_partial_path
11
7
  path = nil
12
8
  prefix = "app/views/"
@@ -20,15 +16,6 @@ module ReflexBehaviors::ApplicationHelper
20
16
  path[(path.index(prefix) + prefix.length), path.rindex("/")]
21
17
  end
22
18
 
23
- def reflex_render(**kwargs)
24
- kwargs[:partial] = idomatic_partial_path(kwargs[:partial])
25
- kwargs[:assigns] ||= {}
26
- kwargs[:assigns].each { |key, val| kwargs[:assigns][key] = transportable_value(val) }
27
- kwargs[:locals] ||= {}
28
- kwargs[:locals].each { |key, val| kwargs[:locals][key] = transportable_value(val) }
29
- kwargs.to_json
30
- end
31
-
32
19
  def method_missing(name, ...)
33
20
  prefixes = %w[toggle_]
34
21
  prefixes.each do |prefix|
@@ -52,9 +39,4 @@ module ReflexBehaviors::ApplicationHelper
52
39
  def toggle_tag_builder
53
40
  @toggle_tag_builder ||= ReflexBehaviors::TagBuilders::ToggleTagsBuilder.new(self)
54
41
  end
55
-
56
- def transportable_value(value)
57
- return value.to_s unless value.respond_to?(:to_sgid_param)
58
- value.try(:persisted?) ? value.to_sgid_param : nil
59
- end
60
42
  end
@@ -22,6 +22,7 @@ export default class TooltipElement extends HTMLElement {
22
22
  <style>${this.stylesheet}</style>
23
23
  <div>
24
24
  <slot name="title"></slot>
25
+ <slot name="subtitle"></slot>
25
26
  <slot name="content-top"></slot>
26
27
  <slot name="content"></slot>
27
28
  <slot name="content-bottom"></slot>
@@ -52,18 +53,29 @@ export default class TooltipElement extends HTMLElement {
52
53
  opacity: 0.9;
53
54
  outline-offset: 1px;
54
55
  outline: dashed 3px ${this.color};
55
- padding: 8px 12px 8px 12px;
56
+ padding: 12px;
56
57
  position: relative;
57
58
  white-space: nowrap;
58
59
  }
59
60
 
60
61
  slot[name="title"] {
61
- border-bottom: dotted 1px ${this.color};
62
62
  color: ${this.color};
63
- display: inline-block;
63
+ display: block;
64
64
  font-weight: bold;
65
+ width: 100%;
66
+ }
67
+
68
+ slot[name="subtitle"] {
69
+ border-bottom: dotted 1px ${this.color};
70
+ border-top: dotted 1px ${this.color};
71
+ color: ${this.color};
72
+ display: block;
73
+ font-size: 0.8rem;
74
+ font-weight: lighter;
65
75
  margin-bottom: 8px;
66
- padding-bottom: 8px;
76
+ margin-top: 4px;
77
+ padding-bottom: 4px;
78
+ padding-top: 4px;
67
79
  width: 100%;
68
80
  }
69
81
 
@@ -12,29 +12,31 @@ document.addEventListener('reflex-behaviors:devtools-start', () =>
12
12
  supervisor.register('toggle', 'toggles<small>(trigger/target)</small>')
13
13
  )
14
14
 
15
- function appendTooltip (title, content, options = {}) {
15
+ function appendTooltip (title, subtitle, content, options = {}) {
16
16
  let { backgroundColor, color, position } = options
17
17
  color = color || 'white'
18
18
  position = position || 'top'
19
19
  return appendHTML(`
20
20
  <reflex-behaviors-devools-tooltip position="${position}" background-color="${backgroundColor}" color="${color}">
21
21
  <div slot='title'>${title}</div>
22
+ <div slot='subtitle'>${subtitle}</div>
22
23
  ${content}
23
24
  </reflex-behaviors-devools-tooltip>
24
25
  `)
25
26
  }
26
27
 
27
28
  export default class ToggleDevtool {
28
- constructor (trigger) {
29
+ constructor (triggerElement) {
29
30
  this.name = 'toggle'
30
- this.reflex = trigger.dataset.turboReflex
31
- this.trigger = trigger
32
- this.target = trigger.target
31
+ this.reflex = triggerElement.dataset.turboReflex
32
+ this.triggerElement = triggerElement // SEE: app/javascript/elements/toggle_trigger_element.js
33
+ this.targetElement = triggerElement.targetElement // SEE: app/javascript/elements/toggle_target_element.js
34
+ this.morphElement = triggerElement.morphElement
33
35
 
34
36
  document.addEventListener('reflex-behaviors:devtool-enable', event => {
35
37
  const { name } = event.detail
36
38
  if (name === this.name) {
37
- addHighlight(this.trigger, {
39
+ addHighlight(this.triggerElement, {
38
40
  outline: '3px dashed blueviolet',
39
41
  outlineOffset: '2px'
40
42
  })
@@ -43,7 +45,7 @@ export default class ToggleDevtool {
43
45
 
44
46
  document.addEventListener('reflex-behaviors:devtool-disable', event => {
45
47
  const { name } = event.detail
46
- if (name === this.name) removeHighlight(this.trigger)
48
+ if (name === this.name) removeHighlight(this.triggerElement)
47
49
  })
48
50
 
49
51
  let hideTimeout
@@ -73,45 +75,47 @@ export default class ToggleDevtool {
73
75
  activeToggle = this
74
76
  this.hide()
75
77
 
76
- addHighlight(this.target, {
78
+ addHighlight(this.targetElement, {
77
79
  outline: '3px dashed darkcyan',
78
80
  outlineOffset: '-2px'
79
81
  })
80
82
 
81
- addHighlight(this.trigger.renderingElement, {
83
+ addHighlight(this.triggerElement.morphElement, {
82
84
  outline: '3px dashed chocolate',
83
85
  outlineOffset: '3px'
84
86
  })
85
87
 
86
- const renderingTooltip = this.createRenderingTooltip()
88
+ const morphTooltip = this.createMorphTooltip()
87
89
  const targetTooltip = this.createTargetTooltip()
88
- this.createTriggerTooltip(targetTooltip, renderingTooltip)
90
+ this.createTriggerTooltip(targetTooltip, morphTooltip)
89
91
 
90
92
  document
91
93
  .querySelectorAll('.leader-line')
92
94
  .forEach(el => (el.style.zIndex = 100000))
93
95
 
94
96
  const data = {
95
- rendering: {
96
- partial: this.trigger.renderingPartial,
97
- id: this.trigger.renderingInfo.id,
98
- status: this.trigger.renderingElement ? 'OK' : 'Not Found'
97
+ morph: {
98
+ partial: this.triggerElement.renders,
99
+ id: this.triggerElement.morphs,
100
+ status: this.morphElement ? 'OK' : 'Not Found'
99
101
  },
100
102
  trigger: { partial: null, id: null, status: 'Not Found' },
101
103
  target: { partial: null, id: null, status: 'Not Found' }
102
104
  }
103
105
 
104
- if (this.trigger)
106
+ if (this.triggerElement) {
105
107
  data.trigger = {
106
- partial: this.trigger.partial,
107
- id: this.trigger.id,
108
+ partial: this.triggerElement.partial,
109
+ id: this.triggerElement.id,
108
110
  status: 'OK'
109
111
  }
112
+ data.target.id = this.triggerElement.controls
113
+ }
110
114
 
111
- if (this.target)
115
+ if (this.targetElement)
112
116
  data.target = {
113
- partial: this.target.partial,
114
- id: this.target.id,
117
+ partial: this.targetElement.partial,
118
+ id: this.targetElement.id,
115
119
  status: 'OK'
116
120
  }
117
121
 
@@ -133,21 +137,24 @@ export default class ToggleDevtool {
133
137
  if (clearActiveToggle) activeToggle = null
134
138
  }
135
139
 
136
- createRenderingTooltip () {
137
- if (!this.trigger.renderingElement)
140
+ createMorphTooltip () {
141
+ if (!this.triggerElement.morphs)
138
142
  return console.debug(
139
- `Unable to create the rendering tooltip! No element matches the DOM id: '${this.trigger.renderingInfo.id}'`
143
+ `Unable to create the morph tooltip! No element matches the DOM id: '${this.triggerElement.morphs}'`
140
144
  )
141
145
 
142
- const title = `RENDERING (id: ${this.trigger.renderingElement.id ||
143
- 'unknown'})`
144
- const content = `<div slot="content">partial: ${this.trigger.renderingPartial}</div>`
145
- const tooltip = appendTooltip(title, content, {
146
+ const title = 'PARTIAL'
147
+ const subtitle = `
148
+ id: ${this.triggerElement.morphs || 'unknown'}<br>
149
+ partial: ${this.triggerElement.renders || 'unknown'}
150
+ `
151
+ const content = '<div slot="content"></div>'
152
+ const tooltip = appendTooltip(title, subtitle, content, {
146
153
  backgroundColor: 'lightyellow',
147
154
  color: 'chocolate'
148
155
  })
149
156
 
150
- const coords = coordinates(this.trigger.renderingElement)
157
+ const coords = coordinates(this.morphElement)
151
158
  const top = Math.ceil(
152
159
  coords.top + coords.height / 2 - tooltip.offsetHeight / 2
153
160
  )
@@ -155,7 +162,7 @@ export default class ToggleDevtool {
155
162
  tooltip.style.top = `${top}px`
156
163
  tooltip.style.left = `${left}px`
157
164
 
158
- tooltip.line = new LeaderLine(tooltip, this.trigger.renderingElement, {
165
+ tooltip.line = new LeaderLine(tooltip, this.morphElement, {
159
166
  ...this.leaderLineOptions,
160
167
  color: 'chocolate'
161
168
  })
@@ -165,34 +172,38 @@ export default class ToggleDevtool {
165
172
  }
166
173
 
167
174
  createTargetTooltip () {
168
- if (!this.target)
175
+ if (!this.targetElement)
169
176
  return console.debug(
170
- `Unable to create the target tooltip! No element matches the DOM id: '${this.trigger.controls}'`
177
+ `Unable to create the target tooltip! No element matches the DOM id: '${this.triggerElement.controls}'`
171
178
  )
172
179
 
173
- const title = `TARGET (id: ${this.target.id})`
174
- const content = this.target.viewStack
180
+ const title = 'TARGET'
181
+ const subtitle = `
182
+ id: ${this.targetElement.id}<br>
183
+ labeled by: ${this.targetElement.labeledBy}
184
+ `
185
+ const content = this.targetElement.viewStack
175
186
  .reverse()
176
187
  .map((view, index) => {
177
- return this.trigger.sharedViews.includes(view)
188
+ return this.triggerElement.sharedViews.includes(view)
178
189
  ? `<div slot="content-top">${index + 1}. ${view}</div>`
179
190
  : `<div slot="content-bottom">${index + 1}. ${view}</div>`
180
191
  }, this)
181
192
  .join('')
182
193
 
183
- const tooltip = appendTooltip(title, content, {
194
+ const tooltip = appendTooltip(title, subtitle, content, {
184
195
  backgroundColor: 'lightcyan',
185
196
  color: 'darkcyan',
186
197
  position: 'bottom'
187
198
  })
188
199
 
189
- const coords = coordinates(this.target)
200
+ const coords = coordinates(this.targetElement)
190
201
  const top = Math.ceil(coords.top + tooltip.offsetHeight)
191
202
  const left = Math.ceil(coords.left + coords.width + tooltip.offsetWidth / 3)
192
203
  tooltip.style.top = `${top}px`
193
204
  tooltip.style.left = `${left}px`
194
205
 
195
- tooltip.line = new LeaderLine(tooltip, this.target, {
206
+ tooltip.line = new LeaderLine(tooltip, this.targetElement, {
196
207
  ...this.leaderLineOptions,
197
208
  color: 'darkcyan'
198
209
  })
@@ -201,30 +212,34 @@ export default class ToggleDevtool {
201
212
  return tooltip
202
213
  }
203
214
 
204
- createTriggerTooltip (targetTooltip, renderingTooltip) {
205
- if (!this.trigger) return
206
- const title = `TRIGGER (controls: ${this.trigger.controls})`
207
- const content = this.trigger.viewStack
215
+ createTriggerTooltip (targetTooltip, morphTooltip) {
216
+ if (!this.triggerElement) return
217
+ const title = 'TRIGGER'
218
+ const subtitle = `
219
+ id: ${this.triggerElement.id}<br>
220
+ controls: ${this.triggerElement.controls}
221
+ `
222
+ const content = this.triggerElement.viewStack
208
223
  .reverse()
209
224
  .map((view, index) => {
210
- return this.trigger.sharedViews.includes(view)
225
+ return this.triggerElement.sharedViews.includes(view)
211
226
  ? `<div slot="content-top">${index + 1}. ${view}</div>`
212
227
  : `<div slot="content-bottom">${index + 1}. ${view}</div>`
213
228
  }, this)
214
229
  .join('')
215
230
 
216
- const tooltip = appendTooltip(title, content, {
231
+ const tooltip = appendTooltip(title, subtitle, content, {
217
232
  backgroundColor: 'lavender',
218
233
  color: 'blueviolet'
219
234
  })
220
235
 
221
- const coords = coordinates(this.trigger)
236
+ const coords = coordinates(this.triggerElement)
222
237
  const top = Math.ceil(coords.top - tooltip.offsetHeight * 2)
223
238
  const left = Math.ceil(coords.left + coords.width + tooltip.offsetWidth / 3)
224
239
  tooltip.style.top = `${top}px`
225
240
  tooltip.style.left = `${left}px`
226
241
 
227
- tooltip.line = new LeaderLine(this.trigger, tooltip, {
242
+ tooltip.line = new LeaderLine(this.triggerElement, tooltip, {
228
243
  ...this.leaderLineOptions,
229
244
  color: 'blueviolet'
230
245
  })
@@ -244,16 +259,16 @@ export default class ToggleDevtool {
244
259
  }
245
260
  }
246
261
 
247
- if (renderingTooltip) {
248
- tooltip.lineToRendering = new LeaderLine(tooltip, renderingTooltip, {
262
+ if (morphTooltip) {
263
+ tooltip.lineToRendering = new LeaderLine(tooltip, morphTooltip, {
249
264
  ...this.leaderLineOptions,
250
265
  color: 'blueviolet',
251
- middleLabel: 'renders',
266
+ middleLabel: 'renders and morphs',
252
267
  size: 2.1
253
268
  })
254
269
 
255
- renderingTooltip.drag.onMove = () => {
256
- renderingTooltip.line.position()
270
+ morphTooltip.drag.onMove = () => {
271
+ morphTooltip.line.position()
257
272
  if (tooltip.lineToTarget) tooltip.lineToTarget.position()
258
273
  tooltip.lineToRendering.position()
259
274
  }
@@ -261,6 +276,7 @@ export default class ToggleDevtool {
261
276
 
262
277
  tooltip.drag = new PlainDraggable(tooltip)
263
278
  tooltip.drag.onMove = () => {
279
+ console.log('nate', tooltip.line)
264
280
  tooltip.line.position()
265
281
  if (tooltip.lineToTarget) tooltip.lineToTarget.position()
266
282
  if (tooltip.lineToRendering) tooltip.lineToRendering.position()
@@ -8,7 +8,6 @@ export default class ReflexElement extends HTMLElement {
8
8
 
9
9
  connectedCallback () {
10
10
  this.ensureId()
11
- this.dataset.elementOrigin = 'hopsoft/reflex_behaviors'
12
11
  }
13
12
 
14
13
  ensureId () {
@@ -27,8 +26,9 @@ export default class ReflexElement extends HTMLElement {
27
26
  }
28
27
 
29
28
  get viewStack () {
30
- if (!this.dataset.viewStack) return []
31
- return JSON.parse(this.dataset.viewStack)
29
+ const value = this.getAttribute('view-stack')
30
+ if (!value) return []
31
+ return JSON.parse(value)
32
32
  }
33
33
 
34
34
  get partial () {
@@ -1,3 +1,83 @@
1
1
  import ReflexElement from './reflex_element'
2
2
 
3
- export default class ToggleTargetElement extends ReflexElement {}
3
+ export default class ToggleTargetElement extends ReflexElement {
4
+ connectedCallback () {
5
+ super.connectedCallback()
6
+
7
+ this.addEventListener('mouseenter', () =>
8
+ clearTimeout(this.collapseTimeout)
9
+ )
10
+
11
+ this.collapseOn.forEach(name =>
12
+ this.addEventListener(name, () => this.collapse())
13
+ )
14
+ }
15
+
16
+ // TODO: get cached content working properly
17
+ // perhaps use a mechanic other than morph
18
+
19
+ cacheHTML () {
20
+ // this.cachedHTML = this.innerHTML
21
+ }
22
+
23
+ renderCachedHTML () {
24
+ // if (!this.cachedHTML) return
25
+ // this.innerHTML = this.cachedHTML
26
+ }
27
+
28
+ collapse () {
29
+ clearTimeout(this.collapseTimeout)
30
+ this.collapseTimeout = setTimeout(() => {
31
+ this.innerHTML = ''
32
+ try {
33
+ this.currentTriggerElement.expanded = false
34
+ this.currentTriggerElement.hideDevtool()
35
+ } catch {}
36
+ }, 250)
37
+ }
38
+
39
+ collapseMatches () {
40
+ document.querySelectorAll(this.collapseSelector).forEach(el => {
41
+ if (el === this) return
42
+ if (el.collapse) el.collapse()
43
+ })
44
+ }
45
+
46
+ get collapseSelector () {
47
+ if (
48
+ this.currentTriggerElement &&
49
+ this.currentTriggerElement.collapseSelector
50
+ )
51
+ return this.currentTriggerElement.collapseSelector
52
+ return this.getAttribute('collapse-selector')
53
+ }
54
+
55
+ focus () {
56
+ clearTimeout(this.focusTimeout)
57
+ this.focusTimeout = setTimeout(() => {
58
+ if (!this.focusElement) return
59
+ this.focusElement.focus()
60
+ this.focusElement.scrollIntoView({ block: 'center', behavior: 'smooth' })
61
+ }, 50)
62
+ }
63
+
64
+ get focusSelector () {
65
+ if (this.currentTriggerElement && this.currentTriggerElement.focusSelector)
66
+ return this.currentTriggerElement.focusSelector
67
+ return this.getAttribute('focus-selector')
68
+ }
69
+
70
+ get focusElement () {
71
+ return this.querySelector(this.focusSelector)
72
+ }
73
+
74
+ get labeledBy () {
75
+ return this.getAttribute('aria-labeledby')
76
+ }
77
+
78
+ get collapseOn () {
79
+ const value = this.getAttribute('collapse-on')
80
+ if (!value) return []
81
+ return JSON.parse(value)
82
+ }
83
+ }
@@ -5,14 +5,38 @@ import ToggleDevtool from '../devtools/toggle'
5
5
  export default class ToggleTriggerElement extends ReflexElement {
6
6
  connectedCallback () {
7
7
  super.connectedCallback()
8
+
9
+ if (this.targetElement) {
10
+ this.targetElement.setAttribute('aria-labeledby', this.id)
11
+ }
12
+
13
+ this.addEventListener(TurboReflex.events.start, () => {
14
+ this.busy = true
15
+ this.targetElement.currentTriggerElement = this
16
+ this.targetElement.renderCachedHTML()
17
+ })
18
+
19
+ this.addEventListener(TurboReflex.events.success, () => {
20
+ this.busy = false
21
+ this.targetElement.focus()
22
+ this.targetElement.collapseMatches()
23
+ this.targetElement.cacheHTML()
24
+ })
25
+
26
+ this.addEventListener(TurboReflex.events.finish, () => (this.busy = false))
27
+
28
+ this.initializeDevtool()
29
+ }
30
+
31
+ initializeDevtool () {
8
32
  const mouseenter = () => this.devtool.show()
9
33
 
10
- document.addEventListener('reflex-behaviors:devtools-start', () => {
34
+ addEventListener('reflex-behaviors:devtools-start', () => {
11
35
  this.devtool = new ToggleDevtool(this)
12
36
  this.addEventListener('mouseenter', mouseenter)
13
37
  })
14
38
 
15
- document.addEventListener('reflex-behaviors:devtools-stop', () => {
39
+ addEventListener('reflex-behaviors:devtools-stop', () => {
16
40
  this.removeEventListener('mouseenter', mouseenter)
17
41
  delete this.devtool
18
42
  })
@@ -20,79 +44,76 @@ export default class ToggleTriggerElement extends ReflexElement {
20
44
  if (DevtoolSupervisor.started) DevtoolSupervisor.restart()
21
45
  }
22
46
 
23
- collapse () {
24
- try {
25
- this.target.remove()
26
- this.setAttribute('aria-expanded', false)
27
- } catch (error) {
28
- console.error('Failed to collapse toggle-trigger target!', error)
29
- }
47
+ hideDevtool () {
48
+ if (this.devtool) this.devtool.hide(true)
30
49
  }
31
50
 
51
+ // a list of views shared between the trigger and target
32
52
  get sharedViews () {
33
- if (!this.target) return []
34
- if (!this.target.viewStack) return []
53
+ if (!this.targetElement) return []
54
+ if (!this.targetElement.viewStack) return []
35
55
  const reducer = (memo, view) => {
36
- if (this.target.viewStack.includes(view)) memo.push(view)
56
+ if (this.targetElement.viewStack.includes(view)) memo.push(view)
37
57
  return memo
38
58
  }
39
59
  return this.viewStack.reduce(reducer.bind(this), [])
40
60
  }
41
61
 
42
- get renderingInfo () {
43
- if (!this.dataset.render) return {}
44
- return JSON.parse(this.dataset.render)
62
+ // the partial to render
63
+ get renders () {
64
+ return this.getAttribute('renders')
65
+ }
66
+
67
+ // the renderered partial's top wrapping dom_id
68
+ get morphs () {
69
+ return this.getAttribute('morphs')
45
70
  }
46
71
 
47
- get renderingPartial () {
48
- return this.renderingInfo.partial
72
+ // the morph element
73
+ get morphElement () {
74
+ if (!this.morphs) return null
75
+ return document.getElementById(this.morphs)
49
76
  }
50
77
 
51
- get renderingElement () {
52
- const { id } = this.renderingInfo
53
- if (!id) return null
54
- return document.getElementById(id)
78
+ // the target's dom_id
79
+ get controls () {
80
+ return this.getAttribute('aria-controls')
81
+ }
82
+
83
+ // the target element
84
+ get targetElement () {
85
+ if (!this.controls) return null
86
+ return document.getElementById(this.controls)
87
+ }
88
+
89
+ get collapseSelector () {
90
+ return this.getAttribute('collapse-selector')
55
91
  }
56
92
 
93
+ get focusSelector () {
94
+ return this.getAttribute('focus-selector')
95
+ }
96
+
97
+ // indicates if the target is expanded
57
98
  get expanded () {
58
99
  return this.getAttribute('aria-expanded') === 'true'
59
100
  }
60
101
 
61
- get controls () {
62
- return this.getAttribute('aria-controls')
102
+ set expanded (value) {
103
+ this.setAttribute('aria-expanded', !!value)
63
104
  }
64
105
 
65
- get target () {
66
- return document.getElementById(this.controls)
106
+ // indicates if the target is expanded
107
+ get collapsed () {
108
+ return !this.expanded
67
109
  }
68
110
 
69
- get active () {
70
- return this.getAttribute('data-active') === 'true'
111
+ // indicates if an rpc call is active/busy
112
+ get busy () {
113
+ return this.getAttribute('busy') === 'true'
71
114
  }
72
115
 
73
- set active (value) {
74
- this.setAttribute('data-active', !!value)
116
+ set busy (value) {
117
+ this.setAttribute('busy', !!value)
75
118
  }
76
119
  }
77
-
78
- addEventListener(
79
- TurboReflex.events.start,
80
- event => (event.target.active = true)
81
- )
82
- addEventListener(
83
- TurboReflex.events.success,
84
- event => (event.target.active = false)
85
- )
86
- addEventListener(
87
- TurboReflex.events.finish,
88
- event => (event.target.active = false)
89
- )
90
-
91
- addEventListener('click', event => {
92
- if (event.target.tagName.match(/reflex-behaviors-devtool/i)) return
93
- setTimeout(() => {
94
- const selector =
95
- 'toggle-trigger[aria-controls][aria-expanded="true"][data-auto-collapse="true"]'
96
- document.querySelectorAll(selector).forEach(trigger => trigger.collapse())
97
- })
98
- })
@@ -21,19 +21,22 @@ class ReflexBehaviors::ApplicationReflex < TurboReflex::Base
21
21
  protected
22
22
 
23
23
  def render_payload
24
- return {} if element.dataset.render.blank?
25
- @render_payload ||= JSON.parse(element.dataset.render).deep_symbolize_keys.tap do |payload|
26
- payload[:assigns] = {} if payload[:assigns].blank?
27
- payload[:assigns].each { |key, value| payload[:assigns][key] = hydrated_value(value) }
28
-
29
- payload[:locals] = {} if payload[:locals].blank?
30
- payload[:locals].each { |key, value| payload[:locals][key] = hydrated_value(value) }
31
- end
24
+ return {} if element.renders.blank?
25
+ @render_payload ||= {partial: idomatic_partial_path(element.renders)}.tap do |payload|
26
+ if element.assigns.present?
27
+ payload[:assigns] = JSON.parse(element.assigns)
28
+ payload[:assigns].each { |key, value| payload[:assigns][key] = hydrate_value(value) }
29
+ end
30
+ if element.locals.present?
31
+ payload[:locals] = JSON.parse(element.locals)
32
+ payload[:locals].each { |key, value| payload[:locals][key] = hydrate_value(value) }
33
+ end
34
+ end.deep_symbolize_keys
32
35
  end
33
36
 
34
37
  private
35
38
 
36
- def hydrated_value(value)
39
+ def hydrate_value(value)
37
40
  hydrated = begin
38
41
  GlobalID::Locator.locate_signed(value)
39
42
  rescue
@@ -41,4 +44,8 @@ class ReflexBehaviors::ApplicationReflex < TurboReflex::Base
41
44
  end
42
45
  hydrated.blank? ? nil : hydrated
43
46
  end
47
+
48
+ def idomatic_partial_path(partial_path)
49
+ partial_path.to_s.gsub("/_", "/").split(".").first
50
+ end
44
51
  end