drixio 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,254 @@
1
+ var e=Object.defineProperty,t=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var n=`
2
+ <header>
3
+ <div id="current-path">
4
+ <span id="db-name">database</span>
5
+ <span id="slash">/</span>
6
+ <div id="current-table">
7
+ <span class="material-symbols-outlined" id="table-icon"> table </span>
8
+ <span id="table-name">users</span>
9
+ </div>
10
+ </div>
11
+
12
+
13
+ <div class="header-actions">
14
+ <button id="export-btn" class="secondary" title="Export Data / DDL" style="display: flex; align-items: center; gap: 6px; padding: 6px 12px; background: transparent; border: 1px solid var(--color-border); border-radius: 6px; cursor: pointer; color: var(--color-text-secondary); font-size: 13px; font-weight: 500;">
15
+ <span class="material-symbols-outlined" style="font-size: 18px;">download</span>
16
+ Export
17
+ </button>
18
+ </div>
19
+ </header>
20
+ `,r=`
21
+ <aside>
22
+ <div id="sidebar-header">
23
+ <span class="material-symbols-outlined" id="database-icon"> database </span>
24
+ <h1 id="brand-title">
25
+ DRIXIO
26
+ <p id="brand-subtitle">STUDIO</p>
27
+ </h1>
28
+ </div>
29
+
30
+ <div id="sidebar-content">
31
+ <div id="search-bar">
32
+ <span class="material-symbols-outlined" id="search-icon"> search </span>
33
+ <input type="text" placeholder="Search" id="search-input" />
34
+ </div>
35
+
36
+ <nav id="table-nav">
37
+ <!-- Display All Table -->
38
+ </nav>
39
+ </div>
40
+
41
+ <div id="sidebar-footer">
42
+ <button id="theme-toggle" title="Toggle Dark Mode">
43
+ <span class="material-symbols-outlined" id="theme-icon">dark_mode</span>
44
+ Theme
45
+ </button>
46
+ </div>
47
+ </aside>
48
+ `,i=`
49
+ <nav id="tab-nav">
50
+ <button
51
+ type="button"
52
+ class="tab-btn"
53
+ onclick="handleSwitchTab('data-btn')"
54
+ id="data-btn"
55
+ >
56
+ <span class="material-symbols-outlined" id="data-icon"> table_rows </span>
57
+ Data
58
+ </button>
59
+ <button
60
+ class="tab-btn"
61
+ onclick="handleSwitchTab('schema-btn')"
62
+ id="schema-btn"
63
+ >
64
+ <span class="material-symbols-outlined" id="schema-icon">
65
+ grid_layout_side
66
+ </span>
67
+ Schema (Table)
68
+ </button>
69
+
70
+ <div style="flex: 1;"></div>
71
+
72
+ <button class="tab-btn" onclick="handleSwitchTab('status-btn')" id="status-btn">
73
+ <span class="material-symbols-outlined" id="status-icon"> database </span>
74
+ Database Status
75
+ </button>
76
+ <button class="tab-btn" onclick="handleSwitchTab('erd-btn')" id="erd-btn">
77
+ <span class="material-symbols-outlined" id="erd-icon"> schema </span>
78
+ ERD Visualization
79
+ </button>
80
+ <button class="tab-btn" onclick="handleSwitchTab('sql-btn')" id="sql-btn">
81
+ <span class="material-symbols-outlined" id="sql-icon"> code </span>
82
+ SQL Console
83
+ </button>
84
+ </nav>
85
+ `,a=t({executeRawQuery:()=>d,fetchTableIndexes:()=>u,fetchTableSchema:()=>l,fetchTableStats:()=>s,fetchTableWithName:()=>c,fetchTables:()=>o});async function o(){return await(await fetch(`/api/tables`)).json()}async function s(){return await(await fetch(`/api/tables/stats`)).json()}async function c(e,t={}){let{where:n=``,limit:r=50,offset:i=0,orderCol:a,orderAsc:o}=t,s=new URLSearchParams;n&&s.append(`where`,n),s.append(`limit`,r.toString()),s.append(`offset`,i.toString()),a&&(s.append(`orderCol`,a),s.append(`orderAsc`,o===!1?`false`:`true`));let c=`/api/tables/${e}/data?${s.toString()}`;return await(await fetch(c)).json()}async function l(e){return await(await fetch(`/api/tables/${e}/schema`)).json()}async function u(e){return await(await fetch(`/api/tables/${e}/indexes`)).json()}async function d(e){return await(await fetch(`/api/query`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({sql:e})})).json()}async function f(){try{let e=await o(),t=document.getElementById(`table-nav`),n=document.getElementById(`not-found-msg`);n&&n.remove(),e.success&&e.data&&e.data.length>0?(e.data.forEach(e=>{let n=document.createElement(`button`);n.type=`button`,n.className=`table-btn`,n.innerHTML=`<span>${e}</span><span class="table-btn-badge" id="badge-${e}" style="display:none;"></span>`,n.onclick=()=>{window.AppState.currentTable=e,window.AppState.currentTableBtnElement=n,window.AppState.currentTab===`erd-btn`||window.AppState.currentTab===`sql-btn`||window.AppState.currentTab===`status-btn`?window.handleSwitchTab(`data-btn`):window.renderCurrentView()},t.appendChild(n)}),window.handleSwitchTab(`data-btn`),s().then(e=>{e.success&&e.data&&Object.entries(e.data).forEach(([e,t])=>{let n=document.getElementById(`badge-${e}`);n&&(n.textContent=Number(t).toLocaleString(),n.style.display=`inline-flex`)})}).catch(e=>console.error(`Failed to load table stats:`,e))):(t.innerHTML=`<div id="not-found-msg">No Tables Found.</div>`,window.handleSwitchTab(`data-btn`))}catch(e){console.error(`Failed to fetch tables:`,e)}}var p=t({bindCellSelection:()=>h,bindColumnResizer:()=>_,renderSelection:()=>m});function m(e,t){document.querySelectorAll(`#${e} .cell-in-range, #${e} .cell-selected, #${e} .range-top, #${e} .range-bottom, #${e} .range-left, #${e} .range-right, #${e} .row-header-selected`).forEach(e=>{e.classList.remove(`cell-in-range`,`cell-selected`,`range-top`,`range-bottom`,`range-left`,`range-right`,`row-header-selected`)});let n=t.selection;if(n.startRow===-1)return;let r=Math.min(n.startRow,n.endRow),i=Math.max(n.startRow,n.endRow),a=Math.min(n.startCol,n.endCol),o=Math.max(n.startCol,n.endCol);document.querySelectorAll(`#${e} td.data-cell`).forEach(e=>{let s=parseInt(e.dataset.rowIdx),c=parseInt(e.dataset.colIdx);s>=r&&s<=i&&c>=a&&c<=o&&(e.classList.add(`cell-in-range`),s===r&&e.classList.add(`range-top`),s===i&&e.classList.add(`range-bottom`),c===a&&e.classList.add(`range-left`),c===o&&e.classList.add(`range-right`),s===n.startRow&&c===n.startCol&&(e.classList.add(`cell-selected`),t.selectedCell=e))}),n.isDraggingRow&&document.querySelectorAll(`#${e} td.row-header`).forEach(e=>{let t=parseInt(e.dataset.rowIdx);t>=r&&t<=i&&e.classList.add(`row-header-selected`)})}function h(e,t,n,r){e.addEventListener(`mousedown`,e=>{if(e.target.tagName===`INPUT`||e.target.tagName===`SELECT`)return;let i=e.target.closest(`td.row-header`);if(i&&e.button!==2){let e=parseInt(i.dataset.rowIdx);n.selection={isDragging:!1,isDraggingRow:!0,startRow:e,endRow:e,startCol:0,endCol:r-1},m(t,n);return}let a=e.target.closest(`td.data-cell`);if(!a)return;let o=parseInt(a.dataset.rowIdx),s=parseInt(a.dataset.colIdx);n.selection={isDragging:!0,startRow:o,startCol:s,endRow:o,endCol:s},m(t,n)}),e.addEventListener(`mouseover`,e=>{if(n.selection.isDraggingRow){let r=e.target.closest(`td.row-header`);if(!r)return;n.selection.endRow=parseInt(r.dataset.rowIdx),m(t,n);return}if(!n.selection.isDragging)return;let r=e.target.closest(`td.data-cell`);r&&(n.selection.endRow=parseInt(r.dataset.rowIdx),n.selection.endCol=parseInt(r.dataset.colIdx),m(t,n))}),e.addEventListener(`mouseup`,()=>{n.selection&&(n.selection.isDragging=!1,n.selection.isDraggingRow=!1)}),e.addEventListener(`contextmenu`,e=>{let r=e.target.closest(`td.row-header`);if(!r)return;let i=parseInt(r.dataset.rowIdx),a=n.selection,o=Math.min(a.startRow,a.endRow),s=Math.max(a.startRow,a.endRow);a.startRow!==-1&&i>=o&&i<=s&&(e.preventDefault(),g(e.pageX,e.pageY,n,t))})}function g(e,t,n,r){let i=document.getElementById(`grid-context-menu`);i||(i=document.createElement(`div`),i.id=`grid-context-menu`,i.className=`context-menu`,document.body.appendChild(i),document.addEventListener(`click`,()=>{i.style.display=`none`}));let a=n.selection,o=Math.min(a.startRow,a.endRow),s=Math.max(a.startRow,a.endRow),c=s-o+1;i.innerHTML=`
86
+ <div class="menu-item delete-action">
87
+ <span class="material-symbols-outlined">delete</span>
88
+ Delete ${c} Row${c>1?`s`:``}
89
+ </div>
90
+ `,i.style.left=`${e}px`,i.style.top=`${t}px`,i.style.display=`block`,i.querySelector(`.delete-action`).onclick=e=>{e.stopPropagation(),i.style.display=`none`;let t=document.querySelectorAll(`#${r} tbody tr:not(.ghost-row-tr)`);for(let e=o;e<=s;e++){let r=t[e];if(!r)continue;let i=r.querySelector(`td.data-cell`);if(i){let e=i.dataset.pk;e!==`undefined`&&e!=null&&(n.pendingDeletes||=new Set,n.pendingDeletes.add(e),r.classList.add(`row-deleted`))}}let a=document.getElementById(`btn-save-changes`);a&&a.classList.add(`has-changes`)}}function _(e,t){let n=document.createElement(`div`);n.className=`resizer`,e.appendChild(n),n.addEventListener(`click`,e=>e.stopPropagation()),n.addEventListener(`mousedown`,n=>{n.preventDefault(),n.stopPropagation();let r=n.pageX,i=e.offsetWidth,a=!1,o=n=>{a=!0,t&&(t.isResizing=!0);let o=i+(n.pageX-r);e.style.width=o+`px`,e.style.minWidth=o+`px`,e.style.maxWidth=o+`px`},s=()=>{document.removeEventListener(`mousemove`,o),document.removeEventListener(`mouseup`,s),document.body.style.cursor=``,a&&setTimeout(()=>{t&&(t.isResizing=!1)},100)};document.body.style.cursor=`col-resize`,document.addEventListener(`mousemove`,o),document.addEventListener(`mouseup`,s)})}var v=t({duplicateDataRows:()=>C,markRowDeleted:()=>x,saveDataGridEdits:()=>y,unmarkRowDeleted:()=>S,updateCell:()=>b});async function y(){if(!window.DataGrid)return;let{pendingEdits:e,pendingInserts:t,pkColumn:n}=window.DataGrid,r=window.AppState.currentTable;if(!r||!n){alert(`Cannot save: No Primary Key detected for this table.`);return}let i=[];for(let[t,a]of Object.entries(e)){if(Object.keys(a).length===0)continue;let e=Object.entries(a).map(([e,t])=>t===``?`"${e}" = NULL`:`"${e}" = '${t.replace(/'/g,`''`)}'`).join(`, `);i.push(`UPDATE "${r}" SET ${e} WHERE "${n}" = '${t.replace(/'/g,`''`)}';`)}for(let e=0;e<t.length;e++){let n=t[e];if(Object.keys(n).length===0||!Object.values(n).some(e=>e!==``))continue;let a=Object.keys(n),o=a.map(e=>{let t=n[e];return t===``?`NULL`:`'${t.replace(/'/g,`''`)}'`});i.push(`INSERT INTO "${r}" ("${a.join(`", "`)}") VALUES (${o.join(`, `)});`)}if(window.DataGrid.pendingDeletes)for(let e of window.DataGrid.pendingDeletes)i.push(`DELETE FROM "${r}" WHERE "${n}" = '${e.replace(/'/g,`''`)}';`);if(i.length===0)return;let a=!0,o=``;for(let e of i)try{let t=await d(e);if(!t.success){a=!1,o=t.error;break}}catch(e){a=!1,o=e.message;break}a?(window.renderCurrentView(),window.showToast&&window.showToast(`Data saved successfully!`)):(window.showToast?window.showToast(`Save failed: `+o,`error`):alert(`Save failed:
91
+ `+o),document.querySelectorAll(`.cell-edited`).forEach(e=>{e.classList.remove(`cell-edited`),e.classList.add(`cell-error`)})),window.updateSidebarDirtyState?.()}function b(e,t,n,r=!0){if(r&&window.DataGrid.currentTransaction){let n=e.textContent;(n===`null`||e.classList.contains(`ghost-row`))&&(n=``),n!==t&&window.DataGrid.currentTransaction.push({td:e,oldVal:n,newVal:t})}let i=e.dataset.col;if(e.innerHTML=t||(e.dataset.insertIndex===void 0?`<em>null</em>`:`+ New`),e.dataset.insertIndex!==void 0){let r=parseInt(e.dataset.insertIndex);if(window.DataGrid.pendingInserts[r]||(window.DataGrid.pendingInserts[r]={}),t&&(window.DataGrid.pendingInserts[r][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`ghost-row`),r===window.DataGrid.pendingInserts.length-1)){e.closest(`tr`).classList.remove(`ghost-row-tr`),window.DataGrid.pendingInserts.push({});let t=document.querySelector(`#data-grid-table-${window.AppState.currentTable} tbody`),i=document.createElement(`tr`);i.className=`ghost-row-tr`;let a=parseInt(e.dataset.rowIdx)+1;i.innerHTML+=`<td class="row-header" data-row-idx="${a}">*</td>`,n.forEach((e,t)=>{i.innerHTML+=`<td class="data-cell ghost-row" data-row-idx="${a}" data-col-idx="${t}" data-insert-index="${r+1}" data-col="${e}">+ New</td>`}),t.appendChild(i)}}else{let n=e.dataset.pk;t===e.dataset.original?(e.classList.remove(`cell-edited`),e.classList.remove(`cell-error`),window.DataGrid.pendingEdits[n]&&delete window.DataGrid.pendingEdits[n][i]):(window.DataGrid.pendingEdits[n]||(window.DataGrid.pendingEdits[n]={}),window.DataGrid.pendingEdits[n][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`cell-error`))}window.updateSidebarDirtyState?.()}function x(e,t=!0){let n=document.querySelector(`td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!n||n.classList.contains(`ghost-row-tr`)||n.classList.contains(`row-deleted`))return;let r=n.querySelector(`td.data-cell`)?.dataset.pk;r!==void 0&&(t&&window.DataGrid.currentTransaction&&window.DataGrid.currentTransaction.push({type:`delete`,rowIdx:e,pk:r}),window.DataGrid.pendingDeletes.add(r),n.classList.add(`row-deleted`)),window.updateSidebarDirtyState?.()}function S(e,t){let n=document.querySelector(`td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);n&&n.classList.remove(`row-deleted`),window.DataGrid.pendingDeletes.delete(t),window.updateSidebarDirtyState?.()}function C(e,t){e.forEach(e=>{let n=window.AppState.currentTable,r=document.querySelector(`#data-grid-table-${n} td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!r||r.classList.contains(`ghost-row-tr`))return;let i=document.querySelector(`#data-grid-table-${n} .ghost-row-tr`);i&&t.forEach((e,n)=>{let a=r.querySelector(`td.data-cell[data-col-idx="${n}"]`),o=i.querySelector(`td.data-cell[data-col-idx="${n}"]`);if(a&&o){let n=a.dataset.insertIndex===void 0?a.classList.contains(`cell-edited`)?window.DataGrid.pendingEdits[a.dataset.pk]?.[e]:a.dataset.original:window.DataGrid.pendingInserts[a.dataset.insertIndex][e];n!=null&&n!==`null`&&b(o,n,t,!0)}})})}var w=`modulepreload`,T=function(e,t){return new URL(e,t).href},E={},D=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=T(t,n),t=s(t),t in E)return;E[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:w,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function O(e,t,n){e.addEventListener(`dblclick`,e=>{let r=e.target.closest(`td.data-cell`);if(!r||r.querySelector(`input, select`))return;let i=r.dataset.col,o=t.find(e=>e.name===i),s=o?.type?.toUpperCase()||``,c=s.includes(`ENUM`),l=s===`DATE`,u=s.includes(`DATETIME`)||s.includes(`TIMESTAMP`),d=s.includes(`BOOL`)||s===`TINYINT(1)`,f=r.textContent===`null`||r.textContent===`+ New`?``:r.textContent,p;if(o&&o.fkTarget){p=document.createElement(`select`);let e=document.createElement(`option`);e.value=f,e.textContent=`Loading...`,p.appendChild(e),D(async()=>{let{executeRawQuery:e}=await Promise.resolve().then(()=>a);return{executeRawQuery:e}},void 0,import.meta.url).then(({executeRawQuery:t})=>{let{table:n,column:r}=o.fkTarget;t(`SELECT * FROM "${n}" LIMIT 100`).then(e=>{if(e.success&&e.data&&e.data.rows){if(p.innerHTML=``,o.nullable){let e=document.createElement(`option`);e.value=``,e.textContent=`-- None --`,p.appendChild(e)}let t=r;if(e.data.columns){let n=[`name`,`title`,`label`,`description`],r=e.data.columns.find(e=>n.includes(e.toLowerCase()));r&&(t=r)}if(e.data.rows.forEach(e=>{let n=String(e[r]),i=t===r?n:`${n} - ${e[t]}`,a=document.createElement(`option`);a.value=n,a.textContent=i,n===f&&(a.selected=!0),p.appendChild(a)}),f&&!e.data.rows.find(e=>String(e[r])===f)){let e=document.createElement(`option`);e.value=f,e.textContent=`${f} (Not in limit)`,e.selected=!0,p.appendChild(e)}}}).catch(t=>{e.textContent=`Error loading options`})})}else if(c){let e=o.type.match(/enum\((.*?)\)/i),t=[];e&&(t=e[1].split(`,`).map(e=>e.trim().replace(/^'|'$/g,``))),p=document.createElement(`select`),t.forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,e===f&&(t.selected=!0),p.appendChild(t)})}else if(l)p=document.createElement(`input`),p.type=`date`,p.value=f;else if(u){p=document.createElement(`input`),p.type=`datetime-local`;let e=f.replace(` `,`T`).slice(0,16);p.value=e}else d?(p=document.createElement(`input`),p.type=`checkbox`,p.checked=f===`1`||f.toLowerCase()===`true`):(p=document.createElement(`input`),p.type=`text`,p.value=f);let m=!1,h=()=>{m=!0;let e=document.getElementById(`modal-editor-overlay`),t=document.getElementById(`modal-textarea`),n=document.getElementById(`modal-cancel-btn`),r=document.getElementById(`modal-save-btn`),a=document.getElementById(`modal-title`);a.textContent=`Edit ${i}`,t.value=p.value,e.style.display=`flex`,t.focus();let o=()=>{e.style.display=`none`,r.onclick=null,n.onclick=null,m=!1,p.focus()};n.onclick=o,r.onclick=()=>{p.value=t.value,o(),g()}};if(r.innerHTML=``,r.appendChild(p),s===``||!c&&!l&&!u&&!d&&!(o&&o.fkTarget)){let e=document.createElement(`span`);e.className=`material-symbols-outlined cell-expand-btn`,e.textContent=`open_in_full`,e.onmousedown=e=>e.preventDefault(),e.onclick=()=>h(),r.appendChild(e),p.style.width=`100%`,p.style.paddingRight=`32px`,p.addEventListener(`keydown`,e=>{e.key===`Enter`&&e.shiftKey?(e.preventDefault(),h()):e.key===`Enter`&&p.blur()})}else p.addEventListener(`keydown`,e=>{e.key===`Enter`&&p.blur()});p.focus();let g=()=>{if(m)return;let e=d?p.checked?`1`:`0`:p.value;u&&e&&(e=e.replace(`T`,` `)+`:00`),window.DataGrid.currentTransaction=[],b(r,e,n),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null};p.addEventListener(`blur`,()=>{setTimeout(()=>{m||g()},100)})})}function k(){let e=window.AppState?.currentTable;if(!e)return``;let t=document.getElementById(`filter-val-${e}`)?.value.trim(),n=document.getElementById(`filter-op-${e}`)?.value,r=document.getElementById(`filter-col-${e}`)?.value,i=``;if(t||n===`IS NULL`){let e=t;e&&!e.startsWith(`'`)&&!e.endsWith(`'`)&&isNaN(Number(e))&&(e.toUpperCase().includes(` AND `)||e.toUpperCase().includes(` OR `)||(e=`'${e.replace(/'/g,`''`)}'`)),i=`"${r}" ${n} ${e}`}return i}function A(e,t,n,r){let i=`<td class="row-header" data-row-idx="${t}">${t+1}</td>`,a=n?e[n]:t;return r.forEach((n,r)=>{let o=e[n]===null?`null`:String(e[n]),s=o.replace(/"/g,`&quot;`),c=o===`null`?`<em>null</em>`:o.replace(/</g,`&lt;`);i+=`<td class="data-cell" data-row-idx="${t}" data-col-idx="${r}" data-pk="${a}" data-col="${n}" data-original="${s}">${c}</td>`}),i}async function j(e,t,n=``,r=!1,i=null){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let a=document.getElementById(`table-name`);a&&(a.textContent=e);let o=i||document.getElementById(`main-content`);r||(o.innerHTML=`<div style='padding:24px;'>Loading...</div>`);try{let i=await l(e);if(!i.success)throw Error(i.error);let a=i.data,s=a.find(e=>e.isPk)?.name;(!r||!window.DataGrid)&&(window.DataGrid={schema:a,pkColumn:s,pendingEdits:{},pendingInserts:[{}],pendingDeletes:new Set,selectedCell:null,history:[],currentTransaction:null,sortState:{col:s||a[0].name,asc:!0},pagination:{limit:50,offset:0,isLoading:!1,hasMore:!0},selection:{isDragging:!1,isDraggingRow:!1,startRow:-1,startCol:-1,endRow:-1,endCol:-1}}),window.TableStates&&window.TableStates[e]&&(window.TableStates[e].dataGrid=window.DataGrid);let u=await c(e,{where:n,limit:window.DataGrid.pagination.limit,offset:window.DataGrid.pagination.offset,orderCol:window.DataGrid.sortState.col,orderAsc:window.DataGrid.sortState.asc});if(u.success&&u.data){let n=u.data.rows,i=u.data.columns;window.DataGrid.pagination.hasMore=n.length===window.DataGrid.pagination.limit;let l=i.map(e=>`<option value="${e}">${e}</option>`).join(``);r||(o.innerHTML=`
92
+ <div class="toolbar">
93
+ <div class="filter-group">
94
+ <div class="filter-icon-container">
95
+ <span class="material-symbols-outlined" id="filter-icon">filter_list</span>
96
+ <span>Filter</span>
97
+ </div>
98
+ <select id="filter-col-${e}" class="filter-select">${l}</select>
99
+ <select id="filter-op-${e}" class="filter-select">
100
+ <option value="=">=</option>
101
+ <option value=">">></option>
102
+ <option value="<"><</option>
103
+ <option value=">=">>=</option>
104
+ <option value="<="><=</option>
105
+ <option value="LIKE">LIKE</option>
106
+ <option value="!=">!=</option>
107
+ </select>
108
+ <input type="text" id="filter-val-${e}" class="filter-input" placeholder="Enter value..." />
109
+ </div>
110
+ <div style="flex:1;"></div>
111
+ <button id="btn-refresh-data-${e}" class="refresh-btn" title="Refresh Data (F5)"><span class="material-symbols-outlined">refresh</span></button>
112
+ </div>
113
+ <div class="table-container" id="data-grid-container-${e}"></div>
114
+ `);let d=`<table class="data-table" id="data-grid-table-${e}"><thead><tr>`;d+=`<th class="row-header">#</th>`,i.forEach(e=>{let t=a.find(t=>t.name===e),n=``,r=``;t&&(t.isPk&&(n=` <span style="opacity:0.5; font-size:10px;">(PK)</span>`),t.name.toLowerCase().includes(`id`)&&!t.isPk&&(n=` <span style="opacity:0.5; font-size:10px;">(FK)</span>`),r=`<br><span style="font-weight:normal; opacity:0.7; font-size:10px; font-family:monospace;">${t.type}</span>`);let i=``;window.DataGrid.sortState.col===e&&(i=window.DataGrid.sortState.asc?`▲`:`▼`),d+=`<th class="sortable" data-col="${e}" style="cursor:pointer; user-select:none;">
115
+ <div style="display: flex; justify-content: space-between; align-items: center;">
116
+ <div>${e}${n}${r}</div>
117
+ <div class="sort-arrow" style="font-size:10px; opacity:0.8; margin-left: 8px; width: 12px; text-align: right;">${i}</div>
118
+ </div>
119
+ </th>`}),d+=`</tr></thead><tbody>`,n&&n.length>0&&n.forEach((e,t)=>{d+=`<tr>${A(e,t,s,i)}</tr>`}),d+=`<tr class="ghost-row-tr">`;let f=n?n.length:0;d+=`<td class="row-header" data-row-idx="${f}">*</td>`,i.forEach((e,t)=>{d+=`<td class="data-cell ghost-row" data-row-idx="${f}" data-col-idx="${t}" data-insert-index="0" data-col="${e}">+ New</td>`}),d+=`</tr></tbody></table>`;let p=document.getElementById(`data-grid-container-${e}`);if(!p)return;if(p.innerHTML=d,document.querySelectorAll(`th.sortable`).forEach(n=>{n.onclick=r=>{if(window.DataGrid&&window.DataGrid.isResizing)return;if(Object.keys(window.DataGrid.pendingEdits).length>0||window.DataGrid.pendingInserts.length>1||window.DataGrid.pendingDeletes.size>0){alert(`You have unsaved changes. Please save changes before sorting.`);return}let i=n.dataset.col;window.DataGrid.sortState.col===i?window.DataGrid.sortState.asc=!window.DataGrid.sortState.asc:(window.DataGrid.sortState.col=i,window.DataGrid.sortState.asc=!0),window.DataGrid.pagination.offset=0,j(e,t,k(),!0)},_(n,window.DataGrid)}),h(p,`data-grid-table-${e}`,window.DataGrid,i.length),O(p,a,i),!r){let n=document.getElementById(`filter-val-${e}`),r=(n=!0)=>{n&&window.DataGrid&&(window.DataGrid.pagination.offset=0),j(e,t,k(),!0)},a;n&&n.addEventListener(`input`,()=>{clearTimeout(a),a=setTimeout(()=>r(!0),400)});let o=document.getElementById(`filter-col-${e}`),l=document.getElementById(`filter-op-${e}`);o&&o.addEventListener(`change`,()=>r(!0)),l&&l.addEventListener(`change`,()=>r(!0));let u=()=>{(Object.keys(window.DataGrid.pendingEdits).length>0||window.DataGrid.pendingInserts.length>1||window.DataGrid.pendingDeletes.size>0)&&!confirm(`You have unsaved changes. Are you sure you want to refresh and discard them?`)||(window.DataGrid.pendingEdits={},window.DataGrid.pendingInserts=[{}],window.DataGrid.pendingDeletes=new Set,window.DataGrid.history=[],window.DataGrid.currentTransaction=null,window.updateSidebarDirtyState?.(),r(!1))},d=document.getElementById(`btn-refresh-data-${e}`);d&&(d.onclick=u),window.DataGrid.refreshData=u;let f=async()=>{if(window.DataGrid.pagination.isLoading||!window.DataGrid.pagination.hasMore)return;window.DataGrid.pagination.isLoading=!0,window.DataGrid.pagination.offset+=window.DataGrid.pagination.limit;let t={where:k(),limit:window.DataGrid.pagination.limit,offset:window.DataGrid.pagination.offset,orderCol:window.DataGrid.sortState.col,orderAsc:window.DataGrid.sortState.asc};try{let n=await c(e,t);if(window.DataGrid.pagination.isLoading=!1,n.success&&n.data){let t=n.data.rows;window.DataGrid.pagination.hasMore=t.length===window.DataGrid.pagination.limit;let r=document.querySelector(`#data-grid-table-${e} tbody`);if(!r)return;let a=r.querySelector(`.ghost-row-tr`);a&&r.removeChild(a);let o=window.DataGrid.pagination.offset;if(t.forEach((e,t)=>{let n=document.createElement(`tr`);n.innerHTML=A(e,o+t,s,i),r.appendChild(n)}),a){let e=o+t.length,n=a.querySelector(`.row-header`);n&&(n.dataset.rowIdx=e),a.querySelectorAll(`.ghost-row`).forEach(t=>{t.dataset.rowIdx=e}),r.appendChild(a)}}}catch{window.DataGrid.pagination.isLoading=!1}};setTimeout(()=>{let t=document.getElementById(`data-grid-container-${e}`);t&&t.addEventListener(`scroll`,e=>{let{scrollTop:t,scrollHeight:n,clientHeight:r}=e.target;t+r>=n-50&&f()})},50)}}else o.innerHTML=`<div style="padding:24px; color:red;">Error: ${u.error}</div>`}catch(e){o.innerHTML=`<div style="padding:24px; color:red;">Failed to load data: ${e.message}</div>`}}var M=t({duplicateSchemaRows:()=>L,markSchemaRowDeleted:()=>F,saveSchemaEdits:()=>N,unmarkSchemaRowDeleted:()=>I,updateSchemaCell:()=>P});async function N(){if(!window.SchemaGrid)return;let{pendingEdits:e,pendingInserts:t,pendingDeletes:n}=window.SchemaGrid,r=window.AppState.currentTable;if(!r)return;let i=[];if(n)for(let e of n)i.push(`ALTER TABLE "${r}" DROP COLUMN "${e}";`);for(let[t,n]of Object.entries(e)){let e=t;if(n.name&&n.name!==t&&(i.push(`ALTER TABLE "${r}" RENAME COLUMN "${t}" TO "${n.name}";`),e=n.name),Object.keys(n).filter(e=>e!==`name`).length>0){let a=window.SchemaGrid.schema?.find(e=>e.name===t)||{},o=n.type===void 0?a.type:n.type,s=[],c=n.isPk===void 0?a.isPk:n.isPk,l=String(c).toUpperCase();if((l===`1`||l===`TRUE`||l===`YES`||l.includes(`PK`)||l===`KEY`)&&s.push(`PRIMARY KEY`),l.includes(`FK:`)){let e=l.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&s.push(`REFERENCES "${t[0]}"("${t[1]}")`)}}let u=n.nullable===void 0?a.nullable:n.nullable;(u===`0`||u===`No`||u===!1)&&s.push(`NOT NULL`);let d=n.defaultValue===void 0?a.defaultValue:n.defaultValue;d&&s.push(`DEFAULT '${String(d).replace(/'/g,`''`)}'`),i.push(`ALTER TABLE "${r}" MODIFY COLUMN "${e}" ${o} ${s.join(` `)};`)}}for(let e=0;e<t.length;e++){let n=t[e];if(Object.keys(n).length===0||!n.name||n.name.trim()===``)continue;let a=n.name.trim(),o=n.type||`TEXT`,s=[],c=String(n.isPk||``).toUpperCase();if((c===`1`||c===`TRUE`||c===`YES`||c.includes(`PK`)||c===`KEY`)&&s.push(`PRIMARY KEY`),c.includes(`FK:`)){let e=c.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&s.push(`REFERENCES "${t[0]}"("${t[1]}")`)}}(n.nullable===`0`||n.nullable===`false`||n.nullable===`No`)&&s.push(`NOT NULL`),n.defaultValue&&s.push(`DEFAULT '${n.defaultValue.replace(/'/g,`''`)}'`),i.push(`ALTER TABLE "${r}" ADD COLUMN "${a}" ${o} ${s.join(` `)};`)}if(window.SchemaGrid.pendingIndexEdits){for(let e of window.SchemaGrid.pendingIndexEdits.dropped)e&&e.trim()!==``&&i.push(`DROP INDEX "${e}";`);for(let e of window.SchemaGrid.pendingIndexEdits.added){let t=``;t=e.name&&e.name.trim()!==``?`"${e.name}"`:`"idx_${r}_${e.columns.join(`_`)}_${Date.now()}"`;let n=e.isUnique?`UNIQUE`:``,a=e.columns.map(e=>`"${e}"`).join(`, `);i.push(`CREATE ${n} INDEX IF NOT EXISTS ${t} ON "${r}" (${a});`)}}if(i.length===0)return;let a=!0,o=``;for(let e of i)try{let t=await d(e);if(!t.success){a=!1,o=t.error;break}}catch(e){a=!1,o=e.message;break}a?(window.renderCurrentView(),window.showToast&&window.showToast(`Schema saved successfully!`)):(o.includes(`near "MODIFY": syntax error`)?o=`SQLite: Currently does not support modifying existing column types or constraints directly. You can only Rename columns or Add new columns.`:o.includes(`syntax error`)&&(o=`SQLite: `+o),window.showToast?window.showToast(`Save failed: `+o,`error`):alert(`Save failed:
120
+ `+o),document.querySelectorAll(`.cell-edited`).forEach(e=>{e.classList.remove(`cell-edited`),e.classList.add(`cell-error`)})),window.updateSidebarDirtyState?.()}function P(e,t,n,r=!0){if(r&&window.SchemaGrid.currentTransaction){let n=e.textContent;(n===`null`||e.classList.contains(`ghost-row`))&&(n=``),n!==t&&window.SchemaGrid.currentTransaction.push({td:e,oldVal:n,newVal:t})}let i=e.dataset.colKey;if(e.innerHTML=t||(e.dataset.insertIndex===void 0?`<span style="color:var(--color-text-soft)">-</span>`:`+ New`),e.dataset.insertIndex!==void 0){let r=parseInt(e.dataset.insertIndex);if(window.SchemaGrid.pendingInserts[r]||(window.SchemaGrid.pendingInserts[r]={}),t&&(window.SchemaGrid.pendingInserts[r][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`ghost-row`),r===window.SchemaGrid.pendingInserts.length-1)){e.closest(`tr`).classList.remove(`ghost-row-tr`),window.SchemaGrid.pendingInserts.push({});let t=document.querySelector(`#schema-grid-table-${window.AppState.currentTable} tbody`),i=document.createElement(`tr`);i.className=`ghost-row-tr`;let a=parseInt(e.dataset.rowIdx)+1;i.innerHTML+=`<td class="row-header" data-row-idx="${a}">*</td>`,n.forEach((e,t)=>{i.innerHTML+=`<td class="data-cell ghost-row" data-row-idx="${a}" data-col-idx="${t}" data-insert-index="${r+1}" data-col-key="${e}">+ New</td>`}),t.appendChild(i)}}else{let n=e.dataset.pk,r=e.dataset.original;r===`-`&&(r=``),t===r?(e.classList.remove(`cell-edited`),e.classList.remove(`cell-error`),window.SchemaGrid.pendingEdits[n]&&delete window.SchemaGrid.pendingEdits[n][i]):(window.SchemaGrid.pendingEdits[n]||(window.SchemaGrid.pendingEdits[n]={}),window.SchemaGrid.pendingEdits[n][i]=t,e.classList.add(`cell-edited`),e.classList.remove(`cell-error`))}window.updateSidebarDirtyState?.()}function F(e,t=!0){let n=document.querySelector(`#schema-grid-table td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!n||n.classList.contains(`ghost-row-tr`)||n.classList.contains(`row-deleted`))return;let r=n.querySelector(`td.data-cell`)?.dataset.pk;r!==void 0&&(t&&window.SchemaGrid.currentTransaction&&window.SchemaGrid.currentTransaction.push({type:`delete`,rowIdx:e,pk:r}),window.SchemaGrid.pendingDeletes.add(r),n.classList.add(`row-deleted`)),window.updateSidebarDirtyState?.()}function I(e,t){let n=document.querySelector(`#schema-grid-table td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);n&&n.classList.remove(`row-deleted`),window.SchemaGrid.pendingDeletes.delete(t),window.updateSidebarDirtyState?.()}function L(e,t){e.forEach(e=>{let n=window.AppState.currentTable,r=document.querySelector(`#schema-grid-table-${n} td.data-cell[data-row-idx="${e}"]`)?.closest(`tr`);if(!r||r.classList.contains(`ghost-row-tr`))return;let i=document.querySelector(`#schema-grid-table-${n} .ghost-row-tr`);i&&t.forEach((e,n)=>{let a=r.querySelector(`td.data-cell[data-col-idx="${n}"]`),o=i.querySelector(`td.data-cell[data-col-idx="${n}"]`);if(a&&o){let n=a.dataset.insertIndex===void 0?a.classList.contains(`cell-edited`)?window.SchemaGrid.pendingEdits[a.dataset.pk]?.[e]:a.dataset.original:window.SchemaGrid.pendingInserts[a.dataset.insertIndex][e];n!=null&&n!==`null`&&(e===`name`&&(n+=`_copy`),P(o,n,t,!0))}})})}function R(){let e=window.SchemaGrid;if(!e)return;let t=document.getElementById(`index-modal`);t&&t.remove();let n=[...e.indexes],r=[...e.pendingIndexEdits.added],i=new Set(e.pendingIndexEdits.dropped),a=n.filter(e=>!i.has(e.name)).concat(r),o=e.schema.map(e=>e.name);e.pendingInserts.forEach(e=>{e.name&&e.name.trim()!==``&&o.push(e.name.trim())});let s=o.map(e=>`<option value="${e}">${e}</option>`).join(``);t=document.createElement(`div`),t.id=`index-modal`,t.style.cssText=`
121
+ position: fixed; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.5);
122
+ display:flex; justify-content:center; align-items:center; z-index:9999;
123
+ `,t.innerHTML=`
124
+ <div style="background:var(--color-bg-primary); width:500px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); overflow:hidden; display:flex; flex-direction:column;">
125
+ <div style="padding:16px; border-bottom:1px solid var(--color-border); display:flex; justify-content:space-between; align-items:center;">
126
+ <h3 style="margin:0;">Manage Indexes</h3>
127
+ <button id="close-idx-modal" style="background:none; border:none; color:var(--color-text-primary); cursor:pointer;"><span class="material-symbols-outlined">close</span></button>
128
+ </div>
129
+ <div style="padding:16px; max-height:300px; overflow-y:auto;" id="idx-list-container">
130
+ </div>
131
+ <div style="padding:16px; border-top:1px solid var(--color-border); background:var(--color-bg-secondary);">
132
+ <div style="font-weight:500; margin-bottom:8px;">Add New Index</div>
133
+ <div style="display:flex; flex-direction:column; gap:8px;">
134
+ <input type="text" id="new-idx-name" placeholder="Index Name (Optional)" style="padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);" />
135
+ <select id="new-idx-cols" multiple style="padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary); height:80px;">
136
+ ${s}
137
+ </select>
138
+ <div style="font-size:12px; color:var(--color-text-soft);">Hold Ctrl/Cmd to select multiple columns</div>
139
+ <label style="display:flex; align-items:center; gap:6px; cursor:pointer;">
140
+ <input type="checkbox" id="new-idx-unique" /> Unique Index
141
+ </label>
142
+ <button id="add-idx-btn" class="primary" style="align-self:flex-end; padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Add</button>
143
+ </div>
144
+ </div>
145
+ <div style="padding:16px; border-top:1px solid var(--color-border); display:flex; justify-content:flex-end; gap:8px;">
146
+ <button id="cancel-idx-btn" class="secondary" style="padding:6px 16px; border-radius:4px; border:1px solid var(--color-border); cursor:pointer;">Cancel</button>
147
+ <button id="save-idx-btn" class="primary" style="padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Save Changes</button>
148
+ </div>
149
+ </div>
150
+ `,document.body.appendChild(t);let c=()=>t.remove();document.getElementById(`close-idx-modal`).onclick=c,document.getElementById(`cancel-idx-btn`).onclick=c;let l=()=>{let e=a.map((e,t)=>`
151
+ <div class="index-row" style="display:flex; gap:8px; align-items:center; margin-bottom:8px; padding:8px; background:var(--color-bg-primary); border:1px solid var(--color-border); border-radius:4px;">
152
+ <div style="flex:1;"><strong>${e.name||`-`}</strong></div>
153
+ <div style="flex:2; font-size:12px; color:var(--color-text-secondary);">${e.columns.join(`, `)}</div>
154
+ <div style="width:60px; font-size:12px; text-align:center;">${e.isUnique?`UNIQUE`:``}</div>
155
+ <button class="icon-btn delete-idx-btn" data-idx="${t}" style="color:var(--color-error); border:none; background:none; cursor:pointer;"><span class="material-symbols-outlined" style="font-size:18px;">delete</span></button>
156
+ </div>
157
+ `).join(``);a.length===0&&(e=`<div style="padding:16px; text-align:center; color:var(--color-text-secondary);">No indexes yet.</div>`),document.getElementById(`idx-list-container`).innerHTML=e,document.querySelectorAll(`.delete-idx-btn`).forEach(e=>{e.onclick=e=>{let t=parseInt(e.currentTarget.dataset.idx,10);a.splice(t,1),l()}})};l(),document.getElementById(`add-idx-btn`).onclick=()=>{let e=document.getElementById(`new-idx-name`).value.trim(),t=document.getElementById(`new-idx-cols`),n=Array.from(t.selectedOptions).map(e=>e.value),r=document.getElementById(`new-idx-unique`).checked;if(n.length===0){alert(`Please select at least one column for the index.`);return}a.push({name:e,columns:n,isUnique:r}),document.getElementById(`new-idx-name`).value=``,document.getElementById(`new-idx-unique`).checked=!1,t.selectedIndex=-1,l()},document.getElementById(`save-idx-btn`).onclick=()=>{let t=[],r=new Set;n.forEach(e=>{a.find(t=>t.name===e.name&&JSON.stringify(t.columns)===JSON.stringify(e.columns))||r.add(e.name)}),a.forEach(e=>{n.find(t=>t.name===e.name&&JSON.stringify(t.columns)===JSON.stringify(e.columns))||t.push(e)}),e.pendingIndexEdits.added=t,e.pendingIndexEdits.dropped=Array.from(r),window.updateSidebarDirtyState?.(),window.renderSchemaGrid(),c()}}async function z(e,t){if(!window.SchemaGrid)return;let n=document.getElementById(`pkfk-modal`);n&&n.remove();let r=e.dataset.insertIndex!==void 0,i=t.includes(`PK`),a=t.includes(`FK`),o=``,s=``;if(a){let e=t.match(/FK \((.*?)\)/);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&(o=t[0],s=t[1])}else{let e=t.match(/FK:\s*([^\s,]+)/i);if(e&&e[1]){let t=e[1].split(`.`);t.length===2&&(o=t[0],s=t[1])}}}n=document.createElement(`div`),n.id=`pkfk-modal`,n.style.cssText=`
158
+ position: fixed; top:0; left:0; width:100vw; height:100vh; background:rgba(0,0,0,0.5);
159
+ display:flex; justify-content:center; align-items:center; z-index:9999;
160
+ `,n.innerHTML=`
161
+ <div style="background:var(--color-bg-primary); width:400px; border-radius:8px; box-shadow:0 4px 12px rgba(0,0,0,0.2); overflow:hidden; display:flex; flex-direction:column;">
162
+ <div style="padding:16px; border-bottom:1px solid var(--color-border); display:flex; justify-content:space-between; align-items:center;">
163
+ <h3 style="margin:0;">Manage Keys</h3>
164
+ <button id="close-pkfk-modal" style="background:none; border:none; color:var(--color-text-primary); cursor:pointer;"><span class="material-symbols-outlined">close</span></button>
165
+ </div>
166
+ <div style="padding:16px; display:flex; flex-direction:column; gap:16px;">
167
+ <label style="display:flex; align-items:center; gap:8px; cursor:pointer;">
168
+ <input type="checkbox" id="modal-is-pk" ${i?`checked`:``} />
169
+ <strong>Primary Key (PK)</strong>
170
+ </label>
171
+
172
+ <div style="border-top: 1px solid var(--color-border); margin: 8px 0;"></div>
173
+
174
+ <label style="display:flex; align-items:center; gap:8px; cursor:${r?`pointer`:`not-allowed`}; opacity:${r?`1`:`0.6`};">
175
+ <input type="checkbox" id="modal-is-fk" ${a?`checked`:``} ${r?``:`disabled`} />
176
+ <strong>Foreign Key (FK)</strong>
177
+ </label>
178
+
179
+ ${r?``:`<div style="font-size:11px; color:var(--color-text-soft); margin-top:-12px; margin-left:24px;">Note: FKs can only be added when creating new columns.</div>`}
180
+
181
+ <div id="fk-settings-container" style="display:${a?`flex`:`none`}; flex-direction:column; gap:8px; padding-left: 24px;">
182
+ <div>
183
+ <div style="font-size:12px; color:var(--color-text-secondary); margin-bottom:4px;">Target Table</div>
184
+ <select id="modal-fk-table" style="width:100%; padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);">
185
+ <option value="">Loading tables...</option>
186
+ </select>
187
+ </div>
188
+ <div>
189
+ <div style="font-size:12px; color:var(--color-text-secondary); margin-bottom:4px;">Target Column</div>
190
+ <select id="modal-fk-col" style="width:100%; padding:6px; border-radius:4px; border:1px solid var(--color-border); background:var(--color-bg-primary); color:var(--color-text-primary);" ${o?``:`disabled`}>
191
+ <option value="">Select a table first</option>
192
+ </select>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ <div style="padding:16px; border-top:1px solid var(--color-border); background:var(--color-bg-secondary); display:flex; justify-content:flex-end; gap:8px;">
197
+ <button id="cancel-pkfk-btn" class="secondary" style="padding:6px 16px; border-radius:4px; border:1px solid var(--color-border); cursor:pointer;">Cancel</button>
198
+ <button id="save-pkfk-btn" class="primary" style="padding:6px 16px; border-radius:4px; border:none; cursor:pointer;">Save</button>
199
+ </div>
200
+ </div>
201
+ `,document.body.appendChild(n);let c=()=>n.remove();document.getElementById(`close-pkfk-modal`).onclick=c,document.getElementById(`cancel-pkfk-btn`).onclick=c;let l=document.getElementById(`modal-is-fk`),u=document.getElementById(`fk-settings-container`),d=document.getElementById(`modal-fk-table`),f=document.getElementById(`modal-fk-col`);l.addEventListener(`change`,e=>{u.style.display=e.target.checked?`flex`:`none`});try{let e=await(await fetch(`/api/tables`)).json();e.success&&e.data&&(d.innerHTML=`<option value="">-- Select Table --</option>`+e.data.map(e=>`<option value="${e}" ${e===o?`selected`:``}>${e}</option>`).join(``),o&&p(o,s))}catch{d.innerHTML=`<option value="">Error loading tables</option>`}async function p(e,t=``){f.disabled=!0,f.innerHTML=`<option value="">Loading columns...</option>`;try{let n=await(await fetch(`/api/tables/${e}/schema`)).json();n.success&&n.data&&(f.innerHTML=`<option value="">-- Select Column --</option>`+n.data.map(e=>`<option value="${e.name}" ${e.name===t?`selected`:``}>${e.name}</option>`).join(``),f.disabled=!1)}catch{f.innerHTML=`<option value="">Error loading columns</option>`}}d.addEventListener(`change`,e=>{let t=e.target.value;t?p(t):(f.innerHTML=`<option value="">Select a table first</option>`,f.disabled=!0)}),document.getElementById(`save-pkfk-btn`).onclick=()=>{let t=document.getElementById(`modal-is-pk`).checked,n=document.getElementById(`modal-is-fk`).checked,r=d.value,l=f.value;if(t===i&&n===a&&r===o&&l===s){c();return}let u=``;if(t&&n){if(!r||!l){alert(`Please select both Target Table and Target Column for the Foreign Key.`);return}u=`PK, FK: ${r}.${l}`}else if(t)u=`PK`;else if(n){if(!r||!l){alert(`Please select both Target Table and Target Column for the Foreign Key.`);return}u=`FK: ${r}.${l}`}window.SchemaGrid.currentTransaction=[];let p=[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`indexing`];D(async()=>{let{updateSchemaCell:e}=await Promise.resolve().then(()=>M);return{updateSchemaCell:e}},void 0,import.meta.url).then(({updateSchemaCell:t})=>{t(e,u,p),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),c()}}function B(e,t){e.addEventListener(`click`,e=>{e.target.closest(`.manage-indexes-cell`)&&R()}),e.addEventListener(`dblclick`,e=>{let n=e.target.closest(`td.data-cell`);if(!n||n.querySelector(`input, select`))return;let r=n.dataset.colKey;n.dataset.insertIndex;let i=n.textContent===`-`||n.textContent===`+ New`||n.textContent===`No`||n.textContent===`null`?``:n.textContent===`Yes`?`1`:n.textContent,a;if(r===`isPk`){z(n,n.textContent);return}else if(r===`nullable`)a=document.createElement(`select`),[`No`,`Yes`].forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,(e===`Yes`&&i===`1`||e===`No`&&i===``)&&(t.selected=!0),a.appendChild(t)});else if(r===`type`){a=document.createElement(`select`);let e=[`INTEGER`,`TEXT`,`REAL`,`BLOB`,`NUMERIC`,`BOOLEAN`,`DATE`,`DATETIME`,`JSON`,`VARCHAR(255)`,`DECIMAL(10,2)`,`UUID`];i&&!e.some(e=>e.toUpperCase()===i.toUpperCase())&&e.unshift(i),e.forEach(e=>{let t=document.createElement(`option`);t.value=e,t.textContent=e,e.toUpperCase()===i.toUpperCase()&&(t.selected=!0),a.appendChild(t)})}else a=document.createElement(`input`),a.type=`text`,a.value=i;n.innerHTML=``,n.appendChild(a),a.style.width=`100%`,a.addEventListener(`keydown`,e=>{e.key===`Enter`&&a.blur()}),a.focus();let o=()=>{let e=a.value;window.SchemaGrid.currentTransaction=[],P(n,e,t),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null};a.addEventListener(`blur`,()=>{o()})})}async function V(e,t,n=null){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let r=document.getElementById(`table-name`);r&&(r.textContent=e+` (Schema)`);let i=n||document.getElementById(`main-content`);i.innerHTML=`<div style='padding:24px;'>Loading Schema...</div>`;try{let[n,r]=await Promise.all([l(e),u(e)]);if(n.success&&n.data){let a=n.data,o=r.success&&r.data?r.data:[];window.SchemaGrid={schema:a,indexes:o,pendingEdits:{},pendingIndexEdits:{added:[],dropped:[]},pendingInserts:[{}],pendingDeletes:new Set,selectedCell:null,history:[],currentTransaction:null,sortState:{colKey:null,asc:!0},filterText:``,isResizing:!1,selection:{startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1}},window.TableStates&&window.TableStates[e]&&(window.TableStates[e].schemaGrid=window.SchemaGrid),i.innerHTML=`
202
+ <div class="toolbar">
203
+ <div class="filter-group">
204
+ <div class="filter-icon-container">
205
+ <span class="material-symbols-outlined">search</span>
206
+ <span>Search</span>
207
+ </div>
208
+ <input type="text" id="schema-search-val-${e}" class="filter-input" placeholder="Search name or type..." style="width: 250px;" value="${window.SchemaGrid.filterText}" />
209
+ </div>
210
+ <div style="flex:1;"></div>
211
+ <button id="btn-refresh-schema-${e}" class="refresh-btn" title="Refresh Schema (F5)"><span class="material-symbols-outlined">refresh</span></button>
212
+ </div>
213
+ <div id="schema-grid-container-${e}" class="table-container"></div>
214
+ `,window.renderSchemaGrid=()=>{let t=document.getElementById(`schema-grid-container-${e}`);if(!t)return;let n=[...window.SchemaGrid.schema];if(window.SchemaGrid.filterText){let e=window.SchemaGrid.filterText.toLowerCase();n=n.filter(t=>t.name&&t.name.toLowerCase().includes(e)||t.type&&t.type.toLowerCase().includes(e))}window.SchemaGrid.sortState.colKey&&n.sort((e,t)=>{let n=window.SchemaGrid.sortState.colKey,r=e[n],i=t[n];return r??=``,i??=``,r<i?window.SchemaGrid.sortState.asc?-1:1:r>i?window.SchemaGrid.sortState.asc?1:-1:0});let r=[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`indexing`],i=[`Name`,`Type`,`PK/FK`,`Nullable`,`Default Value`,`Indexing`],a=`<table class="data-table" id="schema-grid-table-${e}"><thead><tr><th class="row-header">#</th>`;r.forEach((e,t)=>{let n=``;window.SchemaGrid.sortState.colKey===e&&(n=window.SchemaGrid.sortState.asc?`▲`:`▼`),a+=`<th class="sortable" data-col-key="${e}">
215
+ <div style="display: flex; justify-content: space-between; align-items: center;">
216
+ <div>${i[t]}</div>
217
+ <div class="sort-arrow" style="font-size:10px; opacity:0.8; margin-left: 8px; width: 12px; text-align: right;">${n}</div>
218
+ </div>
219
+ </th>`}),a+=`</tr></thead><tbody>`,n&&n.length>0&&n.forEach((e,t)=>{a+=`<tr><td class="row-header" data-row-idx="${t}">${t+1}</td>`,r.forEach((r,i)=>{if(r===`indexing`){if(t===0){let e=(n?n.length:0)+1,t=window.SchemaGrid.indexes.length,r=window.SchemaGrid.pendingIndexEdits.added.length,i=window.SchemaGrid.pendingIndexEdits.dropped.length,o=t+r-i;a+=`<td class="data-cell manage-indexes-cell" rowspan="${e}" style="text-align:center; vertical-align:middle; cursor:pointer; color:var(--color-brand-500); font-weight:500; border-left: 1px solid var(--color-border);">
220
+ Manage Indexes (${o})
221
+ </td>`}return}let o=e[r];if(r===`isPk`){let t=o,n=!!e.fkTarget;o=t&&n?`PK, FK (${e.fkTarget.table}.${e.fkTarget.column})`:t?`PK`:n?`FK (${e.fkTarget.table}.${e.fkTarget.column})`:`-`}else r===`nullable`?o=o?`Yes`:`No`:o??=``;let s=String(o).replace(/"/g,`&quot;`),c=o===``?`<span style="color:var(--color-text-soft)">-</span>`:String(o).replace(/</g,`&lt;`);a+=`<td class="data-cell" data-row-idx="${t}" data-col-idx="${i}" data-pk="${e.name}" data-col-key="${r}" data-original="${s}">${c}</td>`}),a+=`</tr>`}),a+=`<tr class="ghost-row-tr">`;let o=n?n.length:0;a+=`<td class="row-header" data-row-idx="${o}">*</td>`,r.forEach((e,t)=>{e!==`indexing`&&(a+=`<td class="data-cell ghost-row" data-row-idx="${o}" data-col-idx="${t}" data-insert-index="0" data-col-key="${e}">+ New</td>`)}),a+=`</tr></tbody></table>`,t.innerHTML=a,document.querySelectorAll(`#schema-grid-table-${e} th.sortable`).forEach(e=>{e.onclick=t=>{if(window.SchemaGrid.isResizing)return;if(Object.keys(window.SchemaGrid.pendingEdits).length>0||window.SchemaGrid.pendingInserts.length>1||window.SchemaGrid.pendingDeletes.size>0||window.SchemaGrid.pendingIndexEdits.added.length>0||window.SchemaGrid.pendingIndexEdits.dropped.length>0){alert(`You have unsaved changes! Please press Ctrl+S to save them before sorting.`);return}let n=e.dataset.colKey;window.SchemaGrid.sortState.colKey===n?window.SchemaGrid.sortState.asc=!window.SchemaGrid.sortState.asc:(window.SchemaGrid.sortState.colKey=n,window.SchemaGrid.sortState.asc=!0),window.SchemaGrid.selection={startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1},window.renderSchemaGrid()},_(e,window.SchemaGrid)}),h(t,`schema-grid-table-${e}`,window.SchemaGrid,r.length),B(t,r)},window.renderSchemaGrid();let s=document.getElementById(`schema-search-val-${e}`);s&&s.addEventListener(`input`,e=>{window.SchemaGrid.filterText=e.target.value,window.SchemaGrid.selection={startRow:-1,startCol:-1,endRow:-1,endCol:-1,isDragging:!1},window.renderSchemaGrid()});let c=document.getElementById(`btn-refresh-schema-${e}`);c&&(c.onclick=()=>{(Object.keys(window.SchemaGrid.pendingEdits).length>0||window.SchemaGrid.pendingInserts.length>1||window.SchemaGrid.pendingDeletes.size>0||window.SchemaGrid.pendingIndexEdits.added.length>0||window.SchemaGrid.pendingIndexEdits.dropped.length>0)&&!confirm(`You have unsaved changes. Are you sure you want to refresh and discard them?`)||(window.SchemaGrid.pendingEdits={},window.SchemaGrid.pendingInserts=[{}],window.SchemaGrid.pendingDeletes.clear(),window.SchemaGrid.pendingIndexEdits={added:[],dropped:[]},window.SchemaGrid.history=[],window.SchemaGrid.currentTransaction=null,window.updateSidebarDirtyState?.(),V(e,t,document.getElementById(`view-schema-btn-${e}`)))})}else i.innerHTML=`<div style="padding:24px; color:red;">Error: ${n.error}</div>`}catch(e){i.innerHTML=`<div style="padding:24px; color:red;">Failed to load schema: ${e.message}</div>`}}function H(e,t){document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),t&&t.classList.add(`active`);let n=document.getElementById(`table-name`);n&&(n.textContent=`SQL Console`);let r=document.getElementById(`main-content`);r.innerHTML=`
222
+ <div id="console-container" style="display: flex; flex-direction: column; flex: 1; height: 100%; min-width: 0;">
223
+ <div id="console-editor-pane" style="flex: 1; display: flex; flex-direction: column; border-bottom: 1px solid var(--color-border); position: relative; min-height: 200px;">
224
+ <div id="sql-editor" style="flex: 1; font-size: 14px;"></div>
225
+ <button id="run-sql-btn" class="primary" style="position: absolute; bottom: 16px; right: 24px; padding: 8px 16px; border-radius: 6px; border: none; background-color: var(--color-primary); color: #fff; font-weight: 600; cursor: pointer; box-shadow: 0 4px 6px rgba(0,0,0,0.1); z-index: 50; display: flex; align-items: center; gap: 6px; transition: all 0.2s;">
226
+ <span class="material-symbols-outlined" style="font-size: 18px;">play_arrow</span> Run (Ctrl+Enter)
227
+ </button>
228
+ </div>
229
+ <div id="console-results-pane" style="flex: 1; display: flex; flex-direction: column; overflow: hidden; background: #fff; min-height: 200px;">
230
+ <div id="console-results-header" style="padding: 8px 16px; background-color: var(--color-bg-secondary); border-bottom: 1px solid var(--color-border); font-size: 12px; color: var(--color-text-soft); font-weight: 600;">RESULTS</div>
231
+ <div class="table-container" id="console-table-container" style="flex: 1;">
232
+ <div style="padding: 24px; color: var(--color-text-soft); text-align: center; font-size: 14px;">Run a query to see results.</div>
233
+ </div>
234
+ </div>
235
+ </div>
236
+ `;let i=window.ace.edit(`sql-editor`);i.setTheme(`ace/theme/chrome`),i.session.setMode(`ace/mode/sql`),i.setOptions({showPrintMargin:!1,fontSize:`14px`,fontFamily:`ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace`,highlightActiveLine:!0}),window.AppState.lastQuery?i.setValue(window.AppState.lastQuery,1):i.setValue(`-- Enter your SQL query here
237
+ SELECT * FROM sqlite_master;
238
+ `,1),i.focus();let a=async()=>{let e=i.getValue().trim();if(!e)return;window.AppState.lastQuery=e;let t=document.getElementById(`console-table-container`),n=document.getElementById(`console-results-header`);n.textContent=`EXECUTING...`,n.style.color=`var(--color-primary)`,t.innerHTML=`<div style="padding: 24px; text-align: center; color: var(--color-text-soft);">Executing query...</div>`;try{let r=await d(e);if(!r.success){n.textContent=`ERROR`,n.style.color=`red`,t.innerHTML=`<div style="padding: 24px; color: red; font-family: monospace; white-space: pre-wrap;">${r.error}</div>`;return}let i=r.data.rows||[];if(n.textContent=`SUCCESS - ${i.length} rows returned`,n.style.color=`green`,i.length===0){t.innerHTML=`<div style="padding: 24px; text-align: center; color: var(--color-text-soft);">0 rows returned.</div>`;return}let a=Object.keys(i[0]),o=document.createElement(`table`);o.className=`data-table`;let s=document.createElement(`thead`),c=document.createElement(`tr`),l=document.createElement(`th`);l.className=`row-header`,l.textContent=`#`,c.appendChild(l),a.forEach(e=>{let t=document.createElement(`th`);t.textContent=e;let n=document.createElement(`div`);n.className=`resizer`,t.appendChild(n),n.addEventListener(`click`,e=>e.stopPropagation()),n.addEventListener(`mousedown`,e=>{e.preventDefault(),e.stopPropagation();let n=e.pageX,r=t.offsetWidth,i=e=>{let i=r+(e.pageX-n);t.style.width=i+`px`,t.style.minWidth=i+`px`,t.style.maxWidth=i+`px`},a=()=>{document.removeEventListener(`mousemove`,i),document.removeEventListener(`mouseup`,a),document.body.style.cursor=``};document.body.style.cursor=`col-resize`,document.addEventListener(`mousemove`,i),document.addEventListener(`mouseup`,a)}),c.appendChild(t)}),s.appendChild(c),o.appendChild(s);let u=document.createElement(`tbody`);i.forEach((e,t)=>{let n=document.createElement(`tr`),r=document.createElement(`td`);r.className=`row-header`,r.textContent=t+1,n.appendChild(r),a.forEach(t=>{let r=document.createElement(`td`),i=e[t];if(i===null){let e=document.createElement(`span`);e.textContent=`NULL`,e.style.color=`var(--color-text-soft)`,e.style.fontStyle=`italic`,r.appendChild(e)}else r.textContent=String(i);n.appendChild(r)}),u.appendChild(n)}),o.appendChild(u),t.innerHTML=``,t.appendChild(o)}catch(e){n.textContent=`ERROR`,n.style.color=`red`,t.innerHTML=`<div style="padding: 24px; color: red; font-family: monospace; white-space: pre-wrap;">${e.message}</div>`}};document.getElementById(`run-sql-btn`).onclick=a,i.commands.addCommand({name:`run`,bindKey:{win:`Ctrl-Enter`,mac:`Command-Enter`},exec:function(){a()}})}var U=document.getElementById(`header-container`),W=document.getElementById(`sidebar-container`),G=document.getElementById(`tab-container`);U.innerHTML=n,W.innerHTML=r,G.innerHTML=i,window.AppState={currentTable:null,currentTab:`data-btn`,currentTableBtnElement:null},window.TableStates={},window.ViewCache={},window.updateSidebarDirtyState=function(){document.querySelectorAll(`.table-btn`).forEach(e=>{let t=e.dataset.table,n=e.querySelector(`span`).textContent,r=t||n.replace(/\s*\*$/,``),i=window.TableStates[r],a=!1;if(i){if(i.dataGrid){let e=i.dataGrid;(Object.keys(e.pendingEdits||{}).length>0||e.pendingInserts&&e.pendingInserts.length>1||e.pendingDeletes&&e.pendingDeletes.size>0)&&(a=!0)}if(i.schemaGrid){let e=i.schemaGrid,t=e.pendingIndexEdits&&(e.pendingIndexEdits.added.length>0||e.pendingIndexEdits.dropped.length>0);(Object.keys(e.pendingEdits||{}).length>0||e.pendingInserts&&e.pendingInserts.length>1||e.pendingDeletes&&e.pendingDeletes.size>0||t)&&(a=!0)}}let o=e.querySelector(`span`),s=o.textContent.replace(/\s*\*$/,``);a?(o.textContent=s+` *`,o.style.fontWeight=`bold`):(o.textContent=s,o.style.fontWeight=`normal`)})},window.handleSwitchTab=function(e){document.querySelectorAll(`.tab-btn`).forEach(e=>e.classList.remove(`isCurrentTab`));let t=document.getElementById(e);if(t&&t.classList.add(`isCurrentTab`),window.AppState.currentTab=e,e===`erd-btn`||e===`sql-btn`||e===`status-btn`)window.AppState.currentTable=null,window.AppState.currentTableBtnElement=null,document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`));else if((e===`data-btn`||e===`schema-btn`)&&!window.AppState.currentTable){let e=document.querySelector(`.table-btn`);e&&(window.AppState.currentTable=e.querySelector(`span`).textContent,window.AppState.currentTableBtnElement=e,e.classList.add(`active`))}window.renderCurrentView()},window.renderEmptyState=function(e){e.innerHTML=`
239
+ <div class="empty-state">
240
+ <div class="icon-container">
241
+ <span class="material-symbols-outlined">database</span>
242
+ </div>
243
+ <h2>No Table Selected</h2>
244
+ <p>Select a table from the sidebar to view its data, schema, or run SQL queries.</p>
245
+ </div>
246
+ `},window.renderCurrentView=function(e=``,t=!1){let n=[`erd-btn`,`sql-btn`,`status-btn`].includes(window.AppState.currentTab),r=document.getElementById(`main-content`);document.querySelectorAll(`.view-container`).forEach(e=>e.style.display=`none`);let i=n?`view-${window.AppState.currentTab}`:`view-${window.AppState.currentTab}-${window.AppState.currentTable}`,a=document.getElementById(i);if(a||(a=document.createElement(`div`),a.id=i,a.className=`view-container`,a.style.width=`100%`,a.style.flex=`1`,a.style.display=`flex`,a.style.flexDirection=`column`,a.style.overflow=`hidden`,r.appendChild(a)),a.style.display=`flex`,!window.AppState.currentTable&&!n){window.renderEmptyState(a);return}let o=window.AppState.currentTable;o&&!window.TableStates[o]&&(window.TableStates[o]={dataGrid:null,schemaGrid:null}),window.AppState.currentTab===`data-btn`?(window.TableStates[o].dataGrid&&(window.DataGrid=window.TableStates[o].dataGrid),(!window.TableStates[o].dataGrid||!a.hasChildNodes())&&j(o,window.AppState.currentTableBtnElement,e,t,a)):window.AppState.currentTab===`schema-btn`?(window.TableStates[o].schemaGrid&&(window.SchemaGrid=window.TableStates[o].schemaGrid),(!window.TableStates[o].schemaGrid||!a.hasChildNodes())&&V(o,window.AppState.currentTableBtnElement,a)):window.AppState.currentTab===`console-btn`?a.hasChildNodes()||H(o,window.AppState.currentTableBtnElement,a):window.AppState.currentTab===`erd-btn`?a.hasChildNodes()||(a.innerHTML=`<div style='padding:24px; color: var(--color-text-soft);'>ERD Visualization coming soon!</div>`):window.AppState.currentTab===`status-btn`&&(a.hasChildNodes()||(a.innerHTML=`<div style='padding:24px; color: var(--color-text-soft);'>Database Status Dashboard coming soon!</div>`)),document.querySelectorAll(`.table-btn`).forEach(e=>e.classList.remove(`active`)),window.AppState.currentTableBtnElement&&window.AppState.currentTableBtnElement.classList.add(`active`)},window.saveDataGridEdits=y,window.saveSchemaEdits=N,document.addEventListener(`DOMContentLoaded`,()=>{f();let e=localStorage.getItem(`drixio-theme`),t=window.matchMedia&&window.matchMedia(`(prefers-color-scheme: dark)`).matches;if(e===`dark`||!e&&t){document.documentElement.setAttribute(`data-theme`,`dark`);let e=document.getElementById(`theme-icon`);e&&(e.textContent=`light_mode`)}let n=document.getElementById(`theme-toggle`);n&&n.addEventListener(`click`,()=>{let e=document.documentElement.getAttribute(`data-theme`)===`dark`,t=e?`light`:`dark`;document.documentElement.setAttribute(`data-theme`,t),localStorage.setItem(`drixio-theme`,t),document.getElementById(`theme-icon`).textContent=e?`dark_mode`:`light_mode`}),window.showToast=function(e,t=`success`){let n=document.getElementById(`toast-container`);if(!n)return;let r=document.createElement(`div`);r.className=`toast ${t}`,r.innerHTML=`<span class="material-symbols-outlined">${t===`success`?`check_circle`:`error`}</span> <span>${e}</span>`,n.appendChild(r),setTimeout(()=>{r.parentNode&&r.parentNode.removeChild(r)},3e3)},document.addEventListener(`mouseup`,()=>{window.DataGrid&&window.DataGrid.selection&&(window.DataGrid.selection.isDragging=!1),window.SchemaGrid&&window.SchemaGrid.selection&&(window.SchemaGrid.selection.isDragging=!1)}),document.addEventListener(`contextmenu`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(!t&&!n||t&&!window.DataGrid||n&&!window.SchemaGrid)return;let r=e.target.closest(`td.row-header`);if(!r)return;e.preventDefault();let i=parseInt(r.dataset.rowIdx);document.getElementById(`custom-context-menu`)?.remove();let a=document.createElement(`div`);a.id=`custom-context-menu`,a.className=`context-menu`,a.style.top=`${e.clientY}px`,a.style.left=`${e.clientX}px`,a.innerHTML=`
247
+ <div class="context-menu-item" id="cmenu-duplicate">
248
+ <span class="material-symbols-outlined" style="font-size:16px;">content_copy</span> Duplicate Row(s)
249
+ </div>
250
+ <div class="context-menu-item danger" id="cmenu-delete">
251
+ <span class="material-symbols-outlined" style="font-size:16px;">delete</span> Delete Row(s)
252
+ </div>
253
+ `,document.body.appendChild(a);let o=e=>{let r=[i],o=t?window.DataGrid:window.SchemaGrid;if(o&&o.selection&&o.selection.startRow!==-1){let e=o.selection,t=Math.min(e.startRow,e.endRow),n=Math.max(e.startRow,e.endRow);if(i>=t&&i<=n){r=[];for(let e=t;e<=n;e++)r.push(e)}}t?D(()=>Promise.resolve().then(()=>v).then(t=>{window.DataGrid.currentTransaction=[],e===`delete`?r.forEach(e=>t.markRowDeleted(e)):e===`duplicate`&&(t.duplicateDataRows(r,window.DataGrid.schema.map(e=>e.name)),setTimeout(()=>{let e=document.getElementById(`data-grid-container-${window.AppState.currentTable}`);e&&(e.scrollTop=e.scrollHeight)},50)),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(t=>{window.SchemaGrid.currentTransaction=[],e===`delete`?r.forEach(e=>t.markSchemaRowDeleted(e)):e===`duplicate`&&(t.duplicateSchemaRows(r,[`name`,`type`,`isPk`,`nullable`,`defaultValue`,`Index`]),setTimeout(()=>{let e=document.getElementById(`schema-grid-container-${window.AppState.currentTable}`);e&&(e.scrollTop=e.scrollHeight)},50)),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),void 0,import.meta.url),a.remove()};document.getElementById(`cmenu-duplicate`).onclick=()=>o(`duplicate`),document.getElementById(`cmenu-delete`).onclick=()=>o(`delete`);let s=e=>{a.contains(e.target)||(a.remove(),document.removeEventListener(`click`,s))};setTimeout(()=>document.addEventListener(`click`,s),0)}),document.addEventListener(`keydown`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(e.key===`F5`){t&&window.DataGrid?.refreshData?(e.preventDefault(),window.DataGrid.refreshData()):n&&document.getElementById(`btn-refresh-schema`)&&(e.preventDefault(),document.getElementById(`btn-refresh-schema`).click());return}if(!(!t&&!n)&&!(e.target.tagName===`INPUT`||e.target.tagName===`SELECT`||e.target.tagName===`TEXTAREA`)){if([`ArrowUp`,`ArrowDown`,`ArrowLeft`,`ArrowRight`].includes(e.key)){let n=t?window.DataGrid:window.SchemaGrid;if(!n||!n.selection)return;e.preventDefault();let r=n.selection;if(r.startRow===-1)return;let i=t?n.schema.length:5,a=window.AppState?.currentTable,o=document.querySelectorAll(t?`#data-grid-table-${a} tbody tr`:`#schema-grid-table-${a} tbody tr`),s=o.length>0?o.length-1:0,c=e.shiftKey?r.endRow:r.startRow,l=e.shiftKey?r.endCol:r.startCol;e.key===`ArrowUp`&&(c=Math.max(0,c-1)),e.key===`ArrowDown`&&(c=Math.min(s,c+1)),e.key===`ArrowLeft`&&(l=Math.max(0,l-1)),e.key===`ArrowRight`&&(l=Math.min(i-1,l+1)),e.shiftKey?(r.endRow=c,r.endCol=l):(r.startRow=c,r.endRow=c,r.startCol=l,r.endCol=l);let u=t?`data-grid-table-${a}`:`schema-grid-table-${a}`;D(()=>Promise.resolve().then(()=>p).then(e=>e.renderSelection(u,n)),void 0,import.meta.url),setTimeout(()=>{let e=document.querySelector(t?`#data-grid-table-${a} td.data-cell[data-row-idx="${c}"][data-col-idx="${l}"]`:`#schema-grid-table-${a} td.data-cell[data-row-idx="${c}"][data-col-idx="${l}"]`);if(e){let n=document.getElementById(t?`data-grid-container`:`schema-grid-container`);if(n){let t=e.getBoundingClientRect(),r=n.getBoundingClientRect();t.bottom>r.bottom?n.scrollTop+=t.bottom-r.bottom+5:t.top<r.top+30&&(n.scrollTop-=r.top+30-t.top),t.right>r.right?n.scrollLeft+=t.right-r.right+5:t.left<r.left+50&&(n.scrollLeft-=r.left+50-t.left)}}},5);return}if((e.key===`Delete`||e.key===`Backspace`)&&(t?D(()=>Promise.resolve().then(()=>v).then(e=>{window.DataGrid.currentTransaction=[],document.querySelectorAll(`#data-grid-table-${window.AppState.currentTable} .cell-in-range`).forEach(t=>e.updateCell(t,``,window.DataGrid.schema.map(e=>e.name))),window.DataGrid.currentTransaction.length>0&&window.DataGrid.history.push(window.DataGrid.currentTransaction),window.DataGrid.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{window.SchemaGrid.currentTransaction=[];let t=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];document.querySelectorAll(`#schema-grid-table-${window.AppState.currentTable} .cell-in-range`).forEach(n=>{(n.dataset.insertIndex!==void 0||n.dataset.colKey===`name`)&&e.updateSchemaCell(n,``,t)}),window.SchemaGrid.currentTransaction.length>0&&window.SchemaGrid.history.push(window.SchemaGrid.currentTransaction),window.SchemaGrid.currentTransaction=null}),void 0,import.meta.url)),e.key.toLowerCase()===`s`&&(e.ctrlKey||e.metaKey)&&(e.preventDefault(),t&&window.saveDataGridEdits(),n&&window.saveSchemaEdits()),e.key.toLowerCase()===`c`&&(e.ctrlKey||e.metaKey)){let e=(t?window.DataGrid:window.SchemaGrid).selection;if(e.startRow===-1)return;let n=Math.min(e.startRow,e.endRow),r=Math.max(e.startRow,e.endRow),i=Math.min(e.startCol,e.endCol),a=Math.max(e.startCol,e.endCol),o=``;for(let e=n;e<=r;e++){let n=[];for(let r=i;r<=a;r++){let i=document.querySelector(t?`#data-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${e}"][data-col-idx="${r}"]`:`#schema-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${e}"][data-col-idx="${r}"]`);if(i){let e=i.textContent.replace(/^null$|^\+ New$/,``);n.push(e)}}o+=n.join(` `)+`
254
+ `}navigator.clipboard.writeText(o.trimEnd()),document.querySelectorAll(`.cell-in-range`).forEach(e=>{e.style.backgroundColor=`#bfdbfe`,setTimeout(()=>e.style.backgroundColor=``,150)})}if(e.key===`-`&&(e.ctrlKey||e.metaKey)){e.preventDefault();let r=t?window.DataGrid:window.SchemaGrid,i=r.selection;if(i.startRow===-1)return;let a=Math.min(i.startRow,i.endRow),o=Math.max(i.startRow,i.endRow);t?D(()=>Promise.resolve().then(()=>v).then(e=>{r.currentTransaction=[];for(let t=a;t<=o;t++)e.markRowDeleted(t);r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{r.currentTransaction=[];for(let t=a;t<=o;t++)e.markSchemaRowDeleted(t);r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url)}if(e.key.toLowerCase()===`z`&&(e.ctrlKey||e.metaKey)){if(e.preventDefault(),t){let e=window.DataGrid.history?.pop();e&&D(()=>Promise.resolve().then(()=>v).then(t=>{let n=window.DataGrid.schema.map(e=>e.name);for(let r=e.length-1;r>=0;r--){let i=e[r];i.type===`delete`?t.unmarkRowDeleted(i.rowIdx,i.pk):t.updateCell(i.td,i.oldVal,n,!1)}}),void 0,import.meta.url)}else if(n){let e=window.SchemaGrid.history?.pop();e&&D(()=>Promise.resolve().then(()=>M).then(t=>{let n=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];for(let r=e.length-1;r>=0;r--){let i=e[r];i.type===`delete`?t.unmarkSchemaRowDeleted(i.rowIdx,i.pk):t.updateSchemaCell(i.td,i.oldVal,n,!1)}}),void 0,import.meta.url)}}}}),document.addEventListener(`paste`,e=>{let t=window.AppState?.currentTab===`data-btn`,n=window.AppState?.currentTab===`schema-btn`;if(!t&&!n)return;let r=t?window.DataGrid:window.SchemaGrid;if(!r||e.target.tagName===`INPUT`||e.target.tagName===`SELECT`||e.target.tagName===`TEXTAREA`)return;let i=r.selection;if(i.startRow===-1)return;let a=e.clipboardData.getData(`text`);if(!a)return;e.preventDefault();let o=a.split(/\r?\n/).map(e=>e.split(` `)),s=Math.min(i.startRow,i.endRow),c=Math.min(i.startCol,i.endCol);r.currentTransaction=[],t?D(()=>Promise.resolve().then(()=>v).then(e=>{let t=r.schema.map(e=>e.name);o.forEach(n=>{n.forEach((n,r)=>{let i=c+r,a=document.querySelector(`#data-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${s}"][data-col-idx="${i}"]`);a&&e.updateCell(a,n,t)}),s++}),r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url):n&&D(()=>Promise.resolve().then(()=>M).then(e=>{let t=[`name`,`type`,`isPk`,`nullable`,`defaultValue`];o.forEach(n=>{n.forEach((n,r)=>{let i=c+r,a=document.querySelector(`#schema-grid-table-${window.AppState.currentTable} td.data-cell[data-row-idx="${s}"][data-col-idx="${i}"]`);a&&(a.dataset.insertIndex!==void 0||a.dataset.colKey===`name`)&&e.updateSchemaCell(a,n,t)}),s++}),r.currentTransaction.length>0&&r.history.push(r.currentTransaction),r.currentTransaction=null}),void 0,import.meta.url)})});
@@ -0,0 +1 @@
1
+ @import "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap";:root{--color-bg-primary:#fff;--color-bg-secondary:#f8fafc;--color-bg-secondary-dark:#f1f5f9;--color-primary:#2c68ec;--color-primary-active:#eff6ff;--color-primary-dark:#285bb8;--color-text:#0f172a;--color-text-soft:#94a3b8;--color-text-secondary:#64748b;--color-border:#e2e8f0;--color-border-soft:#f1f5f9;--ring-primary-2:0 0 0 2px #2c68ec33;--font-inter:"Inter", sans-serif;--color-btn-active-text:var(--color-primary);--color-cell-range-bg:#dbeafe;--color-cell-edited-bg:#fffbeb;--color-cell-edited-text:#b45309;--color-cell-error-bg:#fef2f2;--color-row-deleted-bg:#fee2e2;--color-row-deleted-text:#ef4444;--color-ghost-row-bg:#f8fafc}[data-theme=dark]{--color-bg-primary:#0f172a;--color-bg-secondary:#1e293b;--color-bg-secondary-dark:#334155;--color-primary:#3b82f6;--color-primary-active:#1e3a8a;--color-primary-dark:#60a5fa;--color-text:#f8fafc;--color-text-soft:#64748b;--color-text-secondary:#cbd5e1;--color-border:#334155;--color-border-soft:#1e293b;--ring-primary-2:0 0 0 2px #3b82f633;--color-btn-active-text:#fff;--color-cell-range-bg:#3b82f626;--color-cell-edited-bg:#f59e0b26;--color-cell-edited-text:#fbbf24;--color-cell-error-bg:#ef444426;--color-row-deleted-bg:#ef444426;--color-row-deleted-text:#f87171;--color-ghost-row-bg:var(--color-bg-secondary)}body,html{background-color:var(--color-bg-primary);width:100vw;height:100vh;color:var(--color-text);font-family:var(--font-inter);margin:0;padding:0;display:flex;overflow:hidden}main{flex-direction:column;flex:1;min-width:0;display:flex}aside{border-right:1px var(--color-border) solid;box-sizing:border-box;flex-direction:column;width:256px;height:100vh;display:flex}#sidebar-header{border-bottom:1px var(--color-border-soft) solid;box-sizing:border-box;align-items:center;gap:8px;height:64px;padding:0 16px;display:flex}.table-btn{color:var(--color-text-secondary);cursor:pointer;letter-spacing:.5px;background-color:#0000;border:1px solid #0000;border-radius:8px;outline:none;justify-content:space-between;align-items:center;padding:10px 16px;font-size:12px;font-weight:500;transition:all .2s;display:flex}#sidebar-footer{flex:1;align-items:center;min-width:0;display:flex}aside{border-right:1px var(--color-border) solid;flex-direction:column;width:256px;height:100vh;display:flex}#sidebar-header{border-bottom:1px var(--color-border-soft) solid;align-items:center;gap:8px;height:64px;padding:0 16px;display:flex}#database-icon{color:var(--color-primary);font-size:26px}#brand-title{letter-spacing:.5px;align-items:center;gap:4px;margin:0;padding:0;font-size:16px;font-weight:bolder;line-height:1;display:flex}#brand-subtitle{background-color:var(--color-primary);color:#fff;border-radius:5px;align-items:center;height:100%;padding:4px 6px;font-size:12px;font-weight:600;line-height:1;display:flex}#sidebar-content{flex-direction:column;flex:1;gap:24px;padding:16px;display:flex}#search-bar{background-color:var(--color-bg-secondary);border:1px var(--color-border) solid;border-radius:8px;outline:none;align-items:center;padding:0 4px;transition:all .1s linear;display:flex;overflow:hidden}#search-bar:focus-within{border:1px var(--color-primary) solid;box-shadow:var(--ring-primary-2);background-color:var(--color-bg-primary);transform:scale(1.02)}#search-icon{color:var(--color-text-soft);margin:0 3px 0 6px;font-size:20px;transition:all .1s linear}#search-bar:focus-within #search-icon{color:var(--color-primary);transform:scale(1.15)}#search-input{width:100%;height:34px;color:var(--color-text);background-color:#0000;border:none;outline:none;font-size:12px}#search-input::placeholder{color:var(--color-text-soft)}#table-nav{flex-direction:column;flex:1;gap:6px;display:flex;overflow-y:auto}#table-nav::-webkit-scrollbar{width:4px}#table-nav::-webkit-scrollbar-track{background:0 0}#table-nav::-webkit-scrollbar-thumb{background:var(--color-border);border-radius:4px}#table-nav::-webkit-scrollbar-thumb:hover{background:var(--color-text-soft)}.table-btn{color:var(--color-text-secondary);cursor:pointer;background-color:#0000;border:1px solid #0000;border-radius:8px;outline:none;justify-content:space-between;align-items:center;padding:10px 16px;font-size:12px;font-weight:500;transition:all .2s;display:flex}.table-btn:hover{background-color:var(--color-bg-secondary);color:var(--color-text)}.table-btn:active{transform:scale(.97)}.table-btn.active{background-color:var(--color-primary-active);border:1px var(--color-primary) solid;color:var(--color-btn-active-text);font-weight:600}.table-btn-badge{background-color:var(--color-bg-secondary-dark);color:var(--color-text-secondary);border-radius:10px;justify-content:center;align-items:center;min-width:16px;min-height:16px;padding:1px;font-size:8px;font-weight:600;line-height:1;display:flex}.table-btn.active .table-btn-badge{background-color:var(--color-primary);color:#fff}#not-found-msg{color:var(--color-text-soft);flex:1;justify-content:center;align-items:center;font-size:12px;font-weight:400;display:flex}#sidebar-footer{border-top:1px var(--color-border-soft) solid;justify-content:center;align-items:center;max-height:fit-content;margin-top:auto;padding:16px;display:flex}#theme-toggle{background-color:var(--color-bg-secondary);color:var(--color-text-secondary);border:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;width:100%;padding:12px 24px;font-weight:600;transition:all .1s linear;display:flex}#theme-toggle:hover{color:var(--color-primary);border-color:var(--color-primary);background-color:var(--color-bg-primary)}header{border-bottom:1px var(--color-border) solid;box-sizing:border-box;justify-content:space-between;align-items:center;width:100%;height:64px;padding:0 32px;font-size:14px;font-weight:300;display:flex;position:sticky;top:0}#current-path{text-transform:lowercase;align-items:center;gap:10px;display:flex}#db-name{color:var(--color-text-secondary)}#slash{color:var(--color-text-soft);font-size:18px;font-weight:lighter}#current-table{align-items:center;gap:4px;display:flex}#table-icon{color:var(--color-primary);font-size:20px}#table-name{color:var(--color-text);font-weight:600}#tab-nav{border-bottom:1px var(--color-border) solid;gap:24px;height:48px;padding:0 32px;display:flex}.tab-btn{height:100%;color:var(--color-text-secondary);cursor:pointer;background-color:#0000;border:none;border-bottom:2px solid #0000;outline:none;align-items:center;gap:8px;padding:0 6px;font-size:12px;font-weight:300;line-height:1;transition:all .1s linear;display:flex}.tab-btn:hover{border-bottom:2px var(--color-border) solid;color:var(--color-text)}.tab-btn.isCurrentTab{border-bottom:2px var(--color-primary) solid;color:var(--color-primary)}.tab-btn .material-symbols-outlined{font-size:16px}#main-content{background-color:var(--color-bg-primary);flex-direction:column;flex:1;min-width:0;display:flex;overflow:hidden}.toolbar{border-bottom:1px var(--color-border) solid;background-color:var(--color-bg-secondary);flex-shrink:0;align-items:center;height:48px;display:flex}.filter-group{flex:1;align-items:center;height:100%;transition:all .15s;display:flex;overflow:hidden}.filter-icon-container{background-color:var(--color-bg-secondary);border-right:1px var(--color-border) solid;align-items:center;gap:6px;height:100%;padding:0 16px;font-size:16px;display:flex}.filter-icon-container .material-symbols-outlined{color:var(--color-text-secondary);font-size:18px}.filter-icon-container span:not(.material-symbols-outlined){text-transform:uppercase;color:var(--color-text-secondary);font-size:13px;font-weight:500}.filter-select{height:100%;color:var(--color-text-secondary);border:none;border-right:1px var(--color-border) solid;cursor:pointer;background-color:#0000;outline:none;padding:0 16px;font-size:13px;font-weight:500}.filter-select:hover{background-color:var(--color-bg-secondary)}.filter-input{height:100%;color:var(--color-text);background:0 0;border:none;outline:none;flex:1;padding:0 20px;font-size:13px;font-weight:200}.filter-input::placeholder{color:var(--color-text-soft)}#btn-run-query{background-color:var(--color-primary);color:#fff;border:none;border-right:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;padding:8px 12px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}#btn-run-query:hover{background-color:var(--color-primary-dark)}#btn-run-query .material-symbols-outlined{margin-bottom:.5px;font-size:16px}#btn-clear-query{background-color:var(--color-bg-primary);color:var(--color-text-secondary);border:none;border:1px var(--color-border) solid;cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;margin-left:16px;padding:8px 12px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}#btn-clear-query:hover{background-color:var(--color-bg-secondary-dark);color:var(--color-text)}#btn-run-query:active,#btn-clear-query:active,.btn-primary:active,.btn-secondary:active,.table-btn:active{transform:scale(.96)}#btn-clear-query .material-symbols-outlined{margin-bottom:.5px;font-size:16px}.refresh-btn{background-color:var(--color-bg-secondary);border:1px var(--color-border) solid;color:var(--color-text-secondary);cursor:pointer;border-radius:8px;outline:none;justify-content:center;align-items:center;gap:8px;margin:16px;padding:6px;font-size:10px;font-weight:700;transition:all .1s linear;display:flex}.refresh-btn:hover{background-color:var(--color-bg-secondary-dark);color:var(--color-text)}.refresh-btn .material-symbols-outlined{margin-bottom:.5px;font-size:18px}.sql-console-wrapper{flex-direction:column;height:100%;display:flex}.sql-editor{resize:vertical;border:none;border-bottom:1px var(--color-border) solid;background-color:var(--color-bg-primary);width:100%;height:200px;min-height:100px;color:var(--color-text);outline:none;padding:16px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px}.sql-editor:focus{background-color:#fcfcfc}.table-container{background-color:var(--color-bg-primary);scrollbar-width:none;-ms-overflow-style:none;flex:1;width:100%;min-width:0;overflow:auto}.table-container::-webkit-scrollbar{display:none}.data-table{border-collapse:separate;border-spacing:0;-webkit-user-select:none;user-select:none;width:max-content;min-width:100%}.data-table input,.data-table select{-webkit-user-select:text;user-select:text;box-sizing:border-box}.data-table th,.data-table td{text-align:left;border-bottom:1px var(--color-border-soft) solid;border-right:1px var(--color-border-soft) solid;white-space:nowrap;cursor:cell;height:24px;padding:8px 16px;font-size:13px;position:relative}.data-table th{background-color:var(--color-primary);color:#fff;text-transform:uppercase;letter-spacing:.5px;z-index:10;border-bottom:1px var(--color-border) solid;box-shadow:0 1px 0 var(--color-border);cursor:default;border-right:1px solid #fff3;font-size:11px;font-weight:600;position:sticky;top:0}.data-table td.cell-in-range{background-color:var(--color-cell-range-bg)}.data-table td.cell-in-range:after{content:"";box-sizing:border-box;pointer-events:none;border-top:var(--border-t,0);border-bottom:var(--border-b,0);border-left:var(--border-l,0);border-right:var(--border-r,0);position:absolute;inset:0}.data-table td.range-top{--border-t:2px solid var(--color-primary)}.data-table td.range-bottom{--border-b:2px solid var(--color-primary)}.data-table td.range-left{--border-l:2px solid var(--color-primary)}.data-table td.range-right{--border-r:2px solid var(--color-primary)}.data-table td.cell-selected{background-color:var(--color-bg-primary);z-index:5;box-shadow:inset 0 0 0 2px var(--color-primary)}.data-table td.row-header,.data-table th.row-header{z-index:9;background-color:var(--color-bg-secondary);color:var(--color-text-soft);text-align:center;border-right:1px var(--color-border) solid;width:32px;min-width:32px;padding:8px 4px;font-weight:500;position:sticky;left:0}.data-table th.row-header{z-index:11;background-color:var(--color-primary);color:#fff}.data-table td.cell-edited{background-color:var(--color-cell-edited-bg);color:var(--color-cell-edited-text);font-weight:700}.data-table td.cell-error{background-color:var(--color-cell-error-bg)}.data-table td.cell-error:not(.cell-in-range):not(.cell-selected){box-shadow:inset 0 0 0 2px #ef4444}.data-table tr.row-deleted td{text-decoration:line-through;background-color:var(--color-row-deleted-bg)!important;color:var(--color-row-deleted-text)!important}.data-table td.ghost-row{color:var(--color-text-soft);background-color:var(--color-ghost-row-bg);font-style:italic}.data-table td input,.data-table td select{box-sizing:border-box;width:100%;height:100%;color:var(--color-text);background-color:var(--color-bg-primary);box-shadow:var(--ring-primary-2);border:none;outline:none;padding:0 16px;font-family:inherit;font-size:13px;position:absolute;top:0;left:0}.data-table tbody tr:hover:not(:has(.manage-indexes-cell:hover)){background-color:var(--color-bg-secondary)}.manage-indexes-cell{background-color:var(--color-bg-primary)!important}.manage-indexes-cell:hover{background-color:var(--color-bg-secondary)!important}.context-menu{background-color:var(--color-bg-primary);border:1px var(--color-border) solid;z-index:9999;border-radius:6px;flex-direction:column;min-width:150px;padding:4px;display:flex;position:absolute;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.context-menu-item{color:var(--color-text);cursor:pointer;border-radius:4px;align-items:center;gap:8px;padding:8px 12px;font-size:13px;display:flex}.context-menu-item:hover{background-color:var(--color-bg-secondary)}.context-menu-item.danger{color:#ef4444}.context-menu-item.danger:hover{background-color:#fef2f2}.resizer{cursor:col-resize;-webkit-user-select:none;user-select:none;z-index:10;width:8px;height:100%;position:absolute;top:0;right:-4px}.resizer:hover,.resizer:active{background-color:var(--color-primary);opacity:.5}.cell-expand-btn{cursor:pointer;color:var(--color-text-soft);background-color:var(--color-bg-primary);border:1px var(--color-border) solid;z-index:10;border-radius:4px;justify-content:center;align-items:center;padding:3px;font-size:14px;transition:all .1s;display:flex;position:absolute;top:50%;right:6px;transform:translateY(-50%);box-shadow:0 2px 4px #0000000d}.cell-expand-btn:hover{color:var(--color-primary);border-color:var(--color-primary)}#modal-editor-overlay{-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);z-index:9999;background-color:#0f172a66;justify-content:center;align-items:center;width:100vw;height:100vh;display:flex;position:fixed;top:0;left:0}.modal-editor-container{background-color:var(--color-bg-primary);background-color:rgba(var(--color-bg-primary), .85);background:var(--color-bg-primary);border-radius:12px;flex-direction:column;width:600px;max-width:90vw;height:500px;max-height:90vh;display:flex;overflow:hidden;box-shadow:0 10px 25px -5px #0000001a,0 8px 10px -6px #0000001a}.modal-header{border-bottom:1px var(--color-border) solid;color:var(--color-text);align-items:center;gap:8px;padding:16px 20px;display:flex}.modal-header h3{margin:0;font-size:16px;font-weight:600}.modal-header .material-symbols-outlined{color:var(--color-primary)}#modal-textarea{resize:none;color:var(--color-text);background-color:var(--color-bg-secondary-dark);border:none;outline:none;flex:1;padding:20px;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:13px}#modal-textarea:focus{background-color:var(--color-bg-primary)}.modal-footer{border-top:1px var(--color-border) solid;background-color:var(--color-bg-secondary);justify-content:flex-end;gap:12px;padding:16px 20px;display:flex}.modal-footer button{cursor:pointer;border:1px var(--color-border) solid;background-color:var(--color-bg-primary);color:var(--color-text);border-radius:6px;padding:8px 16px;font-size:13px;font-weight:500;transition:all .2s}.modal-footer button:active{transform:scale(.97)}.modal-footer button:hover{background-color:var(--color-bg-secondary-dark)}.modal-footer button.primary{background-color:var(--color-primary);color:#fff;border-color:var(--color-primary)}.modal-footer button.primary:hover{background-color:var(--color-primary-dark)}.empty-state{flex-direction:column;flex:1;justify-content:center;align-items:center;display:flex}.empty-state .icon-container{background-color:var(--color-primary);color:#fff;border-radius:10px;justify-content:center;align-items:center;width:64px;height:64px;display:flex;box-shadow:0 4px 6px -1px #0000001a,0 2px 4px -2px #0000001a}.empty-state .material-symbols-outlined{font-size:36px}.empty-state h2{color:var(--color-text);margin-top:32px;margin-bottom:10px;font-size:24px;font-weight:700}.empty-state p{color:var(--color-text-secondary);text-align:center;max-width:500px;margin:0;font-size:16px;line-height:1.5}#toast-container{z-index:10000;flex-direction:column;gap:10px;display:flex;position:fixed;bottom:20px;right:20px}.toast{background-color:var(--color-bg-primary);color:var(--color-text);border-left:4px solid var(--color-primary);opacity:0;border-radius:8px;align-items:center;gap:8px;padding:12px 20px;font-size:14px;font-weight:500;animation:.3s ease-out forwards slideIn,.3s ease-in 2.7s forwards fadeOut;display:flex;transform:translate(100%);box-shadow:0 4px 12px #00000026}.toast.error{border-left-color:#ef4444}@keyframes slideIn{0%{opacity:0;transform:translate(100%)}to{opacity:1;transform:translate(0)}}@keyframes fadeOut{0%{opacity:1}to{opacity:0}}#theme-toggle{color:var(--color-text-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;justify-content:center;align-items:center;padding:6px;transition:all .2s;display:flex}#theme-toggle:hover{background-color:var(--color-bg-secondary);color:var(--color-text)}#theme-toggle:active{transform:scale(.9)}
@@ -10,11 +10,14 @@
10
10
 
11
11
  <title>DRIXIO STUDIO</title>
12
12
  <!-- Ace Editor for SQL Console -->
13
- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js" integrity="sha512-V127u0iE/681x9Z+S3Xz/2aQeY6k/Q+TtwO046sA4K8E0KqNqP/n139xJqG1oE31g3m8L7u5T1WwH0tOWePjxw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
14
- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/mode-sql.min.js"></script>
15
- <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/theme-chrome.min.js"></script>
16
- <script type="module" crossorigin src="./assets/index-BMA9iqkf.js"></script>
17
- <link rel="stylesheet" crossorigin href="./assets/index-D-HpZQEQ.css">
13
+ <script
14
+ src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/ace.js"
15
+ integrity="sha512-V127u0iE/681x9Z+S3Xz/2aQeY6k/Q+TtwO046sA4K8E0KqNqP/n139xJqG1oE31g3m8L7u5T1WwH0tOWePjxw=="
16
+ crossorigin="anonymous"
17
+ referrerpolicy="no-referrer"
18
+ ></script>
19
+ <script type="module" crossorigin src="./assets/index-B2SFgnu7.js"></script>
20
+ <link rel="stylesheet" crossorigin href="./assets/index-CCy0fVAv.css">
18
21
  </head>
19
22
 
20
23
  <body>
@@ -25,7 +28,7 @@
25
28
  <div id="main-content"></div>
26
29
  </main>
27
30
 
28
- <div id="modal-editor-overlay" style="display: none;">
31
+ <div id="modal-editor-overlay" style="display: none">
29
32
  <div class="modal-editor-container">
30
33
  <div class="modal-header">
31
34
  <span class="material-symbols-outlined">edit_document</span>
@@ -34,10 +37,12 @@
34
37
  <textarea id="modal-textarea" placeholder="Enter value..."></textarea>
35
38
  <div class="modal-footer">
36
39
  <button type="button" id="modal-cancel-btn">Cancel</button>
37
- <button type="button" id="modal-save-btn" class="primary">Save</button>
40
+ <button type="button" id="modal-save-btn" class="primary">
41
+ Save
42
+ </button>
38
43
  </div>
39
44
  </div>
40
45
  </div>
41
-
46
+ <div id="toast-container"></div>
42
47
  </body>
43
48
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "drixio",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "A lightweight interactive TUI database client",
5
5
  "bin": {
6
6
  "drixio": "dist/cli.js"
@@ -50,6 +50,7 @@
50
50
  },
51
51
  "scripts": {
52
52
  "dev": "tsx bin/cli.ts",
53
+ "dev:studio": "vite --config studio/vite.config.ts",
53
54
  "build:cli": "tsup",
54
55
  "build:studio": "vite build --config studio/vite.config.ts",
55
56
  "build": "pnpm build:cli && pnpm build:studio"