refactor(suite): clean up base layout and modularize app scripts
This commit is contained in:
parent
fee8b3d2a3
commit
5657e33006
6 changed files with 1473 additions and 2599 deletions
|
|
@ -1,192 +0,0 @@
|
|||
/* =============================================================================
|
||||
BOTUI SUITE - BASE LAYOUT JAVASCRIPT
|
||||
Sentient Theme with AI Assistant Panel
|
||||
============================================================================= */
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// =============================================================================
|
||||
// STATE
|
||||
// =============================================================================
|
||||
|
||||
const state = {
|
||||
aiPanelOpen: true,
|
||||
currentApp: 'dashboard',
|
||||
messages: []
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// AI PANEL
|
||||
// =============================================================================
|
||||
|
||||
window.toggleAIPanel = function() {
|
||||
const panel = document.getElementById('ai-panel');
|
||||
if (panel) {
|
||||
panel.classList.toggle('open');
|
||||
state.aiPanelOpen = panel.classList.contains('open');
|
||||
}
|
||||
};
|
||||
|
||||
window.sendAIMessage = function() {
|
||||
const input = document.getElementById('ai-input');
|
||||
if (!input || !input.value.trim()) return;
|
||||
|
||||
const message = input.value.trim();
|
||||
input.value = '';
|
||||
|
||||
addMessage('user', message);
|
||||
showTypingIndicator();
|
||||
|
||||
// Simulate AI response
|
||||
setTimeout(() => {
|
||||
hideTypingIndicator();
|
||||
addMessage('assistant', `Entendido! Vou processar sua solicitação: "${message}"`);
|
||||
}, 1500);
|
||||
};
|
||||
|
||||
function addMessage(type, content, action) {
|
||||
const container = document.getElementById('ai-messages');
|
||||
if (!container) return;
|
||||
|
||||
const messageEl = document.createElement('div');
|
||||
messageEl.className = `ai-message ${type}`;
|
||||
|
||||
let html = `<div class="ai-message-bubble">${content}</div>`;
|
||||
if (action) {
|
||||
html += `<span class="ai-message-action">${action}</span>`;
|
||||
}
|
||||
|
||||
messageEl.innerHTML = html;
|
||||
container.appendChild(messageEl);
|
||||
container.scrollTop = container.scrollHeight;
|
||||
|
||||
state.messages.push({ type, content, action });
|
||||
}
|
||||
|
||||
function showTypingIndicator() {
|
||||
const container = document.getElementById('ai-messages');
|
||||
if (!container) return;
|
||||
|
||||
const indicator = document.createElement('div');
|
||||
indicator.className = 'ai-message assistant';
|
||||
indicator.id = 'typing-indicator';
|
||||
indicator.innerHTML = `
|
||||
<div class="ai-typing-indicator">
|
||||
<span></span><span></span><span></span>
|
||||
</div>
|
||||
`;
|
||||
container.appendChild(indicator);
|
||||
container.scrollTop = container.scrollHeight;
|
||||
}
|
||||
|
||||
function hideTypingIndicator() {
|
||||
const indicator = document.getElementById('typing-indicator');
|
||||
if (indicator) indicator.remove();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// APP LAUNCHER
|
||||
// =============================================================================
|
||||
|
||||
function initAppLauncher() {
|
||||
document.querySelectorAll('.app-icon').forEach(icon => {
|
||||
icon.addEventListener('click', function() {
|
||||
const app = this.dataset.app;
|
||||
switchApp(app);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function switchApp(appName) {
|
||||
document.querySelectorAll('.app-icon').forEach(icon => {
|
||||
icon.classList.toggle('active', icon.dataset.app === appName);
|
||||
});
|
||||
state.currentApp = appName;
|
||||
|
||||
// Dispatch custom event for app switching
|
||||
document.dispatchEvent(new CustomEvent('app-switch', { detail: { app: appName } }));
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// NAVIGATION TABS
|
||||
// =============================================================================
|
||||
|
||||
function initTabs() {
|
||||
document.querySelectorAll('.topbar-tab').forEach(tab => {
|
||||
tab.addEventListener('click', function() {
|
||||
document.querySelectorAll('.topbar-tab').forEach(t => t.classList.remove('active'));
|
||||
this.classList.add('active');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// QUICK ACTIONS
|
||||
// =============================================================================
|
||||
|
||||
function initQuickActions() {
|
||||
document.querySelectorAll('.quick-action-btn').forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const action = this.textContent;
|
||||
addMessage('user', action);
|
||||
showTypingIndicator();
|
||||
|
||||
setTimeout(() => {
|
||||
hideTypingIndicator();
|
||||
addMessage('assistant', `Ação "${action}" executada com sucesso!`, 'Ver alterações');
|
||||
}, 1000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// KEYBOARD SHORTCUTS
|
||||
// =============================================================================
|
||||
|
||||
function initKeyboardShortcuts() {
|
||||
document.addEventListener('keydown', function(e) {
|
||||
// Enter to send message in AI input
|
||||
if (e.key === 'Enter' && document.activeElement.id === 'ai-input') {
|
||||
e.preventDefault();
|
||||
sendAIMessage();
|
||||
}
|
||||
|
||||
// Escape to close AI panel on mobile
|
||||
if (e.key === 'Escape' && window.innerWidth <= 1024) {
|
||||
const panel = document.getElementById('ai-panel');
|
||||
if (panel && panel.classList.contains('open')) {
|
||||
toggleAIPanel();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// INITIAL MESSAGES
|
||||
// =============================================================================
|
||||
|
||||
function loadInitialMessages() {
|
||||
addMessage('assistant', 'Olá! Sou o AI Developer. Como posso ajudar você hoje?');
|
||||
addMessage('assistant', 'Você pode me pedir para modificar campos, alterar cores, adicionar validações ou qualquer outra mudança no sistema.');
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// INITIALIZE
|
||||
// =============================================================================
|
||||
|
||||
function init() {
|
||||
initAppLauncher();
|
||||
initTabs();
|
||||
initQuickActions();
|
||||
initKeyboardShortcuts();
|
||||
loadInitialMessages();
|
||||
}
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -3,49 +3,19 @@
|
|||
<div class="docs-app" id="docs-app">
|
||||
<div class="docs-toolbar">
|
||||
<div class="toolbar-left">
|
||||
<input
|
||||
type="text"
|
||||
class="doc-name-input"
|
||||
id="docName"
|
||||
value="Untitled Document"
|
||||
spellcheck="false"
|
||||
/>
|
||||
<input type="text" class="doc-name-input" id="docName" value="Untitled Document" spellcheck="false" />
|
||||
</div>
|
||||
<div class="toolbar-center">
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="printPreviewBtn"
|
||||
title="Print Preview"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="printPreviewBtn" title="Print Preview">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="6 9 6 2 18 2 18 9"></polyline>
|
||||
<path
|
||||
d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
|
||||
></path>
|
||||
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
|
||||
<rect x="6" y="14" width="12" height="8"></rect>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="findReplaceBtn"
|
||||
title="Find & Replace (Ctrl+H)"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="findReplaceBtn" title="Find & Replace (Ctrl+H)">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
|
|
@ -54,42 +24,21 @@
|
|||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="undoBtn" title="Undo (Ctrl+Z)">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 7v6h6"></path>
|
||||
<path
|
||||
d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"
|
||||
></path>
|
||||
<path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="redoBtn" title="Redo (Ctrl+Y)">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 7v6h-6"></path>
|
||||
<path
|
||||
d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"
|
||||
></path>
|
||||
<path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<select
|
||||
class="toolbar-select heading-select"
|
||||
id="headingSelect"
|
||||
>
|
||||
<select class="toolbar-select heading-select" id="headingSelect">
|
||||
<option value="p">Normal</option>
|
||||
<option value="h1">Heading 1</option>
|
||||
<option value="h2">Heading 2</option>
|
||||
|
|
@ -120,11 +69,7 @@
|
|||
<button class="btn-icon" id="italicBtn" title="Italic (Ctrl+I)">
|
||||
<em>I</em>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="underlineBtn"
|
||||
title="Underline (Ctrl+U)"
|
||||
>
|
||||
<button class="btn-icon" id="underlineBtn" title="Underline (Ctrl+U)">
|
||||
<u>U</u>
|
||||
</button>
|
||||
<button class="btn-icon" id="strikeBtn" title="Strikethrough">
|
||||
|
|
@ -133,107 +78,45 @@
|
|||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon color-btn"
|
||||
id="textColorBtn"
|
||||
title="Text Color"
|
||||
>
|
||||
<button class="btn-icon color-btn" id="textColorBtn" title="Text Color">
|
||||
<span class="color-letter">A</span>
|
||||
<span
|
||||
class="color-indicator"
|
||||
id="textColorIndicator"
|
||||
></span>
|
||||
<input
|
||||
type="color"
|
||||
class="color-input"
|
||||
id="textColorInput"
|
||||
value="#000000"
|
||||
/>
|
||||
<span class="color-indicator" id="textColorIndicator"></span>
|
||||
<input type="color" class="color-input" id="textColorInput" value="#000000" />
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon color-btn"
|
||||
id="highlightBtn"
|
||||
title="Highlight"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<button class="btn-icon color-btn" id="highlightBtn" title="Highlight">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<path
|
||||
d="M15.243 4.515l-6.738 6.737-.707 2.121-1.04 1.041 2.828 2.828 1.04-1.04 2.122-.707 6.737-6.738-4.242-4.242zm6.364 3.536a1 1 0 0 1 0 1.414l-7.778 7.778-2.122.707-1.414 1.414a1 1 0 0 1-1.414 0l-4.243-4.243a1 1 0 0 1 0-1.414l1.414-1.414.707-2.121 7.778-7.778a1 1 0 0 1 1.414 0l5.657 5.657z"
|
||||
/>
|
||||
d="M15.243 4.515l-6.738 6.737-.707 2.121-1.04 1.041 2.828 2.828 1.04-1.04 2.122-.707 6.737-6.738-4.242-4.242zm6.364 3.536a1 1 0 0 1 0 1.414l-7.778 7.778-2.122.707-1.414 1.414a1 1 0 0 1-1.414 0l-4.243-4.243a1 1 0 0 1 0-1.414l1.414-1.414.707-2.121 7.778-7.778a1 1 0 0 1 1.414 0l5.657 5.657z" />
|
||||
</svg>
|
||||
<span
|
||||
class="color-indicator bg-indicator"
|
||||
id="highlightIndicator"
|
||||
></span>
|
||||
<input
|
||||
type="color"
|
||||
class="color-input"
|
||||
id="highlightInput"
|
||||
value="#ffff00"
|
||||
/>
|
||||
<span class="color-indicator bg-indicator" id="highlightIndicator"></span>
|
||||
<input type="color" class="color-input" id="highlightInput" value="#ffff00" />
|
||||
</button>
|
||||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="alignLeftBtn" title="Align Left">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="12" x2="15" y2="12"></line>
|
||||
<line x1="3" y1="18" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="alignCenterBtn"
|
||||
title="Align Center"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="alignCenterBtn" title="Align Center">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="6" y1="12" x2="18" y2="12"></line>
|
||||
<line x1="4" y1="18" x2="20" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="alignRightBtn" title="Align Right">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="9" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="6" y1="18" x2="21" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="justifyBtn" title="Justify">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="3" y1="18" x2="21" y2="18"></line>
|
||||
|
|
@ -243,110 +126,41 @@
|
|||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="bulletListBtn" title="Bullet List">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="9" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="9" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="9" y1="18" x2="21" y2="18"></line>
|
||||
<circle
|
||||
cx="4"
|
||||
cy="6"
|
||||
r="2"
|
||||
fill="currentColor"
|
||||
></circle>
|
||||
<circle
|
||||
cx="4"
|
||||
cy="12"
|
||||
r="2"
|
||||
fill="currentColor"
|
||||
></circle>
|
||||
<circle
|
||||
cx="4"
|
||||
cy="18"
|
||||
r="2"
|
||||
fill="currentColor"
|
||||
></circle>
|
||||
<circle cx="4" cy="6" r="2" fill="currentColor"></circle>
|
||||
<circle cx="4" cy="12" r="2" fill="currentColor"></circle>
|
||||
<circle cx="4" cy="18" r="2" fill="currentColor"></circle>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="numberListBtn"
|
||||
title="Numbered List"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="numberListBtn" title="Numbered List">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="10" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="10" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="10" y1="18" x2="21" y2="18"></line>
|
||||
<text
|
||||
x="2"
|
||||
y="8"
|
||||
font-size="8"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
>
|
||||
<text x="2" y="8" font-size="8" fill="currentColor" stroke="none">
|
||||
1
|
||||
</text>
|
||||
<text
|
||||
x="2"
|
||||
y="14"
|
||||
font-size="8"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
>
|
||||
<text x="2" y="14" font-size="8" fill="currentColor" stroke="none">
|
||||
2
|
||||
</text>
|
||||
<text
|
||||
x="2"
|
||||
y="20"
|
||||
font-size="8"
|
||||
fill="currentColor"
|
||||
stroke="none"
|
||||
>
|
||||
<text x="2" y="20" font-size="8" fill="currentColor" stroke="none">
|
||||
3
|
||||
</text>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="indentBtn" title="Increase Indent">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="9" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="9" y1="18" x2="21" y2="18"></line>
|
||||
<polyline points="3 10 6 12 3 14"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="outdentBtn"
|
||||
title="Decrease Indent"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="outdentBtn" title="Decrease Indent">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="9" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="9" y1="18" x2="21" y2="18"></line>
|
||||
|
|
@ -356,87 +170,33 @@
|
|||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="headerFooterBtn"
|
||||
title="Edit Header & Footer"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="headerFooterBtn" title="Edit Header & Footer">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"></rect>
|
||||
<line x1="3" y1="7" x2="21" y2="7"></line>
|
||||
<line x1="3" y1="17" x2="21" y2="17"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="pageBreakBtn"
|
||||
title="Insert Page Break"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="pageBreakBtn" title="Insert Page Break">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 12h4l3-9 4 18 3-9h4"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="linkBtn" title="Insert Link">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"
|
||||
></path>
|
||||
<path
|
||||
d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"
|
||||
></path>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"></path>
|
||||
<path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="imageBtn" title="Insert Image">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="18"
|
||||
height="18"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
||||
<polyline points="21 15 16 10 5 21"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="tableBtn" title="Insert Table">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"></rect>
|
||||
<line x1="3" y1="9" x2="21" y2="9"></line>
|
||||
<line x1="3" y1="15" x2="21" y2="15"></line>
|
||||
|
|
@ -449,14 +209,7 @@
|
|||
<div class="toolbar-right">
|
||||
<div class="collaborators" id="collaborators"></div>
|
||||
<button class="btn-primary" id="shareBtn">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="18" cy="5" r="3"></circle>
|
||||
<circle cx="6" cy="12" r="3"></circle>
|
||||
<circle cx="18" cy="19" r="3"></circle>
|
||||
|
|
@ -465,139 +218,19 @@
|
|||
</svg>
|
||||
<span>Share</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon chat-toggle"
|
||||
id="chatToggle"
|
||||
title="Toggle AI Chat"
|
||||
>
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="docs-main">
|
||||
<div class="docs-canvas">
|
||||
<div class="editor-page" id="editorPage">
|
||||
<div
|
||||
class="editor-content"
|
||||
id="editorContent"
|
||||
contenteditable="true"
|
||||
spellcheck="true"
|
||||
data-placeholder="Start typing..."
|
||||
></div>
|
||||
<div class="editor-content" id="editorContent" contenteditable="true" spellcheck="true"
|
||||
data-placeholder="Start typing..."></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="chat-panel" id="chatPanel">
|
||||
<div class="chat-header">
|
||||
<div class="chat-title">
|
||||
<div class="chat-avatar">
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z"
|
||||
/>
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
<path
|
||||
d="M12 15c-3 0-5 1.5-5 3v1h10v-1c0-1.5-2-3-5-3z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3>AI Assistant</h3>
|
||||
<span class="chat-status">Ready to help</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="chat-close" id="chatClose" title="Close">
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="chat-messages" id="chatMessages">
|
||||
<div class="chat-message assistant">
|
||||
<div class="message-bubble">
|
||||
<p>
|
||||
Hi! I can help you edit your document. Try asking me
|
||||
to:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Make text shorter or longer</li>
|
||||
<li>Fix grammar and spelling</li>
|
||||
<li>Translate to another language</li>
|
||||
<li>Change the tone (formal/casual)</li>
|
||||
<li>Add a summary</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-suggestions" id="chatSuggestions">
|
||||
<button class="suggestion-btn" data-action="shorter">
|
||||
Make shorter
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="grammar">
|
||||
Fix grammar
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="formal">
|
||||
Make formal
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="summarize">
|
||||
Summarize
|
||||
</button>
|
||||
</div>
|
||||
<form class="chat-input-container" id="chatForm">
|
||||
<input
|
||||
type="text"
|
||||
class="chat-input"
|
||||
id="chatInput"
|
||||
placeholder="Ask me to edit your document..."
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
class="chat-send"
|
||||
id="chatSend"
|
||||
title="Send"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<line x1="22" y1="2" x2="11" y2="13"></line>
|
||||
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="docs-status-bar">
|
||||
|
|
@ -628,11 +261,7 @@
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="share-input-group">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Enter email address"
|
||||
id="shareEmail"
|
||||
/>
|
||||
<input type="email" placeholder="Enter email address" id="shareEmail" />
|
||||
<select id="sharePermission">
|
||||
<option value="view">Can view</option>
|
||||
<option value="comment">Can comment</option>
|
||||
|
|
@ -645,24 +274,10 @@
|
|||
<div class="share-link-group">
|
||||
<input type="text" readonly id="shareLink" />
|
||||
<button class="btn-icon" id="copyLinkBtn" title="Copy link">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect
|
||||
x="9"
|
||||
y="9"
|
||||
width="13"
|
||||
height="13"
|
||||
rx="2"
|
||||
></rect>
|
||||
<path
|
||||
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
||||
></path>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -680,11 +295,7 @@
|
|||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>URL</label>
|
||||
<input
|
||||
type="url"
|
||||
id="linkUrl"
|
||||
placeholder="https://example.com"
|
||||
/>
|
||||
<input type="url" id="linkUrl" placeholder="https://example.com" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Text (optional)</label>
|
||||
|
|
@ -707,19 +318,11 @@
|
|||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Image URL</label>
|
||||
<input
|
||||
type="url"
|
||||
id="imageUrl"
|
||||
placeholder="https://example.com/image.jpg"
|
||||
/>
|
||||
<input type="url" id="imageUrl" placeholder="https://example.com/image.jpg" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Alt text</label>
|
||||
<input
|
||||
type="text"
|
||||
id="imageAlt"
|
||||
placeholder="Image description"
|
||||
/>
|
||||
<input type="text" id="imageAlt" placeholder="Image description" />
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-secondary" id="cancelImageBtn">
|
||||
|
|
@ -742,23 +345,11 @@
|
|||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label>Rows</label>
|
||||
<input
|
||||
type="number"
|
||||
id="tableRows"
|
||||
value="3"
|
||||
min="1"
|
||||
max="20"
|
||||
/>
|
||||
<input type="number" id="tableRows" value="3" min="1" max="20" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Columns</label>
|
||||
<input
|
||||
type="number"
|
||||
id="tableCols"
|
||||
value="3"
|
||||
min="1"
|
||||
max="10"
|
||||
/>
|
||||
<input type="number" id="tableCols" value="3" min="1" max="10" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -782,19 +373,9 @@
|
|||
<div class="export-options">
|
||||
<button class="export-option" data-format="pdf">
|
||||
<div class="export-icon">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||||
/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<path d="M9 15v-2h1.5a1.5 1.5 0 0 1 0 3H9" />
|
||||
<path d="M13 13h1.5a1.5 1.5 0 0 1 0 3H13v-3z" />
|
||||
|
|
@ -804,19 +385,9 @@
|
|||
</button>
|
||||
<button class="export-option" data-format="docx">
|
||||
<div class="export-icon">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||||
/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<line x1="8" y1="13" x2="16" y2="13" />
|
||||
<line x1="8" y1="17" x2="14" y2="17" />
|
||||
|
|
@ -826,40 +397,21 @@
|
|||
</button>
|
||||
<button class="export-option" data-format="html">
|
||||
<div class="export-icon">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<circle cx="12" cy="12" r="10" />
|
||||
<line x1="2" y1="12" x2="22" y2="12" />
|
||||
<path
|
||||
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z"
|
||||
/>
|
||||
d="M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="export-label">HTML</div>
|
||||
</button>
|
||||
<button class="export-option" data-format="txt">
|
||||
<div class="export-icon">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||||
/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
</svg>
|
||||
</div>
|
||||
|
|
@ -867,19 +419,9 @@
|
|||
</button>
|
||||
<button class="export-option" data-format="md">
|
||||
<div class="export-icon">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path
|
||||
d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"
|
||||
/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
<path d="M7 15l2-2 2 2" />
|
||||
<line x1="9" y1="13" x2="9" y2="17" />
|
||||
|
|
@ -903,20 +445,11 @@
|
|||
<div class="modal-body">
|
||||
<div class="find-replace-group">
|
||||
<label>Find:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="findInput"
|
||||
placeholder="Search text..."
|
||||
autofocus
|
||||
/>
|
||||
<input type="text" id="findInput" placeholder="Search text..." autofocus />
|
||||
</div>
|
||||
<div class="find-replace-group">
|
||||
<label>Replace:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="replaceInput"
|
||||
placeholder="Replace with..."
|
||||
/>
|
||||
<input type="text" id="replaceInput" placeholder="Replace with..." />
|
||||
</div>
|
||||
<div class="find-replace-options">
|
||||
<label class="checkbox-label">
|
||||
|
|
@ -976,18 +509,9 @@
|
|||
<div class="modal-actions">
|
||||
<button class="btn-secondary" id="cancelPrintBtn">Cancel</button>
|
||||
<button class="btn-primary" id="printBtn">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="6 9 6 2 18 2 18 9"></polyline>
|
||||
<path
|
||||
d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
|
||||
></path>
|
||||
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
|
||||
<rect x="6" y="14" width="12" height="8"></rect>
|
||||
</svg>
|
||||
Print
|
||||
|
|
@ -1010,12 +534,8 @@
|
|||
<div class="hf-tab-content active" id="hfHeaderTab">
|
||||
<div class="form-group">
|
||||
<label>Header Content:</label>
|
||||
<div
|
||||
class="hf-editor"
|
||||
id="headerEditor"
|
||||
contenteditable="true"
|
||||
data-placeholder="Enter header text..."
|
||||
></div>
|
||||
<div class="hf-editor" id="headerEditor" contenteditable="true"
|
||||
data-placeholder="Enter header text..."></div>
|
||||
</div>
|
||||
<div class="hf-options">
|
||||
<label class="checkbox-label">
|
||||
|
|
@ -1036,10 +556,7 @@
|
|||
<button class="btn-secondary btn-sm" id="insertDate">
|
||||
Date
|
||||
</button>
|
||||
<button
|
||||
class="btn-secondary btn-sm"
|
||||
id="insertDocTitle"
|
||||
>
|
||||
<button class="btn-secondary btn-sm" id="insertDocTitle">
|
||||
Document Title
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -1048,12 +565,8 @@
|
|||
<div class="hf-tab-content" id="hfFooterTab">
|
||||
<div class="form-group">
|
||||
<label>Footer Content:</label>
|
||||
<div
|
||||
class="hf-editor"
|
||||
id="footerEditor"
|
||||
contenteditable="true"
|
||||
data-placeholder="Enter footer text..."
|
||||
></div>
|
||||
<div class="hf-editor" id="footerEditor" contenteditable="true"
|
||||
data-placeholder="Enter footer text..."></div>
|
||||
</div>
|
||||
<div class="hf-options">
|
||||
<label class="checkbox-label">
|
||||
|
|
@ -1068,22 +581,13 @@
|
|||
<div class="hf-insert-options">
|
||||
<label>Insert:</label>
|
||||
<div class="hf-insert-btns">
|
||||
<button
|
||||
class="btn-secondary btn-sm"
|
||||
id="insertFooterPageNum"
|
||||
>
|
||||
<button class="btn-secondary btn-sm" id="insertFooterPageNum">
|
||||
Page Number
|
||||
</button>
|
||||
<button
|
||||
class="btn-secondary btn-sm"
|
||||
id="insertFooterDate"
|
||||
>
|
||||
<button class="btn-secondary btn-sm" id="insertFooterDate">
|
||||
Date
|
||||
</button>
|
||||
<button
|
||||
class="btn-secondary btn-sm"
|
||||
id="insertFooterDocTitle"
|
||||
>
|
||||
<button class="btn-secondary btn-sm" id="insertFooterDocTitle">
|
||||
Document Title
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
autoSaveTimer: null,
|
||||
ws: null,
|
||||
collaborators: [],
|
||||
chatPanelOpen: true,
|
||||
|
||||
driveSource: null,
|
||||
zoom: 100,
|
||||
findMatches: [],
|
||||
|
|
@ -47,10 +47,7 @@
|
|||
elements.charCount = document.getElementById("charCount");
|
||||
elements.saveStatus = document.getElementById("saveStatus");
|
||||
elements.zoomLevel = document.getElementById("zoomLevel");
|
||||
elements.chatPanel = document.getElementById("chatPanel");
|
||||
elements.chatMessages = document.getElementById("chatMessages");
|
||||
elements.chatInput = document.getElementById("chatInput");
|
||||
elements.chatForm = document.getElementById("chatForm");
|
||||
|
||||
elements.shareModal = document.getElementById("shareModal");
|
||||
elements.linkModal = document.getElementById("linkModal");
|
||||
elements.imageModal = document.getElementById("imageModal");
|
||||
|
|
@ -161,19 +158,7 @@
|
|||
document.getElementById("zoomInBtn")?.addEventListener("click", zoomIn);
|
||||
document.getElementById("zoomOutBtn")?.addEventListener("click", zoomOut);
|
||||
|
||||
document
|
||||
.getElementById("chatToggle")
|
||||
?.addEventListener("click", toggleChatPanel);
|
||||
document
|
||||
.getElementById("chatClose")
|
||||
?.addEventListener("click", toggleChatPanel);
|
||||
elements.chatForm?.addEventListener("submit", handleChatSubmit);
|
||||
|
||||
document.querySelectorAll(".suggestion-btn").forEach((btn) => {
|
||||
btn.addEventListener("click", () =>
|
||||
handleSuggestionClick(btn.dataset.action),
|
||||
);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".btn-close, .modal").forEach((el) => {
|
||||
el.addEventListener("click", (e) => {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,44 @@
|
|||
// Simple initialization for HTMX app
|
||||
// Note: Chat module is self-contained in chat.html
|
||||
// ==========================================
|
||||
// SUITE CORE (Plugin Architecture)
|
||||
// ==========================================
|
||||
window.Suite = {
|
||||
apps: new Map(),
|
||||
|
||||
registerApp(id, config) {
|
||||
console.log(`[Suite] Registering app: ${id}`);
|
||||
this.apps.set(id, {
|
||||
id,
|
||||
icon: "📦",
|
||||
title: id,
|
||||
description: "",
|
||||
actions: [],
|
||||
searchable: true,
|
||||
...config
|
||||
});
|
||||
|
||||
// Trigger UI update if Omnibox is initialized
|
||||
if (typeof Omnibox !== 'undefined' && Omnibox.isActive) {
|
||||
Omnibox.updateActions();
|
||||
}
|
||||
},
|
||||
|
||||
getApp(id) {
|
||||
return this.apps.get(id);
|
||||
},
|
||||
|
||||
getAllApps() {
|
||||
return Array.from(this.apps.values());
|
||||
},
|
||||
|
||||
// Helper to get actions for a specific context
|
||||
getContextActions(contextId) {
|
||||
const app = this.apps.get(contextId);
|
||||
return app ? app.actions : null;
|
||||
}
|
||||
};
|
||||
|
||||
// ==========================================
|
||||
// OMNIBOX (Search + Chat) Functionality
|
||||
// ==========================================
|
||||
|
|
@ -214,6 +253,46 @@
|
|||
target: "calendar",
|
||||
},
|
||||
],
|
||||
sheet: [
|
||||
{
|
||||
icon: "📊",
|
||||
text: "Analyze data",
|
||||
action: "chat",
|
||||
query: "Analyze this data",
|
||||
},
|
||||
{
|
||||
icon: "📈",
|
||||
text: "Create chart",
|
||||
action: "chat",
|
||||
query: "Create a chart for this data",
|
||||
},
|
||||
{
|
||||
icon: "💲",
|
||||
text: "Format currency",
|
||||
action: "chat",
|
||||
query: "Format as currency",
|
||||
},
|
||||
],
|
||||
paper: [
|
||||
{
|
||||
icon: "📝",
|
||||
text: "Summarize",
|
||||
action: "chat",
|
||||
query: "Summarize this document",
|
||||
},
|
||||
{
|
||||
icon: "✨",
|
||||
text: "Fix grammar",
|
||||
action: "chat",
|
||||
query: "Fix grammar and spelling",
|
||||
},
|
||||
{
|
||||
icon: "👔",
|
||||
text: "Make formal",
|
||||
action: "chat",
|
||||
query: "Make the tone more formal",
|
||||
},
|
||||
],
|
||||
default: [
|
||||
{
|
||||
icon: "💬",
|
||||
|
|
@ -228,8 +307,15 @@
|
|||
],
|
||||
};
|
||||
|
||||
const actions =
|
||||
contextActions[currentApp] || contextActions.default;
|
||||
// Check for plugin actions first
|
||||
const pluginActions = window.Suite.getContextActions(currentApp);
|
||||
|
||||
let actions;
|
||||
if (pluginActions && pluginActions.length > 0) {
|
||||
actions = pluginActions;
|
||||
} else {
|
||||
actions = contextActions[currentApp] || contextActions.default;
|
||||
}
|
||||
|
||||
// Add navigation shortcuts
|
||||
const navActions = [
|
||||
|
|
@ -495,9 +581,22 @@
|
|||
title: "Settings",
|
||||
description: "App settings",
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
return items.filter(
|
||||
// Add plugin apps
|
||||
const pluginApps = window.Suite.getAllApps()
|
||||
.filter(app => app.searchable)
|
||||
.map(app => ({
|
||||
target: app.id,
|
||||
icon: app.icon || "📦",
|
||||
title: app.title || app.id,
|
||||
description: app.description || "App plugin"
|
||||
}));
|
||||
|
||||
const allItems = items.concat(pluginApps);
|
||||
|
||||
return allItems.filter(
|
||||
(item) =>
|
||||
item.title.toLowerCase().includes(q) ||
|
||||
item.description.toLowerCase().includes(q),
|
||||
|
|
|
|||
|
|
@ -3,82 +3,35 @@
|
|||
<div class="sheet-app" id="sheet-app">
|
||||
<div class="sheet-toolbar">
|
||||
<div class="toolbar-left">
|
||||
<input
|
||||
type="text"
|
||||
class="sheet-name-input"
|
||||
id="sheetName"
|
||||
value="Untitled Spreadsheet"
|
||||
spellcheck="false"
|
||||
/>
|
||||
<input type="text" class="sheet-name-input" id="sheetName" value="Untitled Spreadsheet"
|
||||
spellcheck="false" />
|
||||
</div>
|
||||
<div class="toolbar-center">
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="undoBtn" title="Undo (Ctrl+Z)">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M3 7v6h6"></path>
|
||||
<path
|
||||
d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"
|
||||
></path>
|
||||
<path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="redoBtn" title="Redo (Ctrl+Y)">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M21 7v6h-6"></path>
|
||||
<path
|
||||
d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"
|
||||
></path>
|
||||
<path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="printPreviewBtn"
|
||||
title="Print Preview"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="printPreviewBtn" title="Print Preview">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="6 9 6 2 18 2 18 9"></polyline>
|
||||
<path
|
||||
d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
|
||||
></path>
|
||||
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
|
||||
<rect x="6" y="14" width="12" height="8"></rect>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="findReplaceBtn"
|
||||
title="Find & Replace (Ctrl+H)"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="findReplaceBtn" title="Find & Replace (Ctrl+H)">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="11" cy="11" r="8"></circle>
|
||||
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
|
||||
</svg>
|
||||
|
|
@ -86,11 +39,7 @@
|
|||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<select
|
||||
class="toolbar-select font-family"
|
||||
id="fontFamily"
|
||||
title="Font"
|
||||
>
|
||||
<select class="toolbar-select font-family" id="fontFamily" title="Font">
|
||||
<option value="Arial">Arial</option>
|
||||
<option value="Helvetica">Helvetica</option>
|
||||
<option value="Times New Roman">Times</option>
|
||||
|
|
@ -98,11 +47,7 @@
|
|||
<option value="Georgia">Georgia</option>
|
||||
<option value="Verdana">Verdana</option>
|
||||
</select>
|
||||
<select
|
||||
class="toolbar-select font-size"
|
||||
id="fontSize"
|
||||
title="Size"
|
||||
>
|
||||
<select class="toolbar-select font-size" id="fontSize" title="Size">
|
||||
<option value="8">8</option>
|
||||
<option value="9">9</option>
|
||||
<option value="10">10</option>
|
||||
|
|
@ -123,11 +68,7 @@
|
|||
<button class="btn-icon" id="italicBtn" title="Italic (Ctrl+I)">
|
||||
<em>I</em>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="underlineBtn"
|
||||
title="Underline (Ctrl+U)"
|
||||
>
|
||||
<button class="btn-icon" id="underlineBtn" title="Underline (Ctrl+U)">
|
||||
<u>U</u>
|
||||
</button>
|
||||
<button class="btn-icon" id="strikeBtn" title="Strikethrough">
|
||||
|
|
@ -136,100 +77,38 @@
|
|||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon color-btn"
|
||||
id="textColorBtn"
|
||||
title="Text Color"
|
||||
>
|
||||
<button class="btn-icon color-btn" id="textColorBtn" title="Text Color">
|
||||
<span class="color-letter">A</span>
|
||||
<span
|
||||
class="color-indicator"
|
||||
id="textColorIndicator"
|
||||
></span>
|
||||
<input
|
||||
type="color"
|
||||
class="color-input"
|
||||
id="textColorInput"
|
||||
value="#000000"
|
||||
/>
|
||||
<span class="color-indicator" id="textColorIndicator"></span>
|
||||
<input type="color" class="color-input" id="textColorInput" value="#000000" />
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon color-btn"
|
||||
id="bgColorBtn"
|
||||
title="Fill Color"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="18"
|
||||
height="18"
|
||||
rx="2"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
/>
|
||||
<button class="btn-icon color-btn" id="bgColorBtn" title="Fill Color">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" fill="none" stroke="currentColor"
|
||||
stroke-width="2" />
|
||||
</svg>
|
||||
<span
|
||||
class="color-indicator bg-indicator"
|
||||
id="bgColorIndicator"
|
||||
></span>
|
||||
<input
|
||||
type="color"
|
||||
class="color-input"
|
||||
id="bgColorInput"
|
||||
value="#ffffff"
|
||||
/>
|
||||
<span class="color-indicator bg-indicator" id="bgColorIndicator"></span>
|
||||
<input type="color" class="color-input" id="bgColorInput" value="#ffffff" />
|
||||
</button>
|
||||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="alignLeftBtn" title="Align Left">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="3" y1="12" x2="15" y2="12"></line>
|
||||
<line x1="3" y1="18" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="alignCenterBtn"
|
||||
title="Align Center"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="alignCenterBtn" title="Align Center">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="6" y1="12" x2="18" y2="12"></line>
|
||||
<line x1="4" y1="18" x2="20" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="alignRightBtn" title="Align Right">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="3" y1="6" x2="21" y2="6"></line>
|
||||
<line x1="9" y1="12" x2="21" y2="12"></line>
|
||||
<line x1="6" y1="18" x2="21" y2="18"></line>
|
||||
|
|
@ -238,11 +117,7 @@
|
|||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<select
|
||||
class="toolbar-select number-format"
|
||||
id="numberFormat"
|
||||
title="Number Format"
|
||||
>
|
||||
<select class="toolbar-select number-format" id="numberFormat" title="Number Format">
|
||||
<option value="general">General</option>
|
||||
<option value="number">Number (1,234.56)</option>
|
||||
<option value="currency">Currency ($1,234.56)</option>
|
||||
|
|
@ -257,38 +132,16 @@
|
|||
<option value="text">Text</option>
|
||||
<option value="custom">Custom...</option>
|
||||
</select>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="decreaseDecimalBtn"
|
||||
title="Decrease Decimal"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="decreaseDecimalBtn" title="Decrease Decimal">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<text x="2" y="16" font-size="10" fill="currentColor">
|
||||
.0
|
||||
</text>
|
||||
<path d="M18 8l-4 4 4 4"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="increaseDecimalBtn"
|
||||
title="Increase Decimal"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="increaseDecimalBtn" title="Increase Decimal">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<text x="2" y="16" font-size="10" fill="currentColor">
|
||||
.00
|
||||
</text>
|
||||
|
|
@ -299,165 +152,56 @@
|
|||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button class="btn-icon" id="mergeCellsBtn" title="Merge Cells">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2"></rect>
|
||||
<line x1="12" y1="3" x2="12" y2="21"></line>
|
||||
<path
|
||||
d="M9 12h6M9 12l2-2M9 12l2 2M15 12l-2-2M15 12l-2 2"
|
||||
></path>
|
||||
<path d="M9 12h6M9 12l2-2M9 12l2 2M15 12l-2-2M15 12l-2 2"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="conditionalFormatBtn"
|
||||
title="Conditional Formatting"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="7"
|
||||
height="7"
|
||||
fill="#4CAF50"
|
||||
></rect>
|
||||
<rect
|
||||
x="14"
|
||||
y="3"
|
||||
width="7"
|
||||
height="7"
|
||||
fill="#FFC107"
|
||||
></rect>
|
||||
<rect
|
||||
x="3"
|
||||
y="14"
|
||||
width="7"
|
||||
height="7"
|
||||
fill="#F44336"
|
||||
></rect>
|
||||
<rect
|
||||
x="14"
|
||||
y="14"
|
||||
width="7"
|
||||
height="7"
|
||||
fill="#2196F3"
|
||||
></rect>
|
||||
<button class="btn-icon" id="conditionalFormatBtn" title="Conditional Formatting">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="7" height="7" fill="#4CAF50"></rect>
|
||||
<rect x="14" y="3" width="7" height="7" fill="#FFC107"></rect>
|
||||
<rect x="3" y="14" width="7" height="7" fill="#F44336"></rect>
|
||||
<rect x="14" y="14" width="7" height="7" fill="#2196F3"></rect>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="dataValidationBtn"
|
||||
title="Data Validation"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="dataValidationBtn" title="Data Validation">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M9 11l3 3L22 4"></path>
|
||||
<path
|
||||
d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"
|
||||
></path>
|
||||
<path d="M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<span class="toolbar-divider"></span>
|
||||
<div class="toolbar-group">
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="insertChartBtn"
|
||||
title="Insert Chart"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-icon" id="insertChartBtn" title="Insert Chart">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="12" width="4" height="9"></rect>
|
||||
<rect x="10" y="6" width="4" height="15"></rect>
|
||||
<rect x="17" y="3" width="4" height="18"></rect>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon"
|
||||
id="insertImageBtn"
|
||||
title="Insert Image"
|
||||
>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="18"
|
||||
height="18"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
<button class="btn-icon" id="insertImageBtn" title="Insert Image">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
||||
<polyline points="21 15 16 10 5 21"></polyline>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="filterBtn" title="Filter">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<polygon
|
||||
points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"
|
||||
></polygon>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"></polygon>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="sortAscBtn" title="Sort A→Z">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M11 5h10M11 9h7M11 13h4"></path>
|
||||
<path d="M3 17l3 3 3-3M6 18V4"></path>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-icon" id="sortDescBtn" title="Sort Z→A">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M11 5h4M11 9h7M11 13h10"></path>
|
||||
<path d="M3 7l3-3 3 3M6 6v12"></path>
|
||||
</svg>
|
||||
|
|
@ -467,14 +211,7 @@
|
|||
<div class="toolbar-right">
|
||||
<div class="collaborators" id="collaborators"></div>
|
||||
<button class="btn-primary" id="shareBtn">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="18" cy="5" r="3"></circle>
|
||||
<circle cx="6" cy="12" r="3"></circle>
|
||||
<circle cx="18" cy="19" r="3"></circle>
|
||||
|
|
@ -483,24 +220,7 @@
|
|||
</svg>
|
||||
<span>Share</span>
|
||||
</button>
|
||||
<button
|
||||
class="btn-icon chat-toggle"
|
||||
id="chatToggle"
|
||||
title="Toggle AI Chat"
|
||||
>
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -509,12 +229,7 @@
|
|||
<div class="formula-bar">
|
||||
<div class="cell-address" id="cellAddress">A1</div>
|
||||
<span class="formula-icon">fx</span>
|
||||
<input
|
||||
type="text"
|
||||
class="formula-input"
|
||||
id="formulaInput"
|
||||
placeholder="Enter value or formula..."
|
||||
/>
|
||||
<input type="text" class="formula-input" id="formulaInput" placeholder="Enter value or formula..." />
|
||||
</div>
|
||||
|
||||
<div class="sheet-grid-container" id="gridContainer">
|
||||
|
|
@ -527,18 +242,9 @@
|
|||
<div class="selection-box" id="selectionBox"></div>
|
||||
<div class="copy-box hidden" id="copyBox"></div>
|
||||
<div class="autofill-handle" id="autofillHandle"></div>
|
||||
<div
|
||||
class="cursor-indicators"
|
||||
id="cursorIndicators"
|
||||
></div>
|
||||
<div
|
||||
class="charts-container"
|
||||
id="chartsContainer"
|
||||
></div>
|
||||
<div
|
||||
class="images-container"
|
||||
id="imagesContainer"
|
||||
></div>
|
||||
<div class="cursor-indicators" id="cursorIndicators"></div>
|
||||
<div class="charts-container" id="chartsContainer"></div>
|
||||
<div class="images-container" id="imagesContainer"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -550,19 +256,8 @@
|
|||
<button class="tab-menu-btn">▼</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="btn-add-sheet"
|
||||
id="addSheetBtn"
|
||||
title="Add Sheet"
|
||||
>
|
||||
<svg
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<button class="btn-add-sheet" id="addSheetBtn" title="Add Sheet">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
|
|
@ -587,105 +282,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="chat-panel" id="chatPanel">
|
||||
<div class="chat-header">
|
||||
<div class="chat-title">
|
||||
<div class="chat-avatar">
|
||||
<svg
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<path
|
||||
d="M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z"
|
||||
/>
|
||||
<circle cx="12" cy="10" r="3" />
|
||||
<path
|
||||
d="M12 15c-3 0-5 1.5-5 3v1h10v-1c0-1.5-2-3-5-3z"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3>AI Assistant</h3>
|
||||
<span class="chat-status">Ready to help</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="chat-close" id="chatClose" title="Close">
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<line x1="18" y1="6" x2="6" y2="18"></line>
|
||||
<line x1="6" y1="6" x2="18" y2="18"></line>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="chat-messages" id="chatMessages">
|
||||
<div class="chat-message assistant">
|
||||
<div class="message-bubble">
|
||||
<p>
|
||||
Hi! I can help you edit your spreadsheet. Try asking
|
||||
me to:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Sum a column or range</li>
|
||||
<li>Format cells as currency</li>
|
||||
<li>Create a chart</li>
|
||||
<li>Sort or filter data</li>
|
||||
<li>Apply conditional formatting</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-suggestions" id="chatSuggestions">
|
||||
<button class="suggestion-btn" data-action="sum">
|
||||
Sum column B
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="format">
|
||||
Format as $
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="chart">
|
||||
Create chart
|
||||
</button>
|
||||
<button class="suggestion-btn" data-action="sort">
|
||||
Sort A-Z
|
||||
</button>
|
||||
</div>
|
||||
<form class="chat-input-container" id="chatForm">
|
||||
<input
|
||||
type="text"
|
||||
class="chat-input"
|
||||
id="chatInput"
|
||||
placeholder="Ask me to edit your spreadsheet..."
|
||||
autocomplete="off"
|
||||
/>
|
||||
<button
|
||||
type="submit"
|
||||
class="chat-send"
|
||||
id="chatSend"
|
||||
title="Send"
|
||||
>
|
||||
<svg
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<line x1="22" y1="2" x2="11" y2="13"></line>
|
||||
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
|
||||
</svg>
|
||||
</button>
|
||||
</form>
|
||||
</aside>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -730,11 +327,7 @@
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="share-input-group">
|
||||
<input
|
||||
type="email"
|
||||
placeholder="Enter email address"
|
||||
id="shareEmail"
|
||||
/>
|
||||
<input type="email" placeholder="Enter email address" id="shareEmail" />
|
||||
<select id="sharePermission">
|
||||
<option value="view">Can view</option>
|
||||
<option value="edit">Can edit</option>
|
||||
|
|
@ -746,25 +339,10 @@
|
|||
<div class="share-link-group">
|
||||
<input type="text" readonly id="shareLink" />
|
||||
<button class="btn-icon" id="copyLinkBtn" title="Copy link">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<rect
|
||||
x="9"
|
||||
y="9"
|
||||
width="13"
|
||||
height="13"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
<path
|
||||
d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"
|
||||
></path>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2">
|
||||
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
|
||||
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
|
@ -782,12 +360,7 @@
|
|||
<div class="modal-body">
|
||||
<div class="chart-type-selector">
|
||||
<button class="chart-type-btn active" data-type="bar">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="currentColor">
|
||||
<rect x="3" y="12" width="4" height="9"></rect>
|
||||
<rect x="10" y="6" width="4" height="15"></rect>
|
||||
<rect x="17" y="3" width="4" height="18"></rect>
|
||||
|
|
@ -795,27 +368,13 @@
|
|||
<span>Bar</span>
|
||||
</button>
|
||||
<button class="chart-type-btn" data-type="line">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="3 18 9 12 13 16 21 6"></polyline>
|
||||
</svg>
|
||||
<span>Line</span>
|
||||
</button>
|
||||
<button class="chart-type-btn" data-type="pie">
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<circle cx="12" cy="12" r="10"></circle>
|
||||
<path d="M12 2v10l8.5 5"></path>
|
||||
</svg>
|
||||
|
|
@ -824,17 +383,9 @@
|
|||
</div>
|
||||
<div class="chart-options">
|
||||
<label>Data Range</label>
|
||||
<input
|
||||
type="text"
|
||||
id="chartDataRange"
|
||||
placeholder="e.g., A1:B10"
|
||||
/>
|
||||
<input type="text" id="chartDataRange" placeholder="e.g., A1:B10" />
|
||||
<label>Chart Title</label>
|
||||
<input
|
||||
type="text"
|
||||
id="chartTitle"
|
||||
placeholder="Enter chart title"
|
||||
/>
|
||||
<input type="text" id="chartTitle" placeholder="Enter chart title" />
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="btn-secondary" id="cancelChartBtn">
|
||||
|
|
@ -857,20 +408,11 @@
|
|||
<div class="modal-body">
|
||||
<div class="find-replace-group">
|
||||
<label>Find:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="findInput"
|
||||
placeholder="Search text..."
|
||||
autofocus
|
||||
/>
|
||||
<input type="text" id="findInput" placeholder="Search text..." autofocus />
|
||||
</div>
|
||||
<div class="find-replace-group">
|
||||
<label>Replace:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="replaceInput"
|
||||
placeholder="Replace with..."
|
||||
/>
|
||||
<input type="text" id="replaceInput" placeholder="Replace with..." />
|
||||
</div>
|
||||
<div class="find-replace-options">
|
||||
<label class="checkbox-label">
|
||||
|
|
@ -939,12 +481,7 @@
|
|||
</div>
|
||||
<div class="cf-section cf-values" id="cfValuesSection">
|
||||
<input type="text" id="cfValue1" placeholder="Value" />
|
||||
<input
|
||||
type="text"
|
||||
id="cfValue2"
|
||||
placeholder="and"
|
||||
class="hidden"
|
||||
/>
|
||||
<input type="text" id="cfValue2" placeholder="and" class="hidden" />
|
||||
</div>
|
||||
<div class="cf-section">
|
||||
<label>Formatting style:</label>
|
||||
|
|
@ -996,11 +533,7 @@
|
|||
<div class="dv-tab-content active" id="dvSettingsTab">
|
||||
<div class="dv-section">
|
||||
<label>Apply to range:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="dvRange"
|
||||
placeholder="e.g., A1:A100"
|
||||
/>
|
||||
<input type="text" id="dvRange" placeholder="e.g., A1:A100" />
|
||||
</div>
|
||||
<div class="dv-section">
|
||||
<label>Allow:</label>
|
||||
|
|
@ -1044,10 +577,7 @@
|
|||
</div>
|
||||
<div class="dv-section dv-list hidden" id="dvListSection">
|
||||
<label>Source (comma-separated):</label>
|
||||
<textarea
|
||||
id="dvListSource"
|
||||
placeholder="Option 1, Option 2, Option 3"
|
||||
></textarea>
|
||||
<textarea id="dvListSource" placeholder="Option 1, Option 2, Option 3"></textarea>
|
||||
</div>
|
||||
<div class="dv-section">
|
||||
<label class="checkbox-label">
|
||||
|
|
@ -1069,18 +599,11 @@
|
|||
</div>
|
||||
<div class="dv-section">
|
||||
<label>Title:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="dvInputTitle"
|
||||
placeholder="Input title"
|
||||
/>
|
||||
<input type="text" id="dvInputTitle" placeholder="Input title" />
|
||||
</div>
|
||||
<div class="dv-section">
|
||||
<label>Input message:</label>
|
||||
<textarea
|
||||
id="dvInputMessage"
|
||||
placeholder="Enter instructions for the user"
|
||||
></textarea>
|
||||
<textarea id="dvInputMessage" placeholder="Enter instructions for the user"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dv-tab-content" id="dvErrorTab">
|
||||
|
|
@ -1100,18 +623,11 @@
|
|||
</div>
|
||||
<div class="dv-section">
|
||||
<label>Title:</label>
|
||||
<input
|
||||
type="text"
|
||||
id="dvErrorTitle"
|
||||
placeholder="Error title"
|
||||
/>
|
||||
<input type="text" id="dvErrorTitle" placeholder="Error title" />
|
||||
</div>
|
||||
<div class="dv-section">
|
||||
<label>Error message:</label>
|
||||
<textarea
|
||||
id="dvErrorMessage"
|
||||
placeholder="Enter error message"
|
||||
></textarea>
|
||||
<textarea id="dvErrorMessage" placeholder="Enter error message"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
|
|
@ -1166,18 +682,9 @@
|
|||
<div class="modal-actions">
|
||||
<button class="btn-secondary" id="cancelPrintBtn">Cancel</button>
|
||||
<button class="btn-primary" id="printBtn">
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="6 9 6 2 18 2 18 9"></polyline>
|
||||
<path
|
||||
d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"
|
||||
></path>
|
||||
<path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
|
||||
<rect x="6" y="14" width="12" height="8"></rect>
|
||||
</svg>
|
||||
Print
|
||||
|
|
@ -1274,22 +781,8 @@
|
|||
<input type="file" id="imgFile" accept="image/*" />
|
||||
</div>
|
||||
<div class="img-drop-zone" id="imgDropZone">
|
||||
<svg
|
||||
width="48"
|
||||
height="48"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1"
|
||||
>
|
||||
<rect
|
||||
x="3"
|
||||
y="3"
|
||||
width="18"
|
||||
height="18"
|
||||
rx="2"
|
||||
ry="2"
|
||||
></rect>
|
||||
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1">
|
||||
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
|
||||
<circle cx="8.5" cy="8.5" r="1.5"></circle>
|
||||
<polyline points="21 15 16 10 5 21"></polyline>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
isSelecting: false,
|
||||
isDirty: false,
|
||||
autoSaveTimer: null,
|
||||
chatPanelOpen: true,
|
||||
|
||||
findMatches: [],
|
||||
findMatchIndex: -1,
|
||||
decimalPlaces: 2,
|
||||
|
|
@ -50,7 +50,7 @@
|
|||
bindEvents();
|
||||
loadFromUrlParams();
|
||||
connectWebSocket();
|
||||
connectChatWebSocket();
|
||||
|
||||
selectCell(0, 0);
|
||||
updateCellAddress();
|
||||
renderCharts();
|
||||
|
|
@ -77,10 +77,7 @@
|
|||
elements.calculationResult = document.getElementById("calculationResult");
|
||||
elements.saveStatus = document.getElementById("saveStatus");
|
||||
elements.zoomLevel = document.getElementById("zoomLevel");
|
||||
elements.chatPanel = document.getElementById("chatPanel");
|
||||
elements.chatMessages = document.getElementById("chatMessages");
|
||||
elements.chatInput = document.getElementById("chatInput");
|
||||
elements.chatForm = document.getElementById("chatForm");
|
||||
|
||||
elements.findReplaceModal = document.getElementById("findReplaceModal");
|
||||
elements.conditionalFormatModal = document.getElementById(
|
||||
"conditionalFormatModal",
|
||||
|
|
@ -453,19 +450,7 @@
|
|||
.getElementById("cnfFormatCode")
|
||||
?.addEventListener("input", updateCnfPreview);
|
||||
|
||||
document
|
||||
.getElementById("chatToggle")
|
||||
?.addEventListener("click", toggleChatPanel);
|
||||
document
|
||||
.getElementById("chatClose")
|
||||
?.addEventListener("click", toggleChatPanel);
|
||||
elements.chatForm?.addEventListener("submit", handleChatSubmit);
|
||||
|
||||
document.querySelectorAll(".suggestion-btn").forEach((btn) => {
|
||||
btn.addEventListener("click", () =>
|
||||
handleSuggestionClick(btn.dataset.action),
|
||||
);
|
||||
});
|
||||
|
||||
document.querySelectorAll(".context-item").forEach((item) => {
|
||||
item.addEventListener("click", () =>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue