diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss index 0b8b335..b170f65 100644 --- a/app/assets/stylesheets/application.scss +++ b/app/assets/stylesheets/application.scss @@ -12,3 +12,4 @@ @import 'components/modal'; @import 'components/autocomplete'; @import 'components/animated_badge'; +@import 'components/command_list'; diff --git a/app/assets/stylesheets/components/_command_list.scss b/app/assets/stylesheets/components/_command_list.scss new file mode 100644 index 0000000..2495723 --- /dev/null +++ b/app/assets/stylesheets/components/_command_list.scss @@ -0,0 +1,27 @@ +.command-list { + .command-list-button { + min-width: 170px; + } + + .modal-dialog { + --bs-modal-width: 600px; + --bs-modal-margin: 5rem; + --bs-modal-padding: 1.5rem; + } + + .list-group-item { + color: $navbar-light-color; + + &.active { + color: white; + } + } + + .command-list-footer { + color: $navbar-light-color; + } + + .command-list-icon { + border: 1px outset $navbar-light-color; + } +} diff --git a/app/components/previews/command_list_component_preview.rb b/app/components/previews/command_list_component_preview.rb new file mode 100644 index 0000000..9498e46 --- /dev/null +++ b/app/components/previews/command_list_component_preview.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +# frozen_literal_string: true + +class CommandListComponentPreview < Lookbook::Preview + include LookbookHelper + + # @source ../../../app/views/components/command_lists/_themes.html.erb + def themes + render 'components/command_lists/themes' + end +end diff --git a/app/javascript/controllers/command_list_controller.js b/app/javascript/controllers/command_list_controller.js new file mode 100644 index 0000000..5df5036 --- /dev/null +++ b/app/javascript/controllers/command_list_controller.js @@ -0,0 +1,88 @@ +import { Controller } from "@hotwired/stimulus" + +export default class CommandListController extends Controller { + static targets = ['list', 'metaKey', "searchField", "listGroup", "listItem"]; + + connect() { + this.modal = new bootstrap.Modal(this.listTarget, {}) + this.children = Array.from(this.listGroupTargets[0].children); + if (this.listItemTargets.length > 0) { + this.switchActive(this.listItemTargets[0]); + } + this.metaKeyTarget.innerText = this.getMetaKey() + + document.addEventListener("keydown", this.handleKeydown.bind(this)); + } + + disconnect() { + document.removeEventListener("keydown", this.handleKeydown.bind(this)); + } + + handleKeydown(event) { + console.log('handling keydown', event.metaKey, event.key); + if ((event.metaKey) && event.key === "k") { + this.openModal(); + } + } + + openModal() { + this.modal.show(); + this.searchField().focus(); + } + + performCommand(event) { + event.preventDefault(); + const searchParts = this.searchField().value.split(',').map(part => part.trim()); + const command = this.activeCommand.dataset.command + .replace('_1_', searchParts[0]) + .replace('_2_', searchParts[1]) + .replace('_3_', searchParts[2]); + if (this.activeCommand.dataset.target == "_blank") { + window.open(command, '_blank'); + } else { + Turbo.visit(command); + } + } + + getMetaKey() { + const userAgent = window.navigator.userAgent.toLowerCase(); + if (userAgent.includes(' mac ')) { + return '⌘'; + } else { + return 'CTRL'; + } + } + + switchActive(element) { + if (this.activeCommand) { + this.activeCommand.classList.remove('active'); + } + element.classList.add('active'); + this.activeCommand = element; + this.searchField().placeholder = element.dataset.placeholder ?? ''; + } + + selectCommand(event) { + event.preventDefault(); + this.switchActive(event.currentTarget); + this.searchField().focus() + } + + previousItem() { + const previous = this.listItemTargets[this.listItemTargets.indexOf(this.activeCommand) - 1]; + if (previous) { + this.switchActive(previous) + } + } + + nextItem() { + const next = this.listItemTargets[this.listItemTargets.indexOf(this.activeCommand) + 1]; + if (next) { + this.switchActive(next) + } + } + + searchField() { + return this.searchFieldTarget + } +} diff --git a/app/views/components/command_lists/_themes.html.erb b/app/views/components/command_lists/_themes.html.erb new file mode 100644 index 0000000..21017ff --- /dev/null +++ b/app/views/components/command_lists/_themes.html.erb @@ -0,0 +1,75 @@ +