turbo_boost-elements 0.0.12 → 0.0.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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