@korajs/devtools 1.0.0-beta.1 → 1.0.0-beta.11
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.
- package/dist/{chunk-K3QOD2IY.js → chunk-ZWXYLFF7.js} +92 -6
- package/dist/chunk-ZWXYLFF7.js.map +1 -0
- package/dist/extension/panel.cjs +33 -0
- package/dist/extension/panel.cjs.map +1 -1
- package/dist/extension/panel.js +33 -0
- package/dist/extension/panel.js.map +1 -1
- package/dist/index.cjs +99 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/dist/overlay.cjs +91 -5
- package/dist/overlay.cjs.map +1 -1
- package/dist/overlay.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-K3QOD2IY.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -191,7 +191,12 @@ var ALL_EVENT_TYPES = [
|
|
|
191
191
|
"sync:disconnected",
|
|
192
192
|
"sync:schema-mismatch",
|
|
193
193
|
"sync:auth-failed",
|
|
194
|
+
"sync:suspended",
|
|
194
195
|
"sync:apply-failed",
|
|
196
|
+
"sync:apply-blocked",
|
|
197
|
+
"sync:apply-retrying",
|
|
198
|
+
"sync:apply-recovered",
|
|
199
|
+
"sync:apply-abandoned",
|
|
195
200
|
"sync:sent",
|
|
196
201
|
"sync:received",
|
|
197
202
|
"sync:acknowledged",
|
|
@@ -200,6 +205,9 @@ var ALL_EVENT_TYPES = [
|
|
|
200
205
|
"sync:initial-sync-progress",
|
|
201
206
|
"store:persistence-error",
|
|
202
207
|
"store:quota-exceeded",
|
|
208
|
+
"store:storage-fallback",
|
|
209
|
+
"store:opfs-unavailable",
|
|
210
|
+
"store:db-name-collision",
|
|
203
211
|
"replay:completed",
|
|
204
212
|
"query:subscribed",
|
|
205
213
|
"query:invalidated",
|
|
@@ -287,10 +295,16 @@ var EVENT_TYPE_CATEGORIES = {
|
|
|
287
295
|
"sync:connected": "sync",
|
|
288
296
|
"sync:disconnected": "sync",
|
|
289
297
|
"sync:auth-failed": "sync",
|
|
298
|
+
"sync:suspended": "sync",
|
|
290
299
|
"sync:clock-skew": "sync",
|
|
291
300
|
"sync:clock-rebase": "sync",
|
|
292
301
|
"sync:schema-mismatch": "sync",
|
|
293
302
|
"sync:apply-failed": "sync",
|
|
303
|
+
"sync:apply-blocked": "sync",
|
|
304
|
+
"sync:apply-retrying": "sync",
|
|
305
|
+
"sync:apply-recovered": "sync",
|
|
306
|
+
"sync:apply-abandoned": "sync",
|
|
307
|
+
"sync:operation-rejected": "sync",
|
|
294
308
|
"sync:sent": "sync",
|
|
295
309
|
"sync:received": "sync",
|
|
296
310
|
"sync:acknowledged": "sync",
|
|
@@ -301,11 +315,16 @@ var EVENT_TYPE_CATEGORIES = {
|
|
|
301
315
|
"sync:diagnostics": "sync",
|
|
302
316
|
"sync:bandwidth": "sync",
|
|
303
317
|
"sync:initial-sync-progress": "sync",
|
|
318
|
+
"sync:delivery-gap": "sync",
|
|
319
|
+
"sync:delivery-stalled": "sync",
|
|
304
320
|
"awareness:updated": "sync",
|
|
305
321
|
"state-machine:transition": "operation",
|
|
306
322
|
"state-machine:rejected": "operation",
|
|
307
323
|
"store:persistence-error": "connection",
|
|
308
324
|
"store:quota-exceeded": "connection",
|
|
325
|
+
"store:storage-fallback": "connection",
|
|
326
|
+
"store:opfs-unavailable": "connection",
|
|
327
|
+
"store:db-name-collision": "connection",
|
|
309
328
|
"replay:completed": "operation"
|
|
310
329
|
};
|
|
311
330
|
function eventTypeToCategory(type) {
|
|
@@ -554,6 +573,8 @@ function timelineLabel(event) {
|
|
|
554
573
|
return "sync disconnected";
|
|
555
574
|
case "sync:auth-failed":
|
|
556
575
|
return "sync auth failed";
|
|
576
|
+
case "sync:suspended":
|
|
577
|
+
return `sync suspended (${event.reason})`;
|
|
557
578
|
case "sync:clock-skew":
|
|
558
579
|
return `clock skew ${Math.round(event.skewMs / 1e3)}s (${event.severity})`;
|
|
559
580
|
case "sync:clock-rebase":
|
|
@@ -562,6 +583,16 @@ function timelineLabel(event) {
|
|
|
562
583
|
return `schema mismatch client ${event.clientSchemaVersion} server ${event.serverSchemaVersion}`;
|
|
563
584
|
case "sync:apply-failed":
|
|
564
585
|
return `sync apply failed ${event.operationId}`;
|
|
586
|
+
case "sync:apply-blocked":
|
|
587
|
+
return `sync apply blocked ${event.failure.collection}/${event.failure.recordId}`;
|
|
588
|
+
case "sync:apply-retrying":
|
|
589
|
+
return `sync apply retry ${event.failure.collection}/${event.failure.recordId}`;
|
|
590
|
+
case "sync:apply-recovered":
|
|
591
|
+
return `sync apply recovered ${event.failure.collection}/${event.failure.recordId}`;
|
|
592
|
+
case "sync:apply-abandoned":
|
|
593
|
+
return `sync apply abandoned ${event.failure.collection}/${event.failure.recordId}`;
|
|
594
|
+
case "sync:operation-rejected":
|
|
595
|
+
return `sync op rejected ${event.collection}/${event.recordId} (${event.code})`;
|
|
565
596
|
case "sync:sent":
|
|
566
597
|
return `sync sent ${event.batchSize}`;
|
|
567
598
|
case "sync:received":
|
|
@@ -582,6 +613,10 @@ function timelineLabel(event) {
|
|
|
582
613
|
return `bandwidth ${event.direction} ${event.bytesPerSecond}B/s`;
|
|
583
614
|
case "sync:initial-sync-progress":
|
|
584
615
|
return `initial sync ${Math.round(event.progress * 100)}%`;
|
|
616
|
+
case "sync:delivery-gap":
|
|
617
|
+
return `delivery gap expected ${event.expectedBase} received ${event.receivedBase}`;
|
|
618
|
+
case "sync:delivery-stalled":
|
|
619
|
+
return `delivery stalled at ${event.watermark} (${event.repeatCount} repeats)`;
|
|
585
620
|
case "awareness:updated":
|
|
586
621
|
return `awareness ${event.states.size} peers`;
|
|
587
622
|
case "state-machine:transition":
|
|
@@ -592,6 +627,12 @@ function timelineLabel(event) {
|
|
|
592
627
|
return `store persistence error ${event.message}`;
|
|
593
628
|
case "store:quota-exceeded":
|
|
594
629
|
return "store quota exceeded";
|
|
630
|
+
case "store:storage-fallback":
|
|
631
|
+
return `store fallback ${event.from} \u2192 ${event.to}`;
|
|
632
|
+
case "store:opfs-unavailable":
|
|
633
|
+
return `store OPFS unavailable (${event.reason}), running in memory`;
|
|
634
|
+
case "store:db-name-collision":
|
|
635
|
+
return `store db-name collision ${event.dbName}`;
|
|
595
636
|
case "replay:completed":
|
|
596
637
|
return `replay ${event.operationsApplied} ops`;
|
|
597
638
|
}
|
|
@@ -1071,7 +1112,7 @@ function renderDevtoolsPanel(target, events) {
|
|
|
1071
1112
|
}
|
|
1072
1113
|
|
|
1073
1114
|
// src/ui/panel-styles.ts
|
|
1074
|
-
var KORA_DEVTOOLS_STYLES = "/* ================================================================\n Kora DevTools \u2014 Dark theme optimized for Chrome DevTools panels\n ================================================================ */\n\n :root {\n --bg-primary: #1e1e2e;\n --bg-secondary: #181825;\n --bg-surface: #313244;\n --bg-hover: #45475a;\n --bg-selected: #585b70;\n --text-primary: #cdd6f4;\n --text-secondary: #a6adc8;\n --text-muted: #6c7086;\n --border: #45475a;\n\n --green: #a6e3a1;\n --red: #f38ba8;\n --yellow: #f9e2af;\n --blue: #89b4fa;\n --purple: #cba6f7;\n --teal: #94e2d5;\n --peach: #fab387;\n\n --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;\n --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --font-size: 12px;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n body {\n background: var(--bg-primary);\n color: var(--text-primary);\n font-family: var(--font-sans);\n font-size: var(--font-size);\n line-height: 1.5;\n overflow: hidden;\n }\n\n #kora-devtools-root {\n width: 100vw;\n height: 100vh;\n display: flex;\n flex-direction: column;\n }\n\n .kora-devtools {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Toolbar ---- */\n\n .kora-toolbar {\n background: var(--bg-secondary);\n border-bottom: 1px solid var(--border);\n padding: 4px 8px;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n }\n\n .kora-tabs {\n display: flex;\n gap: 2px;\n }\n\n .kora-tab {\n background: transparent;\n color: var(--text-secondary);\n border: none;\n padding: 4px 12px;\n border-radius: 4px;\n cursor: pointer;\n font-size: var(--font-size);\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .kora-tab:hover {\n background: var(--bg-hover);\n color: var(--text-primary);\n }\n\n .kora-tab.active {\n background: var(--bg-surface);\n color: var(--text-primary);\n font-weight: 600;\n }\n\n .kora-badge {\n background: var(--bg-hover);\n color: var(--text-muted);\n padding: 0 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n }\n\n .kora-tab.active .kora-badge {\n background: var(--blue);\n color: var(--bg-primary);\n }\n\n .kora-controls {\n display: flex;\n gap: 4px;\n align-items: center;\n margin-left: auto;\n flex-wrap: wrap;\n }\n\n .kora-search {\n background: var(--bg-surface);\n color: var(--text-primary);\n border: 1px solid var(--border);\n padding: 3px 8px;\n border-radius: 4px;\n font-size: var(--font-size);\n font-family: var(--font-sans);\n width: 140px;\n outline: none;\n }\n\n .kora-search:focus {\n border-color: var(--blue);\n }\n\n .kora-btn {\n background: var(--bg-surface);\n color: var(--text-secondary);\n border: 1px solid var(--border);\n padding: 3px 8px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n font-family: var(--font-sans);\n }\n\n .kora-btn:hover {\n background: var(--bg-hover);\n color: var(--text-primary);\n }\n\n .kora-cat-toggle {\n background: transparent;\n color: var(--text-muted);\n border: 1px solid transparent;\n padding: 2px 6px;\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n font-family: var(--font-sans);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kora-cat-toggle:hover {\n color: var(--text-secondary);\n }\n\n .kora-cat-toggle.active {\n background: var(--bg-surface);\n color: var(--text-primary);\n border-color: var(--border);\n }\n\n /* ---- Content ---- */\n\n .kora-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .kora-panel {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n }\n\n .kora-empty {\n color: var(--text-muted);\n text-align: center;\n padding: 40px;\n font-style: italic;\n }\n\n .kora-summary {\n color: var(--text-muted);\n font-size: 11px;\n padding: 4px 0 8px;\n border-bottom: 1px solid var(--border);\n margin-bottom: 4px;\n }\n\n /* ---- Event List (Timeline) ---- */\n\n .kora-event-list {\n display: flex;\n flex-direction: column;\n }\n\n .kora-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 6px;\n border-radius: 3px;\n cursor: pointer;\n min-height: 24px;\n }\n\n .kora-row:hover {\n background: var(--bg-hover);\n }\n\n .kora-row.expanded,\n .kora-row.selected {\n background: var(--bg-surface);\n }\n\n .kora-row.compact {\n padding: 2px 6px;\n font-size: 11px;\n }\n\n .kora-time {\n color: var(--text-muted);\n font-family: var(--font-mono);\n font-size: 11px;\n flex-shrink: 0;\n width: 90px;\n }\n\n .kora-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .kora-type {\n color: var(--text-secondary);\n font-size: 11px;\n flex-shrink: 0;\n width: 140px;\n }\n\n .kora-label {\n color: var(--text-primary);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .kora-deps {\n color: var(--peach);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n /* ---- Detail / Expandable ---- */\n\n .kora-detail,\n .kora-op-detail {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 4px;\n padding: 8px 12px;\n margin: 2px 0 6px 28px;\n font-size: 11px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .kora-detail-label {\n color: var(--text-muted);\n font-weight: 500;\n margin-right: 4px;\n }\n\n .kora-mono {\n font-family: var(--font-mono);\n font-size: 11px;\n }\n\n /* ---- Conflicts Table ---- */\n\n .kora-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 11px;\n }\n\n .kora-table th {\n text-align: left;\n color: var(--text-muted);\n font-weight: 500;\n padding: 6px 8px;\n border-bottom: 1px solid var(--border);\n text-transform: uppercase;\n font-size: 10px;\n letter-spacing: 0.5px;\n }\n\n .kora-table td {\n padding: 5px 8px;\n border-bottom: 1px solid var(--bg-surface);\n }\n\n .kora-conflict-row {\n cursor: pointer;\n }\n\n .kora-conflict-row:hover td {\n background: var(--bg-hover);\n }\n\n .kora-conflict-row.expanded td {\n background: var(--bg-surface);\n }\n\n .kora-conflict-row.violated td {\n border-left: 3px solid var(--red);\n }\n\n .kora-strategy {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n }\n\n .kora-strategy.tier-1 {\n background: rgba(166, 227, 161, 0.15);\n color: var(--green);\n }\n\n .kora-strategy.tier-2 {\n background: rgba(249, 226, 175, 0.15);\n color: var(--yellow);\n }\n\n .kora-strategy.tier-3 {\n background: rgba(203, 166, 247, 0.15);\n color: var(--purple);\n }\n\n .kora-detail-row td {\n padding: 0;\n }\n\n .kora-conflict-detail {\n padding: 12px;\n }\n\n .kora-comparison {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 8px;\n }\n\n .kora-value-box {\n background: var(--bg-primary);\n border: 1px solid var(--border);\n border-radius: 4px;\n padding: 8px;\n }\n\n .kora-value-box.result {\n border-color: var(--green);\n }\n\n .kora-value-label {\n color: var(--text-muted);\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .kora-value-code {\n font-family: var(--font-mono);\n font-size: 11px;\n color: var(--text-primary);\n white-space: pre-wrap;\n word-break: break-all;\n margin: 0;\n }\n\n .kora-constraint-warning {\n margin-top: 8px;\n padding: 6px 10px;\n background: rgba(243, 139, 168, 0.1);\n border: 1px solid var(--red);\n border-radius: 4px;\n color: var(--red);\n font-size: 11px;\n }\n\n /* ---- Operations ---- */\n\n .kora-op-list {\n display: flex;\n flex-direction: column;\n }\n\n .kora-op-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 6px;\n border-radius: 3px;\n cursor: pointer;\n }\n\n .kora-op-row:hover {\n background: var(--bg-hover);\n }\n\n .kora-op-row.expanded {\n background: var(--bg-surface);\n }\n\n .kora-op-type {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n }\n\n .op-insert {\n background: rgba(166, 227, 161, 0.15);\n color: var(--green);\n }\n\n .op-update {\n background: rgba(137, 180, 250, 0.15);\n color: var(--blue);\n }\n\n .op-delete {\n background: rgba(243, 139, 168, 0.15);\n color: var(--red);\n }\n\n .kora-op-collection {\n color: var(--teal);\n font-weight: 500;\n flex-shrink: 0;\n }\n\n .kora-op-record {\n color: var(--text-secondary);\n flex-shrink: 0;\n }\n\n .kora-op-node {\n color: var(--text-muted);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n .kora-op-seq {\n color: var(--text-muted);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n /* ---- Network ---- */\n\n .kora-network-status {\n padding: 12px 0;\n }\n\n .kora-status-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n }\n\n .kora-status-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n }\n\n .connected .kora-status-dot {\n background: var(--green);\n box-shadow: 0 0 8px rgba(166, 227, 161, 0.5);\n }\n\n .disconnected .kora-status-dot {\n background: var(--red);\n box-shadow: 0 0 8px rgba(243, 139, 168, 0.3);\n }\n\n .connected .kora-status-text {\n color: var(--green);\n }\n\n .disconnected .kora-status-text {\n color: var(--red);\n }\n\n .kora-stats-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n margin: 12px 0;\n }\n\n .kora-stat-card {\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 12px;\n text-align: center;\n }\n\n .kora-stat-value {\n font-size: 20px;\n font-weight: 700;\n color: var(--text-primary);\n font-family: var(--font-mono);\n }\n\n .kora-stat-label {\n color: var(--text-muted);\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n }\n\n .kora-vv-section,\n .kora-sync-log {\n margin-top: 16px;\n }\n\n .kora-vv-section h3,\n .kora-sync-log h3 {\n color: var(--text-secondary);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 8px;\n }\n\n .kora-vv-table {\n max-width: 400px;\n }\n\n /* ---- Scrollbar ---- */\n\n ::-webkit-scrollbar {\n width: 8px;\n }\n\n ::-webkit-scrollbar-track {\n background: var(--bg-primary);\n }\n\n ::-webkit-scrollbar-thumb {\n background: var(--bg-hover);\n border-radius: 4px;\n }\n\n ::-webkit-scrollbar-thumb:hover {\n background: var(--bg-selected);\n }";
|
|
1115
|
+
var KORA_DEVTOOLS_STYLES = "/* ================================================================\n Kora DevTools \u2014 Dark theme optimized for Chrome DevTools panels\n ================================================================ */\n\n :host,\n :root {\n --bg-primary: #1e1e2e;\n --bg-secondary: #181825;\n --bg-surface: #313244;\n --bg-hover: #45475a;\n --bg-selected: #585b70;\n --text-primary: #cdd6f4;\n --text-secondary: #a6adc8;\n --text-muted: #6c7086;\n --border: #45475a;\n\n --green: #a6e3a1;\n --red: #f38ba8;\n --yellow: #f9e2af;\n --blue: #89b4fa;\n --purple: #cba6f7;\n --teal: #94e2d5;\n --peach: #fab387;\n\n --font-mono: 'SF Mono', 'Cascadia Code', 'Fira Code', Consolas, monospace;\n --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n --font-size: 12px;\n }\n\n * {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n }\n\n :host,\n body {\n background: var(--bg-primary);\n color: var(--text-primary);\n font-family: var(--font-sans);\n font-size: var(--font-size);\n line-height: 1.5;\n overflow: hidden;\n }\n\n #kora-devtools-root {\n width: 100%;\n height: 100%;\n display: flex;\n flex-direction: column;\n }\n\n .kora-devtools {\n display: flex;\n flex-direction: column;\n height: 100%;\n }\n\n /* ---- Toolbar ---- */\n\n .kora-toolbar {\n background: var(--bg-secondary);\n border-bottom: 1px solid var(--border);\n padding: 4px 8px;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 8px;\n flex-shrink: 0;\n }\n\n .kora-tabs {\n display: flex;\n gap: 2px;\n }\n\n .kora-tab {\n background: transparent;\n color: var(--text-secondary);\n border: none;\n padding: 4px 12px;\n border-radius: 4px;\n cursor: pointer;\n font-size: var(--font-size);\n font-family: var(--font-sans);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n\n .kora-tab:hover {\n background: var(--bg-hover);\n color: var(--text-primary);\n }\n\n .kora-tab.active {\n background: var(--bg-surface);\n color: var(--text-primary);\n font-weight: 600;\n }\n\n .kora-badge {\n background: var(--bg-hover);\n color: var(--text-muted);\n padding: 0 6px;\n border-radius: 10px;\n font-size: 10px;\n font-weight: 500;\n }\n\n .kora-tab.active .kora-badge {\n background: var(--blue);\n color: var(--bg-primary);\n }\n\n .kora-controls {\n display: flex;\n gap: 4px;\n align-items: center;\n margin-left: auto;\n flex-wrap: wrap;\n }\n\n .kora-search {\n background: var(--bg-surface);\n color: var(--text-primary);\n border: 1px solid var(--border);\n padding: 3px 8px;\n border-radius: 4px;\n font-size: var(--font-size);\n font-family: var(--font-sans);\n width: 140px;\n outline: none;\n }\n\n .kora-search:focus {\n border-color: var(--blue);\n }\n\n .kora-btn {\n background: var(--bg-surface);\n color: var(--text-secondary);\n border: 1px solid var(--border);\n padding: 3px 8px;\n border-radius: 4px;\n cursor: pointer;\n font-size: 11px;\n font-family: var(--font-sans);\n }\n\n .kora-btn:hover {\n background: var(--bg-hover);\n color: var(--text-primary);\n }\n\n .kora-cat-toggle {\n background: transparent;\n color: var(--text-muted);\n border: 1px solid transparent;\n padding: 2px 6px;\n border-radius: 3px;\n cursor: pointer;\n font-size: 10px;\n font-family: var(--font-sans);\n text-transform: uppercase;\n letter-spacing: 0.5px;\n }\n\n .kora-cat-toggle:hover {\n color: var(--text-secondary);\n }\n\n .kora-cat-toggle.active {\n background: var(--bg-surface);\n color: var(--text-primary);\n border-color: var(--border);\n }\n\n /* ---- Content ---- */\n\n .kora-content {\n flex: 1;\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .kora-panel {\n flex: 1;\n overflow-y: auto;\n padding: 8px;\n }\n\n .kora-empty {\n color: var(--text-muted);\n text-align: center;\n padding: 40px;\n font-style: italic;\n }\n\n .kora-summary {\n color: var(--text-muted);\n font-size: 11px;\n padding: 4px 0 8px;\n border-bottom: 1px solid var(--border);\n margin-bottom: 4px;\n }\n\n /* ---- Event List (Timeline) ---- */\n\n .kora-event-list {\n display: flex;\n flex-direction: column;\n }\n\n .kora-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 6px;\n border-radius: 3px;\n cursor: pointer;\n min-height: 24px;\n }\n\n .kora-row:hover {\n background: var(--bg-hover);\n }\n\n .kora-row.expanded,\n .kora-row.selected {\n background: var(--bg-surface);\n }\n\n .kora-row.compact {\n padding: 2px 6px;\n font-size: 11px;\n }\n\n .kora-time {\n color: var(--text-muted);\n font-family: var(--font-mono);\n font-size: 11px;\n flex-shrink: 0;\n width: 90px;\n }\n\n .kora-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n }\n\n .kora-type {\n color: var(--text-secondary);\n font-size: 11px;\n flex-shrink: 0;\n width: 140px;\n }\n\n .kora-label {\n color: var(--text-primary);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .kora-deps {\n color: var(--peach);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n /* ---- Detail / Expandable ---- */\n\n .kora-detail,\n .kora-op-detail {\n background: var(--bg-secondary);\n border: 1px solid var(--border);\n border-radius: 4px;\n padding: 8px 12px;\n margin: 2px 0 6px 28px;\n font-size: 11px;\n display: flex;\n flex-direction: column;\n gap: 4px;\n }\n\n .kora-detail-label {\n color: var(--text-muted);\n font-weight: 500;\n margin-right: 4px;\n }\n\n .kora-mono {\n font-family: var(--font-mono);\n font-size: 11px;\n }\n\n /* ---- Conflicts Table ---- */\n\n .kora-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 11px;\n }\n\n .kora-table th {\n text-align: left;\n color: var(--text-muted);\n font-weight: 500;\n padding: 6px 8px;\n border-bottom: 1px solid var(--border);\n text-transform: uppercase;\n font-size: 10px;\n letter-spacing: 0.5px;\n }\n\n .kora-table td {\n padding: 5px 8px;\n border-bottom: 1px solid var(--bg-surface);\n }\n\n .kora-conflict-row {\n cursor: pointer;\n }\n\n .kora-conflict-row:hover td {\n background: var(--bg-hover);\n }\n\n .kora-conflict-row.expanded td {\n background: var(--bg-surface);\n }\n\n .kora-conflict-row.violated td {\n border-left: 3px solid var(--red);\n }\n\n .kora-strategy {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 500;\n }\n\n .kora-strategy.tier-1 {\n background: rgba(166, 227, 161, 0.15);\n color: var(--green);\n }\n\n .kora-strategy.tier-2 {\n background: rgba(249, 226, 175, 0.15);\n color: var(--yellow);\n }\n\n .kora-strategy.tier-3 {\n background: rgba(203, 166, 247, 0.15);\n color: var(--purple);\n }\n\n .kora-detail-row td {\n padding: 0;\n }\n\n .kora-conflict-detail {\n padding: 12px;\n }\n\n .kora-comparison {\n display: grid;\n grid-template-columns: 1fr 1fr 1fr;\n gap: 8px;\n }\n\n .kora-value-box {\n background: var(--bg-primary);\n border: 1px solid var(--border);\n border-radius: 4px;\n padding: 8px;\n }\n\n .kora-value-box.result {\n border-color: var(--green);\n }\n\n .kora-value-label {\n color: var(--text-muted);\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-bottom: 4px;\n }\n\n .kora-value-code {\n font-family: var(--font-mono);\n font-size: 11px;\n color: var(--text-primary);\n white-space: pre-wrap;\n word-break: break-all;\n margin: 0;\n }\n\n .kora-constraint-warning {\n margin-top: 8px;\n padding: 6px 10px;\n background: rgba(243, 139, 168, 0.1);\n border: 1px solid var(--red);\n border-radius: 4px;\n color: var(--red);\n font-size: 11px;\n }\n\n /* ---- Operations ---- */\n\n .kora-op-list {\n display: flex;\n flex-direction: column;\n }\n\n .kora-op-row {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 3px 6px;\n border-radius: 3px;\n cursor: pointer;\n }\n\n .kora-op-row:hover {\n background: var(--bg-hover);\n }\n\n .kora-op-row.expanded {\n background: var(--bg-surface);\n }\n\n .kora-op-type {\n padding: 1px 6px;\n border-radius: 3px;\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n flex-shrink: 0;\n }\n\n .op-insert {\n background: rgba(166, 227, 161, 0.15);\n color: var(--green);\n }\n\n .op-update {\n background: rgba(137, 180, 250, 0.15);\n color: var(--blue);\n }\n\n .op-delete {\n background: rgba(243, 139, 168, 0.15);\n color: var(--red);\n }\n\n .kora-op-collection {\n color: var(--teal);\n font-weight: 500;\n flex-shrink: 0;\n }\n\n .kora-op-record {\n color: var(--text-secondary);\n flex-shrink: 0;\n }\n\n .kora-op-node {\n color: var(--text-muted);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n .kora-op-seq {\n color: var(--text-muted);\n font-size: 10px;\n flex-shrink: 0;\n }\n\n /* ---- Network ---- */\n\n .kora-network-status {\n padding: 12px 0;\n }\n\n .kora-status-indicator {\n display: flex;\n align-items: center;\n gap: 8px;\n font-size: 14px;\n font-weight: 600;\n }\n\n .kora-status-dot {\n width: 12px;\n height: 12px;\n border-radius: 50%;\n }\n\n .connected .kora-status-dot {\n background: var(--green);\n box-shadow: 0 0 8px rgba(166, 227, 161, 0.5);\n }\n\n .disconnected .kora-status-dot {\n background: var(--red);\n box-shadow: 0 0 8px rgba(243, 139, 168, 0.3);\n }\n\n .connected .kora-status-text {\n color: var(--green);\n }\n\n .disconnected .kora-status-text {\n color: var(--red);\n }\n\n .kora-stats-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 8px;\n margin: 12px 0;\n }\n\n .kora-stat-card {\n background: var(--bg-surface);\n border: 1px solid var(--border);\n border-radius: 6px;\n padding: 12px;\n text-align: center;\n }\n\n .kora-stat-value {\n font-size: 20px;\n font-weight: 700;\n color: var(--text-primary);\n font-family: var(--font-mono);\n }\n\n .kora-stat-label {\n color: var(--text-muted);\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 0.5px;\n margin-top: 2px;\n }\n\n .kora-vv-section,\n .kora-sync-log {\n margin-top: 16px;\n }\n\n .kora-vv-section h3,\n .kora-sync-log h3 {\n color: var(--text-secondary);\n font-size: 12px;\n font-weight: 600;\n margin-bottom: 8px;\n }\n\n .kora-vv-table {\n max-width: 400px;\n }\n\n /* ---- Scrollbar ---- */\n\n ::-webkit-scrollbar {\n width: 8px;\n }\n\n ::-webkit-scrollbar-track {\n background: var(--bg-primary);\n }\n\n ::-webkit-scrollbar-thumb {\n background: var(--bg-hover);\n border-radius: 4px;\n }\n\n ::-webkit-scrollbar-thumb:hover {\n background: var(--bg-selected);\n }";
|
|
1075
1116
|
|
|
1076
1117
|
// src/overlay/embed-overlay.ts
|
|
1077
1118
|
var OVERLAY_HOST_ID = "kora-devtools-overlay-host";
|
|
@@ -1089,8 +1130,41 @@ function mountKoraDevtoolsOverlay(instrumenter) {
|
|
|
1089
1130
|
host.style.cssText = "position:fixed;inset:auto 12px 12px 12px;height:42vh;z-index:2147483646;display:none;";
|
|
1090
1131
|
const shadow = host.attachShadow({ mode: "open" });
|
|
1091
1132
|
const style = document.createElement("style");
|
|
1092
|
-
style.textContent = KORA_DEVTOOLS_STYLES
|
|
1133
|
+
style.textContent = `${KORA_DEVTOOLS_STYLES}
|
|
1134
|
+
:host {
|
|
1135
|
+
color-scheme: dark;
|
|
1136
|
+
background: #1e1e2e;
|
|
1137
|
+
color: #cdd6f4;
|
|
1138
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
1139
|
+
overflow: hidden;
|
|
1140
|
+
border: 1px solid #45475a;
|
|
1141
|
+
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
|
|
1142
|
+
}
|
|
1143
|
+
.kora-overlay-close {
|
|
1144
|
+
position: absolute;
|
|
1145
|
+
top: 6px;
|
|
1146
|
+
right: 8px;
|
|
1147
|
+
z-index: 1;
|
|
1148
|
+
background: #313244;
|
|
1149
|
+
color: #cdd6f4;
|
|
1150
|
+
border: 1px solid #45475a;
|
|
1151
|
+
border-radius: 4px;
|
|
1152
|
+
cursor: pointer;
|
|
1153
|
+
font: 12px -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
1154
|
+
line-height: 1;
|
|
1155
|
+
padding: 4px 8px;
|
|
1156
|
+
}
|
|
1157
|
+
.kora-overlay-close:hover {
|
|
1158
|
+
background: #45475a;
|
|
1159
|
+
}
|
|
1160
|
+
`;
|
|
1093
1161
|
shadow.appendChild(style);
|
|
1162
|
+
const closeButton = document.createElement("button");
|
|
1163
|
+
closeButton.type = "button";
|
|
1164
|
+
closeButton.className = "kora-overlay-close";
|
|
1165
|
+
closeButton.textContent = "Close";
|
|
1166
|
+
closeButton.setAttribute("aria-label", "Close Kora DevTools");
|
|
1167
|
+
shadow.appendChild(closeButton);
|
|
1094
1168
|
const panelRoot = document.createElement("div");
|
|
1095
1169
|
panelRoot.id = "kora-devtools-root";
|
|
1096
1170
|
panelRoot.style.height = "100%";
|
|
@@ -1104,7 +1178,8 @@ function mountKoraDevtoolsOverlay(instrumenter) {
|
|
|
1104
1178
|
const setVisible = (next) => {
|
|
1105
1179
|
visible = next;
|
|
1106
1180
|
host.style.display = visible ? "block" : "none";
|
|
1107
|
-
hint.
|
|
1181
|
+
hint.textContent = visible ? "Hide Kora DevTools (Esc)" : "Kora DevTools (Ctrl+Shift+K)";
|
|
1182
|
+
hint.style.display = "block";
|
|
1108
1183
|
};
|
|
1109
1184
|
const refresh = () => {
|
|
1110
1185
|
if (!visible) return;
|
|
@@ -1113,17 +1188,36 @@ function mountKoraDevtoolsOverlay(instrumenter) {
|
|
|
1113
1188
|
const intervalId = window.setInterval(refresh, 300);
|
|
1114
1189
|
const onKeyDown = (event) => {
|
|
1115
1190
|
const isToggle = event.key === "K" && event.shiftKey && (event.ctrlKey || event.metaKey);
|
|
1116
|
-
if (
|
|
1117
|
-
|
|
1191
|
+
if (isToggle) {
|
|
1192
|
+
event.preventDefault();
|
|
1193
|
+
setVisible(!visible);
|
|
1194
|
+
if (visible) {
|
|
1195
|
+
refresh();
|
|
1196
|
+
}
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (event.key === "Escape" && visible) {
|
|
1200
|
+
event.preventDefault();
|
|
1201
|
+
setVisible(false);
|
|
1202
|
+
}
|
|
1203
|
+
};
|
|
1204
|
+
const onHintClick = () => {
|
|
1118
1205
|
setVisible(!visible);
|
|
1119
1206
|
if (visible) {
|
|
1120
1207
|
refresh();
|
|
1121
1208
|
}
|
|
1122
1209
|
};
|
|
1210
|
+
const onCloseClick = () => {
|
|
1211
|
+
setVisible(false);
|
|
1212
|
+
};
|
|
1123
1213
|
window.addEventListener("keydown", onKeyDown);
|
|
1214
|
+
hint.addEventListener("click", onHintClick);
|
|
1215
|
+
closeButton.addEventListener("click", onCloseClick);
|
|
1124
1216
|
return () => {
|
|
1125
1217
|
window.clearInterval(intervalId);
|
|
1126
1218
|
window.removeEventListener("keydown", onKeyDown);
|
|
1219
|
+
hint.removeEventListener("click", onHintClick);
|
|
1220
|
+
closeButton.removeEventListener("click", onCloseClick);
|
|
1127
1221
|
host.remove();
|
|
1128
1222
|
hint.remove();
|
|
1129
1223
|
};
|