botui/ui/suite/slides/slides.html

1143 lines
50 KiB
HTML
Raw Normal View History

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>GB Slides</title>
<link rel="stylesheet" href="slides.css" />
</head>
<body>
<div class="slides-container">
<!-- Sidebar: Slide Thumbnails -->
<aside class="slides-sidebar" id="slides-sidebar">
<div class="sidebar-header">
<h2>Slides</h2>
<button
class="btn-icon"
onclick="toggleSidebar()"
title="Toggle Sidebar"
>
<svg
width="20"
height="20"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
</div>
<div class="sidebar-search">
<input
type="text"
placeholder="Search presentations..."
id="search-input"
oninput="searchPresentations(this.value)"
/>
<svg
class="search-icon"
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>
</div>
<div class="slide-thumbnails" id="slide-thumbnails">
<!-- Thumbnails rendered dynamically -->
</div>
<div class="sidebar-actions">
<button class="btn-add-slide" onclick="addSlide()">
<svg
width="16"
height="16"
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>
<span>Add Slide</span>
</button>
</div>
</aside>
<!-- Main Content Area -->
<main class="slides-main">
<!-- Toolbar -->
<div class="slides-toolbar">
<div class="toolbar-left">
<button
class="btn-icon"
onclick="toggleSidebar()"
title="Toggle Sidebar"
>
<svg
width="20"
height="20"
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>
<line x1="9" y1="3" x2="9" y2="21"></line>
</svg>
</button>
<input
type="text"
class="presentation-name-input"
id="presentation-name"
value="Untitled Presentation"
onchange="renamePresentation(this.value)"
/>
</div>
<div class="toolbar-center">
<!-- Insert Tools -->
<div class="toolbar-group">
<button
class="btn-icon"
onclick="addTextBox()"
title="Add Text"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<polyline
points="4 7 4 4 20 4 20 7"
></polyline>
<line x1="9" y1="20" x2="15" y2="20"></line>
<line x1="12" y1="4" x2="12" y2="20"></line>
</svg>
</button>
<button
class="btn-icon"
onclick="showImageModal()"
title="Add Image"
>
<svg
width="18"
height="18"
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"
onclick="showShapeModal()"
title="Add Shape"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect
x="3"
y="3"
width="18"
height="18"
rx="2"
></rect>
</svg>
</button>
<button
class="btn-icon"
onclick="showChartModal()"
title="Add Chart"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line
x1="18"
y1="20"
x2="18"
y2="10"
></line>
<line x1="12" y1="20" x2="12" y2="4"></line>
<line x1="6" y1="20" x2="6" y2="14"></line>
</svg>
</button>
<button
class="btn-icon"
onclick="addTable()"
title="Add Table"
>
<svg
width="18"
height="18"
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>
<line x1="9" y1="3" x2="9" y2="21"></line>
<line x1="15" y1="3" x2="15" y2="21"></line>
</svg>
</button>
</div>
<span class="toolbar-divider"></span>
<!-- Text Formatting -->
<div class="toolbar-group">
<select
class="toolbar-select font-family"
id="font-family"
onchange="setFontFamily(this.value)"
>
<option value="Inter">Inter</option>
<option value="Arial">Arial</option>
<option value="Helvetica">Helvetica</option>
<option value="Georgia">Georgia</option>
<option value="Times New Roman">
Times New Roman
</option>
<option value="Courier New">Courier New</option>
</select>
<select
class="toolbar-select font-size"
id="font-size"
onchange="setFontSize(this.value)"
>
<option value="12">12</option>
<option value="14">14</option>
<option value="16">16</option>
<option value="18">18</option>
<option value="20">20</option>
<option value="24" selected>24</option>
<option value="28">28</option>
<option value="32">32</option>
<option value="36">36</option>
<option value="48">48</option>
<option value="64">64</option>
<option value="72">72</option>
</select>
</div>
<span class="toolbar-divider"></span>
<!-- Text Style -->
<div class="toolbar-group">
<button
class="btn-icon"
id="btn-bold"
onclick="toggleBold()"
title="Bold (Ctrl+B)"
>
<strong>B</strong>
</button>
<button
class="btn-icon"
id="btn-italic"
onclick="toggleItalic()"
title="Italic (Ctrl+I)"
>
<em>I</em>
</button>
<button
class="btn-icon"
id="btn-underline"
onclick="toggleUnderline()"
title="Underline (Ctrl+U)"
>
<u>U</u>
</button>
</div>
<span class="toolbar-divider"></span>
<!-- Colors -->
<div class="toolbar-group">
<div class="color-btn" title="Text Color">
<span style="font-weight: bold">A</span>
<span
class="color-indicator"
id="text-color-indicator"
style="background: #000000"
></span>
<input
type="color"
class="color-input"
id="text-color"
value="#000000"
onchange="setTextColor(this.value)"
/>
</div>
<div class="color-btn" 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"
></rect>
</svg>
<span
class="color-indicator"
id="fill-color-indicator"
style="background: #3b82f6"
></span>
<input
type="color"
class="color-input"
id="fill-color"
value="#3b82f6"
onchange="setFillColor(this.value)"
/>
</div>
<div class="color-btn" title="Stroke Color">
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="3"
>
<rect
x="3"
y="3"
width="18"
height="18"
rx="2"
></rect>
</svg>
<span
class="color-indicator"
id="stroke-color-indicator"
style="background: #1e293b"
></span>
<input
type="color"
class="color-input"
id="stroke-color"
value="#1e293b"
onchange="setStrokeColor(this.value)"
/>
</div>
</div>
<span class="toolbar-divider"></span>
<!-- Alignment -->
<div class="toolbar-group">
<button
class="btn-icon"
onclick="setTextAlign('left')"
title="Align Left"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="17" y1="10" x2="3" y2="10"></line>
<line x1="21" y1="6" x2="3" y2="6"></line>
<line x1="21" y1="14" x2="3" y2="14"></line>
<line x1="17" y1="18" x2="3" y2="18"></line>
</svg>
</button>
<button
class="btn-icon"
onclick="setTextAlign('center')"
title="Align Center"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="18" y1="10" x2="6" y2="10"></line>
<line x1="21" y1="6" x2="3" y2="6"></line>
<line x1="21" y1="14" x2="3" y2="14"></line>
<line x1="18" y1="18" x2="6" y2="18"></line>
</svg>
</button>
<button
class="btn-icon"
onclick="setTextAlign('right')"
title="Align Right"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<line x1="21" y1="10" x2="7" y2="10"></line>
<line x1="21" y1="6" x2="3" y2="6"></line>
<line x1="21" y1="14" x2="3" y2="14"></line>
<line x1="21" y1="18" x2="7" y2="18"></line>
</svg>
</button>
</div>
<span class="toolbar-divider"></span>
<!-- Layer Order -->
<div class="toolbar-group">
<button
class="btn-icon"
onclick="bringForward()"
title="Bring Forward"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect
x="8"
y="8"
width="13"
height="13"
rx="2"
></rect>
<rect
x="3"
y="3"
width="13"
height="13"
rx="2"
fill="currentColor"
opacity="0.3"
></rect>
</svg>
</button>
<button
class="btn-icon"
onclick="sendBackward()"
title="Send Backward"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<rect
x="3"
y="3"
width="13"
height="13"
rx="2"
></rect>
<rect
x="8"
y="8"
width="13"
height="13"
rx="2"
fill="currentColor"
opacity="0.3"
></rect>
</svg>
</button>
</div>
</div>
<div class="toolbar-right">
<div class="collaborators" id="collaborators"></div>
<button
class="btn-icon"
onclick="showThemeModal()"
title="Themes"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 2a10 10 0 0 1 0 20"></path>
<line x1="2" y1="12" x2="22" y2="12"></line>
</svg>
</button>
<button
class="btn-icon"
onclick="startPresentation()"
title="Present (F5)"
>
<svg
width="18"
height="18"
viewBox="0 0 24 24"
fill="currentColor"
>
<polygon points="5 3 19 12 5 21 5 3"></polygon>
</svg>
</button>
<button
class="btn-primary"
onclick="savePresentation()"
>
<svg
width="16"
height="16"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<path
d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"
></path>
<polyline
points="17 21 17 13 7 13 7 21"
></polyline>
<polyline points="7 3 7 8 15 8"></polyline>
</svg>
<span>Save</span>
</button>
</div>
</div>
<!-- Slide Canvas Area -->
<div class="slide-canvas-container" id="canvas-container">
<div class="slide-canvas" id="slide-canvas">
<!-- Elements rendered here -->
</div>
<!-- Selection handles (shown when element selected) -->
<div
class="selection-handles hidden"
id="selection-handles"
>
<div class="handle nw" data-handle="nw"></div>
<div class="handle n" data-handle="n"></div>
<div class="handle ne" data-handle="ne"></div>
<div class="handle w" data-handle="w"></div>
<div class="handle e" data-handle="e"></div>
<div class="handle sw" data-handle="sw"></div>
<div class="handle s" data-handle="s"></div>
<div class="handle se" data-handle="se"></div>
<div class="rotate-handle" data-handle="rotate"></div>
</div>
<!-- Cursor indicators for collaborators -->
<div class="cursor-indicators" id="cursor-indicators"></div>
</div>
<!-- Status Bar -->
<div class="slides-status-bar">
<div class="status-left">
<span
>Slide <span id="current-slide-num">1</span> of
<span id="total-slides">1</span></span
>
</div>
<div class="status-center">
<span id="save-status"></span>
</div>
<div class="status-right">
<span>Zoom:</span>
<div class="zoom-control">
<button class="btn-zoom" onclick="zoomOut()">
</button>
<span id="zoom-level">100</span>%
<button class="btn-zoom" onclick="zoomIn()">
+
</button>
</div>
</div>
</div>
</main>
<!-- Properties Panel -->
<aside class="slides-properties" id="properties-panel">
<div class="properties-header">
<h3>Properties</h3>
<button
class="btn-icon"
onclick="toggleProperties()"
title="Close"
>
<svg
width="16"
height="16"
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="properties-content" id="properties-content">
<div class="property-group">
<label>Position</label>
<div class="property-row">
<div class="property-input">
<span>X</span>
<input
type="number"
id="prop-x"
onchange="updateElementPosition('x', this.value)"
/>
</div>
<div class="property-input">
<span>Y</span>
<input
type="number"
id="prop-y"
onchange="updateElementPosition('y', this.value)"
/>
</div>
</div>
</div>
<div class="property-group">
<label>Size</label>
<div class="property-row">
<div class="property-input">
<span>W</span>
<input
type="number"
id="prop-width"
onchange="updateElementSize('width', this.value)"
/>
</div>
<div class="property-input">
<span>H</span>
<input
type="number"
id="prop-height"
onchange="updateElementSize('height', this.value)"
/>
</div>
</div>
</div>
<div class="property-group">
<label>Rotation</label>
<div class="property-row">
<input
type="range"
id="prop-rotation"
min="0"
max="360"
value="0"
oninput="updateElementRotation(this.value)"
/>
<span id="rotation-value"></span>
</div>
</div>
<div class="property-group">
<label>Opacity</label>
<div class="property-row">
<input
type="range"
id="prop-opacity"
min="0"
max="100"
value="100"
oninput="updateElementOpacity(this.value)"
/>
<span id="opacity-value">100%</span>
</div>
</div>
</div>
</aside>
</div>
<!-- Context Menu -->
<div class="context-menu hidden" id="context-menu">
<div class="context-item" onclick="cutElement()">
Cut <span class="shortcut">Ctrl+X</span>
</div>
<div class="context-item" onclick="copyElement()">
Copy <span class="shortcut">Ctrl+C</span>
</div>
<div class="context-item" onclick="pasteElement()">
Paste <span class="shortcut">Ctrl+V</span>
</div>
<div class="context-divider"></div>
<div class="context-item" onclick="duplicateElement()">
Duplicate <span class="shortcut">Ctrl+D</span>
</div>
<div class="context-item" onclick="deleteElement()">
Delete <span class="shortcut">Del</span>
</div>
<div class="context-divider"></div>
<div class="context-item" onclick="bringToFront()">
Bring to Front
</div>
<div class="context-item" onclick="sendToBack()">Send to Back</div>
<div class="context-divider"></div>
<div class="context-item" onclick="lockElement()">Lock/Unlock</div>
</div>
<!-- Slide Context Menu -->
<div class="context-menu hidden" id="slide-context-menu">
<div class="context-item" onclick="addSlideAfter()">
Add Slide After
</div>
<div class="context-item" onclick="duplicateSlide()">
Duplicate Slide
</div>
<div class="context-divider"></div>
<div class="context-item" onclick="deleteSlide()">Delete Slide</div>
<div class="context-divider"></div>
<div class="context-item" onclick="showSlideBackground()">
Change Background
</div>
<div class="context-item" onclick="showSlideTransition()">
Transition...
</div>
</div>
<!-- Theme Modal -->
<div class="modal hidden" id="theme-modal">
<div class="modal-content">
<div class="modal-header">
<h3>Themes</h3>
<button
class="btn-close"
onclick="hideModal('theme-modal')"
>
<svg
width="20"
height="20"
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="modal-body">
<div class="theme-grid">
<div class="theme-item" onclick="applyTheme('default')">
<div
class="theme-preview"
style="
background: linear-gradient(
135deg,
#3b82f6,
#1e40af
);
"
></div>
<span>Default</span>
</div>
<div class="theme-item" onclick="applyTheme('dark')">
<div
class="theme-preview"
style="
background: linear-gradient(
135deg,
#1e293b,
#0f172a
);
"
></div>
<span>Dark</span>
</div>
<div class="theme-item" onclick="applyTheme('minimal')">
<div
class="theme-preview"
style="
background: #ffffff;
border: 1px solid #e2e8f0;
"
></div>
<span>Minimal</span>
</div>
<div class="theme-item" onclick="applyTheme('nature')">
<div
class="theme-preview"
style="
background: linear-gradient(
135deg,
#22c55e,
#15803d
);
"
></div>
<span>Nature</span>
</div>
<div class="theme-item" onclick="applyTheme('sunset')">
<div
class="theme-preview"
style="
background: linear-gradient(
135deg,
#f97316,
#dc2626
);
"
></div>
<span>Sunset</span>
</div>
<div class="theme-item" onclick="applyTheme('ocean')">
<div
class="theme-preview"
style="
background: linear-gradient(
135deg,
#06b6d4,
#0284c7
);
"
></div>
<span>Ocean</span>
</div>
</div>
</div>
</div>
</div>
<!-- Shape Modal -->
<div class="modal hidden" id="shape-modal">
<div class="modal-content">
<div class="modal-header">
<h3>Insert Shape</h3>
<button
class="btn-close"
onclick="hideModal('shape-modal')"
>
<svg
width="20"
height="20"
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="modal-body">
<div class="shape-grid">
<button
class="shape-btn"
onclick="addShape('rectangle')"
title="Rectangle"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<rect
x="3"
y="3"
width="18"
height="18"
rx="2"
></rect>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('rounded-rectangle')"
title="Rounded Rectangle"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<rect
x="3"
y="3"
width="18"
height="18"
rx="6"
></rect>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('ellipse')"
title="Ellipse"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<ellipse
cx="12"
cy="12"
rx="9"
ry="9"
></ellipse>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('triangle')"
title="Triangle"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<polygon points="12,3 21,21 3,21"></polygon>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('diamond')"
title="Diamond"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<polygon
points="12,2 22,12 12,22 2,12"
></polygon>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('star')"
title="Star"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<polygon
points="12,2 15,9 22,9 17,14 19,21 12,17 5,21 7,14 2,9 9,9"
></polygon>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('arrow-right')"
title="Arrow Right"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<polygon
points="2,8 14,8 14,4 22,12 14,20 14,16 2,16"
></polygon>
</svg>
</button>
<button
class="shape-btn"
onclick="addShape('callout')"
title="Callout"
>
<svg
width="40"
height="40"
viewBox="0 0 24 24"
fill="#3b82f6"
>
<path
d="M3,3 L21,3 L21,15 L12,15 L6,21 L6,15 L3,15 Z"
></path>
</svg>
</button>
</div>
</div>
</div>
</div>
<!-- Chart Modal -->
<div class="modal hidden" id="chart-modal">
<div class="modal-content modal-large">
<div class="modal-header">
<h3>Insert Chart</h3>
<button
class="btn-close"
onclick="hideModal('chart-modal')"
>
<svg
width="20"
height="20"
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="modal-body">
<div class="chart-type-selector">
<button class="chart-type-btn active" data-type="bar">
<svg
width="32"
height="32"
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="8" width="4" height="13"></rect>
<rect x="17" y="4" width="4" height="17"></rect>
</svg>
<span>Bar</span>
</button>
<button class="chart-type-btn" data-type="line">
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<polyline
points="3,17 8,12 13,16 21,6"
></polyline>
</svg>
<span>Line</span>
</button>
<button class="chart-type-btn" data-type="pie">
<svg
width="32"
height="32"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
>
<circle cx="12" cy="12" r="10"></circle>
<path
d="M12,12 L12,2 A10,10 0 0,1 21,16 Z"
></path>
</svg>
<span>Pie</span>
</button>
</div>
<div class="chart-data-input">
<label>Chart Data (CSV format)</label>
<textarea
id="chart-data-input"
rows="5"
placeholder="Label,Value
Q1,100
Q2,150
Q3,120
Q4,200"
></textarea>
</div>
<div class="modal-footer">
<button
class="btn-secondary"
onclick="hideModal('chart-modal')"
>
Cancel
</button>
<button class="btn-primary" onclick="insertChart()">
Insert Chart
</button>
</div>
</div>
</div>
</div>
<script src="/suite/slides/slides.js"></script>
</body>
</html>