| | class CustomApiKeyModal extends HTMLElement { |
| | constructor() { |
| | super(); |
| | this.attachShadow({ mode: 'open' }); |
| | } |
| |
|
| | static get observedAttributes() { |
| | return ['open']; |
| | } |
| |
|
| | attributeChangedCallback(name, oldValue, newValue) { |
| | if (name === 'open') { |
| | this.render(); |
| | } |
| | } |
| |
|
| | connectedCallback() { |
| | this.render(); |
| | } |
| |
|
| | render() { |
| | const isOpen = this.hasAttribute('open'); |
| | this.shadowRoot.innerHTML = ` |
| | <style> |
| | .modal-overlay { |
| | position: fixed; |
| | top: 0; |
| | left: 0; |
| | right: 0; |
| | bottom: 0; |
| | background-color: rgba(0, 0, 0, 0.5); |
| | display: flex; |
| | align-items: center; |
| | justify-content: center; |
| | z-index: 50; |
| | opacity: 0; |
| | pointer-events: none; |
| | transition: opacity 0.3s ease; |
| | } |
| | |
| | .modal-overlay.open { |
| | opacity: 1; |
| | pointer-events: all; |
| | } |
| | |
| | .modal-content { |
| | background-color: white; |
| | border-radius: 0.5rem; |
| | width: 100%; |
| | max-width: 28rem; |
| | transform: translateY(20px); |
| | transition: transform 0.3s ease; |
| | } |
| | |
| | .dark .modal-content { |
| | background-color: #1f2937; |
| | } |
| | |
| | .modal-overlay.open .modal-content { |
| | transform: translateY(0); |
| | } |
| | </style> |
| | |
| | <div class="modal-overlay ${isOpen ? 'open' : ''}"> |
| | <div class="modal-content shadow-xl"> |
| | <div class="p-6 border-b border-gray-200 dark:border-gray-700"> |
| | <h3 class="text-lg font-medium">Enter Your API Key</h3> |
| | </div> |
| | |
| | <div class="p-6"> |
| | <div class="mb-4"> |
| | <label class="block text-sm font-medium mb-2">DeepSeek API Key</label> |
| | <input type="password" id="api-key-input" placeholder="sk-..." class="bg-gray-50 dark:bg-gray-700 border border-gray-300 dark:border-gray-600 text-gray-900 dark:text-white rounded-lg p-3 focus:ring-blue-500 focus:border-blue-500 block w-full"> |
| | <p class="mt-2 text-sm text-gray-500 dark:text-gray-400">Your API key is stored locally in your browser.</p> |
| | </div> |
| | |
| | <div class="flex justify-end space-x-3"> |
| | <button id="cancel-button" class="px-4 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm font-medium hover:bg-gray-50 dark:hover:bg-gray-700"> |
| | Cancel |
| | </button> |
| | <button id="save-button" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium"> |
| | Save |
| | </button> |
| | </div> |
| | </div> |
| | </div> |
| | </div> |
| | `; |
| |
|
| | if (isOpen) { |
| | setTimeout(() => { |
| | const apiKeyInput = this.shadowRoot.getElementById('api-key-input'); |
| | const cancelButton = this.shadowRoot.getElementById('cancel-button'); |
| | const saveButton = this.shadowRoot.getElementById('save-button'); |
| | |
| | |
| | const savedKey = localStorage.getItem('deepseek_api_key'); |
| | if (savedKey) { |
| | apiKeyInput.value = savedKey; |
| | } |
| | |
| | cancelButton.addEventListener('click', () => { |
| | this.removeAttribute('open'); |
| | }); |
| | |
| | saveButton.addEventListener('click', () => { |
| | const apiKey = apiKeyInput.value.trim(); |
| | if (apiKey) { |
| | localStorage.setItem('deepseek_api_key', apiKey); |
| | this.removeAttribute('open'); |
| | } |
| | }); |
| | |
| | |
| | apiKeyInput.focus(); |
| | }, 0); |
| | } |
| | } |
| | } |
| |
|
| | customElements.define('custom-api-key-modal', CustomApiKeyModal); |