kommandant 0.2.0 → 0.2.1
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.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a2574c9d2b6dfd75efee2ed6f9af3f92cfbd0b89a5e207d546f1e5979f8226ad
|
4
|
+
data.tar.gz: a0451d7914c31befe537e5703a80d22018fb4f60c0abb0faafb7f6c12542dbbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0eb9c48d8e9c06c8d9d1e905a8b4be846aa347abfba90a24479ce07da98eff5f0fec693fee27a24346ccfdf2701e81268272d7decef58eda0c8e31b01c11457b
|
7
|
+
data.tar.gz: afc40b7911d8ee7c02669819b5d331f4500ceec455de4b5ba6a4cbcdf317222b27d5f652886fe976c2e599bacaa3f96ee1a082a70b5e66d6246f9f4f45814776
|
data/lib/kommandant/version.rb
CHANGED
@@ -0,0 +1,120 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
import { enter, leave, toggle } from "./transition"
|
3
|
+
|
4
|
+
export default class extends Controller {
|
5
|
+
static targets = ["background", "panel", "input", "content", "loadingMessage", "previousPageLink", "nextPageLink"]
|
6
|
+
static values = {
|
7
|
+
open: { type: Boolean, default: false },
|
8
|
+
loadingMessageDelay: { type: Number, default: 100 },
|
9
|
+
animationDuration: { type: Number, default: 200 },
|
10
|
+
modifierKeyDown: { type: Boolean, default: false }
|
11
|
+
}
|
12
|
+
|
13
|
+
initialize() {
|
14
|
+
this.submit = this.debounce(this.submit, 500).bind(this);
|
15
|
+
}
|
16
|
+
|
17
|
+
toggle(event) {
|
18
|
+
event.preventDefault()
|
19
|
+
|
20
|
+
toggle(this.backgroundTarget)
|
21
|
+
toggle(this.panelTarget)
|
22
|
+
this.openValue = !this.openValue
|
23
|
+
}
|
24
|
+
|
25
|
+
show(event) {
|
26
|
+
event.preventDefault()
|
27
|
+
|
28
|
+
enter(this.backgroundTarget)
|
29
|
+
enter(this.panelTarget)
|
30
|
+
this.openValue = true
|
31
|
+
}
|
32
|
+
|
33
|
+
hide(event) {
|
34
|
+
event.preventDefault()
|
35
|
+
|
36
|
+
leave(this.backgroundTarget)
|
37
|
+
leave(this.panelTarget)
|
38
|
+
this.openValue = false
|
39
|
+
}
|
40
|
+
|
41
|
+
hideWithBackgroundOverlay(event) {
|
42
|
+
if (event.target === this.panelTarget) {
|
43
|
+
this.hide(event)
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
submit(event) {
|
48
|
+
const ignoreKeys = ["Enter", "Tab", "Escape", "ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight", "Home", "End", "Alt", "Control", "Meta", "Shift"]
|
49
|
+
const modifierKeyPressed = event.ctrlKey || event.metaKey
|
50
|
+
|
51
|
+
if (!modifierKeyPressed && !ignoreKeys.includes(event.key) && this.inputTarget.value !== "") {
|
52
|
+
this.inputTarget.form.requestSubmit()
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
reset() {
|
57
|
+
setTimeout(() => {
|
58
|
+
Turbo.visit("/kommandant/searches/new", { frame: "command_palette" })
|
59
|
+
}, this.animationDurationValue)
|
60
|
+
}
|
61
|
+
|
62
|
+
showLoadingMessage() {
|
63
|
+
this.loadingTimeout = setTimeout(() => {
|
64
|
+
this.contentTarget.classList.add("hidden")
|
65
|
+
this.loadingMessageTarget.classList.remove("hidden")
|
66
|
+
}, this.loadingMessageDelayValue)
|
67
|
+
}
|
68
|
+
|
69
|
+
nextPage(event) {
|
70
|
+
event.preventDefault()
|
71
|
+
|
72
|
+
if (this.hasNextPageLinkTarget) {
|
73
|
+
this.nextPageLinkTarget.click()
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
previousPage(event) {
|
78
|
+
event.preventDefault()
|
79
|
+
|
80
|
+
if (this.hasPreviousPageLinkTarget) {
|
81
|
+
this.previousPageLinkTarget.click()
|
82
|
+
}
|
83
|
+
}
|
84
|
+
|
85
|
+
// Private
|
86
|
+
|
87
|
+
openValueChanged(value, previousValue) {
|
88
|
+
this.focusInputTarget()
|
89
|
+
|
90
|
+
if (value === false && previousValue !== undefined) {
|
91
|
+
this.reset()
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
95
|
+
inputTargetConnected() {
|
96
|
+
this.focusInputTarget()
|
97
|
+
clearTimeout(this.loadingTimeout)
|
98
|
+
}
|
99
|
+
|
100
|
+
focusInputTarget() {
|
101
|
+
if (this.openValue) {
|
102
|
+
this.inputTarget.focus()
|
103
|
+
|
104
|
+
// Set cursor at end of inputted text
|
105
|
+
let temp = this.inputTarget.value
|
106
|
+
this.inputTarget.value = ""
|
107
|
+
this.inputTarget.value = temp
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
111
|
+
debounce(func, delay) {
|
112
|
+
let timeoutId;
|
113
|
+
return function (...args) {
|
114
|
+
clearTimeout(timeoutId);
|
115
|
+
timeoutId = setTimeout(() => {
|
116
|
+
func.apply(this, args);
|
117
|
+
}, delay);
|
118
|
+
};
|
119
|
+
}
|
120
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import { Controller } from "@hotwired/stimulus"
|
2
|
+
|
3
|
+
export default class extends Controller {
|
4
|
+
static targets = ["focusable"]
|
5
|
+
static values = { activeOptionIndex: { type: Number, default: 0 } }
|
6
|
+
|
7
|
+
connect() {
|
8
|
+
if (this.activeOption) {
|
9
|
+
this.activateOption()
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
down(event) {
|
14
|
+
event.preventDefault()
|
15
|
+
|
16
|
+
if (this.activeOptionIndexValue < (this.focusableTargets.length - 1)) {
|
17
|
+
this.deactivateOption()
|
18
|
+
this.activeOptionIndexValue++
|
19
|
+
this.activateOption()
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
up(event) {
|
24
|
+
event.preventDefault()
|
25
|
+
|
26
|
+
if (this.activeOptionIndexValue > 0) {
|
27
|
+
this.deactivateOption()
|
28
|
+
this.activeOptionIndexValue--
|
29
|
+
this.activateOption()
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
focus(event) {
|
34
|
+
this.deactivateOption()
|
35
|
+
this.activeOptionIndexValue = this.focusableTargets.indexOf(event.currentTarget)
|
36
|
+
this.activateOption()
|
37
|
+
}
|
38
|
+
|
39
|
+
select(event) {
|
40
|
+
if (this.hasFocusableTarget && this.focusableTargetIsVisible) {
|
41
|
+
event.preventDefault()
|
42
|
+
|
43
|
+
this.activeOption.click()
|
44
|
+
}
|
45
|
+
}
|
46
|
+
|
47
|
+
// Private
|
48
|
+
|
49
|
+
deactivateOption() {
|
50
|
+
this.activeOption.dataset.active = false
|
51
|
+
}
|
52
|
+
|
53
|
+
activateOption() {
|
54
|
+
this.activeOption.dataset.active = true
|
55
|
+
}
|
56
|
+
|
57
|
+
focusableTargetDisconnected() {
|
58
|
+
this.activeOptionIndexValue = 0
|
59
|
+
}
|
60
|
+
|
61
|
+
focusableTargetConnected() {
|
62
|
+
this.activateOption()
|
63
|
+
}
|
64
|
+
|
65
|
+
get activeOption() {
|
66
|
+
return this.focusableTargets[this.activeOptionIndexValue]
|
67
|
+
}
|
68
|
+
|
69
|
+
get focusableTargetIsVisible() {
|
70
|
+
return this.focusableTarget.offsetParent !== null
|
71
|
+
}
|
72
|
+
}
|
@@ -0,0 +1,57 @@
|
|
1
|
+
// This was taken from https://github.com/mmccall10/el-transition but is included here to avoid the need for a separate package
|
2
|
+
|
3
|
+
export async function enter(element, transitionName = null) {
|
4
|
+
element.classList.remove('hidden')
|
5
|
+
await transition('enter', element, transitionName)
|
6
|
+
}
|
7
|
+
|
8
|
+
export async function leave(element, transitionName = null) {
|
9
|
+
await transition('leave', element, transitionName)
|
10
|
+
element.classList.add('hidden')
|
11
|
+
}
|
12
|
+
|
13
|
+
export async function toggle(element, transitionName = null) {
|
14
|
+
if (element.classList.contains('hidden')) {
|
15
|
+
await enter(element, transitionName)
|
16
|
+
} else {
|
17
|
+
await leave(element, transitionName)
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
async function transition(direction, element, animation) {
|
22
|
+
const dataset = element.dataset
|
23
|
+
const animationClass = animation ? `${animation}-${direction}` : direction
|
24
|
+
let transition = `transition${direction.charAt(0).toUpperCase() + direction.slice(1)}`
|
25
|
+
const genesis = dataset[transition] ? dataset[transition].split(" ") : [animationClass]
|
26
|
+
const start = dataset[`${transition}Start`] ? dataset[`${transition}Start`].split(" ") : [`${animationClass}-start`]
|
27
|
+
const end = dataset[`${transition}End`] ? dataset[`${transition}End`].split(" ") : [`${animationClass}-end`]
|
28
|
+
|
29
|
+
addClasses(element, genesis)
|
30
|
+
addClasses(element, start)
|
31
|
+
await nextFrame()
|
32
|
+
removeClasses(element, start)
|
33
|
+
addClasses(element, end);
|
34
|
+
await afterTransition(element)
|
35
|
+
removeClasses(element, end)
|
36
|
+
removeClasses(element, genesis)
|
37
|
+
}
|
38
|
+
|
39
|
+
function addClasses(element, classes) {
|
40
|
+
element.classList.add(...classes)
|
41
|
+
}
|
42
|
+
|
43
|
+
function removeClasses(element, classes) {
|
44
|
+
element.classList.remove(...classes)
|
45
|
+
}
|
46
|
+
|
47
|
+
function nextFrame() {
|
48
|
+
return new Promise(resolve => {
|
49
|
+
requestAnimationFrame(() => {
|
50
|
+
requestAnimationFrame(resolve)
|
51
|
+
});
|
52
|
+
});
|
53
|
+
}
|
54
|
+
|
55
|
+
function afterTransition(element) {
|
56
|
+
return Promise.all(element.getAnimations().map(animation => animation.finished));
|
57
|
+
}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kommandant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nicolai Bach Woller
|
@@ -133,6 +133,10 @@ files:
|
|
133
133
|
- lib/kommandant/engine.rb
|
134
134
|
- lib/kommandant/version.rb
|
135
135
|
- lib/tasks/kommandant_tasks.rake
|
136
|
+
- vendor/assets/javascripts/command_palette.js
|
137
|
+
- vendor/assets/javascripts/keyboard_navigation.js
|
138
|
+
- vendor/assets/javascripts/kommandant.js
|
139
|
+
- vendor/assets/javascripts/transition.js
|
136
140
|
homepage: https://traels.it
|
137
141
|
licenses:
|
138
142
|
- MIT
|