Download components/command-panel.js from Wathuta/taskflow-calendar-commander: direct link, hf CLI and curl.
- Browser
- Download file 15.4 kB
-
https://huggingface.co/spaces/Wathuta/taskflow-calendar-commander/resolve/main/components/command-panel.js
- Command line
-
hf download hf://spaces/Wathuta/taskflow-calendar-commander/components/command-panel.js
-
curl -L -o command-panel.js https://huggingface.co/spaces/Wathuta/taskflow-calendar-commander/resolve/main/components/command-panel.js
15.4 kB
| class CustomCommandPanel extends HTMLElement { | |
| constructor() { | |
| super(); | |
| this.isOpen = false; | |
| } | |
| connectedCallback() { | |
| this.attachShadow({ mode: 'open' }); | |
| this.render(); | |
| this.setupEventListeners(); | |
| } | |
| render() { | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| position: relative; | |
| } | |
| .panel-toggle { | |
| position: fixed; | |
| right: 0; | |
| top: 50%; | |
| transform: translateY(-50%); | |
| background: #0ea5e9; | |
| color: white; | |
| padding: 1rem 0.5rem; | |
| border-radius: 0.5rem 0 0 0.5rem; | |
| writing-mode: vertical-rl; | |
| cursor: pointer; | |
| z-index: 40; | |
| transition: all 0.3s ease; | |
| box-shadow: -2px 0 8px rgba(0, 0, 0, 0.1); | |
| font-weight: 600; | |
| font-size: 0.875rem; | |
| } | |
| .panel-toggle:hover { | |
| background: #0284c7; | |
| padding-right: 0.75rem; | |
| } | |
| .command-panel { | |
| position: fixed; | |
| right: 0; | |
| top: 0; | |
| height: 100vh; | |
| width: 400px; | |
| background: white; | |
| border-left: 1px solid #e5e7eb; | |
| box-shadow: -4px 0 16px rgba(0, 0, 0, 0.1); | |
| transform: translateX(100%); | |
| transition: transform 0.3s ease-in-out; | |
| z-index: 50; | |
| display: flex; | |
| flex-direction: column; | |
| } | |
| .panel-open { | |
| transform: translateX(0); | |
| } | |
| .panel-header { | |
| padding: 1rem 1.5rem; | |
| border-bottom: 1px solid #e5e7eb; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| } | |
| .panel-title { | |
| font-size: 1.25rem; | |
| font-weight: 600; | |
| color: #1f2937; | |
| } | |
| .close-button { | |
| background: none; | |
| border: none; | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| color: #6b7280; | |
| padding: 0.25rem; | |
| border-radius: 0.25rem; | |
| } | |
| .close-button:hover { | |
| background: #f3f4f6; | |
| } | |
| .search-container { | |
| padding: 1rem 1.5rem; | |
| border-bottom: 1px solid #e5e7eb; | |
| } | |
| .search-input { | |
| width: 100%; | |
| padding: 0.75rem 1rem; | |
| border: 1px solid #d1d5db; | |
| border-radius: 0.5rem; | |
| font-size: 0.875rem; | |
| focus:outline-none; | |
| focus:ring-2; | |
| focus:ring-primary-500; | |
| focus:border-primary-500; | |
| } | |
| .search-input:focus { | |
| outline: none; | |
| border-color: #0ea5e9; | |
| box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.1); | |
| } | |
| .content-area { | |
| flex: 1; | |
| overflow-y: auto; | |
| padding: 1rem 1.5rem; | |
| } | |
| .section { | |
| margin-bottom: 1.5rem; | |
| } | |
| .section-title { | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| color: #374151; | |
| margin-bottom: 0.75rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| } | |
| .command-list { | |
| list-style: none; | |
| } | |
| .command-item { | |
| padding: 0.75rem 1rem; | |
| border-radius: 0.5rem; | |
| cursor: pointer; | |
| margin-bottom: 0.25rem; | |
| display: flex; | |
| align-items: center; | |
| transition: all 0.2s ease; | |
| } | |
| .command-item:hover { | |
| background: #f9fafb; | |
| } | |
| .command-icon { | |
| width: 20px; | |
| height: 20px; | |
| margin-right: 0.75rem; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .command-text { | |
| flex: 1; | |
| } | |
| .command-name { | |
| font-weight: 500; | |
| color: #1f2937; | |
| margin-bottom: 0.125rem; | |
| } | |
| .command-desc { | |
| font-size: 0.75rem; | |
| color: #6b7280; | |
| } | |
| .badge { | |
| background: #eff6ff; | |
| color: #1d4ed8; | |
| padding: 0.125rem 0.5rem; | |
| border-radius: 9999px; | |
| font-size: 0.75rem; | |
| font-weight: 500; | |
| } | |
| .context-suggestions { | |
| background: #f0f9ff; | |
| border-radius: 0.5rem; | |
| padding: 1rem; | |
| margin-top: 1rem; | |
| } | |
| .suggestion-title { | |
| font-size: 0.875rem; | |
| font-weight: 600; | |
| color: #0369a1; | |
| margin-bottom: 0.5rem; | |
| } | |
| .suggestion-list { | |
| list-style: none; | |
| } | |
| .suggestion-item { | |
| padding: 0.5rem; | |
| border-radius: 0.25rem; | |
| cursor: pointer; | |
| font-size: 0.875rem; | |
| color: #0369a1; | |
| transition: background 0.2s ease; | |
| } | |
| .suggestion-item:hover { | |
| background: #e0f2fe; | |
| } | |
| </style> | |
| <div class="panel-toggle" id="toggle-button"> | |
| CMD | |
| </div> | |
| <div class="command-panel" id="command-panel"> | |
| <div class="panel-header"> | |
| <div class="panel-title">Command Center</div> | |
| <button class="close-button" id="close-button">Γ</button> | |
| </div> | |
| <div class="search-container"> | |
| <input type="text" class="search-input" placeholder="Search commands... Ctrl+K" id="search-input"> | |
| </div> | |
| <div class="content-area"> | |
| <div class="section"> | |
| <div class="section-title"> | |
| <span>β± Recent Commands</span> | |
| </div> | |
| <ul class="command-list"> | |
| <li class="command-item"> | |
| <div class="command-icon">π</div> | |
| <div class="command-text"> | |
| <div class="command-name">/task create "API integration" @john</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">βοΈ</div> | |
| <div class="command-text"> | |
| <div class="command-name">/bulk assign sprint:Q1-3 to:@alice</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">ποΈ</div> | |
| <div class="command-text"> | |
| <div class="command-name">/schedule pto @bob from:3/1 to:3/5</div> | |
| </div> | |
| </li> | |
| </ul> | |
| </div> | |
| <div class="section"> | |
| <div class="section-title"> | |
| <span>π Command Templates</span> | |
| </div> | |
| <ul class="command-list"> | |
| <li class="command-item"> | |
| <div class="command-icon">π</div> | |
| <div class="command-text"> | |
| <div class="command-name">Create Task</div> | |
| <div class="command-desc">Create a new task with specified details</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">βοΈ</div> | |
| <div class="command-text"> | |
| <div class="command-name">Move Task</div> | |
| <div class="command-desc">Move task to different date/assignee</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">π</div> | |
| <div class="command-text"> | |
| <div class="command-name">Update Status</div> | |
| <div class="command-desc">Update task properties</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">ποΈ</div> | |
| <div class="command-text"> | |
| <div class="command-name">Delete Task</div> | |
| <div class="command-desc">Delete specific task</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">ποΈ</div> | |
| <div class="command-text"> | |
| <div class="command-name">Scheduling (6 commands)</div> | |
| </div> | |
| </li> | |
| <li class="command-item"> | |
| <div class="command-icon">π</div> | |
| <div class="command-text"> | |
| <div class="command-name">Multi-Task Operations (8 commands)</div> | |
| </div> | |
| </li> | |
| </ul> | |
| </div> | |
| <div class="context-suggestions"> | |
| <div class="suggestion-title">π‘ Context Suggestions</div> | |
| <div class="suggestion-desc">Based on your selection:</div> | |
| <ul class="suggestion-list"> | |
| <li class="suggestion-item">β’ Assign 3 selected tasks to...</li> | |
| <li class="suggestion-item">β’ Move selection to next sprint</li> | |
| <li class="suggestion-item">β’ Mark selected as complete</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| } | |
| setupEventListeners() { | |
| const toggleButton = this.shadowRoot.getElementById('toggle-button'); | |
| const closeButton = this.shadowRoot.getElementById('close-button'); | |
| const commandPanel = this.shadowRoot.getElementById('command-panel'); | |
| const searchInput = this.shadowRoot.getElementById('search-input'); | |
| toggleButton.addEventListener('click', () => { | |
| this.togglePanel(); | |
| }); | |
| closeButton.addEventListener('click', () => { | |
| this.closePanel(); | |
| }); | |
| // Close panel when clicking outside | |
| document.addEventListener('click', (event) => { | |
| if (this.isOpen && !commandPanel.contains(event.target) && !toggleButton.contains(event.target)) { | |
| this.closePanel(); | |
| } | |
| }); | |
| // Keyboard shortcuts | |
| document.addEventListener('keydown', (event) => { | |
| // Ctrl+K or Cmd+K to toggle panel | |
| if ((event.ctrlKey || event.metaKey) && event.key === 'k') { | |
| event.preventDefault(); | |
| this.togglePanel(); | |
| } | |
| // Escape to close panel | |
| if (event.key === 'Escape' && this.isOpen) { | |
| this.closePanel(); | |
| } | |
| }); | |
| // Focus search input when panel opens | |
| searchInput.addEventListener('focus', () => { | |
| // Handle autocomplete suggestions | |
| }); | |
| } | |
| togglePanel() { | |
| this.isOpen = !this.isOpen; | |
| const panel = this.shadowRoot.getElementById('command-panel'); | |
| const toggleButton = this.shadowRoot.getElementById('toggle-button'); | |
| if (this.isOpen) { | |
| panel.classList.add('panel-open'); | |
| toggleButton.textContent = 'Γ'; | |
| } else { | |
| panel.classList.remove('panel-open'); | |
| toggleButton.textContent = 'CMD'; | |
| } | |
| } | |
| openPanel(template = null) { | |
| this.isOpen = true; | |
| const panel = this.shadowRoot.getElementById('command-panel'); | |
| const toggleButton = this.shadowRoot.getElementById('toggle-button'); | |
| panel.classList.add('panel-open'); | |
| toggleButton.textContent = 'Γ'; | |
| // If template specified, load that template | |
| if (template) { | |
| this.loadTemplate(template); | |
| } | |
| } | |
| closePanel() { | |
| this.isOpen = false; | |
| const panel = this.shadowRoot.getElementById('command-panel'); | |
| const toggleButton = this.shadowRoot.getElementById('toggle-button'); | |
| panel.classList.remove('panel-open'); | |
| toggleButton.textContent = 'CMD'; | |
| } | |
| loadTemplate(templateName) { | |
| // Load specific command template | |
| console.log('Loading template:', templateName); | |
| } | |
| } | |
| customElements.define('custom-command-panel', CustomCommandPanel); |