turbo_boost-elements 0.0.12 → 0.0.14

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,5 +1,4 @@
1
1
  import ToggleElement from '../toggle_element'
2
- import './focus'
3
2
 
4
3
  export default class ToggleTargetElement extends ToggleElement {
5
4
  connectedCallback () {
@@ -60,6 +59,7 @@ export default class ToggleTargetElement extends ToggleElement {
60
59
 
61
60
  collapse (delay = 250) {
62
61
  clearTimeout(this.collapseTimeout)
62
+ if (this.busy) return
63
63
  if (typeof delay !== 'number') delay = 250
64
64
 
65
65
  if (delay > 0)
@@ -79,7 +79,7 @@ export default class ToggleTargetElement extends ToggleElement {
79
79
 
80
80
  collapseMatches () {
81
81
  document.querySelectorAll(this.collapseSelector).forEach(el => {
82
- if (el === this) return
82
+ if (el.id === this.id) return
83
83
  if (el.collapse) el.collapse(0)
84
84
  })
85
85
  }
@@ -91,29 +91,29 @@ export default class ToggleTargetElement extends ToggleElement {
91
91
  )
92
92
  }
93
93
 
94
- applyFocus () {
95
- if (this.focusElement) this.focusElement.focus()
96
- }
97
-
98
94
  get focusSelector () {
99
- let value = this.getAttribute('focus-selector')
100
- if (this.triggerElement)
101
- value = this.triggerElement.getAttribute('focus-selector') || value
102
- return value
103
- }
104
-
105
- get focusElement () {
106
- return this.querySelector(this.focusSelector)
95
+ return this.getAttribute('focus-selector')
107
96
  }
108
97
 
98
+ // the active trigger
109
99
  get triggerElement () {
110
100
  return document.getElementById(this.labeledBy)
111
101
  }
112
102
 
103
+ // all triggers
104
+ get triggerElements () {
105
+ return document.querySelectorAll(`[aria-controls="${this.id}"]`)
106
+ }
107
+
108
+ // the dom id of the active trigger
113
109
  get labeledBy () {
114
110
  return this.getAttribute('aria-labeledby')
115
111
  }
116
112
 
113
+ set labeledBy (value) {
114
+ return this.setAttribute('aria-labeledby', value)
115
+ }
116
+
117
117
  get collapseOn () {
118
118
  const value = this.getAttribute('collapse-on')
119
119
  if (!value) return []
@@ -121,10 +121,14 @@ export default class ToggleTargetElement extends ToggleElement {
121
121
  }
122
122
 
123
123
  get expanded () {
124
- return this.triggerElement.expanded
124
+ return this.triggerElement ? this.triggerElement.expanded : false
125
125
  }
126
126
 
127
127
  set expanded (value) {
128
- return (this.triggerElement.expanded = value)
128
+ this.triggerElements.forEach(el => (el.expanded = value))
129
+ }
130
+
131
+ get busy () {
132
+ return this.triggerElement && this.triggerElement.busy
129
133
  }
130
134
  }
@@ -1,3 +1,5 @@
1
+ let focusTimeout
2
+
1
3
  function deactivateTrixAttributes (editor) {
2
4
  const attributes = [
3
5
  'bold',
@@ -43,35 +45,26 @@ function focusTrixEditorElement (element) {
43
45
  ])
44
46
  }
45
47
 
46
- function shouldEnhanceFocus (element) {
47
- if (!element.tagName.match(/^input|textarea|trix-editor$/i)) return false
48
- const toggleTargetElement = element.closest('turbo-boost-toggle-target') || {}
49
- return !!toggleTargetElement.focusElement
50
- }
48
+ function debouncedFocus (element) {
49
+ clearTimeout(focusTimeout)
51
50
 
52
- function enhanceFocus (element) {
53
- const trixEditorElement = element.closest('trix-editor')
51
+ focusTimeout = setTimeout(() => {
52
+ if (!element) return
54
53
 
55
- try {
56
- if (trixEditorElement) {
57
- focusTrixEditorElement(trixEditorElement)
58
- } else {
59
- element.selectionStart = element.selectionEnd = element.value.length
54
+ element.focus()
55
+ const trixEditorElement = element.closest('trix-editor')
56
+
57
+ try {
58
+ if (trixEditorElement) {
59
+ focusTrixEditorElement(trixEditorElement)
60
+ } else {
61
+ element.selectionStart = element.selectionEnd = element.value.length
62
+ }
63
+ } catch (_) {
64
+ } finally {
65
+ element.scrollIntoView({ block: 'center', behavior: 'smooth' })
60
66
  }
61
- } catch (_) {
62
- } finally {
63
- setTimeout(
64
- () => element.scrollIntoView({ block: 'center', behavior: 'smooth' }),
65
- 100
66
- )
67
- }
67
+ }, 100)
68
68
  }
69
69
 
70
- addEventListener(
71
- 'focus',
72
- event => {
73
- if (shouldEnhanceFocus(document.activeElement))
74
- enhanceFocus(document.activeElement)
75
- },
76
- true
77
- )
70
+ export default element => debouncedFocus(element)
@@ -1,13 +1,13 @@
1
1
  import ToggleElement, { busyDuration } from '../toggle_element'
2
2
  import Devtool from './devtool'
3
+ import focus from './focus'
4
+
5
+ let currentFocusSelector
3
6
 
4
7
  export default class ToggleTriggerElement extends ToggleElement {
5
8
  connectedCallback () {
6
9
  super.connectedCallback()
7
10
 
8
- if (this.targetElement)
9
- this.targetElement.setAttribute('aria-labeledby', this.id)
10
-
11
11
  const { start: commandStartEvent } = TurboBoost.Commands.events
12
12
  this.commandStartHandler = this.onCommandStart.bind(this)
13
13
  this.addEventListener(commandStartEvent, this.commandStartHandler)
@@ -25,15 +25,19 @@ export default class ToggleTriggerElement extends ToggleElement {
25
25
  }
26
26
 
27
27
  disconnectedCallback () {
28
- const { start: commandStartEvent } = TurboBoost.Commands.events
29
- this.removeEventListener(commandStartEvent, this.commandStartHandler)
28
+ // delay cleanup because the trigger may have been morphed out of the DOM,
29
+ // but it's needed to apply behavior like focus etc...
30
+ setTimeout(() => {
31
+ const { start: commandStartEvent } = TurboBoost.Commands.events
32
+ this.removeEventListener(commandStartEvent, this.commandStartHandler)
30
33
 
31
- const { before: beforeInvokeEvent } = TurboBoost.Streams.invokeEvents
32
- removeEventListener(beforeInvokeEvent, this.beforeInvokeHandler)
34
+ const { before: beforeInvokeEvent } = TurboBoost.Streams.invokeEvents
35
+ removeEventListener(beforeInvokeEvent, this.beforeInvokeHandler)
33
36
 
34
- this.devtool.hide({ active: false })
35
- this.devtool.unregisterEventListeners()
36
- delete this.devtool
37
+ this.devtool.hide({ active: false })
38
+ this.devtool.unregisterEventListeners()
39
+ delete this.devtool
40
+ }, 1000)
37
41
  }
38
42
 
39
43
  initializeDevtool () {
@@ -61,9 +65,9 @@ export default class ToggleTriggerElement extends ToggleElement {
61
65
  }
62
66
 
63
67
  onCommandStart (event) {
64
- this.targetElement.setAttribute('aria-labeledby', this.id)
68
+ currentFocusSelector = this.focusSelector
69
+ this.targetElement.labeledBy = this.id
65
70
  this.targetElement.collapseMatches()
66
- this.targetElement.busy = true
67
71
  this.busy = true
68
72
  // TODO: implement cache - this.targetElement.renderCachedHTML()
69
73
  }
@@ -87,15 +91,14 @@ export default class ToggleTriggerElement extends ToggleElement {
87
91
  // runs before the morph is executed
88
92
  setTimeout(() => {
89
93
  this.busy = false
90
- this.targetElement.busy = false
91
- this.morphToggleElements.forEach(el => (el.busy = false))
94
+ this.morphToggleTriggerElements.forEach(el => (el.busy = false))
92
95
  }, delay - 10)
93
96
 
94
97
  // runs after the morph is executed
95
- setTimeout(() => {
96
- this.targetElement.setAttribute('aria-labeledby', this.id)
97
- this.targetElement.applyFocus()
98
- }, delay + 100)
98
+ setTimeout(
99
+ () => focus(this.targetElement.querySelector(currentFocusSelector)),
100
+ delay + 100
101
+ )
99
102
  }
100
103
 
101
104
  // a list of views shared between the trigger and target
@@ -126,11 +129,9 @@ export default class ToggleTriggerElement extends ToggleElement {
126
129
  }
127
130
 
128
131
  // all toggle elements contained by the `morphElement`
129
- get morphToggleElements () {
132
+ get morphToggleTriggerElements () {
130
133
  return Array.from(
131
- this.morphElement.querySelectorAll(
132
- 'turbo-boost-toggle-trigger,turbo-boost-toggle-target'
133
- )
134
+ this.morphElement.querySelectorAll('turbo-boost-toggle-trigger')
134
135
  )
135
136
  }
136
137
 
@@ -151,8 +152,7 @@ export default class ToggleTriggerElement extends ToggleElement {
151
152
 
152
153
  get focusSelector () {
153
154
  return (
154
- this.getAttribute('focus-selector') ||
155
- this.targetElement.getAttribute('focus-selector')
155
+ this.getAttribute('focus-selector') || this.targetElement.focusSelector
156
156
  )
157
157
  }
158
158
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module TurboBoost
4
4
  module Elements
5
- VERSION = "0.0.12"
5
+ VERSION = "0.0.14"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: turbo_boost-elements
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Hopkins (hopsoft)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-02-07 00:00:00.000000000 Z
11
+ date: 2023-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -144,10 +144,10 @@ files:
144
144
  - app/javascript/devtools/index.js
145
145
  - app/javascript/devtools/supervisor.js
146
146
  - app/javascript/elements/index.js
147
- - app/javascript/elements/toggle_elements/target_element/focus.js
148
147
  - app/javascript/elements/toggle_elements/target_element/index.js
149
148
  - app/javascript/elements/toggle_elements/toggle_element/index.js
150
149
  - app/javascript/elements/toggle_elements/trigger_element/devtool.js
150
+ - app/javascript/elements/toggle_elements/trigger_element/focus.js
151
151
  - app/javascript/elements/toggle_elements/trigger_element/index.js
152
152
  - app/javascript/elements/turbo_boost_element/index.js
153
153
  - app/javascript/index.js