@sqlite-sync/devtools 0.12.2 → 0.13.0
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/README.md +6 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +88 -46
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -29,6 +29,12 @@ Database instances register when `createSyncedDb()` completes and unregister on
|
|
|
29
29
|
|
|
30
30
|
Pass `hidden` and `onHiddenChange` if your app has its own toggle. Skip them and `Ctrl+Alt+S` (⌘⌥S on macOS) hides the button. That choice is stored in `localStorage`.
|
|
31
31
|
|
|
32
|
+
To open the dialog from your own UI, pass `open` and `onOpenChange`. Add `launcher={false}` to drop the floating button entirely:
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<SQLiteSyncDevtools launcher={false} open={devtoolsOpen} onOpenChange={setDevtoolsOpen} />
|
|
36
|
+
```
|
|
37
|
+
|
|
32
38
|
Query runner rules:
|
|
33
39
|
|
|
34
40
|
- Worker DB queries are read-only.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
//#region src/devtools.d.ts
|
|
2
2
|
type SQLiteSyncDevtoolsProps = {
|
|
3
3
|
className?: string;
|
|
4
|
+
/** Render the floating launcher button. Set to `false` to open the dialog only via `open`. Defaults to `true`. */
|
|
5
|
+
launcher?: boolean;
|
|
4
6
|
/** Hide the floating launcher. Omit to let the user toggle it with Ctrl+Alt+S (⌘⌥S on macOS). */
|
|
5
7
|
hidden?: boolean;
|
|
6
8
|
onHiddenChange?: (hidden: boolean) => void;
|
|
9
|
+
/** Control whether the devtools dialog is open. Omit to let the launcher manage it. */
|
|
10
|
+
open?: boolean;
|
|
11
|
+
onOpenChange?: (open: boolean) => void;
|
|
7
12
|
};
|
|
8
|
-
declare function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }: SQLiteSyncDevtoolsProps): import("react").JSX.Element;
|
|
13
|
+
declare function SQLiteSyncDevtools({ className, launcher, hidden: hiddenProp, onHiddenChange, open: openProp, onOpenChange }: SQLiteSyncDevtoolsProps): import("react").JSX.Element;
|
|
9
14
|
//#endregion
|
|
10
15
|
export { SQLiteSyncDevtools, type SQLiteSyncDevtoolsProps };
|
|
11
16
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ function getOrCreateSQLiteSyncDevtoolsRegistry() {
|
|
|
46
46
|
}
|
|
47
47
|
//#endregion
|
|
48
48
|
//#region src/devtools.css?inline
|
|
49
|
-
var devtools_default = ":host {\n all: initial;\n z-index: 9998;\n --ss-bg: #0e1015;\n --ss-bg-panel: #161921;\n --ss-bg-card: #1c2030;\n --ss-bg-input: #111318;\n --ss-border: #2a2f3e;\n --ss-border-light: #343a4f;\n --ss-text: #e2e8f0;\n --ss-text-muted: #6b7280;\n --ss-text-dim: #9ca3af;\n --ss-teal: #2dd4bf;\n --ss-teal-dim: #2dd4bf1f;\n --ss-teal-glow: #2dd4bf0f;\n --ss-error: #f87171;\n --ss-error-bg: #f8717114;\n --ss-error-border: #f8717140;\n --ss-success: #34d399;\n --ss-success-bg: #34d39914;\n --ss-amber: #fbbf24;\n color: var(--ss-text);\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: block;\n position: relative;\n}\n\n:host *, :host :before, :host :after {\n box-sizing: border-box;\n}\n\n.mono {\n font-family: ui-monospace, monospace;\n}\n\n.sm {\n font-size: .78rem;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.mlAuto {\n margin-left: auto;\n}\n\n.hiddenInput {\n display: none;\n}\n\n.floatingRoot {\n pointer-events: none;\n z-index: 9998;\n position: fixed;\n inset: 0;\n}\n\n.triggerButton {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n color: var(--ss-text);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 4px 16px #00000080;\n cursor: grab;\n touch-action: none;\n user-select: none;\n pointer-events: auto;\n border-radius: 8px;\n align-items: center;\n gap: .3rem;\n padding: .3rem .45rem;\n display: inline-flex;\n position: absolute;\n bottom: 16px;\n right: 16px;\n}\n\n.triggerIcon {\n color: var(--ss-teal);\n font-size: .9rem;\n line-height: 1;\n}\n\n.triggerCount {\n background-color: var(--ss-teal-dim);\n min-width: 1.1rem;\n color: var(--ss-teal);\n text-align: center;\n border-radius: 4px;\n padding: .05rem .25rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.overlay {\n z-index: 9999;\n backdrop-filter: blur(8px);\n background-color: #000000b8;\n justify-content: center;\n align-items: center;\n padding: 1.5rem;\n display: flex;\n position: fixed;\n inset: 0;\n}\n\n.dialog {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg);\n width: min(72rem, 100%);\n height: min(90vh, 860px);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 40px 80px #000c,\n 0 0 60px #2dd4bf0a;\n color: var(--ss-text);\n border-radius: 16px;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: flex;\n overflow: hidden;\n}\n\n.header {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-shrink: 0;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: .85rem 1.1rem;\n display: flex;\n}\n\n.headerLeft {\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.headerLogo {\n color: var(--ss-teal);\n font-size: 1.3rem;\n line-height: 1;\n}\n\n.eyebrow {\n letter-spacing: .1em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.title {\n color: var(--ss-text);\n letter-spacing: -.01em;\n margin: .05rem 0 0;\n font-size: .95rem;\n font-weight: 700;\n}\n\n.headerRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.instancePickerLabel {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.instancePickerText {\n color: var(--ss-text-muted);\n text-transform: uppercase;\n letter-spacing: .06em;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.instancePickerSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n}\n\n.instanceCountBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.closeButton {\n border: 1px solid var(--ss-border);\n width: 28px;\n height: 28px;\n color: var(--ss-text-muted);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n justify-content: center;\n align-items: center;\n font-size: .82rem;\n font-weight: 600;\n display: flex;\n}\n\n.hideLauncherButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .3rem .65rem;\n font-size: .75rem;\n font-weight: 600;\n}\n\n.emptyState {\n flex-direction: column;\n flex: 1;\n justify-content: center;\n align-items: center;\n gap: .75rem;\n padding: 4rem 2rem;\n display: flex;\n}\n\n.emptyStateIcon {\n color: var(--ss-text-muted);\n opacity: .4;\n font-size: 2.5rem;\n}\n\n.emptyStateText {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .95rem;\n font-weight: 600;\n}\n\n.emptyStateSubtext {\n color: var(--ss-text-muted);\n text-align: center;\n margin: 0;\n font-size: .82rem;\n}\n\n.inlineCode {\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n border-radius: 4px;\n padding: .1em .4em;\n font-family: ui-monospace, monospace;\n font-size: .88em;\n}\n\n.contentLayout {\n flex: 1;\n grid-template-columns: 200px minmax(0, 1fr);\n min-height: 0;\n display: grid;\n overflow: hidden;\n}\n\n.sidebar {\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-direction: column;\n gap: 0;\n padding: .75rem;\n display: flex;\n overflow-y: auto;\n}\n\n.nav {\n flex-direction: column;\n gap: .25rem;\n margin-bottom: 1rem;\n display: flex;\n}\n\n.navIcon {\n opacity: .7;\n font-size: .7rem;\n}\n\n.sidebarInfo {\n background: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n margin-top: auto;\n padding: .75rem;\n}\n\n.sidebarInfoLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .3rem;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.sidebarInfoValue {\n color: var(--ss-text);\n word-break: break-word;\n font-family: ui-monospace, monospace;\n font-size: .88rem;\n font-weight: 600;\n}\n\n.sidebarInfoSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.mainPane {\n min-width: 0;\n padding: 1rem;\n overflow-y: auto;\n}\n\n.overviewLayout {\n flex-direction: column;\n gap: 1.25rem;\n display: flex;\n}\n\n.overviewCardsRow {\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: .75rem;\n display: grid;\n}\n\n.overviewCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n padding: .9rem 1rem;\n}\n\n.overviewCardLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .4rem;\n font-size: .68rem;\n font-weight: 600;\n}\n\n.overviewCardValue {\n color: var(--ss-text);\n word-break: break-word;\n font-size: 1rem;\n font-weight: 700;\n}\n\n.overviewCardSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.overviewSection {\n flex-direction: column;\n gap: .5rem;\n display: flex;\n}\n\n.overviewSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 600;\n}\n\n.overviewSectionHeader {\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.refreshButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .7rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.overviewAccumulatorValue {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n color: var(--ss-text);\n word-break: break-all;\n border-radius: 8px;\n padding: .75rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.overviewAccumulatorEmpty {\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.overviewAccumulatorError {\n color: var(--ss-error);\n}\n\n.overviewEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventCountGrid {\n grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n gap: .5rem;\n display: grid;\n}\n\n.eventCountCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n padding: .75rem .85rem;\n}\n\n.eventCountValue {\n color: var(--ss-text);\n margin-bottom: .35rem;\n font-family: ui-monospace, monospace;\n font-size: 1.05rem;\n font-weight: 700;\n}\n\n.eventCountValue[data-tone=\"amber\"][data-emphasize=\"true\"] {\n color: var(--ss-amber);\n}\n\n.eventCountValue[data-tone=\"success\"][data-emphasize=\"true\"] {\n color: var(--ss-success);\n}\n\n.eventCountValue[data-tone=\"error\"][data-emphasize=\"true\"] {\n color: var(--ss-error);\n}\n\n.dataActions {\n gap: .4rem;\n display: flex;\n}\n\n.dataButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .4rem .8rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.dataStatusSuccess {\n color: var(--ss-success);\n font-size: .75rem;\n}\n\n.dataStatusError {\n color: var(--ss-error);\n word-break: break-word;\n font-size: .75rem;\n}\n\n.dangerZone {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n margin-top: auto;\n padding: .75rem 1rem;\n}\n\n.dangerZoneTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-error);\n margin-bottom: .5rem;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.dangerZoneRow {\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n display: flex;\n}\n\n.dangerZoneDesc {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.dangerZoneActions {\n flex-shrink: 0;\n gap: .4rem;\n display: flex;\n}\n\n.resetButton {\n border: 1px solid var(--ss-error-border);\n color: var(--ss-error);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetCancelButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .35rem .65rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetConfirmButton {\n background-color: var(--ss-error);\n color: #0e1015;\n cursor: pointer;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 700;\n}\n\n.queryRunnerLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.queryToolbar {\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.targetToggle {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n gap: 0;\n display: flex;\n overflow: hidden;\n}\n\n.queryToolbarRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.noInstanceWarning {\n color: var(--ss-amber);\n font-size: .75rem;\n font-weight: 500;\n}\n\n.shortcutHint {\n color: var(--ss-text-muted);\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.editorWrapper {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-input);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.textarea {\n resize: vertical;\n width: 100%;\n min-height: 9rem;\n color: var(--ss-text);\n box-sizing: border-box;\n background-color: #0000;\n border: none;\n outline: none;\n padding: .85rem 1rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .875rem;\n line-height: 1.6;\n}\n\n.helperText {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.resultPanel {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n display: flex;\n overflow: hidden;\n}\n\n.errorPanel {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n padding: .85rem 1rem;\n display: flex;\n}\n\n.resultHeader {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n align-items: center;\n gap: .6rem;\n padding: .6rem .85rem;\n display: flex;\n}\n\n.successBadge {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.errorBadge {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.resultMeta {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.resultEmpty {\n color: var(--ss-text-muted);\n text-align: center;\n padding: 1.5rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.resultRaw {\n white-space: pre-wrap;\n word-break: break-word;\n color: var(--ss-text);\n margin: 0;\n padding: .85rem 1rem;\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n line-height: 1.5;\n overflow-x: auto;\n}\n\n.errorMessage {\n color: var(--ss-error);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n line-height: 1.6;\n}\n\n.tableWrapper {\n max-height: 320px;\n overflow: auto;\n}\n\n.table {\n border-collapse: collapse;\n width: 100%;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .8rem;\n}\n\n.table tbody tr:nth-child(2n) {\n background: var(--ss-teal-glow);\n}\n\n.th {\n text-align: left;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.thRowNum {\n text-align: right;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n opacity: .5;\n width: 2.5rem;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.td {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text);\n white-space: nowrap;\n text-overflow: ellipsis;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.tdRowNum {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n white-space: nowrap;\n text-overflow: ellipsis;\n opacity: .5;\n text-align: right;\n user-select: none;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.nullValue {\n color: var(--ss-text-muted);\n opacity: .6;\n font-style: italic;\n}\n\n.jsonValue {\n color: var(--ss-text-dim);\n}\n\n.tabButton {\n width: 100%;\n color: var(--ss-text-dim);\n text-align: left;\n cursor: pointer;\n background: none;\n border: none;\n border-left: 2px solid #0000;\n border-radius: 7px;\n align-items: center;\n gap: .5rem;\n padding: .6rem .75rem;\n font-size: .82rem;\n font-weight: 500;\n transition: background .15s;\n display: flex;\n}\n\n.tabButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n border-left: 2px solid var(--ss-teal);\n font-weight: 700;\n}\n\n.targetButton {\n border: none;\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n cursor: pointer;\n white-space: nowrap;\n background: none;\n padding: .45rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n font-weight: 500;\n transition: background .1s;\n}\n\n.targetButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n}\n\n.runButton {\n background: var(--ss-bg-card);\n color: var(--ss-text-muted);\n cursor: not-allowed;\n opacity: 1;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n align-items: center;\n gap: .4rem;\n padding: .45rem .9rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n font-weight: 700;\n transition: background .15s;\n display: inline-flex;\n}\n\n.runButton[data-enabled=\"true\"] {\n background: var(--ss-teal);\n color: #0e1015;\n cursor: pointer;\n}\n\n.runButton[data-running=\"true\"] {\n opacity: .75;\n}\n\n.runningDot {\n background-color: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.schemaLayout {\n flex-direction: column;\n gap: 1.5rem;\n display: flex;\n}\n\n.schemaSection {\n flex-direction: column;\n gap: .65rem;\n display: flex;\n}\n\n.schemaSectionHeader {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.schemaSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 700;\n}\n\n.schemaBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaVersionChip {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .1rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.schemaTableGrid {\n border: 1px solid var(--ss-border);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaColHeader {\n letter-spacing: .07em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-right: 1px solid var(--ss-border);\n padding: .5rem .85rem;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaStatusCell {\n justify-content: center;\n align-items: center;\n padding: .6rem .5rem;\n display: flex;\n}\n\n.schemaActiveTag {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.schemaTableList {\n flex-direction: column;\n gap: .85rem;\n display: flex;\n}\n\n.schemaTableCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaTableCardHeader {\n border-bottom: 1px solid var(--ss-border);\n flex-direction: column;\n gap: .45rem;\n padding: .75rem .85rem .7rem;\n display: flex;\n}\n\n.schemaTableCardTitleRow {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.schemaTableCardName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .92rem;\n font-weight: 700;\n}\n\n.schemaTableCardDescription {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .78rem;\n line-height: 1.45;\n}\n\n.schemaTableCardMeta {\n flex-wrap: wrap;\n gap: .35rem;\n display: flex;\n}\n\n.schemaPolicyChip {\n color: var(--ss-text-muted);\n background: var(--ss-bg-input);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .12rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n}\n\n.schemaPolicyChip[data-tone=\"warn\"] {\n color: var(--ss-amber);\n background: #fbbf2414;\n border-color: #fbbf2440;\n}\n\n.schemaColumnGrid {\n flex-direction: column;\n display: flex;\n overflow-x: auto;\n}\n\n.schemaColumnRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(6.5rem, .7fr) minmax(8rem, 1fr) minmax(7.5rem, .9fr) minmax(0, 1.8fr);\n min-width: 36rem;\n display: grid;\n}\n\n.schemaColumnRow:last-child {\n border-bottom: none;\n}\n\n.schemaColumnRow[data-system=\"true\"] {\n opacity: .62;\n}\n\n.schemaColumnHeaderRow {\n background: var(--ss-bg-panel);\n}\n\n.schemaColumnHeaderRow .schemaColHeader:last-child {\n border-right: none;\n}\n\n.schemaColumnName, .schemaColumnType, .schemaColumnFlags, .schemaColumnDescription {\n border-right: 1px solid var(--ss-border);\n min-width: 0;\n padding: .5rem .85rem;\n font-size: .76rem;\n}\n\n.schemaColumnDescription {\n color: var(--ss-text-dim);\n overflow-wrap: anywhere;\n border-right: none;\n}\n\n.schemaColumnName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-weight: 600;\n}\n\n.schemaColumnType {\n color: var(--ss-teal);\n flex-direction: column;\n gap: .15rem;\n font-family: ui-monospace, monospace;\n display: flex;\n}\n\n.schemaColumnTypeDetail {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-size: .65rem;\n font-weight: 400;\n}\n\n.schemaColumnFlags {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-family: ui-monospace, monospace;\n}\n\n.liveQueryHeaderRow {\n background-color: var(--ss-bg-card);\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQueryRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQuerySql {\n color: var(--ss-text);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryParameters {\n color: var(--ss-text-dim);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryIdleTag {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.eventLogLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.eventLogToolbar {\n flex-wrap: wrap;\n flex-shrink: 0;\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.eventLogFilterSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventLogCount {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.eventLogEmpty {\n text-align: center;\n color: var(--ss-text-muted);\n padding: 2rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventLogList {\n flex-direction: column;\n flex: 1;\n gap: .25rem;\n display: flex;\n overflow-y: auto;\n}\n\n.eventRow {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.eventRow[data-expanded=\"true\"] {\n background: var(--ss-teal-glow);\n border: 1px solid #2dd4bf40;\n}\n\n.eventRowHeader {\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n flex-wrap: wrap;\n align-items: center;\n gap: .5rem;\n width: 100%;\n padding: .5rem .75rem;\n display: flex;\n}\n\n.eventSyncId {\n color: var(--ss-text-muted);\n min-width: 3.5rem;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventDataset {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n font-weight: 600;\n}\n\n.eventItemId {\n color: var(--ss-text-muted);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n min-width: 0;\n font-family: ui-monospace, monospace;\n font-size: .75rem;\n overflow: hidden;\n}\n\n.eventTimestamp {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventChevron {\n color: var(--ss-text-muted);\n margin-left: .25rem;\n font-size: .6rem;\n}\n\n.eventPayload {\n border-top: 1px solid var(--ss-border);\n padding: .6rem .75rem;\n}\n\n.eventPayloadMeta {\n gap: .75rem;\n margin-bottom: .5rem;\n display: flex;\n}\n\n.eventMetaItem {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.eventPayloadPre {\n color: var(--ss-text);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.loadMoreButton {\n border: 1px solid var(--ss-border);\n width: 100%;\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 8px;\n flex-shrink: 0;\n padding: .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventBadge {\n white-space: nowrap;\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.eventBadge[data-variant=\"create\"] {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n}\n\n.eventBadge[data-variant=\"update\"] {\n color: #a78bfa;\n background-color: #a78bfa1f;\n}\n\n.eventBadge[data-variant=\"delete\"] {\n color: var(--ss-error);\n background-color: #f871711f;\n}\n\n.eventBadge[data-variant=\"own\"], .eventBadge[data-variant=\"applied\"] {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n}\n\n.eventBadge[data-variant=\"remote\"], .eventBadge[data-variant=\"pending\"] {\n color: var(--ss-amber);\n background-color: #fbbf241a;\n}\n\n.eventBadge[data-variant=\"local\"] {\n color: var(--ss-text-dim);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.eventBadge[data-variant=\"failed\"] {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n}\n\n.eventBadge[data-variant=\"skipped\"] {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n}\n";
|
|
49
|
+
var devtools_default = ":host {\n all: initial;\n z-index: 9998;\n --ss-bg: #0e1015;\n --ss-bg-panel: #161921;\n --ss-bg-card: #1c2030;\n --ss-bg-input: #111318;\n --ss-border: #2a2f3e;\n --ss-border-light: #343a4f;\n --ss-text: #e2e8f0;\n --ss-text-muted: #6b7280;\n --ss-text-dim: #9ca3af;\n --ss-teal: #2dd4bf;\n --ss-teal-dim: #2dd4bf1f;\n --ss-teal-glow: #2dd4bf0f;\n --ss-error: #f87171;\n --ss-error-bg: #f8717114;\n --ss-error-border: #f8717140;\n --ss-success: #34d399;\n --ss-success-bg: #34d39914;\n --ss-amber: #fbbf24;\n color: var(--ss-text);\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: block;\n position: relative;\n}\n\n:host *, :host :before, :host :after {\n box-sizing: border-box;\n}\n\n.mono {\n font-family: ui-monospace, monospace;\n}\n\n.sm {\n font-size: .78rem;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.mlAuto {\n margin-left: auto;\n}\n\n.hiddenInput {\n display: none;\n}\n\n.floatingRoot {\n pointer-events: none;\n z-index: 9998;\n position: fixed;\n inset: 0;\n}\n\n.triggerButton {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n color: var(--ss-text);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 4px 16px #00000080;\n cursor: grab;\n touch-action: none;\n user-select: none;\n pointer-events: auto;\n border-radius: 8px;\n align-items: center;\n gap: .3rem;\n padding: .3rem .45rem;\n display: inline-flex;\n position: absolute;\n bottom: 16px;\n right: 16px;\n}\n\n.triggerIcon {\n color: var(--ss-teal);\n font-size: .9rem;\n line-height: 1;\n}\n\n.triggerCount {\n background-color: var(--ss-teal-dim);\n min-width: 1.1rem;\n color: var(--ss-teal);\n text-align: center;\n border-radius: 4px;\n padding: .05rem .25rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.overlay {\n z-index: 9999;\n backdrop-filter: blur(8px);\n background-color: #000000b8;\n justify-content: center;\n align-items: center;\n padding: 1.5rem;\n display: flex;\n position: fixed;\n inset: 0;\n}\n\n.dialog {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg);\n width: min(72rem, 100%);\n height: min(90vh, 860px);\n box-shadow: 0 0 0 1px var(--ss-border),\n 0 40px 80px #000c,\n 0 0 60px #2dd4bf0a;\n color: var(--ss-text);\n border-radius: 16px;\n flex-direction: column;\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: .88rem;\n display: flex;\n overflow: hidden;\n}\n\n.header {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-shrink: 0;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: .85rem 1.1rem;\n display: flex;\n}\n\n.headerLeft {\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.headerLogo {\n color: var(--ss-teal);\n font-size: 1.3rem;\n line-height: 1;\n}\n\n.eyebrow {\n letter-spacing: .1em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.title {\n color: var(--ss-text);\n letter-spacing: -.01em;\n margin: .05rem 0 0;\n font-size: .95rem;\n font-weight: 700;\n}\n\n.headerRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.instancePickerLabel {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.instancePickerText {\n color: var(--ss-text-muted);\n text-transform: uppercase;\n letter-spacing: .06em;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.instancePickerSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n}\n\n.instanceCountBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 600;\n}\n\n.closeButton {\n border: 1px solid var(--ss-border);\n width: 28px;\n height: 28px;\n color: var(--ss-text-muted);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n justify-content: center;\n align-items: center;\n font-size: .82rem;\n font-weight: 600;\n display: flex;\n}\n\n.hideLauncherButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .3rem .65rem;\n font-size: .75rem;\n font-weight: 600;\n}\n\n.emptyState {\n flex-direction: column;\n flex: 1;\n justify-content: center;\n align-items: center;\n gap: .75rem;\n padding: 4rem 2rem;\n display: flex;\n}\n\n.emptyStateIcon {\n color: var(--ss-text-muted);\n opacity: .4;\n font-size: 2.5rem;\n}\n\n.emptyStateText {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .95rem;\n font-weight: 600;\n}\n\n.emptyStateSubtext {\n color: var(--ss-text-muted);\n text-align: center;\n margin: 0;\n font-size: .82rem;\n}\n\n.inlineCode {\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n border-radius: 4px;\n padding: .1em .4em;\n font-family: ui-monospace, monospace;\n font-size: .88em;\n}\n\n.contentLayout {\n flex: 1;\n grid-template-columns: 200px minmax(0, 1fr);\n min-height: 0;\n display: grid;\n overflow: hidden;\n}\n\n.sidebar {\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-direction: column;\n gap: 0;\n padding: .75rem;\n display: flex;\n overflow-y: auto;\n}\n\n.nav {\n flex-direction: column;\n gap: .25rem;\n margin-bottom: 1rem;\n display: flex;\n}\n\n.navIcon {\n opacity: .7;\n font-size: .7rem;\n}\n\n.sidebarInfo {\n background: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n margin-top: auto;\n padding: .75rem;\n}\n\n.sidebarInfoLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .3rem;\n font-size: .65rem;\n font-weight: 600;\n}\n\n.sidebarInfoValue {\n color: var(--ss-text);\n word-break: break-word;\n font-family: ui-monospace, monospace;\n font-size: .88rem;\n font-weight: 600;\n}\n\n.sidebarInfoSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.mainPane {\n min-width: 0;\n padding: 1rem;\n overflow-y: auto;\n}\n\n.overviewLayout {\n flex-direction: column;\n gap: 1.25rem;\n display: flex;\n}\n\n.overviewCardsRow {\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: .75rem;\n display: grid;\n}\n\n.overviewCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n padding: .9rem 1rem;\n}\n\n.overviewCardLabel {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: .4rem;\n font-size: .68rem;\n font-weight: 600;\n}\n\n.overviewCardValue {\n color: var(--ss-text);\n word-break: break-word;\n font-size: 1rem;\n font-weight: 700;\n}\n\n.overviewCardSub {\n color: var(--ss-text-muted);\n margin-top: .25rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.overviewSection {\n flex-direction: column;\n gap: .5rem;\n display: flex;\n}\n\n.overviewSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 600;\n}\n\n.overviewSectionHeader {\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.refreshButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .7rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.overviewAccumulatorValue {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n color: var(--ss-text);\n word-break: break-all;\n border-radius: 8px;\n padding: .75rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.overviewAccumulatorEmpty {\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.overviewAccumulatorError {\n color: var(--ss-error);\n}\n\n.overviewEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventCountGrid {\n grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n gap: .5rem;\n display: grid;\n}\n\n.eventCountCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n padding: .75rem .85rem;\n}\n\n.eventCountValue {\n color: var(--ss-text);\n margin-bottom: .35rem;\n font-family: ui-monospace, monospace;\n font-size: 1.05rem;\n font-weight: 700;\n}\n\n.eventCountValue[data-tone=\"amber\"][data-emphasize=\"true\"] {\n color: var(--ss-amber);\n}\n\n.eventCountValue[data-tone=\"success\"][data-emphasize=\"true\"] {\n color: var(--ss-success);\n}\n\n.eventCountValue[data-tone=\"error\"][data-emphasize=\"true\"] {\n color: var(--ss-error);\n}\n\n.dataActions {\n gap: .4rem;\n display: flex;\n}\n\n.dataButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-teal);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .4rem .8rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.dataStatusSuccess {\n color: var(--ss-success);\n font-size: .75rem;\n}\n\n.dataStatusError {\n color: var(--ss-error);\n word-break: break-word;\n font-size: .75rem;\n}\n\n.dangerZone {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n margin-top: auto;\n padding: .75rem 1rem;\n}\n\n.dangerZoneTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-error);\n margin-bottom: .5rem;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.dangerZoneRow {\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n display: flex;\n}\n\n.dangerZoneDesc {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.dangerZoneActions {\n flex-shrink: 0;\n gap: .4rem;\n display: flex;\n}\n\n.resetButton {\n border: 1px solid var(--ss-error-border);\n color: var(--ss-error);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n flex-shrink: 0;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetCancelButton {\n border: 1px solid var(--ss-border);\n color: var(--ss-text-dim);\n cursor: pointer;\n white-space: nowrap;\n background-color: #0000;\n border-radius: 7px;\n padding: .35rem .65rem;\n font-size: .78rem;\n font-weight: 600;\n}\n\n.resetConfirmButton {\n background-color: var(--ss-error);\n color: #0e1015;\n cursor: pointer;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n padding: .35rem .75rem;\n font-size: .78rem;\n font-weight: 700;\n}\n\n.queryRunnerLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.queryToolbar {\n flex-wrap: wrap;\n justify-content: space-between;\n align-items: center;\n gap: .75rem;\n display: flex;\n}\n\n.targetToggle {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n gap: 0;\n display: flex;\n overflow: hidden;\n}\n\n.queryToolbarRight {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.noInstanceWarning {\n color: var(--ss-amber);\n font-size: .75rem;\n font-weight: 500;\n}\n\n.shortcutHint {\n color: var(--ss-text-muted);\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 5px;\n padding: .2rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.editorWrapper {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-input);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.textarea {\n resize: vertical;\n width: 100%;\n min-height: 9rem;\n color: var(--ss-text);\n box-sizing: border-box;\n background-color: #0000;\n border: none;\n outline: none;\n padding: .85rem 1rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .875rem;\n line-height: 1.6;\n}\n\n.helperText {\n color: var(--ss-text-muted);\n font-size: .75rem;\n line-height: 1.5;\n}\n\n.resultPanel {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n display: flex;\n overflow: hidden;\n}\n\n.errorPanel {\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n border-radius: 10px;\n flex-direction: column;\n gap: .6rem;\n padding: .85rem 1rem;\n display: flex;\n}\n\n.resultHeader {\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n align-items: center;\n gap: .6rem;\n padding: .6rem .85rem;\n display: flex;\n}\n\n.successBadge {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.errorBadge {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n border-radius: 5px;\n padding: .15rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n font-weight: 700;\n}\n\n.resultMeta {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.resultEmpty {\n color: var(--ss-text-muted);\n text-align: center;\n padding: 1.5rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.resultRaw {\n white-space: pre-wrap;\n word-break: break-word;\n color: var(--ss-text);\n margin: 0;\n padding: .85rem 1rem;\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n line-height: 1.5;\n overflow-x: auto;\n}\n\n.errorMessage {\n color: var(--ss-error);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n line-height: 1.6;\n}\n\n.tableWrapper {\n max-height: 320px;\n overflow: auto;\n}\n\n.table {\n border-collapse: collapse;\n width: 100%;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n font-size: .8rem;\n}\n\n.table tbody tr:nth-child(2n) {\n background: var(--ss-teal-glow);\n}\n\n.th {\n text-align: left;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.thRowNum {\n text-align: right;\n letter-spacing: .05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n opacity: .5;\n width: 2.5rem;\n padding: .5rem .85rem;\n font-size: .7rem;\n font-weight: 600;\n position: sticky;\n top: 0;\n}\n\n.td {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text);\n white-space: nowrap;\n text-overflow: ellipsis;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.tdRowNum {\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n white-space: nowrap;\n text-overflow: ellipsis;\n opacity: .5;\n text-align: right;\n user-select: none;\n max-width: 300px;\n padding: .45rem .85rem;\n overflow: hidden;\n}\n\n.nullValue {\n color: var(--ss-text-muted);\n opacity: .6;\n font-style: italic;\n}\n\n.jsonValue {\n color: var(--ss-text-dim);\n}\n\n.tabButton {\n width: 100%;\n color: var(--ss-text-dim);\n text-align: left;\n cursor: pointer;\n background: none;\n border: none;\n border-left: 2px solid #0000;\n border-radius: 7px;\n align-items: center;\n gap: .5rem;\n padding: .6rem .75rem;\n font-size: .82rem;\n font-weight: 500;\n transition: background .15s;\n display: flex;\n}\n\n.tabButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n border-left: 2px solid var(--ss-teal);\n font-weight: 700;\n}\n\n.targetButton {\n border: none;\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n cursor: pointer;\n white-space: nowrap;\n background: none;\n padding: .45rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n font-weight: 500;\n transition: background .1s;\n}\n\n.targetButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n}\n\n.runButton {\n background: var(--ss-bg-card);\n color: var(--ss-text-muted);\n cursor: not-allowed;\n opacity: 1;\n white-space: nowrap;\n border: none;\n border-radius: 7px;\n align-items: center;\n gap: .4rem;\n padding: .45rem .9rem;\n font-family: ui-monospace, monospace;\n font-size: .82rem;\n font-weight: 700;\n transition: background .15s;\n display: inline-flex;\n}\n\n.runButton[data-enabled=\"true\"] {\n background: var(--ss-teal);\n color: #0e1015;\n cursor: pointer;\n}\n\n.runButton[data-running=\"true\"] {\n opacity: .75;\n}\n\n.runningDot {\n background-color: currentColor;\n border-radius: 50%;\n width: 6px;\n height: 6px;\n}\n\n.schemaLayout {\n flex-direction: column;\n gap: 1.5rem;\n display: flex;\n}\n\n.schemaSection {\n flex-direction: column;\n gap: .65rem;\n display: flex;\n}\n\n.schemaSectionHeader {\n align-items: center;\n gap: .6rem;\n display: flex;\n}\n\n.schemaSectionTitle {\n letter-spacing: .08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-size: .72rem;\n font-weight: 700;\n}\n\n.schemaBadge {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaVersionChip {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .1rem .5rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.schemaTableGrid {\n border: 1px solid var(--ss-border);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaColHeader {\n letter-spacing: .07em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-right: 1px solid var(--ss-border);\n padding: .5rem .85rem;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaStatusCell {\n justify-content: center;\n align-items: center;\n padding: .6rem .5rem;\n display: flex;\n}\n\n.schemaActiveTag {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.schemaEmpty {\n color: var(--ss-text-muted);\n font-size: .82rem;\n font-style: italic;\n}\n\n.schemaTableList {\n flex-direction: column;\n gap: .85rem;\n display: flex;\n}\n\n.schemaTableCard {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 10px;\n overflow: hidden;\n}\n\n.schemaTableCardHeader {\n border-bottom: 1px solid var(--ss-border);\n flex-direction: column;\n gap: .45rem;\n padding: .75rem .85rem .7rem;\n display: flex;\n}\n\n.schemaTableCardTitleRow {\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.schemaTableCardName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .92rem;\n font-weight: 700;\n}\n\n.schemaTableCardDescription {\n color: var(--ss-text-dim);\n margin: 0;\n font-size: .78rem;\n line-height: 1.45;\n}\n\n.schemaTableCardMeta {\n flex-wrap: wrap;\n gap: .35rem;\n display: flex;\n}\n\n.schemaPolicyChip {\n color: var(--ss-text-muted);\n background: var(--ss-bg-input);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .12rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n}\n\n.schemaPolicyChip[data-tone=\"warn\"] {\n color: var(--ss-amber);\n background: #fbbf2414;\n border-color: #fbbf2440;\n}\n\n.schemaColumnGrid {\n flex-direction: column;\n display: flex;\n overflow-x: auto;\n}\n\n.schemaColumnRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(6.5rem, .7fr) minmax(8rem, 1fr) minmax(7.5rem, .9fr) minmax(0, 1.8fr);\n min-width: 36rem;\n display: grid;\n}\n\n.schemaColumnRow:last-child {\n border-bottom: none;\n}\n\n.schemaColumnRow[data-system=\"true\"] {\n opacity: .62;\n}\n\n.schemaColumnHeaderRow {\n background: var(--ss-bg-panel);\n}\n\n.schemaColumnHeaderRow .schemaColHeader:last-child {\n border-right: none;\n}\n\n.schemaColumnName, .schemaColumnType, .schemaColumnFlags, .schemaColumnDescription {\n border-right: 1px solid var(--ss-border);\n min-width: 0;\n padding: .5rem .85rem;\n font-size: .76rem;\n}\n\n.schemaColumnDescription {\n color: var(--ss-text-dim);\n overflow-wrap: anywhere;\n border-right: none;\n}\n\n.schemaColumnName {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-weight: 600;\n}\n\n.schemaColumnType {\n color: var(--ss-teal);\n flex-direction: column;\n gap: .15rem;\n font-family: ui-monospace, monospace;\n display: flex;\n}\n\n.schemaColumnTypeDetail {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-size: .65rem;\n font-weight: 400;\n}\n\n.schemaColumnFlags {\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n font-family: ui-monospace, monospace;\n}\n\n.liveQueryHeaderRow {\n background-color: var(--ss-bg-card);\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQueryRow {\n border-bottom: 1px solid var(--ss-border);\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n display: grid;\n}\n\n.liveQuerySql {\n color: var(--ss-text);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryParameters {\n color: var(--ss-text-dim);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n padding: .6rem .85rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.liveQueryIdleTag {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: .15rem .45rem;\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n font-weight: 700;\n}\n\n.eventLogLayout {\n flex-direction: column;\n gap: .75rem;\n height: 100%;\n display: flex;\n}\n\n.eventLogToolbar {\n flex-wrap: wrap;\n flex-shrink: 0;\n align-items: center;\n gap: .5rem;\n display: flex;\n}\n\n.eventLogFilterSelect {\n border: 1px solid var(--ss-border);\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n cursor: pointer;\n border-radius: 7px;\n padding: .35rem .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventLogCount {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .72rem;\n}\n\n.eventLogEmpty {\n text-align: center;\n color: var(--ss-text-muted);\n padding: 2rem;\n font-size: .82rem;\n font-style: italic;\n}\n\n.eventLogList {\n flex-direction: column;\n flex: 1;\n gap: .25rem;\n display: flex;\n overflow-y: auto;\n}\n\n.eventRow {\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n border-radius: 8px;\n flex-shrink: 0;\n overflow: hidden;\n}\n\n.eventRow[data-expanded=\"true\"] {\n background: var(--ss-teal-glow);\n border: 1px solid #2dd4bf40;\n}\n\n.eventRowHeader {\n cursor: pointer;\n text-align: left;\n background: none;\n border: none;\n flex-wrap: wrap;\n align-items: center;\n gap: .5rem;\n width: 100%;\n padding: .5rem .75rem;\n display: flex;\n}\n\n.eventSyncId {\n color: var(--ss-text-muted);\n min-width: 3.5rem;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventDataset {\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n font-size: .8rem;\n font-weight: 600;\n}\n\n.eventItemId {\n color: var(--ss-text-muted);\n text-overflow: ellipsis;\n white-space: nowrap;\n flex: 1;\n min-width: 0;\n font-family: ui-monospace, monospace;\n font-size: .75rem;\n overflow: hidden;\n}\n\n.eventTimestamp {\n color: var(--ss-text-muted);\n margin-left: auto;\n font-family: ui-monospace, monospace;\n font-size: .7rem;\n}\n\n.eventChevron {\n color: var(--ss-text-muted);\n margin-left: .25rem;\n font-size: .6rem;\n}\n\n.eventPayload {\n border-top: 1px solid var(--ss-border);\n padding: .6rem .75rem;\n}\n\n.eventPayloadMeta {\n gap: .75rem;\n margin-bottom: .5rem;\n display: flex;\n}\n\n.eventMetaItem {\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n font-size: .68rem;\n}\n\n.eventPayloadPre {\n color: var(--ss-text);\n white-space: pre-wrap;\n word-break: break-word;\n margin: 0;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n line-height: 1.5;\n}\n\n.loadMoreButton {\n border: 1px solid var(--ss-border);\n width: 100%;\n color: var(--ss-text-dim);\n cursor: pointer;\n background-color: #0000;\n border-radius: 8px;\n flex-shrink: 0;\n padding: .6rem;\n font-family: ui-monospace, monospace;\n font-size: .78rem;\n}\n\n.eventBadge {\n white-space: nowrap;\n border-radius: 4px;\n padding: .1rem .4rem;\n font-family: ui-monospace, monospace;\n font-size: .65rem;\n font-weight: 700;\n}\n\n.eventBadge[data-variant=\"create\"] {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n}\n\n.eventBadge[data-variant=\"update\"] {\n color: #a78bfa;\n background-color: #a78bfa1f;\n}\n\n.eventBadge[data-variant=\"delete\"] {\n color: var(--ss-error);\n background-color: #f871711f;\n}\n\n.eventBadge[data-variant=\"own\"], .eventBadge[data-variant=\"applied\"] {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n}\n\n.eventBadge[data-variant=\"remote\"], .eventBadge[data-variant=\"pending\"] {\n color: var(--ss-amber);\n background-color: #fbbf241a;\n}\n\n.eventBadge[data-variant=\"local\"] {\n color: var(--ss-text-dim);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.eventBadge[data-variant=\"failed\"] {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n}\n\n.eventBadge[data-variant=\"skipped\"] {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n}\n\n@media (width <= 640px) {\n .overlay {\n padding: 0;\n }\n\n .dialog {\n border: none;\n border-radius: 0;\n width: 100%;\n height: 100%;\n }\n\n .header {\n padding: .6rem .75rem;\n padding-top: max(.6rem, env(safe-area-inset-top));\n flex-wrap: wrap;\n gap: .5rem;\n }\n\n .headerRight {\n flex: 1;\n justify-content: flex-end;\n min-width: 0;\n }\n\n .instancePickerLabel {\n min-width: 0;\n }\n\n .instancePickerSelect {\n min-width: 0;\n max-width: 100%;\n }\n\n .instanceCountBadge {\n display: none;\n }\n\n .closeButton {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n }\n\n .contentLayout {\n grid-template-rows: auto minmax(0, 1fr);\n grid-template-columns: minmax(0, 1fr);\n }\n\n .sidebar {\n border-right: none;\n border-bottom: 1px solid var(--ss-border);\n padding: .4rem .5rem;\n overflow: auto hidden;\n }\n\n .nav {\n flex-direction: row;\n margin-bottom: 0;\n }\n\n .tabButton {\n white-space: nowrap;\n border-bottom: 2px solid #0000;\n border-left: none;\n flex-shrink: 0;\n width: auto;\n }\n\n .tabButton[data-active=\"true\"] {\n border-left: none;\n border-bottom: 2px solid var(--ss-teal);\n }\n\n .sidebarInfo {\n display: none;\n }\n\n .mainPane {\n padding: .75rem;\n padding-bottom: max(.75rem, env(safe-area-inset-bottom));\n }\n\n .liveQueryHeaderRow, .liveQueryRow {\n grid-template-columns: minmax(0, 1fr) minmax(0, .6fr) 6.5rem;\n }\n\n .liveQueryHeaderRow .schemaColHeader, .liveQuerySql, .liveQueryParameters {\n padding-left: .5rem;\n padding-right: .5rem;\n }\n\n .liveQueryHeaderRow .schemaColHeader {\n letter-spacing: .02em;\n }\n}\n\n@media (hover: none) {\n .hideLauncherButton {\n display: none;\n }\n}\n";
|
|
50
50
|
//#endregion
|
|
51
51
|
//#region src/shadow-root.tsx
|
|
52
52
|
function ShadowRoot({ children, className }) {
|
|
@@ -83,6 +83,14 @@ function readStoredTriggerPosition() {
|
|
|
83
83
|
} catch {}
|
|
84
84
|
return null;
|
|
85
85
|
}
|
|
86
|
+
function clampTriggerPosition(position, button) {
|
|
87
|
+
const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;
|
|
88
|
+
const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;
|
|
89
|
+
return {
|
|
90
|
+
x: Math.max(VIEWPORT_MARGIN_PX, Math.min(position.x, maxX)),
|
|
91
|
+
y: Math.max(VIEWPORT_MARGIN_PX, Math.min(position.y, maxY))
|
|
92
|
+
};
|
|
93
|
+
}
|
|
86
94
|
function useDraggableTrigger() {
|
|
87
95
|
const buttonRef = useRef(null);
|
|
88
96
|
const [position, setPosition] = useState(readStoredTriggerPosition);
|
|
@@ -103,18 +111,33 @@ function useDraggableTrigger() {
|
|
|
103
111
|
};
|
|
104
112
|
button.setPointerCapture(event.pointerId);
|
|
105
113
|
}, []);
|
|
114
|
+
const clampToViewport = useCallback(() => {
|
|
115
|
+
const button = buttonRef.current;
|
|
116
|
+
if (!button) return;
|
|
117
|
+
setPosition((current) => {
|
|
118
|
+
if (!current) return current;
|
|
119
|
+
const next = clampTriggerPosition(current, button);
|
|
120
|
+
return next.x === current.x && next.y === current.y ? current : next;
|
|
121
|
+
});
|
|
122
|
+
}, []);
|
|
123
|
+
const setButtonRef = useCallback((button) => {
|
|
124
|
+
buttonRef.current = button;
|
|
125
|
+
clampToViewport();
|
|
126
|
+
}, [clampToViewport]);
|
|
127
|
+
useEffect(() => {
|
|
128
|
+
window.addEventListener("resize", clampToViewport);
|
|
129
|
+
return () => window.removeEventListener("resize", clampToViewport);
|
|
130
|
+
}, [clampToViewport]);
|
|
106
131
|
const onPointerMove = useCallback((event) => {
|
|
107
132
|
const drag = dragRef.current;
|
|
108
133
|
const button = buttonRef.current;
|
|
109
134
|
if (!drag || !button || drag.pointerId !== event.pointerId) return;
|
|
110
135
|
if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < DRAG_THRESHOLD_PX) return;
|
|
111
136
|
drag.moved = true;
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
y: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientY - drag.offsetY, maxY))
|
|
117
|
-
});
|
|
137
|
+
setPosition(clampTriggerPosition({
|
|
138
|
+
x: event.clientX - drag.offsetX,
|
|
139
|
+
y: event.clientY - drag.offsetY
|
|
140
|
+
}, button));
|
|
118
141
|
}, []);
|
|
119
142
|
const endDrag = useCallback((event) => {
|
|
120
143
|
const drag = dragRef.current;
|
|
@@ -136,7 +159,7 @@ function useDraggableTrigger() {
|
|
|
136
159
|
return true;
|
|
137
160
|
}, []);
|
|
138
161
|
return {
|
|
139
|
-
buttonRef,
|
|
162
|
+
buttonRef: setButtonRef,
|
|
140
163
|
positionStyle: position ? {
|
|
141
164
|
left: position.x,
|
|
142
165
|
top: position.y,
|
|
@@ -164,12 +187,13 @@ function isToggleLauncherShortcut(event) {
|
|
|
164
187
|
if (event.shiftKey || !event.altKey || event.code !== "KeyS") return false;
|
|
165
188
|
return event.ctrlKey || event.metaKey;
|
|
166
189
|
}
|
|
167
|
-
function useLauncherVisibility({ hidden: hiddenProp, onHiddenChange }) {
|
|
190
|
+
function useLauncherVisibility({ launcher, hidden: hiddenProp, onHiddenChange, onHide }) {
|
|
168
191
|
const isControlled = hiddenProp !== void 0;
|
|
169
192
|
const [uncontrolledHidden, setUncontrolledHidden] = useState(readStoredTriggerHidden);
|
|
170
|
-
const hidden = isControlled ? hiddenProp : uncontrolledHidden;
|
|
171
|
-
const canToggle = !isControlled || onHiddenChange !== void 0;
|
|
193
|
+
const hidden = !launcher || (isControlled ? hiddenProp : uncontrolledHidden);
|
|
194
|
+
const canToggle = launcher && (!isControlled || onHiddenChange !== void 0);
|
|
172
195
|
const setHidden = useCallback((next) => {
|
|
196
|
+
if (next) onHide();
|
|
173
197
|
if (isControlled) {
|
|
174
198
|
onHiddenChange?.(next);
|
|
175
199
|
return;
|
|
@@ -178,7 +202,11 @@ function useLauncherVisibility({ hidden: hiddenProp, onHiddenChange }) {
|
|
|
178
202
|
try {
|
|
179
203
|
window.localStorage.setItem(TRIGGER_HIDDEN_STORAGE_KEY, next ? "1" : "0");
|
|
180
204
|
} catch {}
|
|
181
|
-
}, [
|
|
205
|
+
}, [
|
|
206
|
+
isControlled,
|
|
207
|
+
onHiddenChange,
|
|
208
|
+
onHide
|
|
209
|
+
]);
|
|
182
210
|
useEffect(() => {
|
|
183
211
|
if (!canToggle) return;
|
|
184
212
|
const onKeyDown = (event) => {
|
|
@@ -199,33 +227,47 @@ function useLauncherVisibility({ hidden: hiddenProp, onHiddenChange }) {
|
|
|
199
227
|
canToggle
|
|
200
228
|
};
|
|
201
229
|
}
|
|
202
|
-
function
|
|
230
|
+
function useOpenState({ open: openProp, onOpenChange }) {
|
|
231
|
+
const isControlled = openProp !== void 0;
|
|
232
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
|
|
233
|
+
return {
|
|
234
|
+
isOpen: isControlled ? openProp : uncontrolledOpen,
|
|
235
|
+
setIsOpen: useCallback((next) => {
|
|
236
|
+
if (!isControlled) setUncontrolledOpen(next);
|
|
237
|
+
onOpenChange?.(next);
|
|
238
|
+
}, [isControlled, onOpenChange])
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function SQLiteSyncDevtools({ className, launcher = true, hidden: hiddenProp, onHiddenChange, open: openProp, onOpenChange }) {
|
|
203
242
|
const registry = getOrCreateSQLiteSyncDevtoolsRegistry();
|
|
204
243
|
const instances = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot).instances;
|
|
205
244
|
const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();
|
|
245
|
+
const { isOpen, setIsOpen } = useOpenState({
|
|
246
|
+
open: openProp,
|
|
247
|
+
onOpenChange
|
|
248
|
+
});
|
|
249
|
+
const closeDialog = useCallback(() => setIsOpen(false), [setIsOpen]);
|
|
206
250
|
const { hidden, setHidden, canToggle } = useLauncherVisibility({
|
|
251
|
+
launcher,
|
|
207
252
|
hidden: hiddenProp,
|
|
208
|
-
onHiddenChange
|
|
253
|
+
onHiddenChange,
|
|
254
|
+
onHide: closeDialog
|
|
209
255
|
});
|
|
210
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
211
256
|
const [activeTab, setActiveTab] = useState("overview");
|
|
212
257
|
const [selectedInstanceId, setSelectedInstanceId] = useState("");
|
|
213
258
|
const [queryTarget, setQueryTarget] = useState("memory");
|
|
214
259
|
const [query, setQuery] = useState("");
|
|
215
260
|
const [queryState, setQueryState] = useState({ status: "idle" });
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
if (hidden) setIsOpen(false);
|
|
218
|
-
}, [hidden]);
|
|
219
261
|
useEffect(() => {
|
|
220
262
|
if (!isOpen) return;
|
|
221
263
|
const onKeyDown = (event) => {
|
|
222
|
-
if (event.key === "Escape")
|
|
264
|
+
if (event.key === "Escape") closeDialog();
|
|
223
265
|
};
|
|
224
266
|
window.addEventListener("keydown", onKeyDown);
|
|
225
267
|
return () => {
|
|
226
268
|
window.removeEventListener("keydown", onKeyDown);
|
|
227
269
|
};
|
|
228
|
-
}, [isOpen]);
|
|
270
|
+
}, [isOpen, closeDialog]);
|
|
229
271
|
useEffect(() => {
|
|
230
272
|
if (instances.length === 0) {
|
|
231
273
|
setSelectedInstanceId("");
|
|
@@ -309,7 +351,7 @@ function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }) {
|
|
|
309
351
|
})
|
|
310
352
|
}), isOpen ? /* @__PURE__ */ jsx("div", {
|
|
311
353
|
className: "overlay",
|
|
312
|
-
onClick:
|
|
354
|
+
onClick: closeDialog,
|
|
313
355
|
children: /* @__PURE__ */ jsxs("section", {
|
|
314
356
|
role: "dialog",
|
|
315
357
|
"aria-modal": "true",
|
|
@@ -366,7 +408,7 @@ function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }) {
|
|
|
366
408
|
/* @__PURE__ */ jsx("button", {
|
|
367
409
|
type: "button",
|
|
368
410
|
className: "closeButton",
|
|
369
|
-
onClick:
|
|
411
|
+
onClick: closeDialog,
|
|
370
412
|
"aria-label": "Close",
|
|
371
413
|
children: "✕"
|
|
372
414
|
})
|
|
@@ -495,7 +537,7 @@ function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }) {
|
|
|
495
537
|
}) : null]
|
|
496
538
|
});
|
|
497
539
|
}
|
|
498
|
-
const
|
|
540
|
+
const STATE_HASH_QUERY = `SELECT value FROM "worker"."kv" WHERE key = 'crdt.consistency.state_hash.v1'`;
|
|
499
541
|
const EVENT_STATUS_COUNTS_QUERY = `SELECT status, COUNT(*) AS count FROM "worker"."crdt_events" GROUP BY status`;
|
|
500
542
|
const MEMORY_DB_SIZE_QUERY = "SELECT (SELECT page_count FROM pragma_page_count()) * (SELECT page_size FROM pragma_page_size()) AS bytes";
|
|
501
543
|
const WORKER_DB_SIZE_QUERY = `SELECT
|
|
@@ -582,9 +624,9 @@ function formatByteSize(bytes) {
|
|
|
582
624
|
};
|
|
583
625
|
}
|
|
584
626
|
function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
585
|
-
const [
|
|
586
|
-
const [
|
|
587
|
-
const [
|
|
627
|
+
const [stateHash, setStateHash] = useState(null);
|
|
628
|
+
const [stateHashError, setStateHashError] = useState(null);
|
|
629
|
+
const [isStateHashLoading, setIsStateHashLoading] = useState(false);
|
|
588
630
|
const [eventCounts, setEventCounts] = useState(null);
|
|
589
631
|
const [eventCountsError, setEventCountsError] = useState(null);
|
|
590
632
|
const [isEventCountsLoading, setIsEventCountsLoading] = useState(false);
|
|
@@ -593,22 +635,22 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
593
635
|
const [workerBytes, setWorkerBytes] = useState(null);
|
|
594
636
|
const [workerSizeError, setWorkerSizeError] = useState(null);
|
|
595
637
|
const [isSizeLoading, setIsSizeLoading] = useState(false);
|
|
596
|
-
const
|
|
638
|
+
const refreshStateHash = useCallback(async () => {
|
|
597
639
|
if (!selectedInstance) return;
|
|
598
|
-
|
|
599
|
-
|
|
640
|
+
setIsStateHashLoading(true);
|
|
641
|
+
setStateHashError(null);
|
|
600
642
|
try {
|
|
601
643
|
const row = (await selectedInstance.instance._internal.executeAsync({
|
|
602
|
-
sql:
|
|
644
|
+
sql: STATE_HASH_QUERY,
|
|
603
645
|
parameters: []
|
|
604
646
|
})).rows[0];
|
|
605
647
|
const value = typeof row === "object" && row !== null && "value" in row && typeof row.value === "string" ? row.value : "";
|
|
606
|
-
|
|
648
|
+
setStateHash(value);
|
|
607
649
|
} catch (error) {
|
|
608
|
-
|
|
609
|
-
|
|
650
|
+
setStateHashError(error instanceof Error ? error.message : String(error));
|
|
651
|
+
setStateHash(null);
|
|
610
652
|
} finally {
|
|
611
|
-
|
|
653
|
+
setIsStateHashLoading(false);
|
|
612
654
|
}
|
|
613
655
|
}, [selectedInstance]);
|
|
614
656
|
const refreshEventCounts = useCallback(async () => {
|
|
@@ -660,19 +702,19 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
660
702
|
setIsSizeLoading(false);
|
|
661
703
|
}, [selectedInstance]);
|
|
662
704
|
useEffect(() => {
|
|
663
|
-
|
|
664
|
-
|
|
705
|
+
setStateHash(null);
|
|
706
|
+
setStateHashError(null);
|
|
665
707
|
setEventCounts(null);
|
|
666
708
|
setEventCountsError(null);
|
|
667
709
|
setMemoryBytes(null);
|
|
668
710
|
setMemorySizeError(null);
|
|
669
711
|
setWorkerBytes(null);
|
|
670
712
|
setWorkerSizeError(null);
|
|
671
|
-
|
|
713
|
+
refreshStateHash();
|
|
672
714
|
refreshEventCounts();
|
|
673
715
|
refreshDbSizes();
|
|
674
716
|
}, [
|
|
675
|
-
|
|
717
|
+
refreshStateHash,
|
|
676
718
|
refreshEventCounts,
|
|
677
719
|
refreshDbSizes
|
|
678
720
|
]);
|
|
@@ -787,23 +829,23 @@ function OverviewTab({ selectedInstance, dbIdCounts }) {
|
|
|
787
829
|
className: "overviewSectionHeader",
|
|
788
830
|
children: [/* @__PURE__ */ jsx("div", {
|
|
789
831
|
className: "overviewSectionTitle",
|
|
790
|
-
children: "
|
|
832
|
+
children: "State hash"
|
|
791
833
|
}), /* @__PURE__ */ jsxs("button", {
|
|
792
834
|
type: "button",
|
|
793
835
|
className: "refreshButton",
|
|
794
|
-
disabled:
|
|
795
|
-
onClick: () => void
|
|
796
|
-
children: [
|
|
836
|
+
disabled: isStateHashLoading,
|
|
837
|
+
onClick: () => void refreshStateHash(),
|
|
838
|
+
children: [isStateHashLoading ? "…" : "↻", " Refresh"]
|
|
797
839
|
})]
|
|
798
840
|
}), /* @__PURE__ */ jsx("div", {
|
|
799
841
|
className: "overviewAccumulatorValue",
|
|
800
|
-
children:
|
|
842
|
+
children: stateHashError ? /* @__PURE__ */ jsx("span", {
|
|
801
843
|
className: "overviewAccumulatorError",
|
|
802
|
-
children:
|
|
803
|
-
}) :
|
|
844
|
+
children: stateHashError
|
|
845
|
+
}) : isStateHashLoading && stateHash === null ? "Loading…" : stateHash === "" ? /* @__PURE__ */ jsx("span", {
|
|
804
846
|
className: "overviewAccumulatorEmpty",
|
|
805
847
|
children: "(empty)"
|
|
806
|
-
}) :
|
|
848
|
+
}) : stateHash
|
|
807
849
|
})]
|
|
808
850
|
}),
|
|
809
851
|
/* @__PURE__ */ jsx(DataSection, {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["cssText"],"sources":["../src/devtools-registry.ts","../src/devtools.css?inline","../src/shadow-root.tsx","../src/devtools.tsx"],"sourcesContent":["import type { SyncedDb } from \"@sqlite-sync/core\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n",":host {\n all: initial;\n display: block;\n position: relative;\n z-index: 9998;\n --ss-bg: #0e1015;\n --ss-bg-panel: #161921;\n --ss-bg-card: #1c2030;\n --ss-bg-input: #111318;\n --ss-border: #2a2f3e;\n --ss-border-light: #343a4f;\n --ss-text: #e2e8f0;\n --ss-text-muted: #6b7280;\n --ss-text-dim: #9ca3af;\n --ss-teal: #2dd4bf;\n --ss-teal-dim: rgba(45, 212, 191, 0.12);\n --ss-teal-glow: rgba(45, 212, 191, 0.06);\n --ss-error: #f87171;\n --ss-error-bg: rgba(248, 113, 113, 0.08);\n --ss-error-border: rgba(248, 113, 113, 0.25);\n --ss-success: #34d399;\n --ss-success-bg: rgba(52, 211, 153, 0.08);\n --ss-amber: #fbbf24;\n font-family: ui-sans-serif, system-ui, sans-serif;\n color: var(--ss-text);\n font-size: 0.88rem;\n}\n\n:host *,\n:host *::before,\n:host *::after {\n box-sizing: border-box;\n}\n\n.mono {\n font-family: ui-monospace, monospace;\n}\n\n.sm {\n font-size: 0.78rem;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.mlAuto {\n margin-left: auto;\n}\n\n.hiddenInput {\n display: none;\n}\n\n.floatingRoot {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9998;\n}\n\n.triggerButton {\n position: absolute;\n right: 16px;\n bottom: 16px;\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n padding: 0.3rem 0.45rem;\n background: var(--ss-bg-panel);\n color: var(--ss-text);\n box-shadow:\n 0 0 0 1px var(--ss-border),\n 0 4px 16px rgba(0, 0, 0, 0.5);\n cursor: grab;\n touch-action: none;\n user-select: none;\n pointer-events: auto;\n}\n\n.triggerIcon {\n color: var(--ss-teal);\n font-size: 0.9rem;\n line-height: 1;\n}\n\n.triggerCount {\n min-width: 1.1rem;\n border-radius: 4px;\n padding: 0.05rem 0.25rem;\n background-color: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-size: 0.65rem;\n font-weight: 700;\n text-align: center;\n font-family: ui-monospace, monospace;\n}\n\n.overlay {\n position: fixed;\n inset: 0;\n z-index: 9999;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n background-color: rgba(0, 0, 0, 0.72);\n backdrop-filter: blur(8px);\n}\n\n.dialog {\n width: min(72rem, 100%);\n height: min(90vh, 860px);\n display: flex;\n flex-direction: column;\n border: 1px solid var(--ss-border);\n border-radius: 16px;\n background: var(--ss-bg);\n box-shadow:\n 0 0 0 1px var(--ss-border),\n 0 40px 80px rgba(0, 0, 0, 0.8),\n 0 0 60px rgba(45, 212, 191, 0.04);\n overflow: hidden;\n font-family: ui-sans-serif, system-ui, sans-serif;\n color: var(--ss-text);\n font-size: 0.88rem;\n}\n\n.header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: 0.85rem 1.1rem;\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-shrink: 0;\n}\n\n.headerLeft {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.headerLogo {\n font-size: 1.3rem;\n color: var(--ss-teal);\n line-height: 1;\n}\n\n.eyebrow {\n font-size: 0.65rem;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n}\n\n.title {\n margin: 0.05rem 0 0;\n font-size: 0.95rem;\n font-weight: 700;\n color: var(--ss-text);\n letter-spacing: -0.01em;\n}\n\n.headerRight {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.instancePickerLabel {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.instancePickerText {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--ss-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.instancePickerSelect {\n border-radius: 7px;\n border: 1px solid var(--ss-border);\n padding: 0.35rem 0.6rem;\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n font-size: 0.82rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n}\n\n.instanceCountBadge {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 5px;\n padding: 0.2rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.closeButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: transparent;\n color: var(--ss-text-muted);\n font-size: 0.82rem;\n font-weight: 600;\n cursor: pointer;\n}\n\n.hideLauncherButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.3rem 0.65rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.75rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.emptyState {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n gap: 0.75rem;\n flex: 1;\n}\n\n.emptyStateIcon {\n font-size: 2.5rem;\n color: var(--ss-text-muted);\n opacity: 0.4;\n}\n\n.emptyStateText {\n margin: 0;\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--ss-text-dim);\n}\n\n.emptyStateSubtext {\n margin: 0;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n text-align: center;\n}\n\n.inlineCode {\n font-family: ui-monospace, monospace;\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.1em 0.4em;\n font-size: 0.88em;\n color: var(--ss-teal);\n}\n\n.contentLayout {\n display: grid;\n grid-template-columns: 200px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.sidebar {\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0.75rem;\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n overflow-y: auto;\n}\n\n.nav {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n margin-bottom: 1rem;\n}\n\n.navIcon {\n font-size: 0.7rem;\n opacity: 0.7;\n}\n\n.sidebarInfo {\n margin-top: auto;\n padding: 0.75rem;\n border-radius: 8px;\n background: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.sidebarInfoLabel {\n font-size: 0.65rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: 0.3rem;\n}\n\n.sidebarInfoValue {\n font-size: 0.88rem;\n font-weight: 600;\n color: var(--ss-text);\n word-break: break-word;\n font-family: ui-monospace, monospace;\n}\n\n.sidebarInfoSub {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n margin-top: 0.25rem;\n}\n\n.mainPane {\n min-width: 0;\n overflow-y: auto;\n padding: 1rem;\n}\n\n.overviewLayout {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n\n.overviewCardsRow {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: 0.75rem;\n}\n\n.overviewCard {\n padding: 0.9rem 1rem;\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.overviewCardLabel {\n font-size: 0.68rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: 0.4rem;\n}\n\n.overviewCardValue {\n font-size: 1rem;\n font-weight: 700;\n color: var(--ss-text);\n word-break: break-word;\n}\n\n.overviewCardSub {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n margin-top: 0.25rem;\n}\n\n.overviewSection {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.overviewSectionTitle {\n font-size: 0.72rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n}\n\n.overviewSectionHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n}\n\n.refreshButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.35rem 0.7rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.overviewAccumulatorValue {\n padding: 0.75rem;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n font-family: ui-monospace, monospace;\n font-size: 0.78rem;\n color: var(--ss-text);\n line-height: 1.5;\n word-break: break-all;\n}\n\n.overviewAccumulatorEmpty {\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.overviewAccumulatorError {\n color: var(--ss-error);\n}\n\n.overviewEmpty {\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.eventCountGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n gap: 0.5rem;\n}\n\n.eventCountCard {\n padding: 0.75rem 0.85rem;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.eventCountValue {\n font-size: 1.05rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n margin-bottom: 0.35rem;\n}\n\n.eventCountValue[data-tone=\"amber\"][data-emphasize=\"true\"] {\n color: var(--ss-amber);\n}\n\n.eventCountValue[data-tone=\"success\"][data-emphasize=\"true\"] {\n color: var(--ss-success);\n}\n\n.eventCountValue[data-tone=\"error\"][data-emphasize=\"true\"] {\n color: var(--ss-error);\n}\n\n.dataActions {\n display: flex;\n gap: 0.4rem;\n}\n\n.dataButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.4rem 0.8rem;\n background-color: transparent;\n color: var(--ss-teal);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.dataStatusSuccess {\n font-size: 0.75rem;\n color: var(--ss-success);\n}\n\n.dataStatusError {\n font-size: 0.75rem;\n color: var(--ss-error);\n word-break: break-word;\n}\n\n.dangerZone {\n margin-top: auto;\n border-radius: 10px;\n border: 1px solid var(--ss-error-border);\n padding: 0.75rem 1rem;\n background: var(--ss-error-bg);\n}\n\n.dangerZoneTitle {\n font-size: 0.65rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-error);\n margin-bottom: 0.5rem;\n}\n\n.dangerZoneRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n}\n\n.dangerZoneDesc {\n font-size: 0.75rem;\n color: var(--ss-text-muted);\n line-height: 1.5;\n}\n\n.dangerZoneActions {\n display: flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n\n.resetButton {\n flex-shrink: 0;\n border: 1px solid var(--ss-error-border);\n border-radius: 7px;\n padding: 0.35rem 0.75rem;\n background-color: transparent;\n color: var(--ss-error);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.resetCancelButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.35rem 0.65rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.resetConfirmButton {\n border: none;\n border-radius: 7px;\n padding: 0.35rem 0.75rem;\n background-color: var(--ss-error);\n color: #0e1015;\n font-size: 0.78rem;\n font-weight: 700;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.queryRunnerLayout {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n height: 100%;\n}\n\n.queryToolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.targetToggle {\n display: flex;\n gap: 0;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-card);\n}\n\n.queryToolbarRight {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.noInstanceWarning {\n font-size: 0.75rem;\n color: var(--ss-amber);\n font-weight: 500;\n}\n\n.shortcutHint {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n padding: 0.2rem 0.5rem;\n border-radius: 5px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.editorWrapper {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-input);\n}\n\n.textarea {\n width: 100%;\n min-height: 9rem;\n resize: vertical;\n border: none;\n padding: 0.85rem 1rem;\n background-color: transparent;\n color: var(--ss-text);\n font-size: 0.875rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n line-height: 1.6;\n outline: none;\n box-sizing: border-box;\n}\n\n.helperText {\n font-size: 0.75rem;\n line-height: 1.5;\n color: var(--ss-text-muted);\n}\n\n.resultPanel {\n display: flex;\n flex-direction: column;\n gap: 0.6rem;\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-panel);\n}\n\n.errorPanel {\n display: flex;\n flex-direction: column;\n gap: 0.6rem;\n padding: 0.85rem 1rem;\n border-radius: 10px;\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n}\n\n.resultHeader {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.6rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.successBadge {\n font-size: 0.72rem;\n font-weight: 700;\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 5px;\n padding: 0.15rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.errorBadge {\n font-size: 0.72rem;\n font-weight: 700;\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n border-radius: 5px;\n padding: 0.15rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.resultMeta {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n}\n\n.resultEmpty {\n padding: 1.5rem;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n text-align: center;\n}\n\n.resultRaw {\n margin: 0;\n padding: 0.85rem 1rem;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 0.8rem;\n line-height: 1.5;\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n}\n\n.errorMessage {\n margin: 0;\n font-size: 0.82rem;\n line-height: 1.6;\n color: var(--ss-error);\n font-family: ui-monospace, monospace;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.tableWrapper {\n overflow-x: auto;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.8rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n}\n\n.table tbody tr:nth-child(even) {\n background: var(--ss-teal-glow);\n}\n\n.th {\n padding: 0.5rem 0.85rem;\n text-align: left;\n font-weight: 600;\n font-size: 0.7rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n position: sticky;\n top: 0;\n}\n\n.thRowNum {\n padding: 0.5rem 0.85rem;\n text-align: right;\n font-weight: 600;\n font-size: 0.7rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n position: sticky;\n top: 0;\n opacity: 0.5;\n width: 2.5rem;\n}\n\n.td {\n padding: 0.45rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text);\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tdRowNum {\n padding: 0.45rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n opacity: 0.5;\n text-align: right;\n user-select: none;\n}\n\n.nullValue {\n color: var(--ss-text-muted);\n font-style: italic;\n opacity: 0.6;\n}\n\n.jsonValue {\n color: var(--ss-text-dim);\n}\n\n.tabButton {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n border: none;\n border-radius: 7px;\n padding: 0.6rem 0.75rem;\n background: transparent;\n color: var(--ss-text-dim);\n font-size: 0.82rem;\n font-weight: 500;\n text-align: left;\n cursor: pointer;\n transition: background 0.15s;\n border-left: 2px solid transparent;\n}\n\n.tabButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n border-left: 2px solid var(--ss-teal);\n}\n\n.targetButton {\n border: none;\n border-right: 1px solid var(--ss-border);\n padding: 0.45rem 0.85rem;\n background: transparent;\n color: var(--ss-text-muted);\n font-size: 0.78rem;\n font-weight: 500;\n cursor: pointer;\n font-family: ui-monospace, monospace;\n transition: background 0.1s;\n white-space: nowrap;\n}\n\n.targetButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n}\n\n.runButton {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n border: none;\n border-radius: 7px;\n padding: 0.45rem 0.9rem;\n background: var(--ss-bg-card);\n color: var(--ss-text-muted);\n font-size: 0.82rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n cursor: not-allowed;\n opacity: 1;\n transition: background 0.15s;\n white-space: nowrap;\n}\n\n.runButton[data-enabled=\"true\"] {\n background: var(--ss-teal);\n color: #0e1015;\n cursor: pointer;\n}\n\n.runButton[data-running=\"true\"] {\n opacity: 0.75;\n}\n\n.runningDot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: currentColor;\n}\n\n.schemaLayout {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.schemaSection {\n display: flex;\n flex-direction: column;\n gap: 0.65rem;\n}\n\n.schemaSectionHeader {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.schemaSectionTitle {\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n}\n\n.schemaBadge {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 4px;\n padding: 0.1rem 0.4rem;\n font-family: ui-monospace, monospace;\n}\n\n.schemaVersionChip {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.1rem 0.5rem;\n}\n\n.schemaTableGrid {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n}\n\n.schemaColHeader {\n padding: 0.5rem 0.85rem;\n font-size: 0.68rem;\n font-weight: 700;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-right: 1px solid var(--ss-border);\n}\n\n.schemaStatusCell {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.6rem 0.5rem;\n}\n\n.schemaActiveTag {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 4px;\n padding: 0.15rem 0.45rem;\n font-family: ui-monospace, monospace;\n}\n\n.schemaEmpty {\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.schemaTableList {\n display: flex;\n flex-direction: column;\n gap: 0.85rem;\n}\n\n.schemaTableCard {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n overflow: hidden;\n}\n\n.schemaTableCardHeader {\n display: flex;\n flex-direction: column;\n gap: 0.45rem;\n padding: 0.75rem 0.85rem 0.7rem;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.schemaTableCardTitleRow {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.schemaTableCardName {\n font-size: 0.92rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n}\n\n.schemaTableCardDescription {\n margin: 0;\n font-size: 0.78rem;\n line-height: 1.45;\n color: var(--ss-text-dim);\n}\n\n.schemaTableCardMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem;\n}\n\n.schemaPolicyChip {\n font-size: 0.65rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n background: var(--ss-bg-input);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.12rem 0.4rem;\n}\n\n.schemaPolicyChip[data-tone=\"warn\"] {\n color: var(--ss-amber);\n background: rgba(251, 191, 36, 0.08);\n border-color: rgba(251, 191, 36, 0.25);\n}\n\n.schemaColumnGrid {\n display: flex;\n flex-direction: column;\n overflow-x: auto;\n}\n\n.schemaColumnRow {\n display: grid;\n grid-template-columns: minmax(6.5rem, 0.7fr) minmax(8rem, 1fr) minmax(7.5rem, 0.9fr) minmax(0, 1.8fr);\n min-width: 36rem;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.schemaColumnRow:last-child {\n border-bottom: none;\n}\n\n.schemaColumnRow[data-system=\"true\"] {\n opacity: 0.62;\n}\n\n.schemaColumnHeaderRow {\n background: var(--ss-bg-panel);\n}\n\n.schemaColumnHeaderRow .schemaColHeader:last-child {\n border-right: none;\n}\n\n.schemaColumnName,\n.schemaColumnType,\n.schemaColumnFlags,\n.schemaColumnDescription {\n padding: 0.5rem 0.85rem;\n font-size: 0.76rem;\n border-right: 1px solid var(--ss-border);\n min-width: 0;\n}\n\n.schemaColumnDescription {\n border-right: none;\n color: var(--ss-text-dim);\n overflow-wrap: anywhere;\n}\n\n.schemaColumnName {\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n font-weight: 600;\n}\n\n.schemaColumnType {\n display: flex;\n flex-direction: column;\n gap: 0.15rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-teal);\n}\n\n.schemaColumnTypeDetail {\n font-size: 0.65rem;\n color: var(--ss-text-muted);\n font-weight: 400;\n overflow-wrap: anywhere;\n}\n\n.schemaColumnFlags {\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n}\n\n.liveQueryHeaderRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n background-color: var(--ss-bg-card);\n border-bottom: 1px solid var(--ss-border);\n}\n\n.liveQueryRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.liveQuerySql {\n padding: 0.6rem 0.85rem;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.liveQueryParameters {\n padding: 0.6rem 0.85rem;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-dim);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.liveQueryIdleTag {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.15rem 0.45rem;\n font-family: ui-monospace, monospace;\n}\n\n.eventLogLayout {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n height: 100%;\n}\n\n.eventLogToolbar {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n\n.eventLogFilterSelect {\n border-radius: 7px;\n border: 1px solid var(--ss-border);\n padding: 0.35rem 0.6rem;\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n}\n\n.eventLogCount {\n margin-left: auto;\n font-size: 0.72rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n}\n\n.eventLogEmpty {\n padding: 2rem;\n text-align: center;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.eventLogList {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n overflow-y: auto;\n flex: 1;\n}\n\n.eventRow {\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.eventRow[data-expanded=\"true\"] {\n border: 1px solid #2dd4bf40;\n background: var(--ss-teal-glow);\n}\n\n.eventRowHeader {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.75rem;\n background: transparent;\n border: none;\n cursor: pointer;\n text-align: left;\n flex-wrap: wrap;\n}\n\n.eventSyncId {\n font-size: 0.7rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n min-width: 3.5rem;\n}\n\n.eventDataset {\n font-size: 0.8rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n font-weight: 600;\n}\n\n.eventItemId {\n font-size: 0.75rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.eventTimestamp {\n font-size: 0.7rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n margin-left: auto;\n}\n\n.eventChevron {\n font-size: 0.6rem;\n color: var(--ss-text-muted);\n margin-left: 0.25rem;\n}\n\n.eventPayload {\n border-top: 1px solid var(--ss-border);\n padding: 0.6rem 0.75rem;\n}\n\n.eventPayloadMeta {\n display: flex;\n gap: 0.75rem;\n margin-bottom: 0.5rem;\n}\n\n.eventMetaItem {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n}\n\n.eventPayloadPre {\n margin: 0;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.loadMoreButton {\n width: 100%;\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n padding: 0.6rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.eventBadge {\n font-size: 0.65rem;\n font-weight: 700;\n border-radius: 4px;\n padding: 0.1rem 0.4rem;\n font-family: ui-monospace, monospace;\n white-space: nowrap;\n}\n\n.eventBadge[data-variant=\"create\"] {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n}\n\n.eventBadge[data-variant=\"update\"] {\n color: #a78bfa;\n background-color: rgba(167, 139, 250, 0.12);\n}\n\n.eventBadge[data-variant=\"delete\"] {\n color: var(--ss-error);\n background-color: rgba(248, 113, 113, 0.12);\n}\n\n.eventBadge[data-variant=\"own\"],\n.eventBadge[data-variant=\"applied\"] {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n}\n\n.eventBadge[data-variant=\"remote\"],\n.eventBadge[data-variant=\"pending\"] {\n color: var(--ss-amber);\n background-color: rgba(251, 191, 36, 0.1);\n}\n\n.eventBadge[data-variant=\"local\"] {\n color: var(--ss-text-dim);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.eventBadge[data-variant=\"failed\"] {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n}\n\n.eventBadge[data-variant=\"skipped\"] {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n}\n","import { type ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport cssText from \"./devtools.css?inline\";\n\nexport function ShadowRoot({ children, className }: { children: ReactNode; className?: string }) {\n const hostRef = useRef<HTMLDivElement>(null);\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n setShadowRoot(host.shadowRoot ?? host.attachShadow({ mode: \"open\" }));\n }, []);\n\n return (\n <div ref={hostRef} className={className}>\n {shadowRoot\n ? createPortal(\n <>\n <style>{cssText}</style>\n {children}\n </>,\n shadowRoot,\n )\n : null}\n </div>\n );\n}\n","import type { ColumnMeta, SharedLiveQuerySnapshot, SyncedDbExport } from \"@sqlite-sync/core\";\nimport type { CSSProperties, PointerEvent as ReactPointerEvent } from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n getOrCreateSQLiteSyncDevtoolsRegistry,\n type SQLiteSyncDevtoolsInstance,\n type SQLiteSyncDevtoolsSnapshot,\n} from \"./devtools-registry\";\nimport { ShadowRoot } from \"./shadow-root\";\n\nexport type SQLiteSyncDevtoolsProps = {\n className?: string;\n /** Hide the floating launcher. Omit to let the user toggle it with Ctrl+Alt+S (⌘⌥S on macOS). */\n hidden?: boolean;\n onHiddenChange?: (hidden: boolean) => void;\n};\n\ntype DevtoolsTab = \"overview\" | \"schema\" | \"live-queries\" | \"event-log\" | \"query-runner\";\ntype QueryTarget = \"memory\" | \"worker\";\n\ntype QueryState =\n | {\n status: \"idle\";\n }\n | {\n status: \"running\";\n }\n | {\n status: \"success\";\n output: {\n target: QueryTarget;\n sql: string;\n rowCount: number;\n durationMs: number;\n rows: unknown[];\n };\n }\n | {\n status: \"error\";\n error: {\n target: QueryTarget;\n sql: string;\n message: string;\n };\n };\n\nconst TRIGGER_POSITION_STORAGE_KEY = \"sqlite-sync-devtools.trigger-position\";\nconst TRIGGER_HIDDEN_STORAGE_KEY = \"sqlite-sync-devtools.trigger-hidden\";\nconst DRAG_THRESHOLD_PX = 4;\nconst VIEWPORT_MARGIN_PX = 8;\nconst IS_APPLE_PLATFORM = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform);\nconst TOGGLE_LAUNCHER_HINT = IS_APPLE_PLATFORM ? \"⌘⌥S\" : \"Ctrl+Alt+S\";\n\ntype TriggerPosition = { x: number; y: number };\n\nfunction readStoredTriggerPosition(): TriggerPosition | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.localStorage.getItem(TRIGGER_POSITION_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Partial<TriggerPosition>;\n if (typeof parsed.x === \"number\" && typeof parsed.y === \"number\") {\n return { x: parsed.x, y: parsed.y };\n }\n } catch {}\n return null;\n}\n\nfunction useDraggableTrigger() {\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [position, setPosition] = useState<TriggerPosition | null>(readStoredTriggerPosition);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n offsetX: number;\n offsetY: number;\n moved: boolean;\n } | null>(null);\n // pointerup clears dragRef before the click event fires, so the moved flag is\n // stashed here to suppress the click that a drag gesture would otherwise emit.\n const suppressClickRef = useRef(false);\n\n const onPointerDown = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const button = buttonRef.current;\n if (!button || event.button !== 0) return;\n suppressClickRef.current = false;\n const rect = button.getBoundingClientRect();\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n offsetX: event.clientX - rect.left,\n offsetY: event.clientY - rect.top,\n moved: false,\n };\n button.setPointerCapture(event.pointerId);\n }, []);\n\n const onPointerMove = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const drag = dragRef.current;\n const button = buttonRef.current;\n if (!drag || !button || drag.pointerId !== event.pointerId) return;\n if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < DRAG_THRESHOLD_PX) {\n return;\n }\n drag.moved = true;\n const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;\n const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;\n setPosition({\n x: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientX - drag.offsetX, maxX)),\n y: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientY - drag.offsetY, maxY)),\n });\n }, []);\n\n const endDrag = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n dragRef.current = null;\n buttonRef.current?.releasePointerCapture(event.pointerId);\n if (!drag.moved) return;\n suppressClickRef.current = true;\n setPosition((current) => {\n if (current && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(TRIGGER_POSITION_STORAGE_KEY, JSON.stringify(current));\n } catch {}\n }\n return current;\n });\n }, []);\n\n const consumeDragClick = useCallback(() => {\n if (!suppressClickRef.current) return false;\n suppressClickRef.current = false;\n return true;\n }, []);\n\n const positionStyle: CSSProperties = position\n ? { left: position.x, top: position.y, right: \"auto\", bottom: \"auto\" }\n : {};\n\n return {\n buttonRef,\n positionStyle,\n triggerHandlers: { onPointerDown, onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag },\n consumeDragClick,\n };\n}\n\nfunction readStoredTriggerHidden(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return window.localStorage.getItem(TRIGGER_HIDDEN_STORAGE_KEY) === \"1\";\n } catch {\n return false;\n }\n}\n\nfunction isToggleLauncherShortcut(event: KeyboardEvent): boolean {\n // Option/Alt remaps event.key (Option+S is \"ß\" on US Mac), so match the physical key.\n if (event.shiftKey || !event.altKey || event.code !== \"KeyS\") return false;\n return event.ctrlKey || event.metaKey;\n}\n\nfunction useLauncherVisibility({\n hidden: hiddenProp,\n onHiddenChange,\n}: Pick<SQLiteSyncDevtoolsProps, \"hidden\" | \"onHiddenChange\">) {\n const isControlled = hiddenProp !== undefined;\n const [uncontrolledHidden, setUncontrolledHidden] = useState(readStoredTriggerHidden);\n const hidden = isControlled ? hiddenProp : uncontrolledHidden;\n const canToggle = !isControlled || onHiddenChange !== undefined;\n\n const setHidden = useCallback(\n (next: boolean) => {\n if (isControlled) {\n onHiddenChange?.(next);\n return;\n }\n setUncontrolledHidden(next);\n try {\n window.localStorage.setItem(TRIGGER_HIDDEN_STORAGE_KEY, next ? \"1\" : \"0\");\n } catch {}\n },\n [isControlled, onHiddenChange],\n );\n\n useEffect(() => {\n if (!canToggle) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (!isToggleLauncherShortcut(event)) return;\n event.preventDefault();\n setHidden(!hidden);\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [canToggle, hidden, setHidden]);\n\n return { hidden, setHidden, canToggle };\n}\n\nexport function SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }: SQLiteSyncDevtoolsProps) {\n const registry = getOrCreateSQLiteSyncDevtoolsRegistry();\n const snapshot = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot);\n const instances = snapshot.instances;\n\n const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();\n const { hidden, setHidden, canToggle } = useLauncherVisibility({ hidden: hiddenProp, onHiddenChange });\n\n const [isOpen, setIsOpen] = useState(false);\n const [activeTab, setActiveTab] = useState<DevtoolsTab>(\"overview\");\n const [selectedInstanceId, setSelectedInstanceId] = useState<string>(\"\");\n const [queryTarget, setQueryTarget] = useState<QueryTarget>(\"memory\");\n const [query, setQuery] = useState(\"\");\n const [queryState, setQueryState] = useState<QueryState>({\n status: \"idle\",\n });\n\n useEffect(() => {\n if (hidden) setIsOpen(false);\n }, [hidden]);\n\n useEffect(() => {\n if (!isOpen) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [isOpen]);\n\n useEffect(() => {\n if (instances.length === 0) {\n setSelectedInstanceId(\"\");\n return;\n }\n\n if (instances.some((instance) => instance.instanceId === selectedInstanceId)) {\n return;\n }\n\n setSelectedInstanceId(instances[0]?.instanceId ?? \"\");\n }, [instances, selectedInstanceId]);\n\n const dbIdCounts = useMemo(() => {\n const counts = new Map<string, number>();\n\n for (const instance of instances) {\n counts.set(instance.dbId, (counts.get(instance.dbId) ?? 0) + 1);\n }\n\n return counts;\n }, [instances]);\n\n const selectedInstance = useMemo(() => {\n return instances.find((instance) => instance.instanceId === selectedInstanceId) ?? null;\n }, [instances, selectedInstanceId]);\n\n const canRunQuery = selectedInstance !== null && query.trim().length > 0 && queryState.status !== \"running\";\n\n const runQuery = async () => {\n if (!selectedInstance) return;\n\n let normalizedQuery = query.trim();\n\n try {\n normalizedQuery = normalizeSingleStatement(query);\n const statementKind = getStatementKind(normalizedQuery);\n\n if (queryTarget === \"worker\") {\n if (!isWorkerReadOnlyStatement(statementKind)) {\n throw new Error(\"Worker DB devtools only allows read-only SQL: SELECT, PRAGMA.\");\n }\n } else {\n const touchedTables = selectedInstance.instance._internal.getMemoryQueryTables(normalizedQuery);\n const writtenTables = touchedTables.filter((table) => table.isWrite).map((table) => table.name);\n const allowedTables = new Set(selectedInstance.instance._internal.crdtTableNames);\n\n const invalidTables = writtenTables.filter((table) => !allowedTables.has(table));\n if (invalidTables.length > 0) {\n throw new Error(\n `Memory DB writes are only allowed for CRDT tables. Rejected tables: ${invalidTables.join(\", \")}`,\n );\n }\n }\n\n setQueryState({ status: \"running\" });\n const startedAt = performance.now();\n\n const result =\n queryTarget === \"memory\"\n ? selectedInstance.instance.db.execute(normalizedQuery)\n : await selectedInstance.instance._internal.executeAsync({\n sql: normalizedQuery,\n parameters: [],\n });\n\n setQueryState({\n status: \"success\",\n output: {\n target: queryTarget,\n sql: normalizedQuery,\n rowCount: result.rows.length,\n durationMs: Number((performance.now() - startedAt).toFixed(2)),\n rows: result.rows,\n },\n });\n } catch (error) {\n setQueryState({\n status: \"error\",\n error: {\n target: queryTarget,\n sql: normalizedQuery,\n message: error instanceof Error ? error.message : String(error),\n },\n });\n }\n };\n\n return (\n <ShadowRoot className={className}>\n {hidden ? null : (\n <div className=\"floatingRoot\">\n <button\n ref={buttonRef}\n type=\"button\"\n className=\"triggerButton\"\n style={positionStyle}\n onClick={() => {\n if (consumeDragClick()) return;\n setIsOpen(true);\n }}\n title={`SQLite Sync Devtools (${TOGGLE_LAUNCHER_HINT} to hide)`}\n {...triggerHandlers}\n >\n <span className=\"triggerIcon\">◈</span>\n <span className=\"triggerCount\">{instances.length}</span>\n </button>\n </div>\n )}\n\n {isOpen ? (\n <div className=\"overlay\" onClick={() => setIsOpen(false)}>\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"SQLite Sync devtools\"\n className=\"dialog\"\n onClick={(event) => event.stopPropagation()}\n >\n {/* Dialog header */}\n <div className=\"header\">\n <div className=\"headerLeft\">\n <span className=\"headerLogo\">◈</span>\n <div>\n <div className=\"eyebrow\">sqlite-sync</div>\n <h2 className=\"title\">Devtools</h2>\n </div>\n </div>\n\n <div className=\"headerRight\">\n {instances.length > 0 && (\n <label className=\"instancePickerLabel\">\n <span className=\"instancePickerText\">DB</span>\n <select\n value={selectedInstanceId}\n onChange={(event) => setSelectedInstanceId(event.target.value)}\n className=\"instancePickerSelect\"\n >\n {instances.map((instance) => (\n <option key={instance.instanceId} value={instance.instanceId}>\n {formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0)}\n </option>\n ))}\n </select>\n </label>\n )}\n <span className=\"instanceCountBadge\">\n {instances.length} instance{instances.length !== 1 ? \"s\" : \"\"}\n </span>\n {canToggle && (\n <button\n type=\"button\"\n className=\"hideLauncherButton\"\n onClick={() => setHidden(true)}\n title={`Hide launcher (${TOGGLE_LAUNCHER_HINT} to show again)`}\n >\n Hide\n </button>\n )}\n <button type=\"button\" className=\"closeButton\" onClick={() => setIsOpen(false)} aria-label=\"Close\">\n ✕\n </button>\n </div>\n </div>\n\n {instances.length === 0 ? (\n <div className=\"emptyState\">\n <div className=\"emptyStateIcon\">◈</div>\n <p className=\"emptyStateText\">No SQLite Sync database instances registered.</p>\n <p className=\"emptyStateSubtext\">\n Call <code className=\"inlineCode\">registerDevtools(db)</code> in your app to get started.\n </p>\n </div>\n ) : (\n <div className=\"contentLayout\">\n {/* Sidebar nav */}\n <aside className=\"sidebar\">\n <nav className=\"nav\">\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"overview\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"overview\")}\n >\n <span className=\"navIcon\">▦</span>\n Overview\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"schema\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"schema\")}\n >\n <span className=\"navIcon\">⬡</span>\n Schema\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"live-queries\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"live-queries\")}\n >\n <span className=\"navIcon\">◉</span>\n Live Queries\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"event-log\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"event-log\")}\n >\n <span className=\"navIcon\">≡</span>\n Event Log\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"query-runner\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"query-runner\")}\n >\n <span className=\"navIcon\">▶</span>\n Query Runner\n </button>\n </nav>\n\n {selectedInstance && (\n <div className=\"sidebarInfo\">\n <div className=\"sidebarInfoLabel\">Active instance</div>\n <div className=\"sidebarInfoValue\">\n {formatInstanceLabel(\n selectedInstance.dbId,\n selectedInstance.instanceId,\n dbIdCounts.get(selectedInstance.dbId) ?? 0,\n )}\n </div>\n <div className=\"sidebarInfoSub\">id: {selectedInstance.instanceId.slice(0, 12)}…</div>\n </div>\n )}\n </aside>\n\n {/* Main pane */}\n <div className=\"mainPane\">\n {activeTab === \"overview\" ? (\n <OverviewTab selectedInstance={selectedInstance} dbIdCounts={dbIdCounts} />\n ) : activeTab === \"schema\" ? (\n <SchemaTab selectedInstance={selectedInstance} />\n ) : activeTab === \"live-queries\" ? (\n <LiveQueriesTab selectedInstance={selectedInstance} />\n ) : activeTab === \"event-log\" ? (\n <EventLogTab selectedInstance={selectedInstance} />\n ) : (\n <QueryRunnerTab\n selectedInstance={selectedInstance}\n queryTarget={queryTarget}\n setQueryTarget={setQueryTarget}\n query={query}\n setQuery={setQuery}\n queryState={queryState}\n canRunQuery={canRunQuery}\n runQuery={runQuery}\n />\n )}\n </div>\n </div>\n )}\n </section>\n </div>\n ) : null}\n </ShadowRoot>\n );\n}\n\nconst EVENT_HLC_ACCUMULATOR_KV_KEY = \"crdt.consistency.event_hlc_sum.v2\";\nconst EVENT_HLC_ACCUMULATOR_QUERY = `SELECT value FROM \"worker\".\"kv\" WHERE key = '${EVENT_HLC_ACCUMULATOR_KV_KEY}'`;\nconst EVENT_STATUS_COUNTS_QUERY = `SELECT status, COUNT(*) AS count FROM \"worker\".\"crdt_events\" GROUP BY status`;\nconst MEMORY_DB_SIZE_QUERY =\n \"SELECT (SELECT page_count FROM pragma_page_count()) * (SELECT page_size FROM pragma_page_size()) AS bytes\";\n// Persisted main file plus the attached worker schema (event log, kv).\nconst WORKER_DB_SIZE_QUERY = `SELECT\n (SELECT page_count FROM pragma_page_count('main')) * (SELECT page_size FROM pragma_page_size('main'))\n + (SELECT page_count FROM pragma_page_count('worker')) * (SELECT page_size FROM pragma_page_size('worker'))\n AS bytes`;\n\ntype EventStatus = \"pending\" | \"applied\" | \"failed\" | \"deduped\";\ntype EventStatusCounts = { total: number } & Record<EventStatus, number>;\n\nconst EVENT_STATUS_META: Record<EventStatus, { label: string; tone: \"amber\" | \"success\" | \"error\" | \"muted\" }> = {\n pending: { label: \"Pending\", tone: \"amber\" },\n applied: { label: \"Applied\", tone: \"success\" },\n failed: { label: \"Failed\", tone: \"error\" },\n deduped: { label: \"Deduped\", tone: \"muted\" },\n};\n\nfunction isEventStatus(value: unknown): value is EventStatus {\n return value === \"pending\" || value === \"applied\" || value === \"failed\" || value === \"deduped\";\n}\n\nfunction emptyEventStatusCounts(): EventStatusCounts {\n return { total: 0, pending: 0, applied: 0, failed: 0, deduped: 0 };\n}\n\nfunction parseEventStatusCounts(rows: readonly unknown[]): EventStatusCounts {\n const counts = emptyEventStatusCounts();\n\n for (const row of rows) {\n if (typeof row !== \"object\" || row === null || !(\"status\" in row) || !(\"count\" in row)) {\n continue;\n }\n const { status, count } = row;\n if (!isEventStatus(status)) continue;\n const n = typeof count === \"number\" ? count : Number(count);\n if (!Number.isFinite(n)) continue;\n counts[status] = n;\n counts.total += n;\n }\n\n return counts;\n}\n\nfunction readCount(rows: readonly unknown[]): number {\n const row = rows[0];\n if (typeof row !== \"object\" || row === null || !(\"count\" in row)) return 0;\n const n = typeof row.count === \"number\" ? row.count : Number(row.count);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction readBytes(rows: readonly unknown[]): number | null {\n const row = rows[0];\n if (typeof row !== \"object\" || row === null || !(\"bytes\" in row)) return null;\n const n = typeof row.bytes === \"number\" ? row.bytes : Number(row.bytes);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction formatByteSize(bytes: number): { label: string; exact: string } {\n const exact = `${bytes.toLocaleString(\"en-US\")} B`;\n if (bytes < 1024) return { label: exact, exact };\n\n const units = [\"KB\", \"MB\", \"GB\", \"TB\"] as const;\n let value = bytes / 1024;\n let unitIndex = 0;\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n const decimals = value >= 100 ? 0 : value >= 10 ? 1 : 2;\n return { label: `${Number(value.toFixed(decimals))} ${units[unitIndex]}`, exact };\n}\n\nfunction OverviewTab({\n selectedInstance,\n dbIdCounts,\n}: {\n selectedInstance: SQLiteSyncDevtoolsInstance | null;\n dbIdCounts: Map<string, number>;\n}) {\n const [eventHlcAccumulator, setEventHlcAccumulator] = useState<string | null>(null);\n const [accumulatorError, setAccumulatorError] = useState<string | null>(null);\n const [isAccumulatorLoading, setIsAccumulatorLoading] = useState(false);\n const [eventCounts, setEventCounts] = useState<EventStatusCounts | null>(null);\n const [eventCountsError, setEventCountsError] = useState<string | null>(null);\n const [isEventCountsLoading, setIsEventCountsLoading] = useState(false);\n const [memoryBytes, setMemoryBytes] = useState<number | null>(null);\n const [memorySizeError, setMemorySizeError] = useState<string | null>(null);\n const [workerBytes, setWorkerBytes] = useState<number | null>(null);\n const [workerSizeError, setWorkerSizeError] = useState<string | null>(null);\n const [isSizeLoading, setIsSizeLoading] = useState(false);\n\n const refreshEventHlcAccumulator = useCallback(async () => {\n if (!selectedInstance) return;\n setIsAccumulatorLoading(true);\n setAccumulatorError(null);\n try {\n const result = await selectedInstance.instance._internal.executeAsync({\n sql: EVENT_HLC_ACCUMULATOR_QUERY,\n parameters: [],\n });\n const row = result.rows[0];\n const value =\n typeof row === \"object\" && row !== null && \"value\" in row && typeof row.value === \"string\" ? row.value : \"\";\n setEventHlcAccumulator(value);\n } catch (error) {\n setAccumulatorError(error instanceof Error ? error.message : String(error));\n setEventHlcAccumulator(null);\n } finally {\n setIsAccumulatorLoading(false);\n }\n }, [selectedInstance]);\n\n const refreshEventCounts = useCallback(async () => {\n if (!selectedInstance) return;\n setIsEventCountsLoading(true);\n setEventCountsError(null);\n try {\n const result = await selectedInstance.instance._internal.executeAsync({\n sql: EVENT_STATUS_COUNTS_QUERY,\n parameters: [],\n });\n setEventCounts(parseEventStatusCounts(result.rows));\n } catch (error) {\n setEventCountsError(error instanceof Error ? error.message : String(error));\n setEventCounts(null);\n } finally {\n setIsEventCountsLoading(false);\n }\n }, [selectedInstance]);\n\n const refreshDbSizes = useCallback(async () => {\n if (!selectedInstance) return;\n setIsSizeLoading(true);\n setMemorySizeError(null);\n setWorkerSizeError(null);\n\n const memoryResult = Promise.resolve()\n .then(() => selectedInstance.instance.db.execute(MEMORY_DB_SIZE_QUERY))\n .then((result) => {\n const bytes = readBytes(result.rows);\n if (bytes === null) throw new Error(\"Memory DB did not return a size.\");\n return bytes;\n });\n const workerResult = selectedInstance.instance._internal\n .executeAsync({ sql: WORKER_DB_SIZE_QUERY, parameters: [] })\n .then((result) => {\n const bytes = readBytes(result.rows);\n if (bytes === null) throw new Error(\"Worker DB did not return a size.\");\n return bytes;\n });\n\n const [memorySettled, workerSettled] = await Promise.allSettled([memoryResult, workerResult]);\n if (memorySettled.status === \"fulfilled\") {\n setMemoryBytes(memorySettled.value);\n } else {\n setMemoryBytes(null);\n setMemorySizeError(\n memorySettled.reason instanceof Error ? memorySettled.reason.message : String(memorySettled.reason),\n );\n }\n if (workerSettled.status === \"fulfilled\") {\n setWorkerBytes(workerSettled.value);\n } else {\n setWorkerBytes(null);\n setWorkerSizeError(\n workerSettled.reason instanceof Error ? workerSettled.reason.message : String(workerSettled.reason),\n );\n }\n setIsSizeLoading(false);\n }, [selectedInstance]);\n\n useEffect(() => {\n setEventHlcAccumulator(null);\n setAccumulatorError(null);\n setEventCounts(null);\n setEventCountsError(null);\n setMemoryBytes(null);\n setMemorySizeError(null);\n setWorkerBytes(null);\n setWorkerSizeError(null);\n void refreshEventHlcAccumulator();\n void refreshEventCounts();\n void refreshDbSizes();\n }, [refreshEventHlcAccumulator, refreshEventCounts, refreshDbSizes]);\n\n if (!selectedInstance) return null;\n\n const label = formatInstanceLabel(\n selectedInstance.dbId,\n selectedInstance.instanceId,\n dbIdCounts.get(selectedInstance.dbId) ?? 0,\n );\n\n return (\n <div className=\"overviewLayout\">\n <div className=\"overviewCardsRow\">\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">Database</div>\n <div className=\"overviewCardValue\">{label}</div>\n </div>\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">Instance ID</div>\n <div className=\"overviewCardValue mono sm\">{selectedInstance.instanceId.slice(0, 16)}…</div>\n </div>\n <DbSizeCard label=\"Memory DB\" bytes={memoryBytes} error={memorySizeError} loading={isSizeLoading} />\n <DbSizeCard label=\"Worker DB\" bytes={workerBytes} error={workerSizeError} loading={isSizeLoading} />\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">CRDT Events</div>\n <div className=\"overviewCardValue\">\n {eventCountsError ? \"—\" : isEventCountsLoading && eventCounts === null ? \"…\" : (eventCounts?.total ?? 0)}\n </div>\n </div>\n </div>\n\n <div className=\"overviewSection\">\n <div className=\"overviewSectionHeader\">\n <div className=\"overviewSectionTitle\">CRDT events</div>\n <button\n type=\"button\"\n className=\"refreshButton\"\n disabled={isEventCountsLoading || isSizeLoading}\n title=\"Refresh event counts and DB sizes\"\n onClick={() => {\n void refreshEventCounts();\n void refreshDbSizes();\n }}\n >\n {isEventCountsLoading || isSizeLoading ? \"…\" : \"↻\"} Refresh\n </button>\n </div>\n {eventCountsError ? (\n <div className=\"overviewAccumulatorError\">{eventCountsError}</div>\n ) : (\n <div className=\"eventCountGrid\">\n {([\"pending\", \"applied\", \"failed\", \"deduped\"] satisfies EventStatus[]).map((status) => {\n const item = EVENT_STATUS_META[status];\n const value = eventCounts?.[status] ?? 0;\n return (\n <div key={status} className=\"eventCountCard\">\n <div\n className=\"eventCountValue\"\n data-tone={item.tone}\n data-emphasize={value > 0 ? \"true\" : undefined}\n >\n {isEventCountsLoading && eventCounts === null ? \"…\" : value}\n </div>\n <div className=\"overviewCardLabel\">{item.label}</div>\n </div>\n );\n })}\n </div>\n )}\n <div className=\"overviewEmpty\">Counts are remaining worker log rows after GC, not lifetime history.</div>\n </div>\n\n <div className=\"overviewSection\">\n <div className=\"overviewSectionHeader\">\n <div className=\"overviewSectionTitle\">Event HLC accumulator</div>\n <button\n type=\"button\"\n className=\"refreshButton\"\n disabled={isAccumulatorLoading}\n onClick={() => void refreshEventHlcAccumulator()}\n >\n {isAccumulatorLoading ? \"…\" : \"↻\"} Refresh\n </button>\n </div>\n <div className=\"overviewAccumulatorValue\">\n {accumulatorError ? (\n <span className=\"overviewAccumulatorError\">{accumulatorError}</span>\n ) : isAccumulatorLoading && eventHlcAccumulator === null ? (\n \"Loading…\"\n ) : eventHlcAccumulator === \"\" ? (\n <span className=\"overviewAccumulatorEmpty\">(empty)</span>\n ) : (\n eventHlcAccumulator\n )}\n </div>\n </div>\n\n <DataSection\n key={selectedInstance.instanceId}\n dbId={selectedInstance.dbId}\n instance={selectedInstance.instance}\n />\n\n <ResetSection dbId={selectedInstance.dbId} instance={selectedInstance.instance} />\n </div>\n );\n}\n\nfunction DbSizeCard({\n label,\n bytes,\n error,\n loading,\n}: {\n label: string;\n bytes: number | null;\n error: string | null;\n loading: boolean;\n}) {\n let value = \"…\";\n let sub: string | undefined;\n let title: string | undefined;\n\n if (error) {\n value = \"—\";\n title = error;\n } else if (bytes !== null) {\n const formatted = formatByteSize(bytes);\n value = formatted.label;\n title = formatted.exact;\n sub = formatted.label === formatted.exact ? undefined : formatted.exact;\n } else if (!loading) {\n value = \"—\";\n }\n\n return (\n <div className=\"overviewCard\" title={title}>\n <div className=\"overviewCardLabel\">{label}</div>\n <div className=\"overviewCardValue mono\">{value}</div>\n {sub ? <div className=\"overviewCardSub\">{sub}</div> : null}\n </div>\n );\n}\n\nfunction DataSection({ dbId, instance }: { dbId: string; instance: SQLiteSyncDevtoolsInstance[\"instance\"] }) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [status, setStatus] = useState<{ kind: \"success\" | \"error\"; message: string } | null>(null);\n\n const handleExport = () => {\n try {\n const data = instance.exportData();\n const json = JSON.stringify(data, null, 2);\n const blob = new Blob([json], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${dbId}-${data.exportedAt.replace(/[:.]/g, \"-\")}.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n const rowCount = Object.values(data.tables).reduce((sum, rows) => sum + rows.length, 0);\n setStatus({ kind: \"success\", message: `Exported ${rowCount} row${rowCount === 1 ? \"\" : \"s\"}.` });\n } catch (error) {\n setStatus({ kind: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n };\n\n const handleImportFile = async (file: File) => {\n setIsImporting(true);\n setStatus(null);\n try {\n const data = JSON.parse(await file.text()) as SyncedDbExport;\n const result = await instance.importData(data);\n setStatus({ kind: \"success\", message: `Imported ${result.imported} row${result.imported === 1 ? \"\" : \"s\"}.` });\n } catch (error) {\n setStatus({ kind: \"error\", message: error instanceof Error ? error.message : String(error) });\n } finally {\n setIsImporting(false);\n }\n };\n\n return (\n <div className=\"overviewSection\">\n <div className=\"overviewSectionTitle\">Backup & Restore</div>\n <div className=\"dangerZoneDesc\">\n Export the active rows of every CRDT table as JSON, or import a dump to seed/restore. Import overwrites rows\n with matching ids and is propagated to the server.\n </div>\n <div className=\"dataActions\">\n <button type=\"button\" className=\"dataButton\" onClick={handleExport}>\n ↓ Export JSON\n </button>\n <button\n type=\"button\"\n className=\"dataButton\"\n disabled={isImporting}\n onClick={() => fileInputRef.current?.click()}\n >\n {isImporting ? \"Importing…\" : \"↑ Import JSON\"}\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"application/json,.json\"\n className=\"hiddenInput\"\n onChange={(event) => {\n const file = event.target.files?.[0];\n event.target.value = \"\";\n if (file) void handleImportFile(file);\n }}\n />\n </div>\n {status && (\n <div className={status.kind === \"error\" ? \"dataStatusError\" : \"dataStatusSuccess\"}>{status.message}</div>\n )}\n </div>\n );\n}\n\nfunction ResetSection({ dbId, instance }: { dbId: string; instance: SQLiteSyncDevtoolsInstance[\"instance\"] }) {\n const [confirming, setConfirming] = useState(false);\n const [isResetting, setIsResetting] = useState(false);\n\n const handleReset = () => {\n setIsResetting(true);\n // Worker-owned clean reset: durably records a reset epoch, broadcasts a\n // reload to all tabs, and the next elected worker wipes the persisted DB.\n // The promise may never settle — the page unloads first.\n void instance.requestReload({ clean: true });\n };\n\n return (\n <div className=\"dangerZone\">\n <div className=\"dangerZoneTitle\">Danger Zone</div>\n <div className=\"dangerZoneRow\">\n <div className=\"dangerZoneDesc\">\n Requests a clean reload, so <code className=\"inlineCode\">{dbId}</code> is wiped on next load via{\" \"}\n <code className=\"inlineCode\">clearOnInit</code>, then reloads all tabs.\n </div>\n {confirming ? (\n <div className=\"dangerZoneActions\">\n <button\n type=\"button\"\n className=\"resetCancelButton\"\n disabled={isResetting}\n onClick={() => setConfirming(false)}\n >\n Cancel\n </button>\n <button type=\"button\" className=\"resetConfirmButton\" disabled={isResetting} onClick={handleReset}>\n {isResetting ? \"Resetting…\" : \"Confirm reset\"}\n </button>\n </div>\n ) : (\n <button type=\"button\" className=\"resetButton\" onClick={() => setConfirming(true)}>\n Reset DB\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst SYSTEM_COLUMNS = new Set([\"id\", \"tombstone\"]);\n\nfunction formatDefaultValue(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (typeof value === \"boolean\" || typeof value === \"number\") return String(value);\n if (value === null) return \"null\";\n return JSON.stringify(value);\n}\n\nfunction SchemaTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n if (!selectedInstance) return null;\n\n const { tables, schemaVersion } = selectedInstance.instance._internal;\n const tableEntries = Object.entries(tables);\n\n return (\n <div className=\"schemaLayout\">\n <div className=\"schemaSection\">\n <div className=\"schemaSectionHeader\">\n <div className=\"schemaSectionTitle\">Tables</div>\n <span className=\"schemaBadge\">{tableEntries.length}</span>\n <span className=\"schemaVersionChip mlAuto\" title=\"Latest applied migration version\">\n applied v{schemaVersion}\n </span>\n </div>\n {tableEntries.length === 0 ? (\n <div className=\"schemaEmpty\">No tables declared on this schema.</div>\n ) : (\n <div className=\"schemaTableList\">\n {tableEntries.map(([crdtTableName, table]) => {\n const baseTableName = table.baseName ?? `_${crdtTableName}`;\n const columns = Object.entries(table.columns);\n return (\n <div key={crdtTableName} className=\"schemaTableCard\">\n <div className=\"schemaTableCardHeader\">\n <div className=\"schemaTableCardTitleRow\">\n <div className=\"schemaTableCardName\">{crdtTableName}</div>\n <span className=\"schemaBadge\">{columns.length}</span>\n </div>\n {table.description ? <p className=\"schemaTableCardDescription\">{table.description}</p> : null}\n <div className=\"schemaTableCardMeta\">\n <span className=\"schemaPolicyChip\" title=\"Base table\">\n {baseTableName}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.writeOrigin === \"server\" ? \"warn\" : undefined}\n title=\"Who may write CRDT events\"\n >\n writes {table.writeOrigin}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.aiAccess === \"read-write\" ? undefined : \"warn\"}\n title=\"AI agent access\"\n >\n ai {table.aiAccess}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.exportImport === \"ignore\" ? \"warn\" : undefined}\n title=\"Export / import\"\n >\n export {table.exportImport}\n </span>\n </div>\n </div>\n <div className=\"schemaColumnGrid\">\n <div className=\"schemaColumnRow schemaColumnHeaderRow\">\n <div className=\"schemaColHeader\">Column</div>\n <div className=\"schemaColHeader\">Type</div>\n <div className=\"schemaColHeader\">Flags</div>\n <div className=\"schemaColHeader\">Description</div>\n </div>\n {columns.map(([name, meta]) => (\n <SchemaColumnRow key={name} name={name} meta={meta} />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction SchemaColumnRow({ name, meta }: { name: string; meta: ColumnMeta }) {\n const flags: string[] = [];\n if (name === \"id\") flags.push(\"pk\");\n if (meta.nullable) flags.push(\"nullable\");\n if (meta.hasDefault) flags.push(`default ${formatDefaultValue(meta.defaultValue)}`);\n\n return (\n <div className=\"schemaColumnRow\" data-system={SYSTEM_COLUMNS.has(name) ? \"true\" : undefined}>\n <div className=\"schemaColumnName\">{name}</div>\n <div className=\"schemaColumnType\">\n <span>{meta.kind}</span>\n {meta.kind === \"boolean\" ? <span className=\"schemaColumnTypeDetail\">integer 0/1</span> : null}\n {meta.kind === \"enum\" && meta.enumValues && meta.enumValues.length > 0 ? (\n <span className=\"schemaColumnTypeDetail\">{meta.enumValues.map((value) => `\"${value}\"`).join(\" | \")}</span>\n ) : null}\n </div>\n <div className=\"schemaColumnFlags\">{flags.length > 0 ? flags.join(\" · \") : \"—\"}</div>\n <div className=\"schemaColumnDescription\">{meta.description ?? \"\"}</div>\n </div>\n );\n}\n\nfunction LiveQueriesTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n const [queries, setQueries] = useState<SharedLiveQuerySnapshot[]>([]);\n\n const refresh = useCallback(() => {\n if (!selectedInstance) {\n setQueries([]);\n return;\n }\n\n setQueries(\n selectedInstance.instance._internal\n .getSharedLiveQueriesSnapshot()\n .sort(\n (a, b) =>\n a.sql.localeCompare(b.sql) ||\n formatLiveQueryParameters(a.parameters).localeCompare(formatLiveQueryParameters(b.parameters)),\n ),\n );\n }, [selectedInstance]);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const totalSubscribers = queries.reduce((total, query) => total + query.subscriberCount, 0);\n\n return (\n <div className=\"schemaLayout\">\n <div className=\"schemaSection\">\n <div className=\"schemaSectionHeader\">\n <div className=\"schemaSectionTitle\">Shared Live Queries</div>\n <span className=\"schemaBadge\">{queries.length}</span>\n <span className=\"schemaVersionChip\">\n {totalSubscribers} subscriber{totalSubscribers !== 1 ? \"s\" : \"\"}\n </span>\n <button type=\"button\" className=\"refreshButton mlAuto\" onClick={refresh} disabled={!selectedInstance}>\n ↻ Refresh\n </button>\n </div>\n {queries.length === 0 ? (\n <div className=\"schemaEmpty\">\n No active live queries. Queries created via <code className=\"inlineCode\">useDbQuery</code> appear here while\n components are subscribed.\n </div>\n ) : (\n <div className=\"schemaTableGrid\">\n <div className=\"liveQueryHeaderRow\">\n <div className=\"schemaColHeader\">SQL</div>\n <div className=\"schemaColHeader\">Parameters</div>\n <div className=\"schemaColHeader alignCenter\">Subscribers</div>\n </div>\n {queries.map((query) => {\n const parameters = formatLiveQueryParameters(query.parameters);\n return (\n <div key={`${query.sql}|${parameters}`} className=\"liveQueryRow\">\n <div className=\"liveQuerySql\">{query.sql}</div>\n <div className=\"liveQueryParameters\">{parameters}</div>\n <div className=\"schemaStatusCell\">\n <span className={query.subscriberCount > 0 ? \"schemaActiveTag\" : \"liveQueryIdleTag\"}>\n {query.subscriberCount}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction formatLiveQueryParameters(parameters: readonly unknown[]): string {\n try {\n return JSON.stringify(parameters);\n } catch {\n return String(parameters);\n }\n}\n\ntype PersistedCrdtEvent = {\n sync_id: number;\n schema_version: number;\n status: \"pending\" | \"applied\" | \"failed\" | \"deduped\";\n type: \"item-created\" | \"item-updated\" | \"item-deleted\";\n timestamp: string;\n origin: \"remote\" | \"own\" | \"local\";\n source_node_id: string;\n dataset: string;\n item_id: string;\n payload: string;\n};\n\nfunction isPersistedCrdtEvent(value: unknown): value is PersistedCrdtEvent {\n if (typeof value !== \"object\" || value === null) return false;\n return (\n \"sync_id\" in value &&\n typeof value.sync_id === \"number\" &&\n \"status\" in value &&\n typeof value.status === \"string\" &&\n \"type\" in value &&\n typeof value.type === \"string\" &&\n \"origin\" in value &&\n typeof value.origin === \"string\" &&\n \"dataset\" in value &&\n typeof value.dataset === \"string\" &&\n \"item_id\" in value &&\n typeof value.item_id === \"string\" &&\n \"payload\" in value &&\n typeof value.payload === \"string\" &&\n \"timestamp\" in value &&\n typeof value.timestamp === \"string\"\n );\n}\n\ntype EventLogFilters = {\n dataset: string;\n origin: string;\n status: string;\n};\n\nconst PAGE_SIZE = 50;\n\nfunction sqlStringLiteral(value: string): string {\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction eventLogWhereClause(filters: EventLogFilters, afterSyncId: number | null): string {\n const conditions: string[] = [];\n\n if (filters.dataset) conditions.push(`dataset = ${sqlStringLiteral(filters.dataset)}`);\n if (filters.origin) conditions.push(`origin = ${sqlStringLiteral(filters.origin)}`);\n if (filters.status) conditions.push(`status = ${sqlStringLiteral(filters.status)}`);\n if (afterSyncId !== null) conditions.push(`sync_id < ${afterSyncId}`);\n\n return conditions.length > 0 ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n}\n\nfunction buildEventLogQuery(filters: EventLogFilters, afterSyncId: number | null): string {\n return `SELECT * FROM \"worker\".\"crdt_events\" ${eventLogWhereClause(filters, afterSyncId)} ORDER BY sync_id DESC LIMIT ${PAGE_SIZE + 1}`;\n}\n\nfunction buildEventLogCountQuery(filters: EventLogFilters): string {\n return `SELECT COUNT(*) AS count FROM \"worker\".\"crdt_events\" ${eventLogWhereClause(filters, null)}`;\n}\n\nfunction EventLogTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n const baseTableNames = useMemo(\n () => selectedInstance?.instance._internal.crdtTablesConfig.map((table) => table.baseTableName) ?? [],\n [selectedInstance],\n );\n\n const [filters, setFilters] = useState<EventLogFilters>({ dataset: \"\", origin: \"\", status: \"\" });\n const [events, setEvents] = useState<PersistedCrdtEvent[]>([]);\n const [totalCount, setTotalCount] = useState<number | null>(null);\n const [hasMore, setHasMore] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [expandedId, setExpandedId] = useState<number | null>(null);\n const afterSyncIdRef = useRef<number | null>(null);\n const isLoadingRef = useRef(false);\n\n const executeRows = useCallback(\n async (sql: string): Promise<unknown[]> => {\n if (!selectedInstance) return [];\n const result = await selectedInstance.instance._internal.executeAsync({ sql, parameters: [] });\n return result.rows;\n },\n [selectedInstance],\n );\n\n const load = useCallback(\n async (reset: boolean, currentFilters: EventLogFilters) => {\n if (!selectedInstance || isLoadingRef.current) return;\n isLoadingRef.current = true;\n setIsLoading(true);\n try {\n const afterSyncId = reset ? null : afterSyncIdRef.current;\n const sql = buildEventLogQuery(currentFilters, afterSyncId);\n const rowsPromise = executeRows(sql);\n const countPromise = reset ? executeRows(buildEventLogCountQuery(currentFilters)) : Promise.resolve(null);\n const [rows, countRows] = await Promise.all([rowsPromise, countPromise]);\n const page = rows.filter(isPersistedCrdtEvent).slice(0, PAGE_SIZE);\n setHasMore(rows.length > PAGE_SIZE);\n if (reset) {\n setEvents(page);\n setTotalCount(countRows ? readCount(countRows) : null);\n } else {\n setEvents((prev) => [...prev, ...page]);\n }\n afterSyncIdRef.current = page.at(-1)?.sync_id ?? null;\n } finally {\n isLoadingRef.current = false;\n setIsLoading(false);\n }\n },\n [selectedInstance, executeRows],\n );\n\n // Initial load and reload on instance or filter change\n useEffect(() => {\n afterSyncIdRef.current = null;\n setEvents([]);\n setTotalCount(null);\n void load(true, filters);\n }, [filters, load]);\n\n const applyFilters = (next: EventLogFilters) => {\n setFilters(next);\n };\n\n if (!selectedInstance) return null;\n\n return (\n <div className=\"eventLogLayout\">\n {/* Toolbar */}\n <div className=\"eventLogToolbar\">\n <select\n value={filters.dataset}\n onChange={(e) => applyFilters({ ...filters, dataset: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All datasets</option>\n {baseTableNames.map((name) => (\n <option key={name} value={name}>\n {name}\n </option>\n ))}\n </select>\n <select\n value={filters.origin}\n onChange={(e) => applyFilters({ ...filters, origin: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All origins</option>\n <option value=\"own\">own</option>\n <option value=\"remote\">remote</option>\n <option value=\"local\">local</option>\n </select>\n <select\n value={filters.status}\n onChange={(e) => applyFilters({ ...filters, status: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All statuses</option>\n <option value=\"applied\">applied</option>\n <option value=\"pending\">pending</option>\n <option value=\"failed\">failed</option>\n <option value=\"deduped\">deduped</option>\n </select>\n <button type=\"button\" className=\"refreshButton\" disabled={isLoading} onClick={() => void load(true, filters)}>\n {isLoading ? \"…\" : \"↻\"} Refresh\n </button>\n {totalCount !== null && (\n <span className=\"eventLogCount\">\n {events.length === totalCount\n ? `${totalCount} event${totalCount === 1 ? \"\" : \"s\"}`\n : `${events.length} of ${totalCount}`}\n </span>\n )}\n </div>\n\n {/* Event list */}\n {events.length === 0 && !isLoading ? (\n <div className=\"eventLogEmpty\">No events match the current filters.</div>\n ) : (\n <div className=\"eventLogList\">\n {events.map((event) => {\n const isExpanded = expandedId === event.sync_id;\n return (\n <div key={event.sync_id} className=\"eventRow\" data-expanded={isExpanded ? \"true\" : undefined}>\n <button\n type=\"button\"\n className=\"eventRowHeader\"\n onClick={() => setExpandedId(isExpanded ? null : event.sync_id)}\n >\n <span className=\"eventSyncId\">#{event.sync_id}</span>\n <EventTypeBadge type={event.type} />\n <EventOriginBadge origin={event.origin} />\n <EventStatusBadge status={event.status} />\n <span className=\"eventDataset\">{event.dataset}</span>\n <span className=\"eventItemId\">{event.item_id}</span>\n <span className=\"eventTimestamp\">{formatHlcTimestamp(event.timestamp)}</span>\n <span className=\"eventChevron\">{isExpanded ? \"▲\" : \"▼\"}</span>\n </button>\n\n {isExpanded && (\n <div className=\"eventPayload\">\n <div className=\"eventPayloadMeta\">\n <span className=\"eventMetaItem\">schema v{event.schema_version}</span>\n <span className=\"eventMetaItem\">node: {event.source_node_id || \"—\"}</span>\n <span className=\"eventMetaItem\">ts: {event.timestamp}</span>\n </div>\n <pre className=\"eventPayloadPre\">{formatPayload(event.payload)}</pre>\n </div>\n )}\n </div>\n );\n })}\n\n {hasMore && (\n <button\n type=\"button\"\n className=\"loadMoreButton\"\n disabled={isLoading}\n onClick={() => void load(false, filters)}\n >\n {isLoading ? \"Loading…\" : `Load ${PAGE_SIZE} more`}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction EventTypeBadge({ type }: { type: string }) {\n const { variant, label } =\n type === \"item-created\"\n ? { variant: \"create\", label: \"create\" }\n : type === \"item-deleted\"\n ? { variant: \"delete\", label: \"delete\" }\n : { variant: \"update\", label: \"update\" };\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {label}\n </span>\n );\n}\n\nfunction EventOriginBadge({ origin }: { origin: string }) {\n const variant = origin === \"own\" ? \"own\" : origin === \"remote\" ? \"remote\" : \"local\";\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {origin}\n </span>\n );\n}\n\nfunction EventStatusBadge({ status }: { status: string }) {\n const variant =\n status === \"applied\" ? \"applied\" : status === \"pending\" ? \"pending\" : status === \"failed\" ? \"failed\" : \"skipped\";\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {status}\n </span>\n );\n}\n\nfunction formatHlcTimestamp(ts: string): string {\n // HLC format: \"<unix_ms>-<counter>-<node>\" or just an ISO string\n const ms = Number(ts.split(\"-\")[0]);\n if (!Number.isNaN(ms) && ms > 1e12) {\n return new Date(ms).toLocaleTimeString();\n }\n return ts.slice(0, 19).replace(\"T\", \" \");\n}\n\nfunction formatPayload(raw: string): string {\n try {\n return JSON.stringify(JSON.parse(raw), null, 2);\n } catch {\n return raw;\n }\n}\n\nfunction QueryRunnerTab({\n selectedInstance,\n queryTarget,\n setQueryTarget,\n query,\n setQuery,\n queryState,\n canRunQuery,\n runQuery,\n}: {\n selectedInstance: unknown;\n queryTarget: QueryTarget;\n setQueryTarget: (t: QueryTarget) => void;\n query: string;\n setQuery: (q: string) => void;\n queryState: QueryState;\n canRunQuery: boolean;\n runQuery: () => Promise<void>;\n}) {\n return (\n <div className=\"queryRunnerLayout\">\n {/* Top toolbar */}\n <div className=\"queryToolbar\">\n <div className=\"targetToggle\">\n <button\n type=\"button\"\n className=\"targetButton\"\n data-active={queryTarget === \"memory\" ? \"true\" : undefined}\n onClick={() => setQueryTarget(\"memory\")}\n >\n Memory DB\n </button>\n <button\n type=\"button\"\n className=\"targetButton\"\n data-active={queryTarget === \"worker\" ? \"true\" : undefined}\n onClick={() => setQueryTarget(\"worker\")}\n >\n Worker DB\n </button>\n </div>\n\n <div className=\"queryToolbarRight\">\n {!selectedInstance && <span className=\"noInstanceWarning\">No instance selected</span>}\n <span className=\"shortcutHint\">⌘↵ to run</span>\n <button\n type=\"button\"\n className=\"runButton\"\n data-enabled={canRunQuery ? \"true\" : undefined}\n data-running={queryState.status === \"running\" ? \"true\" : undefined}\n disabled={!canRunQuery}\n onClick={() => void runQuery()}\n >\n {queryState.status === \"running\" ? (\n <>\n <span className=\"runningDot\" />\n Running…\n </>\n ) : (\n <>▶ Run</>\n )}\n </button>\n </div>\n </div>\n\n {/* SQL textarea */}\n <div className=\"editorWrapper\">\n <textarea\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\" && canRunQuery) {\n event.preventDefault();\n void runQuery();\n }\n }}\n className=\"textarea\"\n placeholder=\"SELECT * FROM your_table LIMIT 100\"\n spellCheck={false}\n />\n </div>\n\n {/* Constraint hint */}\n <div className=\"helperText\">\n {queryTarget === \"worker\"\n ? \"Worker DB is read-only — only SELECT, PRAGMA, and EXPLAIN are allowed.\"\n : \"Memory DB allows writes only to CRDT tables.\"}\n </div>\n\n {/* Results */}\n {queryState.status === \"error\" && (\n <div className=\"errorPanel\">\n <div className=\"resultHeader\">\n <span className=\"errorBadge\">Error</span>\n <span className=\"resultMeta\">\n {queryState.error.target} · {queryState.error.sql}\n </span>\n </div>\n <pre className=\"errorMessage\">{queryState.error.message}</pre>\n </div>\n )}\n\n {queryState.status === \"success\" && (\n <div className=\"resultPanel\">\n <div className=\"resultHeader\">\n <span className=\"successBadge\">\n {queryState.output.rowCount} row{queryState.output.rowCount !== 1 ? \"s\" : \"\"}\n </span>\n <span className=\"resultMeta\">\n {queryState.output.target} · {queryState.output.durationMs}ms\n </span>\n </div>\n <ResultTable rows={queryState.output.rows} />\n </div>\n )}\n </div>\n );\n}\n\nfunction ResultTable({ rows }: { rows: unknown[] }) {\n if (rows.length === 0) {\n return <div className=\"resultEmpty\">Query returned 0 rows.</div>;\n }\n\n const firstRow = rows[0];\n if (typeof firstRow !== \"object\" || firstRow === null) {\n return <pre className=\"resultRaw\">{JSON.stringify(rows, null, 2)}</pre>;\n }\n\n const columns = Object.keys(firstRow as object);\n\n return (\n <div className=\"tableWrapper\">\n <table className=\"table\">\n <thead>\n <tr>\n <th className=\"thRowNum\">#</th>\n {columns.map((col) => (\n <th key={col} className=\"th\">\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr key={rowIdx}>\n <td className=\"tdRowNum\">{rowIdx + 1}</td>\n {columns.map((col) => {\n const val = (row as Record<string, unknown>)[col];\n return (\n <td key={col} className=\"td\">\n {val === null ? (\n <span className=\"nullValue\">NULL</span>\n ) : typeof val === \"object\" ? (\n <span className=\"jsonValue\">{JSON.stringify(val)}</span>\n ) : (\n String(val)\n )}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatInstanceLabel(dbId: string, instanceId: string, duplicateCount: number): string {\n if (duplicateCount < 2) {\n return dbId;\n }\n\n return `${dbId} (${instanceId.slice(0, 6)})`;\n}\n\nfunction normalizeSingleStatement(query: string): string {\n const trimmed = query.trim();\n if (!trimmed) {\n throw new Error(\"Enter a SQL statement.\");\n }\n\n const withoutTrailingSemicolons = trimmed.replace(/;+\\s*$/u, \"\");\n if (withoutTrailingSemicolons.includes(\";\")) {\n throw new Error(\"Devtools only supports a single SQL statement.\");\n }\n\n return withoutTrailingSemicolons;\n}\n\nfunction getStatementKind(query: string): string {\n const match = query.trimStart().match(/^([a-z]+)/iu);\n return match?.[1]?.toLowerCase() ?? \"\";\n}\n\nfunction isWorkerReadOnlyStatement(statementKind: string): boolean {\n return statementKind === \"select\" || statementKind === \"pragma\";\n}\n\nfunction getEmptySnapshot(): SQLiteSyncDevtoolsSnapshot {\n return emptySnapshot;\n}\n\nconst emptySnapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["cssText"],"sources":["../src/devtools-registry.ts","../src/devtools.css?inline","../src/shadow-root.tsx","../src/devtools.tsx"],"sourcesContent":["import type { SyncedDb } from \"@sqlite-sync/core\";\n\nconst devtoolsRegistrySymbol = Symbol.for(\"@sqlite-sync/devtools\");\n\nexport type SQLiteSyncDevtoolsInstance = {\n instanceId: string;\n dbId: string;\n createdAt: number;\n instance: SyncedDb<any>;\n};\n\nexport type SQLiteSyncDevtoolsSnapshot = {\n instances: readonly SQLiteSyncDevtoolsInstance[];\n};\n\nexport type SQLiteSyncDevtoolsRegistry = {\n version: 1;\n instances: Map<string, SQLiteSyncDevtoolsInstance>;\n subscribe(listener: () => void): () => void;\n getSnapshot(): SQLiteSyncDevtoolsSnapshot;\n register(instance: SQLiteSyncDevtoolsInstance): () => void;\n};\n\ntype RegistryGlobal = typeof globalThis & {\n [key: symbol]: SQLiteSyncDevtoolsRegistry | undefined;\n};\n\nfunction createSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const instances = new Map<string, SQLiteSyncDevtoolsInstance>();\n const listeners = new Set<() => void>();\n let snapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n };\n\n const notify = () => {\n for (const listener of listeners) {\n listener();\n }\n };\n\n const updateSnapshot = () => {\n snapshot = {\n instances: Array.from(instances.values()),\n };\n notify();\n };\n\n return {\n version: 1,\n instances,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n getSnapshot() {\n return snapshot;\n },\n register(instance) {\n instances.set(instance.instanceId, instance);\n updateSnapshot();\n\n let isUnregistered = false;\n return () => {\n if (isUnregistered) return;\n isUnregistered = true;\n\n if (!instances.delete(instance.instanceId)) return;\n updateSnapshot();\n };\n },\n };\n}\n\nexport function getOrCreateSQLiteSyncDevtoolsRegistry(): SQLiteSyncDevtoolsRegistry {\n const registryGlobal = globalThis as RegistryGlobal;\n\n registryGlobal[devtoolsRegistrySymbol] ??= createSQLiteSyncDevtoolsRegistry();\n\n return registryGlobal[devtoolsRegistrySymbol];\n}\n",":host {\n all: initial;\n display: block;\n position: relative;\n z-index: 9998;\n --ss-bg: #0e1015;\n --ss-bg-panel: #161921;\n --ss-bg-card: #1c2030;\n --ss-bg-input: #111318;\n --ss-border: #2a2f3e;\n --ss-border-light: #343a4f;\n --ss-text: #e2e8f0;\n --ss-text-muted: #6b7280;\n --ss-text-dim: #9ca3af;\n --ss-teal: #2dd4bf;\n --ss-teal-dim: rgba(45, 212, 191, 0.12);\n --ss-teal-glow: rgba(45, 212, 191, 0.06);\n --ss-error: #f87171;\n --ss-error-bg: rgba(248, 113, 113, 0.08);\n --ss-error-border: rgba(248, 113, 113, 0.25);\n --ss-success: #34d399;\n --ss-success-bg: rgba(52, 211, 153, 0.08);\n --ss-amber: #fbbf24;\n font-family: ui-sans-serif, system-ui, sans-serif;\n color: var(--ss-text);\n font-size: 0.88rem;\n}\n\n:host *,\n:host *::before,\n:host *::after {\n box-sizing: border-box;\n}\n\n.mono {\n font-family: ui-monospace, monospace;\n}\n\n.sm {\n font-size: 0.78rem;\n}\n\n.alignCenter {\n text-align: center;\n}\n\n.mlAuto {\n margin-left: auto;\n}\n\n.hiddenInput {\n display: none;\n}\n\n.floatingRoot {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 9998;\n}\n\n.triggerButton {\n position: absolute;\n right: 16px;\n bottom: 16px;\n display: inline-flex;\n align-items: center;\n gap: 0.3rem;\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n padding: 0.3rem 0.45rem;\n background: var(--ss-bg-panel);\n color: var(--ss-text);\n box-shadow:\n 0 0 0 1px var(--ss-border),\n 0 4px 16px rgba(0, 0, 0, 0.5);\n cursor: grab;\n touch-action: none;\n user-select: none;\n pointer-events: auto;\n}\n\n.triggerIcon {\n color: var(--ss-teal);\n font-size: 0.9rem;\n line-height: 1;\n}\n\n.triggerCount {\n min-width: 1.1rem;\n border-radius: 4px;\n padding: 0.05rem 0.25rem;\n background-color: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-size: 0.65rem;\n font-weight: 700;\n text-align: center;\n font-family: ui-monospace, monospace;\n}\n\n.overlay {\n position: fixed;\n inset: 0;\n z-index: 9999;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1.5rem;\n background-color: rgba(0, 0, 0, 0.72);\n backdrop-filter: blur(8px);\n}\n\n.dialog {\n width: min(72rem, 100%);\n height: min(90vh, 860px);\n display: flex;\n flex-direction: column;\n border: 1px solid var(--ss-border);\n border-radius: 16px;\n background: var(--ss-bg);\n box-shadow:\n 0 0 0 1px var(--ss-border),\n 0 40px 80px rgba(0, 0, 0, 0.8),\n 0 0 60px rgba(45, 212, 191, 0.04);\n overflow: hidden;\n font-family: ui-sans-serif, system-ui, sans-serif;\n color: var(--ss-text);\n font-size: 0.88rem;\n}\n\n.header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n gap: 1rem;\n padding: 0.85rem 1.1rem;\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n flex-shrink: 0;\n}\n\n.headerLeft {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.headerLogo {\n font-size: 1.3rem;\n color: var(--ss-teal);\n line-height: 1;\n}\n\n.eyebrow {\n font-size: 0.65rem;\n font-weight: 600;\n letter-spacing: 0.1em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n}\n\n.title {\n margin: 0.05rem 0 0;\n font-size: 0.95rem;\n font-weight: 700;\n color: var(--ss-text);\n letter-spacing: -0.01em;\n}\n\n.headerRight {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.instancePickerLabel {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.instancePickerText {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--ss-text-muted);\n text-transform: uppercase;\n letter-spacing: 0.06em;\n}\n\n.instancePickerSelect {\n border-radius: 7px;\n border: 1px solid var(--ss-border);\n padding: 0.35rem 0.6rem;\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n font-size: 0.82rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n}\n\n.instanceCountBadge {\n font-size: 0.72rem;\n font-weight: 600;\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 5px;\n padding: 0.2rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.closeButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n width: 28px;\n height: 28px;\n display: flex;\n align-items: center;\n justify-content: center;\n background-color: transparent;\n color: var(--ss-text-muted);\n font-size: 0.82rem;\n font-weight: 600;\n cursor: pointer;\n}\n\n.hideLauncherButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.3rem 0.65rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.75rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.emptyState {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n padding: 4rem 2rem;\n gap: 0.75rem;\n flex: 1;\n}\n\n.emptyStateIcon {\n font-size: 2.5rem;\n color: var(--ss-text-muted);\n opacity: 0.4;\n}\n\n.emptyStateText {\n margin: 0;\n font-size: 0.95rem;\n font-weight: 600;\n color: var(--ss-text-dim);\n}\n\n.emptyStateSubtext {\n margin: 0;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n text-align: center;\n}\n\n.inlineCode {\n font-family: ui-monospace, monospace;\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.1em 0.4em;\n font-size: 0.88em;\n color: var(--ss-teal);\n}\n\n.contentLayout {\n display: grid;\n grid-template-columns: 200px minmax(0, 1fr);\n flex: 1;\n min-height: 0;\n overflow: hidden;\n}\n\n.sidebar {\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0.75rem;\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-panel);\n overflow-y: auto;\n}\n\n.nav {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n margin-bottom: 1rem;\n}\n\n.navIcon {\n font-size: 0.7rem;\n opacity: 0.7;\n}\n\n.sidebarInfo {\n margin-top: auto;\n padding: 0.75rem;\n border-radius: 8px;\n background: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.sidebarInfoLabel {\n font-size: 0.65rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: 0.3rem;\n}\n\n.sidebarInfoValue {\n font-size: 0.88rem;\n font-weight: 600;\n color: var(--ss-text);\n word-break: break-word;\n font-family: ui-monospace, monospace;\n}\n\n.sidebarInfoSub {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n margin-top: 0.25rem;\n}\n\n.mainPane {\n min-width: 0;\n overflow-y: auto;\n padding: 1rem;\n}\n\n.overviewLayout {\n display: flex;\n flex-direction: column;\n gap: 1.25rem;\n}\n\n.overviewCardsRow {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));\n gap: 0.75rem;\n}\n\n.overviewCard {\n padding: 0.9rem 1rem;\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.overviewCardLabel {\n font-size: 0.68rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n margin-bottom: 0.4rem;\n}\n\n.overviewCardValue {\n font-size: 1rem;\n font-weight: 700;\n color: var(--ss-text);\n word-break: break-word;\n}\n\n.overviewCardSub {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n margin-top: 0.25rem;\n}\n\n.overviewSection {\n display: flex;\n flex-direction: column;\n gap: 0.5rem;\n}\n\n.overviewSectionTitle {\n font-size: 0.72rem;\n font-weight: 600;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n}\n\n.overviewSectionHeader {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n}\n\n.refreshButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.35rem 0.7rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.overviewAccumulatorValue {\n padding: 0.75rem;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n font-family: ui-monospace, monospace;\n font-size: 0.78rem;\n color: var(--ss-text);\n line-height: 1.5;\n word-break: break-all;\n}\n\n.overviewAccumulatorEmpty {\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.overviewAccumulatorError {\n color: var(--ss-error);\n}\n\n.overviewEmpty {\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.eventCountGrid {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(7.5rem, 1fr));\n gap: 0.5rem;\n}\n\n.eventCountCard {\n padding: 0.75rem 0.85rem;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.eventCountValue {\n font-size: 1.05rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n margin-bottom: 0.35rem;\n}\n\n.eventCountValue[data-tone=\"amber\"][data-emphasize=\"true\"] {\n color: var(--ss-amber);\n}\n\n.eventCountValue[data-tone=\"success\"][data-emphasize=\"true\"] {\n color: var(--ss-success);\n}\n\n.eventCountValue[data-tone=\"error\"][data-emphasize=\"true\"] {\n color: var(--ss-error);\n}\n\n.dataActions {\n display: flex;\n gap: 0.4rem;\n}\n\n.dataButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.4rem 0.8rem;\n background-color: transparent;\n color: var(--ss-teal);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.dataStatusSuccess {\n font-size: 0.75rem;\n color: var(--ss-success);\n}\n\n.dataStatusError {\n font-size: 0.75rem;\n color: var(--ss-error);\n word-break: break-word;\n}\n\n.dangerZone {\n margin-top: auto;\n border-radius: 10px;\n border: 1px solid var(--ss-error-border);\n padding: 0.75rem 1rem;\n background: var(--ss-error-bg);\n}\n\n.dangerZoneTitle {\n font-size: 0.65rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-error);\n margin-bottom: 0.5rem;\n}\n\n.dangerZoneRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 1rem;\n}\n\n.dangerZoneDesc {\n font-size: 0.75rem;\n color: var(--ss-text-muted);\n line-height: 1.5;\n}\n\n.dangerZoneActions {\n display: flex;\n gap: 0.4rem;\n flex-shrink: 0;\n}\n\n.resetButton {\n flex-shrink: 0;\n border: 1px solid var(--ss-error-border);\n border-radius: 7px;\n padding: 0.35rem 0.75rem;\n background-color: transparent;\n color: var(--ss-error);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.resetCancelButton {\n border: 1px solid var(--ss-border);\n border-radius: 7px;\n padding: 0.35rem 0.65rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-weight: 600;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.resetConfirmButton {\n border: none;\n border-radius: 7px;\n padding: 0.35rem 0.75rem;\n background-color: var(--ss-error);\n color: #0e1015;\n font-size: 0.78rem;\n font-weight: 700;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.queryRunnerLayout {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n height: 100%;\n}\n\n.queryToolbar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.targetToggle {\n display: flex;\n gap: 0;\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-card);\n}\n\n.queryToolbarRight {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.noInstanceWarning {\n font-size: 0.75rem;\n color: var(--ss-amber);\n font-weight: 500;\n}\n\n.shortcutHint {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n padding: 0.2rem 0.5rem;\n border-radius: 5px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.editorWrapper {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-input);\n}\n\n.textarea {\n width: 100%;\n min-height: 9rem;\n resize: vertical;\n border: none;\n padding: 0.85rem 1rem;\n background-color: transparent;\n color: var(--ss-text);\n font-size: 0.875rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n line-height: 1.6;\n outline: none;\n box-sizing: border-box;\n}\n\n.helperText {\n font-size: 0.75rem;\n line-height: 1.5;\n color: var(--ss-text-muted);\n}\n\n.resultPanel {\n display: flex;\n flex-direction: column;\n gap: 0.6rem;\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n background: var(--ss-bg-panel);\n}\n\n.errorPanel {\n display: flex;\n flex-direction: column;\n gap: 0.6rem;\n padding: 0.85rem 1rem;\n border-radius: 10px;\n border: 1px solid var(--ss-error-border);\n background: var(--ss-error-bg);\n}\n\n.resultHeader {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n padding: 0.6rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n}\n\n.successBadge {\n font-size: 0.72rem;\n font-weight: 700;\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 5px;\n padding: 0.15rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.errorBadge {\n font-size: 0.72rem;\n font-weight: 700;\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n border-radius: 5px;\n padding: 0.15rem 0.5rem;\n font-family: ui-monospace, monospace;\n}\n\n.resultMeta {\n font-size: 0.72rem;\n color: var(--ss-text-muted);\n font-family: ui-monospace, monospace;\n}\n\n.resultEmpty {\n padding: 1.5rem;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n text-align: center;\n}\n\n.resultRaw {\n margin: 0;\n padding: 0.85rem 1rem;\n overflow-x: auto;\n white-space: pre-wrap;\n word-break: break-word;\n font-size: 0.8rem;\n line-height: 1.5;\n color: var(--ss-text);\n font-family: ui-monospace, monospace;\n}\n\n.errorMessage {\n margin: 0;\n font-size: 0.82rem;\n line-height: 1.6;\n color: var(--ss-error);\n font-family: ui-monospace, monospace;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.tableWrapper {\n overflow-x: auto;\n max-height: 320px;\n overflow-y: auto;\n}\n\n.table {\n width: 100%;\n border-collapse: collapse;\n font-size: 0.8rem;\n font-family: ui-monospace, SFMono-Regular, Menlo, monospace;\n}\n\n.table tbody tr:nth-child(even) {\n background: var(--ss-teal-glow);\n}\n\n.th {\n padding: 0.5rem 0.85rem;\n text-align: left;\n font-weight: 600;\n font-size: 0.7rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n position: sticky;\n top: 0;\n}\n\n.thRowNum {\n padding: 0.5rem 0.85rem;\n text-align: right;\n font-weight: 600;\n font-size: 0.7rem;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n white-space: nowrap;\n position: sticky;\n top: 0;\n opacity: 0.5;\n width: 2.5rem;\n}\n\n.td {\n padding: 0.45rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text);\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n}\n\n.tdRowNum {\n padding: 0.45rem 0.85rem;\n border-bottom: 1px solid var(--ss-border);\n border-right: 1px solid var(--ss-border);\n color: var(--ss-text-muted);\n white-space: nowrap;\n max-width: 300px;\n overflow: hidden;\n text-overflow: ellipsis;\n opacity: 0.5;\n text-align: right;\n user-select: none;\n}\n\n.nullValue {\n color: var(--ss-text-muted);\n font-style: italic;\n opacity: 0.6;\n}\n\n.jsonValue {\n color: var(--ss-text-dim);\n}\n\n.tabButton {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n border: none;\n border-radius: 7px;\n padding: 0.6rem 0.75rem;\n background: transparent;\n color: var(--ss-text-dim);\n font-size: 0.82rem;\n font-weight: 500;\n text-align: left;\n cursor: pointer;\n transition: background 0.15s;\n border-left: 2px solid transparent;\n}\n\n.tabButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n border-left: 2px solid var(--ss-teal);\n}\n\n.targetButton {\n border: none;\n border-right: 1px solid var(--ss-border);\n padding: 0.45rem 0.85rem;\n background: transparent;\n color: var(--ss-text-muted);\n font-size: 0.78rem;\n font-weight: 500;\n cursor: pointer;\n font-family: ui-monospace, monospace;\n transition: background 0.1s;\n white-space: nowrap;\n}\n\n.targetButton[data-active=\"true\"] {\n background: var(--ss-teal-dim);\n color: var(--ss-teal);\n font-weight: 700;\n}\n\n.runButton {\n display: inline-flex;\n align-items: center;\n gap: 0.4rem;\n border: none;\n border-radius: 7px;\n padding: 0.45rem 0.9rem;\n background: var(--ss-bg-card);\n color: var(--ss-text-muted);\n font-size: 0.82rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n cursor: not-allowed;\n opacity: 1;\n transition: background 0.15s;\n white-space: nowrap;\n}\n\n.runButton[data-enabled=\"true\"] {\n background: var(--ss-teal);\n color: #0e1015;\n cursor: pointer;\n}\n\n.runButton[data-running=\"true\"] {\n opacity: 0.75;\n}\n\n.runningDot {\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background-color: currentColor;\n}\n\n.schemaLayout {\n display: flex;\n flex-direction: column;\n gap: 1.5rem;\n}\n\n.schemaSection {\n display: flex;\n flex-direction: column;\n gap: 0.65rem;\n}\n\n.schemaSectionHeader {\n display: flex;\n align-items: center;\n gap: 0.6rem;\n}\n\n.schemaSectionTitle {\n font-size: 0.72rem;\n font-weight: 700;\n letter-spacing: 0.08em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n}\n\n.schemaBadge {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n border-radius: 4px;\n padding: 0.1rem 0.4rem;\n font-family: ui-monospace, monospace;\n}\n\n.schemaVersionChip {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.1rem 0.5rem;\n}\n\n.schemaTableGrid {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n overflow: hidden;\n}\n\n.schemaColHeader {\n padding: 0.5rem 0.85rem;\n font-size: 0.68rem;\n font-weight: 700;\n letter-spacing: 0.07em;\n text-transform: uppercase;\n color: var(--ss-text-muted);\n border-right: 1px solid var(--ss-border);\n}\n\n.schemaStatusCell {\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0.6rem 0.5rem;\n}\n\n.schemaActiveTag {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n border-radius: 4px;\n padding: 0.15rem 0.45rem;\n font-family: ui-monospace, monospace;\n}\n\n.schemaEmpty {\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.schemaTableList {\n display: flex;\n flex-direction: column;\n gap: 0.85rem;\n}\n\n.schemaTableCard {\n border-radius: 10px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n overflow: hidden;\n}\n\n.schemaTableCardHeader {\n display: flex;\n flex-direction: column;\n gap: 0.45rem;\n padding: 0.75rem 0.85rem 0.7rem;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.schemaTableCardTitleRow {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n}\n\n.schemaTableCardName {\n font-size: 0.92rem;\n font-weight: 700;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n}\n\n.schemaTableCardDescription {\n margin: 0;\n font-size: 0.78rem;\n line-height: 1.45;\n color: var(--ss-text-dim);\n}\n\n.schemaTableCardMeta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.35rem;\n}\n\n.schemaPolicyChip {\n font-size: 0.65rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n background: var(--ss-bg-input);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.12rem 0.4rem;\n}\n\n.schemaPolicyChip[data-tone=\"warn\"] {\n color: var(--ss-amber);\n background: rgba(251, 191, 36, 0.08);\n border-color: rgba(251, 191, 36, 0.25);\n}\n\n.schemaColumnGrid {\n display: flex;\n flex-direction: column;\n overflow-x: auto;\n}\n\n.schemaColumnRow {\n display: grid;\n grid-template-columns: minmax(6.5rem, 0.7fr) minmax(8rem, 1fr) minmax(7.5rem, 0.9fr) minmax(0, 1.8fr);\n min-width: 36rem;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.schemaColumnRow:last-child {\n border-bottom: none;\n}\n\n.schemaColumnRow[data-system=\"true\"] {\n opacity: 0.62;\n}\n\n.schemaColumnHeaderRow {\n background: var(--ss-bg-panel);\n}\n\n.schemaColumnHeaderRow .schemaColHeader:last-child {\n border-right: none;\n}\n\n.schemaColumnName,\n.schemaColumnType,\n.schemaColumnFlags,\n.schemaColumnDescription {\n padding: 0.5rem 0.85rem;\n font-size: 0.76rem;\n border-right: 1px solid var(--ss-border);\n min-width: 0;\n}\n\n.schemaColumnDescription {\n border-right: none;\n color: var(--ss-text-dim);\n overflow-wrap: anywhere;\n}\n\n.schemaColumnName {\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n font-weight: 600;\n}\n\n.schemaColumnType {\n display: flex;\n flex-direction: column;\n gap: 0.15rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-teal);\n}\n\n.schemaColumnTypeDetail {\n font-size: 0.65rem;\n color: var(--ss-text-muted);\n font-weight: 400;\n overflow-wrap: anywhere;\n}\n\n.schemaColumnFlags {\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n overflow-wrap: anywhere;\n}\n\n.liveQueryHeaderRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n background-color: var(--ss-bg-card);\n border-bottom: 1px solid var(--ss-border);\n}\n\n.liveQueryRow {\n display: grid;\n grid-template-columns: minmax(0, 1fr) 220px 110px;\n gap: 0;\n border-bottom: 1px solid var(--ss-border);\n}\n\n.liveQuerySql {\n padding: 0.6rem 0.85rem;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.liveQueryParameters {\n padding: 0.6rem 0.85rem;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-dim);\n border-right: 1px solid var(--ss-border);\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n}\n\n.liveQueryIdleTag {\n font-size: 0.68rem;\n font-weight: 700;\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n border-radius: 4px;\n padding: 0.15rem 0.45rem;\n font-family: ui-monospace, monospace;\n}\n\n.eventLogLayout {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n height: 100%;\n}\n\n.eventLogToolbar {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n flex-wrap: wrap;\n flex-shrink: 0;\n}\n\n.eventLogFilterSelect {\n border-radius: 7px;\n border: 1px solid var(--ss-border);\n padding: 0.35rem 0.6rem;\n background-color: var(--ss-bg-card);\n color: var(--ss-text);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n}\n\n.eventLogCount {\n margin-left: auto;\n font-size: 0.72rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n}\n\n.eventLogEmpty {\n padding: 2rem;\n text-align: center;\n font-size: 0.82rem;\n color: var(--ss-text-muted);\n font-style: italic;\n}\n\n.eventLogList {\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n overflow-y: auto;\n flex: 1;\n}\n\n.eventRow {\n border-radius: 8px;\n border: 1px solid var(--ss-border);\n background: var(--ss-bg-card);\n overflow: hidden;\n flex-shrink: 0;\n}\n\n.eventRow[data-expanded=\"true\"] {\n border: 1px solid #2dd4bf40;\n background: var(--ss-teal-glow);\n}\n\n.eventRowHeader {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n width: 100%;\n padding: 0.5rem 0.75rem;\n background: transparent;\n border: none;\n cursor: pointer;\n text-align: left;\n flex-wrap: wrap;\n}\n\n.eventSyncId {\n font-size: 0.7rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n min-width: 3.5rem;\n}\n\n.eventDataset {\n font-size: 0.8rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n font-weight: 600;\n}\n\n.eventItemId {\n font-size: 0.75rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n min-width: 0;\n}\n\n.eventTimestamp {\n font-size: 0.7rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n margin-left: auto;\n}\n\n.eventChevron {\n font-size: 0.6rem;\n color: var(--ss-text-muted);\n margin-left: 0.25rem;\n}\n\n.eventPayload {\n border-top: 1px solid var(--ss-border);\n padding: 0.6rem 0.75rem;\n}\n\n.eventPayloadMeta {\n display: flex;\n gap: 0.75rem;\n margin-bottom: 0.5rem;\n}\n\n.eventMetaItem {\n font-size: 0.68rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text-muted);\n}\n\n.eventPayloadPre {\n margin: 0;\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n color: var(--ss-text);\n line-height: 1.5;\n white-space: pre-wrap;\n word-break: break-word;\n}\n\n.loadMoreButton {\n width: 100%;\n border: 1px solid var(--ss-border);\n border-radius: 8px;\n padding: 0.6rem;\n background-color: transparent;\n color: var(--ss-text-dim);\n font-size: 0.78rem;\n font-family: ui-monospace, monospace;\n cursor: pointer;\n flex-shrink: 0;\n}\n\n.eventBadge {\n font-size: 0.65rem;\n font-weight: 700;\n border-radius: 4px;\n padding: 0.1rem 0.4rem;\n font-family: ui-monospace, monospace;\n white-space: nowrap;\n}\n\n.eventBadge[data-variant=\"create\"] {\n color: var(--ss-teal);\n background-color: var(--ss-teal-dim);\n}\n\n.eventBadge[data-variant=\"update\"] {\n color: #a78bfa;\n background-color: rgba(167, 139, 250, 0.12);\n}\n\n.eventBadge[data-variant=\"delete\"] {\n color: var(--ss-error);\n background-color: rgba(248, 113, 113, 0.12);\n}\n\n.eventBadge[data-variant=\"own\"],\n.eventBadge[data-variant=\"applied\"] {\n color: var(--ss-success);\n background-color: var(--ss-success-bg);\n}\n\n.eventBadge[data-variant=\"remote\"],\n.eventBadge[data-variant=\"pending\"] {\n color: var(--ss-amber);\n background-color: rgba(251, 191, 36, 0.1);\n}\n\n.eventBadge[data-variant=\"local\"] {\n color: var(--ss-text-dim);\n background-color: var(--ss-bg-card);\n border: 1px solid var(--ss-border);\n}\n\n.eventBadge[data-variant=\"failed\"] {\n color: var(--ss-error);\n background-color: var(--ss-error-bg);\n}\n\n.eventBadge[data-variant=\"skipped\"] {\n color: var(--ss-text-muted);\n background-color: var(--ss-bg-card);\n}\n\n@media (max-width: 640px) {\n .overlay {\n padding: 0;\n }\n\n .dialog {\n width: 100%;\n height: 100%;\n border: none;\n border-radius: 0;\n }\n\n .header {\n flex-wrap: wrap;\n gap: 0.5rem;\n padding: 0.6rem 0.75rem;\n padding-top: max(0.6rem, env(safe-area-inset-top));\n }\n\n .headerRight {\n flex: 1;\n justify-content: flex-end;\n min-width: 0;\n }\n\n .instancePickerLabel {\n min-width: 0;\n }\n\n .instancePickerSelect {\n min-width: 0;\n max-width: 100%;\n }\n\n .instanceCountBadge {\n display: none;\n }\n\n .closeButton {\n flex-shrink: 0;\n width: 36px;\n height: 36px;\n }\n\n .contentLayout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .sidebar {\n padding: 0.4rem 0.5rem;\n border-right: none;\n border-bottom: 1px solid var(--ss-border);\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .nav {\n flex-direction: row;\n margin-bottom: 0;\n }\n\n .tabButton {\n width: auto;\n flex-shrink: 0;\n white-space: nowrap;\n border-left: none;\n border-bottom: 2px solid transparent;\n }\n\n .tabButton[data-active=\"true\"] {\n border-left: none;\n border-bottom: 2px solid var(--ss-teal);\n }\n\n .sidebarInfo {\n display: none;\n }\n\n .mainPane {\n padding: 0.75rem;\n padding-bottom: max(0.75rem, env(safe-area-inset-bottom));\n }\n\n .liveQueryHeaderRow,\n .liveQueryRow {\n grid-template-columns: minmax(0, 1fr) minmax(0, 0.6fr) 6.5rem;\n }\n\n .liveQueryHeaderRow .schemaColHeader,\n .liveQuerySql,\n .liveQueryParameters {\n padding-left: 0.5rem;\n padding-right: 0.5rem;\n }\n\n .liveQueryHeaderRow .schemaColHeader {\n letter-spacing: 0.02em;\n }\n}\n\n@media (hover: none) {\n .hideLauncherButton {\n display: none;\n }\n}\n","import { type ReactNode, useLayoutEffect, useRef, useState } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport cssText from \"./devtools.css?inline\";\n\nexport function ShadowRoot({ children, className }: { children: ReactNode; className?: string }) {\n const hostRef = useRef<HTMLDivElement>(null);\n const [shadowRoot, setShadowRoot] = useState<ShadowRoot | null>(null);\n\n useLayoutEffect(() => {\n const host = hostRef.current;\n if (!host) return;\n setShadowRoot(host.shadowRoot ?? host.attachShadow({ mode: \"open\" }));\n }, []);\n\n return (\n <div ref={hostRef} className={className}>\n {shadowRoot\n ? createPortal(\n <>\n <style>{cssText}</style>\n {children}\n </>,\n shadowRoot,\n )\n : null}\n </div>\n );\n}\n","import type { ColumnMeta, SharedLiveQuerySnapshot, SyncedDbExport } from \"@sqlite-sync/core\";\nimport type { CSSProperties, PointerEvent as ReactPointerEvent } from \"react\";\nimport { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from \"react\";\nimport {\n getOrCreateSQLiteSyncDevtoolsRegistry,\n type SQLiteSyncDevtoolsInstance,\n type SQLiteSyncDevtoolsSnapshot,\n} from \"./devtools-registry\";\nimport { ShadowRoot } from \"./shadow-root\";\n\nexport type SQLiteSyncDevtoolsProps = {\n className?: string;\n /** Render the floating launcher button. Set to `false` to open the dialog only via `open`. Defaults to `true`. */\n launcher?: boolean;\n /** Hide the floating launcher. Omit to let the user toggle it with Ctrl+Alt+S (⌘⌥S on macOS). */\n hidden?: boolean;\n onHiddenChange?: (hidden: boolean) => void;\n /** Control whether the devtools dialog is open. Omit to let the launcher manage it. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n};\n\ntype DevtoolsTab = \"overview\" | \"schema\" | \"live-queries\" | \"event-log\" | \"query-runner\";\ntype QueryTarget = \"memory\" | \"worker\";\n\ntype QueryState =\n | {\n status: \"idle\";\n }\n | {\n status: \"running\";\n }\n | {\n status: \"success\";\n output: {\n target: QueryTarget;\n sql: string;\n rowCount: number;\n durationMs: number;\n rows: unknown[];\n };\n }\n | {\n status: \"error\";\n error: {\n target: QueryTarget;\n sql: string;\n message: string;\n };\n };\n\nconst TRIGGER_POSITION_STORAGE_KEY = \"sqlite-sync-devtools.trigger-position\";\nconst TRIGGER_HIDDEN_STORAGE_KEY = \"sqlite-sync-devtools.trigger-hidden\";\nconst DRAG_THRESHOLD_PX = 4;\nconst VIEWPORT_MARGIN_PX = 8;\nconst IS_APPLE_PLATFORM = typeof navigator !== \"undefined\" && /Mac|iPhone|iPad/.test(navigator.platform);\nconst TOGGLE_LAUNCHER_HINT = IS_APPLE_PLATFORM ? \"⌘⌥S\" : \"Ctrl+Alt+S\";\n\ntype TriggerPosition = { x: number; y: number };\n\nfunction readStoredTriggerPosition(): TriggerPosition | null {\n if (typeof window === \"undefined\") return null;\n try {\n const raw = window.localStorage.getItem(TRIGGER_POSITION_STORAGE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw) as Partial<TriggerPosition>;\n if (typeof parsed.x === \"number\" && typeof parsed.y === \"number\") {\n return { x: parsed.x, y: parsed.y };\n }\n } catch {}\n return null;\n}\n\nfunction clampTriggerPosition(position: TriggerPosition, button: HTMLElement): TriggerPosition {\n const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;\n const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;\n return {\n x: Math.max(VIEWPORT_MARGIN_PX, Math.min(position.x, maxX)),\n y: Math.max(VIEWPORT_MARGIN_PX, Math.min(position.y, maxY)),\n };\n}\n\nfunction useDraggableTrigger() {\n const buttonRef = useRef<HTMLButtonElement>(null);\n const [position, setPosition] = useState<TriggerPosition | null>(readStoredTriggerPosition);\n const dragRef = useRef<{\n pointerId: number;\n startX: number;\n startY: number;\n offsetX: number;\n offsetY: number;\n moved: boolean;\n } | null>(null);\n // pointerup clears dragRef before the click event fires, so the moved flag is\n // stashed here to suppress the click that a drag gesture would otherwise emit.\n const suppressClickRef = useRef(false);\n\n const onPointerDown = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const button = buttonRef.current;\n if (!button || event.button !== 0) return;\n suppressClickRef.current = false;\n const rect = button.getBoundingClientRect();\n dragRef.current = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n offsetX: event.clientX - rect.left,\n offsetY: event.clientY - rect.top,\n moved: false,\n };\n button.setPointerCapture(event.pointerId);\n }, []);\n\n const clampToViewport = useCallback(() => {\n const button = buttonRef.current;\n if (!button) return;\n setPosition((current) => {\n if (!current) return current;\n const next = clampTriggerPosition(current, button);\n return next.x === current.x && next.y === current.y ? current : next;\n });\n }, []);\n\n const setButtonRef = useCallback(\n (button: HTMLButtonElement | null) => {\n buttonRef.current = button;\n clampToViewport();\n },\n [clampToViewport],\n );\n\n useEffect(() => {\n window.addEventListener(\"resize\", clampToViewport);\n return () => window.removeEventListener(\"resize\", clampToViewport);\n }, [clampToViewport]);\n\n const onPointerMove = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const drag = dragRef.current;\n const button = buttonRef.current;\n if (!drag || !button || drag.pointerId !== event.pointerId) return;\n if (!drag.moved && Math.hypot(event.clientX - drag.startX, event.clientY - drag.startY) < DRAG_THRESHOLD_PX) {\n return;\n }\n drag.moved = true;\n setPosition(clampTriggerPosition({ x: event.clientX - drag.offsetX, y: event.clientY - drag.offsetY }, button));\n }, []);\n\n const endDrag = useCallback((event: ReactPointerEvent<HTMLButtonElement>) => {\n const drag = dragRef.current;\n if (!drag || drag.pointerId !== event.pointerId) return;\n dragRef.current = null;\n buttonRef.current?.releasePointerCapture(event.pointerId);\n if (!drag.moved) return;\n suppressClickRef.current = true;\n setPosition((current) => {\n if (current && typeof window !== \"undefined\") {\n try {\n window.localStorage.setItem(TRIGGER_POSITION_STORAGE_KEY, JSON.stringify(current));\n } catch {}\n }\n return current;\n });\n }, []);\n\n const consumeDragClick = useCallback(() => {\n if (!suppressClickRef.current) return false;\n suppressClickRef.current = false;\n return true;\n }, []);\n\n const positionStyle: CSSProperties = position\n ? { left: position.x, top: position.y, right: \"auto\", bottom: \"auto\" }\n : {};\n\n return {\n buttonRef: setButtonRef,\n positionStyle,\n triggerHandlers: { onPointerDown, onPointerMove, onPointerUp: endDrag, onPointerCancel: endDrag },\n consumeDragClick,\n };\n}\n\nfunction readStoredTriggerHidden(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n return window.localStorage.getItem(TRIGGER_HIDDEN_STORAGE_KEY) === \"1\";\n } catch {\n return false;\n }\n}\n\nfunction isToggleLauncherShortcut(event: KeyboardEvent): boolean {\n // Option/Alt remaps event.key (Option+S is \"ß\" on US Mac), so match the physical key.\n if (event.shiftKey || !event.altKey || event.code !== \"KeyS\") return false;\n return event.ctrlKey || event.metaKey;\n}\n\nfunction useLauncherVisibility({\n launcher,\n hidden: hiddenProp,\n onHiddenChange,\n onHide,\n}: Pick<SQLiteSyncDevtoolsProps, \"hidden\" | \"onHiddenChange\"> & { launcher: boolean; onHide: () => void }) {\n const isControlled = hiddenProp !== undefined;\n const [uncontrolledHidden, setUncontrolledHidden] = useState(readStoredTriggerHidden);\n const hidden = !launcher || (isControlled ? hiddenProp : uncontrolledHidden);\n const canToggle = launcher && (!isControlled || onHiddenChange !== undefined);\n\n const setHidden = useCallback(\n (next: boolean) => {\n if (next) onHide();\n if (isControlled) {\n onHiddenChange?.(next);\n return;\n }\n setUncontrolledHidden(next);\n try {\n window.localStorage.setItem(TRIGGER_HIDDEN_STORAGE_KEY, next ? \"1\" : \"0\");\n } catch {}\n },\n [isControlled, onHiddenChange, onHide],\n );\n\n useEffect(() => {\n if (!canToggle) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (!isToggleLauncherShortcut(event)) return;\n event.preventDefault();\n setHidden(!hidden);\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, [canToggle, hidden, setHidden]);\n\n return { hidden, setHidden, canToggle };\n}\n\nfunction useOpenState({ open: openProp, onOpenChange }: Pick<SQLiteSyncDevtoolsProps, \"open\" | \"onOpenChange\">) {\n const isControlled = openProp !== undefined;\n const [uncontrolledOpen, setUncontrolledOpen] = useState(false);\n const isOpen = isControlled ? openProp : uncontrolledOpen;\n\n const setIsOpen = useCallback(\n (next: boolean) => {\n if (!isControlled) setUncontrolledOpen(next);\n onOpenChange?.(next);\n },\n [isControlled, onOpenChange],\n );\n\n return { isOpen, setIsOpen };\n}\n\nexport function SQLiteSyncDevtools({\n className,\n launcher = true,\n hidden: hiddenProp,\n onHiddenChange,\n open: openProp,\n onOpenChange,\n}: SQLiteSyncDevtoolsProps) {\n const registry = getOrCreateSQLiteSyncDevtoolsRegistry();\n const snapshot = useSyncExternalStore(registry.subscribe, registry.getSnapshot, getEmptySnapshot);\n const instances = snapshot.instances;\n\n const { buttonRef, positionStyle, triggerHandlers, consumeDragClick } = useDraggableTrigger();\n const { isOpen, setIsOpen } = useOpenState({ open: openProp, onOpenChange });\n const closeDialog = useCallback(() => setIsOpen(false), [setIsOpen]);\n const { hidden, setHidden, canToggle } = useLauncherVisibility({\n launcher,\n hidden: hiddenProp,\n onHiddenChange,\n onHide: closeDialog,\n });\n\n const [activeTab, setActiveTab] = useState<DevtoolsTab>(\"overview\");\n const [selectedInstanceId, setSelectedInstanceId] = useState<string>(\"\");\n const [queryTarget, setQueryTarget] = useState<QueryTarget>(\"memory\");\n const [query, setQuery] = useState(\"\");\n const [queryState, setQueryState] = useState<QueryState>({\n status: \"idle\",\n });\n\n useEffect(() => {\n if (!isOpen) return;\n\n const onKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n closeDialog();\n }\n };\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => {\n window.removeEventListener(\"keydown\", onKeyDown);\n };\n }, [isOpen, closeDialog]);\n\n useEffect(() => {\n if (instances.length === 0) {\n setSelectedInstanceId(\"\");\n return;\n }\n\n if (instances.some((instance) => instance.instanceId === selectedInstanceId)) {\n return;\n }\n\n setSelectedInstanceId(instances[0]?.instanceId ?? \"\");\n }, [instances, selectedInstanceId]);\n\n const dbIdCounts = useMemo(() => {\n const counts = new Map<string, number>();\n\n for (const instance of instances) {\n counts.set(instance.dbId, (counts.get(instance.dbId) ?? 0) + 1);\n }\n\n return counts;\n }, [instances]);\n\n const selectedInstance = useMemo(() => {\n return instances.find((instance) => instance.instanceId === selectedInstanceId) ?? null;\n }, [instances, selectedInstanceId]);\n\n const canRunQuery = selectedInstance !== null && query.trim().length > 0 && queryState.status !== \"running\";\n\n const runQuery = async () => {\n if (!selectedInstance) return;\n\n let normalizedQuery = query.trim();\n\n try {\n normalizedQuery = normalizeSingleStatement(query);\n const statementKind = getStatementKind(normalizedQuery);\n\n if (queryTarget === \"worker\") {\n if (!isWorkerReadOnlyStatement(statementKind)) {\n throw new Error(\"Worker DB devtools only allows read-only SQL: SELECT, PRAGMA.\");\n }\n } else {\n const touchedTables = selectedInstance.instance._internal.getMemoryQueryTables(normalizedQuery);\n const writtenTables = touchedTables.filter((table) => table.isWrite).map((table) => table.name);\n const allowedTables = new Set(selectedInstance.instance._internal.crdtTableNames);\n\n const invalidTables = writtenTables.filter((table) => !allowedTables.has(table));\n if (invalidTables.length > 0) {\n throw new Error(\n `Memory DB writes are only allowed for CRDT tables. Rejected tables: ${invalidTables.join(\", \")}`,\n );\n }\n }\n\n setQueryState({ status: \"running\" });\n const startedAt = performance.now();\n\n const result =\n queryTarget === \"memory\"\n ? selectedInstance.instance.db.execute(normalizedQuery)\n : await selectedInstance.instance._internal.executeAsync({\n sql: normalizedQuery,\n parameters: [],\n });\n\n setQueryState({\n status: \"success\",\n output: {\n target: queryTarget,\n sql: normalizedQuery,\n rowCount: result.rows.length,\n durationMs: Number((performance.now() - startedAt).toFixed(2)),\n rows: result.rows,\n },\n });\n } catch (error) {\n setQueryState({\n status: \"error\",\n error: {\n target: queryTarget,\n sql: normalizedQuery,\n message: error instanceof Error ? error.message : String(error),\n },\n });\n }\n };\n\n return (\n <ShadowRoot className={className}>\n {hidden ? null : (\n <div className=\"floatingRoot\">\n <button\n ref={buttonRef}\n type=\"button\"\n className=\"triggerButton\"\n style={positionStyle}\n onClick={() => {\n if (consumeDragClick()) return;\n setIsOpen(true);\n }}\n title={`SQLite Sync Devtools (${TOGGLE_LAUNCHER_HINT} to hide)`}\n {...triggerHandlers}\n >\n <span className=\"triggerIcon\">◈</span>\n <span className=\"triggerCount\">{instances.length}</span>\n </button>\n </div>\n )}\n\n {isOpen ? (\n <div className=\"overlay\" onClick={closeDialog}>\n <section\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label=\"SQLite Sync devtools\"\n className=\"dialog\"\n onClick={(event) => event.stopPropagation()}\n >\n {/* Dialog header */}\n <div className=\"header\">\n <div className=\"headerLeft\">\n <span className=\"headerLogo\">◈</span>\n <div>\n <div className=\"eyebrow\">sqlite-sync</div>\n <h2 className=\"title\">Devtools</h2>\n </div>\n </div>\n\n <div className=\"headerRight\">\n {instances.length > 0 && (\n <label className=\"instancePickerLabel\">\n <span className=\"instancePickerText\">DB</span>\n <select\n value={selectedInstanceId}\n onChange={(event) => setSelectedInstanceId(event.target.value)}\n className=\"instancePickerSelect\"\n >\n {instances.map((instance) => (\n <option key={instance.instanceId} value={instance.instanceId}>\n {formatInstanceLabel(instance.dbId, instance.instanceId, dbIdCounts.get(instance.dbId) ?? 0)}\n </option>\n ))}\n </select>\n </label>\n )}\n <span className=\"instanceCountBadge\">\n {instances.length} instance{instances.length !== 1 ? \"s\" : \"\"}\n </span>\n {canToggle && (\n <button\n type=\"button\"\n className=\"hideLauncherButton\"\n onClick={() => setHidden(true)}\n title={`Hide launcher (${TOGGLE_LAUNCHER_HINT} to show again)`}\n >\n Hide\n </button>\n )}\n <button type=\"button\" className=\"closeButton\" onClick={closeDialog} aria-label=\"Close\">\n ✕\n </button>\n </div>\n </div>\n\n {instances.length === 0 ? (\n <div className=\"emptyState\">\n <div className=\"emptyStateIcon\">◈</div>\n <p className=\"emptyStateText\">No SQLite Sync database instances registered.</p>\n <p className=\"emptyStateSubtext\">\n Call <code className=\"inlineCode\">registerDevtools(db)</code> in your app to get started.\n </p>\n </div>\n ) : (\n <div className=\"contentLayout\">\n {/* Sidebar nav */}\n <aside className=\"sidebar\">\n <nav className=\"nav\">\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"overview\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"overview\")}\n >\n <span className=\"navIcon\">▦</span>\n Overview\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"schema\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"schema\")}\n >\n <span className=\"navIcon\">⬡</span>\n Schema\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"live-queries\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"live-queries\")}\n >\n <span className=\"navIcon\">◉</span>\n Live Queries\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"event-log\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"event-log\")}\n >\n <span className=\"navIcon\">≡</span>\n Event Log\n </button>\n <button\n type=\"button\"\n className=\"tabButton\"\n data-active={activeTab === \"query-runner\" ? \"true\" : undefined}\n onClick={() => setActiveTab(\"query-runner\")}\n >\n <span className=\"navIcon\">▶</span>\n Query Runner\n </button>\n </nav>\n\n {selectedInstance && (\n <div className=\"sidebarInfo\">\n <div className=\"sidebarInfoLabel\">Active instance</div>\n <div className=\"sidebarInfoValue\">\n {formatInstanceLabel(\n selectedInstance.dbId,\n selectedInstance.instanceId,\n dbIdCounts.get(selectedInstance.dbId) ?? 0,\n )}\n </div>\n <div className=\"sidebarInfoSub\">id: {selectedInstance.instanceId.slice(0, 12)}…</div>\n </div>\n )}\n </aside>\n\n {/* Main pane */}\n <div className=\"mainPane\">\n {activeTab === \"overview\" ? (\n <OverviewTab selectedInstance={selectedInstance} dbIdCounts={dbIdCounts} />\n ) : activeTab === \"schema\" ? (\n <SchemaTab selectedInstance={selectedInstance} />\n ) : activeTab === \"live-queries\" ? (\n <LiveQueriesTab selectedInstance={selectedInstance} />\n ) : activeTab === \"event-log\" ? (\n <EventLogTab selectedInstance={selectedInstance} />\n ) : (\n <QueryRunnerTab\n selectedInstance={selectedInstance}\n queryTarget={queryTarget}\n setQueryTarget={setQueryTarget}\n query={query}\n setQuery={setQuery}\n queryState={queryState}\n canRunQuery={canRunQuery}\n runQuery={runQuery}\n />\n )}\n </div>\n </div>\n )}\n </section>\n </div>\n ) : null}\n </ShadowRoot>\n );\n}\n\nconst STATE_HASH_KV_KEY = \"crdt.consistency.state_hash.v1\";\nconst STATE_HASH_QUERY = `SELECT value FROM \"worker\".\"kv\" WHERE key = '${STATE_HASH_KV_KEY}'`;\nconst EVENT_STATUS_COUNTS_QUERY = `SELECT status, COUNT(*) AS count FROM \"worker\".\"crdt_events\" GROUP BY status`;\nconst MEMORY_DB_SIZE_QUERY =\n \"SELECT (SELECT page_count FROM pragma_page_count()) * (SELECT page_size FROM pragma_page_size()) AS bytes\";\n// Persisted main file plus the attached worker schema (event log, kv).\nconst WORKER_DB_SIZE_QUERY = `SELECT\n (SELECT page_count FROM pragma_page_count('main')) * (SELECT page_size FROM pragma_page_size('main'))\n + (SELECT page_count FROM pragma_page_count('worker')) * (SELECT page_size FROM pragma_page_size('worker'))\n AS bytes`;\n\ntype EventStatus = \"pending\" | \"applied\" | \"failed\" | \"deduped\";\ntype EventStatusCounts = { total: number } & Record<EventStatus, number>;\n\nconst EVENT_STATUS_META: Record<EventStatus, { label: string; tone: \"amber\" | \"success\" | \"error\" | \"muted\" }> = {\n pending: { label: \"Pending\", tone: \"amber\" },\n applied: { label: \"Applied\", tone: \"success\" },\n failed: { label: \"Failed\", tone: \"error\" },\n deduped: { label: \"Deduped\", tone: \"muted\" },\n};\n\nfunction isEventStatus(value: unknown): value is EventStatus {\n return value === \"pending\" || value === \"applied\" || value === \"failed\" || value === \"deduped\";\n}\n\nfunction emptyEventStatusCounts(): EventStatusCounts {\n return { total: 0, pending: 0, applied: 0, failed: 0, deduped: 0 };\n}\n\nfunction parseEventStatusCounts(rows: readonly unknown[]): EventStatusCounts {\n const counts = emptyEventStatusCounts();\n\n for (const row of rows) {\n if (typeof row !== \"object\" || row === null || !(\"status\" in row) || !(\"count\" in row)) {\n continue;\n }\n const { status, count } = row;\n if (!isEventStatus(status)) continue;\n const n = typeof count === \"number\" ? count : Number(count);\n if (!Number.isFinite(n)) continue;\n counts[status] = n;\n counts.total += n;\n }\n\n return counts;\n}\n\nfunction readCount(rows: readonly unknown[]): number {\n const row = rows[0];\n if (typeof row !== \"object\" || row === null || !(\"count\" in row)) return 0;\n const n = typeof row.count === \"number\" ? row.count : Number(row.count);\n return Number.isFinite(n) ? n : 0;\n}\n\nfunction readBytes(rows: readonly unknown[]): number | null {\n const row = rows[0];\n if (typeof row !== \"object\" || row === null || !(\"bytes\" in row)) return null;\n const n = typeof row.bytes === \"number\" ? row.bytes : Number(row.bytes);\n return Number.isFinite(n) ? n : null;\n}\n\nfunction formatByteSize(bytes: number): { label: string; exact: string } {\n const exact = `${bytes.toLocaleString(\"en-US\")} B`;\n if (bytes < 1024) return { label: exact, exact };\n\n const units = [\"KB\", \"MB\", \"GB\", \"TB\"] as const;\n let value = bytes / 1024;\n let unitIndex = 0;\n while (value >= 1024 && unitIndex < units.length - 1) {\n value /= 1024;\n unitIndex += 1;\n }\n const decimals = value >= 100 ? 0 : value >= 10 ? 1 : 2;\n return { label: `${Number(value.toFixed(decimals))} ${units[unitIndex]}`, exact };\n}\n\nfunction OverviewTab({\n selectedInstance,\n dbIdCounts,\n}: {\n selectedInstance: SQLiteSyncDevtoolsInstance | null;\n dbIdCounts: Map<string, number>;\n}) {\n const [stateHash, setStateHash] = useState<string | null>(null);\n const [stateHashError, setStateHashError] = useState<string | null>(null);\n const [isStateHashLoading, setIsStateHashLoading] = useState(false);\n const [eventCounts, setEventCounts] = useState<EventStatusCounts | null>(null);\n const [eventCountsError, setEventCountsError] = useState<string | null>(null);\n const [isEventCountsLoading, setIsEventCountsLoading] = useState(false);\n const [memoryBytes, setMemoryBytes] = useState<number | null>(null);\n const [memorySizeError, setMemorySizeError] = useState<string | null>(null);\n const [workerBytes, setWorkerBytes] = useState<number | null>(null);\n const [workerSizeError, setWorkerSizeError] = useState<string | null>(null);\n const [isSizeLoading, setIsSizeLoading] = useState(false);\n\n const refreshStateHash = useCallback(async () => {\n if (!selectedInstance) return;\n setIsStateHashLoading(true);\n setStateHashError(null);\n try {\n const result = await selectedInstance.instance._internal.executeAsync({\n sql: STATE_HASH_QUERY,\n parameters: [],\n });\n const row = result.rows[0];\n const value =\n typeof row === \"object\" && row !== null && \"value\" in row && typeof row.value === \"string\" ? row.value : \"\";\n setStateHash(value);\n } catch (error) {\n setStateHashError(error instanceof Error ? error.message : String(error));\n setStateHash(null);\n } finally {\n setIsStateHashLoading(false);\n }\n }, [selectedInstance]);\n\n const refreshEventCounts = useCallback(async () => {\n if (!selectedInstance) return;\n setIsEventCountsLoading(true);\n setEventCountsError(null);\n try {\n const result = await selectedInstance.instance._internal.executeAsync({\n sql: EVENT_STATUS_COUNTS_QUERY,\n parameters: [],\n });\n setEventCounts(parseEventStatusCounts(result.rows));\n } catch (error) {\n setEventCountsError(error instanceof Error ? error.message : String(error));\n setEventCounts(null);\n } finally {\n setIsEventCountsLoading(false);\n }\n }, [selectedInstance]);\n\n const refreshDbSizes = useCallback(async () => {\n if (!selectedInstance) return;\n setIsSizeLoading(true);\n setMemorySizeError(null);\n setWorkerSizeError(null);\n\n const memoryResult = Promise.resolve()\n .then(() => selectedInstance.instance.db.execute(MEMORY_DB_SIZE_QUERY))\n .then((result) => {\n const bytes = readBytes(result.rows);\n if (bytes === null) throw new Error(\"Memory DB did not return a size.\");\n return bytes;\n });\n const workerResult = selectedInstance.instance._internal\n .executeAsync({ sql: WORKER_DB_SIZE_QUERY, parameters: [] })\n .then((result) => {\n const bytes = readBytes(result.rows);\n if (bytes === null) throw new Error(\"Worker DB did not return a size.\");\n return bytes;\n });\n\n const [memorySettled, workerSettled] = await Promise.allSettled([memoryResult, workerResult]);\n if (memorySettled.status === \"fulfilled\") {\n setMemoryBytes(memorySettled.value);\n } else {\n setMemoryBytes(null);\n setMemorySizeError(\n memorySettled.reason instanceof Error ? memorySettled.reason.message : String(memorySettled.reason),\n );\n }\n if (workerSettled.status === \"fulfilled\") {\n setWorkerBytes(workerSettled.value);\n } else {\n setWorkerBytes(null);\n setWorkerSizeError(\n workerSettled.reason instanceof Error ? workerSettled.reason.message : String(workerSettled.reason),\n );\n }\n setIsSizeLoading(false);\n }, [selectedInstance]);\n\n useEffect(() => {\n setStateHash(null);\n setStateHashError(null);\n setEventCounts(null);\n setEventCountsError(null);\n setMemoryBytes(null);\n setMemorySizeError(null);\n setWorkerBytes(null);\n setWorkerSizeError(null);\n void refreshStateHash();\n void refreshEventCounts();\n void refreshDbSizes();\n }, [refreshStateHash, refreshEventCounts, refreshDbSizes]);\n\n if (!selectedInstance) return null;\n\n const label = formatInstanceLabel(\n selectedInstance.dbId,\n selectedInstance.instanceId,\n dbIdCounts.get(selectedInstance.dbId) ?? 0,\n );\n\n return (\n <div className=\"overviewLayout\">\n <div className=\"overviewCardsRow\">\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">Database</div>\n <div className=\"overviewCardValue\">{label}</div>\n </div>\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">Instance ID</div>\n <div className=\"overviewCardValue mono sm\">{selectedInstance.instanceId.slice(0, 16)}…</div>\n </div>\n <DbSizeCard label=\"Memory DB\" bytes={memoryBytes} error={memorySizeError} loading={isSizeLoading} />\n <DbSizeCard label=\"Worker DB\" bytes={workerBytes} error={workerSizeError} loading={isSizeLoading} />\n <div className=\"overviewCard\">\n <div className=\"overviewCardLabel\">CRDT Events</div>\n <div className=\"overviewCardValue\">\n {eventCountsError ? \"—\" : isEventCountsLoading && eventCounts === null ? \"…\" : (eventCounts?.total ?? 0)}\n </div>\n </div>\n </div>\n\n <div className=\"overviewSection\">\n <div className=\"overviewSectionHeader\">\n <div className=\"overviewSectionTitle\">CRDT events</div>\n <button\n type=\"button\"\n className=\"refreshButton\"\n disabled={isEventCountsLoading || isSizeLoading}\n title=\"Refresh event counts and DB sizes\"\n onClick={() => {\n void refreshEventCounts();\n void refreshDbSizes();\n }}\n >\n {isEventCountsLoading || isSizeLoading ? \"…\" : \"↻\"} Refresh\n </button>\n </div>\n {eventCountsError ? (\n <div className=\"overviewAccumulatorError\">{eventCountsError}</div>\n ) : (\n <div className=\"eventCountGrid\">\n {([\"pending\", \"applied\", \"failed\", \"deduped\"] satisfies EventStatus[]).map((status) => {\n const item = EVENT_STATUS_META[status];\n const value = eventCounts?.[status] ?? 0;\n return (\n <div key={status} className=\"eventCountCard\">\n <div\n className=\"eventCountValue\"\n data-tone={item.tone}\n data-emphasize={value > 0 ? \"true\" : undefined}\n >\n {isEventCountsLoading && eventCounts === null ? \"…\" : value}\n </div>\n <div className=\"overviewCardLabel\">{item.label}</div>\n </div>\n );\n })}\n </div>\n )}\n <div className=\"overviewEmpty\">Counts are remaining worker log rows after GC, not lifetime history.</div>\n </div>\n\n <div className=\"overviewSection\">\n <div className=\"overviewSectionHeader\">\n <div className=\"overviewSectionTitle\">State hash</div>\n <button\n type=\"button\"\n className=\"refreshButton\"\n disabled={isStateHashLoading}\n onClick={() => void refreshStateHash()}\n >\n {isStateHashLoading ? \"…\" : \"↻\"} Refresh\n </button>\n </div>\n <div className=\"overviewAccumulatorValue\">\n {stateHashError ? (\n <span className=\"overviewAccumulatorError\">{stateHashError}</span>\n ) : isStateHashLoading && stateHash === null ? (\n \"Loading…\"\n ) : stateHash === \"\" ? (\n <span className=\"overviewAccumulatorEmpty\">(empty)</span>\n ) : (\n stateHash\n )}\n </div>\n </div>\n\n <DataSection\n key={selectedInstance.instanceId}\n dbId={selectedInstance.dbId}\n instance={selectedInstance.instance}\n />\n\n <ResetSection dbId={selectedInstance.dbId} instance={selectedInstance.instance} />\n </div>\n );\n}\n\nfunction DbSizeCard({\n label,\n bytes,\n error,\n loading,\n}: {\n label: string;\n bytes: number | null;\n error: string | null;\n loading: boolean;\n}) {\n let value = \"…\";\n let sub: string | undefined;\n let title: string | undefined;\n\n if (error) {\n value = \"—\";\n title = error;\n } else if (bytes !== null) {\n const formatted = formatByteSize(bytes);\n value = formatted.label;\n title = formatted.exact;\n sub = formatted.label === formatted.exact ? undefined : formatted.exact;\n } else if (!loading) {\n value = \"—\";\n }\n\n return (\n <div className=\"overviewCard\" title={title}>\n <div className=\"overviewCardLabel\">{label}</div>\n <div className=\"overviewCardValue mono\">{value}</div>\n {sub ? <div className=\"overviewCardSub\">{sub}</div> : null}\n </div>\n );\n}\n\nfunction DataSection({ dbId, instance }: { dbId: string; instance: SQLiteSyncDevtoolsInstance[\"instance\"] }) {\n const fileInputRef = useRef<HTMLInputElement>(null);\n const [isImporting, setIsImporting] = useState(false);\n const [status, setStatus] = useState<{ kind: \"success\" | \"error\"; message: string } | null>(null);\n\n const handleExport = () => {\n try {\n const data = instance.exportData();\n const json = JSON.stringify(data, null, 2);\n const blob = new Blob([json], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `${dbId}-${data.exportedAt.replace(/[:.]/g, \"-\")}.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n const rowCount = Object.values(data.tables).reduce((sum, rows) => sum + rows.length, 0);\n setStatus({ kind: \"success\", message: `Exported ${rowCount} row${rowCount === 1 ? \"\" : \"s\"}.` });\n } catch (error) {\n setStatus({ kind: \"error\", message: error instanceof Error ? error.message : String(error) });\n }\n };\n\n const handleImportFile = async (file: File) => {\n setIsImporting(true);\n setStatus(null);\n try {\n const data = JSON.parse(await file.text()) as SyncedDbExport;\n const result = await instance.importData(data);\n setStatus({ kind: \"success\", message: `Imported ${result.imported} row${result.imported === 1 ? \"\" : \"s\"}.` });\n } catch (error) {\n setStatus({ kind: \"error\", message: error instanceof Error ? error.message : String(error) });\n } finally {\n setIsImporting(false);\n }\n };\n\n return (\n <div className=\"overviewSection\">\n <div className=\"overviewSectionTitle\">Backup & Restore</div>\n <div className=\"dangerZoneDesc\">\n Export the active rows of every CRDT table as JSON, or import a dump to seed/restore. Import overwrites rows\n with matching ids and is propagated to the server.\n </div>\n <div className=\"dataActions\">\n <button type=\"button\" className=\"dataButton\" onClick={handleExport}>\n ↓ Export JSON\n </button>\n <button\n type=\"button\"\n className=\"dataButton\"\n disabled={isImporting}\n onClick={() => fileInputRef.current?.click()}\n >\n {isImporting ? \"Importing…\" : \"↑ Import JSON\"}\n </button>\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"application/json,.json\"\n className=\"hiddenInput\"\n onChange={(event) => {\n const file = event.target.files?.[0];\n event.target.value = \"\";\n if (file) void handleImportFile(file);\n }}\n />\n </div>\n {status && (\n <div className={status.kind === \"error\" ? \"dataStatusError\" : \"dataStatusSuccess\"}>{status.message}</div>\n )}\n </div>\n );\n}\n\nfunction ResetSection({ dbId, instance }: { dbId: string; instance: SQLiteSyncDevtoolsInstance[\"instance\"] }) {\n const [confirming, setConfirming] = useState(false);\n const [isResetting, setIsResetting] = useState(false);\n\n const handleReset = () => {\n setIsResetting(true);\n // Worker-owned clean reset: durably records a reset epoch, broadcasts a\n // reload to all tabs, and the next elected worker wipes the persisted DB.\n // The promise may never settle — the page unloads first.\n void instance.requestReload({ clean: true });\n };\n\n return (\n <div className=\"dangerZone\">\n <div className=\"dangerZoneTitle\">Danger Zone</div>\n <div className=\"dangerZoneRow\">\n <div className=\"dangerZoneDesc\">\n Requests a clean reload, so <code className=\"inlineCode\">{dbId}</code> is wiped on next load via{\" \"}\n <code className=\"inlineCode\">clearOnInit</code>, then reloads all tabs.\n </div>\n {confirming ? (\n <div className=\"dangerZoneActions\">\n <button\n type=\"button\"\n className=\"resetCancelButton\"\n disabled={isResetting}\n onClick={() => setConfirming(false)}\n >\n Cancel\n </button>\n <button type=\"button\" className=\"resetConfirmButton\" disabled={isResetting} onClick={handleReset}>\n {isResetting ? \"Resetting…\" : \"Confirm reset\"}\n </button>\n </div>\n ) : (\n <button type=\"button\" className=\"resetButton\" onClick={() => setConfirming(true)}>\n Reset DB\n </button>\n )}\n </div>\n </div>\n );\n}\n\nconst SYSTEM_COLUMNS = new Set([\"id\", \"tombstone\"]);\n\nfunction formatDefaultValue(value: unknown): string {\n if (typeof value === \"string\") return JSON.stringify(value);\n if (typeof value === \"boolean\" || typeof value === \"number\") return String(value);\n if (value === null) return \"null\";\n return JSON.stringify(value);\n}\n\nfunction SchemaTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n if (!selectedInstance) return null;\n\n const { tables, schemaVersion } = selectedInstance.instance._internal;\n const tableEntries = Object.entries(tables);\n\n return (\n <div className=\"schemaLayout\">\n <div className=\"schemaSection\">\n <div className=\"schemaSectionHeader\">\n <div className=\"schemaSectionTitle\">Tables</div>\n <span className=\"schemaBadge\">{tableEntries.length}</span>\n <span className=\"schemaVersionChip mlAuto\" title=\"Latest applied migration version\">\n applied v{schemaVersion}\n </span>\n </div>\n {tableEntries.length === 0 ? (\n <div className=\"schemaEmpty\">No tables declared on this schema.</div>\n ) : (\n <div className=\"schemaTableList\">\n {tableEntries.map(([crdtTableName, table]) => {\n const baseTableName = table.baseName ?? `_${crdtTableName}`;\n const columns = Object.entries(table.columns);\n return (\n <div key={crdtTableName} className=\"schemaTableCard\">\n <div className=\"schemaTableCardHeader\">\n <div className=\"schemaTableCardTitleRow\">\n <div className=\"schemaTableCardName\">{crdtTableName}</div>\n <span className=\"schemaBadge\">{columns.length}</span>\n </div>\n {table.description ? <p className=\"schemaTableCardDescription\">{table.description}</p> : null}\n <div className=\"schemaTableCardMeta\">\n <span className=\"schemaPolicyChip\" title=\"Base table\">\n {baseTableName}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.writeOrigin === \"server\" ? \"warn\" : undefined}\n title=\"Who may write CRDT events\"\n >\n writes {table.writeOrigin}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.aiAccess === \"read-write\" ? undefined : \"warn\"}\n title=\"AI agent access\"\n >\n ai {table.aiAccess}\n </span>\n <span\n className=\"schemaPolicyChip\"\n data-tone={table.exportImport === \"ignore\" ? \"warn\" : undefined}\n title=\"Export / import\"\n >\n export {table.exportImport}\n </span>\n </div>\n </div>\n <div className=\"schemaColumnGrid\">\n <div className=\"schemaColumnRow schemaColumnHeaderRow\">\n <div className=\"schemaColHeader\">Column</div>\n <div className=\"schemaColHeader\">Type</div>\n <div className=\"schemaColHeader\">Flags</div>\n <div className=\"schemaColHeader\">Description</div>\n </div>\n {columns.map(([name, meta]) => (\n <SchemaColumnRow key={name} name={name} meta={meta} />\n ))}\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction SchemaColumnRow({ name, meta }: { name: string; meta: ColumnMeta }) {\n const flags: string[] = [];\n if (name === \"id\") flags.push(\"pk\");\n if (meta.nullable) flags.push(\"nullable\");\n if (meta.hasDefault) flags.push(`default ${formatDefaultValue(meta.defaultValue)}`);\n\n return (\n <div className=\"schemaColumnRow\" data-system={SYSTEM_COLUMNS.has(name) ? \"true\" : undefined}>\n <div className=\"schemaColumnName\">{name}</div>\n <div className=\"schemaColumnType\">\n <span>{meta.kind}</span>\n {meta.kind === \"boolean\" ? <span className=\"schemaColumnTypeDetail\">integer 0/1</span> : null}\n {meta.kind === \"enum\" && meta.enumValues && meta.enumValues.length > 0 ? (\n <span className=\"schemaColumnTypeDetail\">{meta.enumValues.map((value) => `\"${value}\"`).join(\" | \")}</span>\n ) : null}\n </div>\n <div className=\"schemaColumnFlags\">{flags.length > 0 ? flags.join(\" · \") : \"—\"}</div>\n <div className=\"schemaColumnDescription\">{meta.description ?? \"\"}</div>\n </div>\n );\n}\n\nfunction LiveQueriesTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n const [queries, setQueries] = useState<SharedLiveQuerySnapshot[]>([]);\n\n const refresh = useCallback(() => {\n if (!selectedInstance) {\n setQueries([]);\n return;\n }\n\n setQueries(\n selectedInstance.instance._internal\n .getSharedLiveQueriesSnapshot()\n .sort(\n (a, b) =>\n a.sql.localeCompare(b.sql) ||\n formatLiveQueryParameters(a.parameters).localeCompare(formatLiveQueryParameters(b.parameters)),\n ),\n );\n }, [selectedInstance]);\n\n useEffect(() => {\n refresh();\n }, [refresh]);\n\n const totalSubscribers = queries.reduce((total, query) => total + query.subscriberCount, 0);\n\n return (\n <div className=\"schemaLayout\">\n <div className=\"schemaSection\">\n <div className=\"schemaSectionHeader\">\n <div className=\"schemaSectionTitle\">Shared Live Queries</div>\n <span className=\"schemaBadge\">{queries.length}</span>\n <span className=\"schemaVersionChip\">\n {totalSubscribers} subscriber{totalSubscribers !== 1 ? \"s\" : \"\"}\n </span>\n <button type=\"button\" className=\"refreshButton mlAuto\" onClick={refresh} disabled={!selectedInstance}>\n ↻ Refresh\n </button>\n </div>\n {queries.length === 0 ? (\n <div className=\"schemaEmpty\">\n No active live queries. Queries created via <code className=\"inlineCode\">useDbQuery</code> appear here while\n components are subscribed.\n </div>\n ) : (\n <div className=\"schemaTableGrid\">\n <div className=\"liveQueryHeaderRow\">\n <div className=\"schemaColHeader\">SQL</div>\n <div className=\"schemaColHeader\">Parameters</div>\n <div className=\"schemaColHeader alignCenter\">Subscribers</div>\n </div>\n {queries.map((query) => {\n const parameters = formatLiveQueryParameters(query.parameters);\n return (\n <div key={`${query.sql}|${parameters}`} className=\"liveQueryRow\">\n <div className=\"liveQuerySql\">{query.sql}</div>\n <div className=\"liveQueryParameters\">{parameters}</div>\n <div className=\"schemaStatusCell\">\n <span className={query.subscriberCount > 0 ? \"schemaActiveTag\" : \"liveQueryIdleTag\"}>\n {query.subscriberCount}\n </span>\n </div>\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction formatLiveQueryParameters(parameters: readonly unknown[]): string {\n try {\n return JSON.stringify(parameters);\n } catch {\n return String(parameters);\n }\n}\n\ntype PersistedCrdtEvent = {\n sync_id: number;\n schema_version: number;\n status: \"pending\" | \"applied\" | \"failed\" | \"deduped\";\n type: \"item-created\" | \"item-updated\" | \"item-deleted\";\n timestamp: string;\n origin: \"remote\" | \"own\" | \"local\";\n source_node_id: string;\n dataset: string;\n item_id: string;\n payload: string;\n};\n\nfunction isPersistedCrdtEvent(value: unknown): value is PersistedCrdtEvent {\n if (typeof value !== \"object\" || value === null) return false;\n return (\n \"sync_id\" in value &&\n typeof value.sync_id === \"number\" &&\n \"status\" in value &&\n typeof value.status === \"string\" &&\n \"type\" in value &&\n typeof value.type === \"string\" &&\n \"origin\" in value &&\n typeof value.origin === \"string\" &&\n \"dataset\" in value &&\n typeof value.dataset === \"string\" &&\n \"item_id\" in value &&\n typeof value.item_id === \"string\" &&\n \"payload\" in value &&\n typeof value.payload === \"string\" &&\n \"timestamp\" in value &&\n typeof value.timestamp === \"string\"\n );\n}\n\ntype EventLogFilters = {\n dataset: string;\n origin: string;\n status: string;\n};\n\nconst PAGE_SIZE = 50;\n\nfunction sqlStringLiteral(value: string): string {\n return `'${value.replaceAll(\"'\", \"''\")}'`;\n}\n\nfunction eventLogWhereClause(filters: EventLogFilters, afterSyncId: number | null): string {\n const conditions: string[] = [];\n\n if (filters.dataset) conditions.push(`dataset = ${sqlStringLiteral(filters.dataset)}`);\n if (filters.origin) conditions.push(`origin = ${sqlStringLiteral(filters.origin)}`);\n if (filters.status) conditions.push(`status = ${sqlStringLiteral(filters.status)}`);\n if (afterSyncId !== null) conditions.push(`sync_id < ${afterSyncId}`);\n\n return conditions.length > 0 ? `WHERE ${conditions.join(\" AND \")}` : \"\";\n}\n\nfunction buildEventLogQuery(filters: EventLogFilters, afterSyncId: number | null): string {\n return `SELECT * FROM \"worker\".\"crdt_events\" ${eventLogWhereClause(filters, afterSyncId)} ORDER BY sync_id DESC LIMIT ${PAGE_SIZE + 1}`;\n}\n\nfunction buildEventLogCountQuery(filters: EventLogFilters): string {\n return `SELECT COUNT(*) AS count FROM \"worker\".\"crdt_events\" ${eventLogWhereClause(filters, null)}`;\n}\n\nfunction EventLogTab({ selectedInstance }: { selectedInstance: SQLiteSyncDevtoolsInstance | null }) {\n const baseTableNames = useMemo(\n () => selectedInstance?.instance._internal.crdtTablesConfig.map((table) => table.baseTableName) ?? [],\n [selectedInstance],\n );\n\n const [filters, setFilters] = useState<EventLogFilters>({ dataset: \"\", origin: \"\", status: \"\" });\n const [events, setEvents] = useState<PersistedCrdtEvent[]>([]);\n const [totalCount, setTotalCount] = useState<number | null>(null);\n const [hasMore, setHasMore] = useState(false);\n const [isLoading, setIsLoading] = useState(false);\n const [expandedId, setExpandedId] = useState<number | null>(null);\n const afterSyncIdRef = useRef<number | null>(null);\n const isLoadingRef = useRef(false);\n\n const executeRows = useCallback(\n async (sql: string): Promise<unknown[]> => {\n if (!selectedInstance) return [];\n const result = await selectedInstance.instance._internal.executeAsync({ sql, parameters: [] });\n return result.rows;\n },\n [selectedInstance],\n );\n\n const load = useCallback(\n async (reset: boolean, currentFilters: EventLogFilters) => {\n if (!selectedInstance || isLoadingRef.current) return;\n isLoadingRef.current = true;\n setIsLoading(true);\n try {\n const afterSyncId = reset ? null : afterSyncIdRef.current;\n const sql = buildEventLogQuery(currentFilters, afterSyncId);\n const rowsPromise = executeRows(sql);\n const countPromise = reset ? executeRows(buildEventLogCountQuery(currentFilters)) : Promise.resolve(null);\n const [rows, countRows] = await Promise.all([rowsPromise, countPromise]);\n const page = rows.filter(isPersistedCrdtEvent).slice(0, PAGE_SIZE);\n setHasMore(rows.length > PAGE_SIZE);\n if (reset) {\n setEvents(page);\n setTotalCount(countRows ? readCount(countRows) : null);\n } else {\n setEvents((prev) => [...prev, ...page]);\n }\n afterSyncIdRef.current = page.at(-1)?.sync_id ?? null;\n } finally {\n isLoadingRef.current = false;\n setIsLoading(false);\n }\n },\n [selectedInstance, executeRows],\n );\n\n // Initial load and reload on instance or filter change\n useEffect(() => {\n afterSyncIdRef.current = null;\n setEvents([]);\n setTotalCount(null);\n void load(true, filters);\n }, [filters, load]);\n\n const applyFilters = (next: EventLogFilters) => {\n setFilters(next);\n };\n\n if (!selectedInstance) return null;\n\n return (\n <div className=\"eventLogLayout\">\n {/* Toolbar */}\n <div className=\"eventLogToolbar\">\n <select\n value={filters.dataset}\n onChange={(e) => applyFilters({ ...filters, dataset: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All datasets</option>\n {baseTableNames.map((name) => (\n <option key={name} value={name}>\n {name}\n </option>\n ))}\n </select>\n <select\n value={filters.origin}\n onChange={(e) => applyFilters({ ...filters, origin: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All origins</option>\n <option value=\"own\">own</option>\n <option value=\"remote\">remote</option>\n <option value=\"local\">local</option>\n </select>\n <select\n value={filters.status}\n onChange={(e) => applyFilters({ ...filters, status: e.target.value })}\n className=\"eventLogFilterSelect\"\n >\n <option value=\"\">All statuses</option>\n <option value=\"applied\">applied</option>\n <option value=\"pending\">pending</option>\n <option value=\"failed\">failed</option>\n <option value=\"deduped\">deduped</option>\n </select>\n <button type=\"button\" className=\"refreshButton\" disabled={isLoading} onClick={() => void load(true, filters)}>\n {isLoading ? \"…\" : \"↻\"} Refresh\n </button>\n {totalCount !== null && (\n <span className=\"eventLogCount\">\n {events.length === totalCount\n ? `${totalCount} event${totalCount === 1 ? \"\" : \"s\"}`\n : `${events.length} of ${totalCount}`}\n </span>\n )}\n </div>\n\n {/* Event list */}\n {events.length === 0 && !isLoading ? (\n <div className=\"eventLogEmpty\">No events match the current filters.</div>\n ) : (\n <div className=\"eventLogList\">\n {events.map((event) => {\n const isExpanded = expandedId === event.sync_id;\n return (\n <div key={event.sync_id} className=\"eventRow\" data-expanded={isExpanded ? \"true\" : undefined}>\n <button\n type=\"button\"\n className=\"eventRowHeader\"\n onClick={() => setExpandedId(isExpanded ? null : event.sync_id)}\n >\n <span className=\"eventSyncId\">#{event.sync_id}</span>\n <EventTypeBadge type={event.type} />\n <EventOriginBadge origin={event.origin} />\n <EventStatusBadge status={event.status} />\n <span className=\"eventDataset\">{event.dataset}</span>\n <span className=\"eventItemId\">{event.item_id}</span>\n <span className=\"eventTimestamp\">{formatHlcTimestamp(event.timestamp)}</span>\n <span className=\"eventChevron\">{isExpanded ? \"▲\" : \"▼\"}</span>\n </button>\n\n {isExpanded && (\n <div className=\"eventPayload\">\n <div className=\"eventPayloadMeta\">\n <span className=\"eventMetaItem\">schema v{event.schema_version}</span>\n <span className=\"eventMetaItem\">node: {event.source_node_id || \"—\"}</span>\n <span className=\"eventMetaItem\">ts: {event.timestamp}</span>\n </div>\n <pre className=\"eventPayloadPre\">{formatPayload(event.payload)}</pre>\n </div>\n )}\n </div>\n );\n })}\n\n {hasMore && (\n <button\n type=\"button\"\n className=\"loadMoreButton\"\n disabled={isLoading}\n onClick={() => void load(false, filters)}\n >\n {isLoading ? \"Loading…\" : `Load ${PAGE_SIZE} more`}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n\nfunction EventTypeBadge({ type }: { type: string }) {\n const { variant, label } =\n type === \"item-created\"\n ? { variant: \"create\", label: \"create\" }\n : type === \"item-deleted\"\n ? { variant: \"delete\", label: \"delete\" }\n : { variant: \"update\", label: \"update\" };\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {label}\n </span>\n );\n}\n\nfunction EventOriginBadge({ origin }: { origin: string }) {\n const variant = origin === \"own\" ? \"own\" : origin === \"remote\" ? \"remote\" : \"local\";\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {origin}\n </span>\n );\n}\n\nfunction EventStatusBadge({ status }: { status: string }) {\n const variant =\n status === \"applied\" ? \"applied\" : status === \"pending\" ? \"pending\" : status === \"failed\" ? \"failed\" : \"skipped\";\n return (\n <span className=\"eventBadge\" data-variant={variant}>\n {status}\n </span>\n );\n}\n\nfunction formatHlcTimestamp(ts: string): string {\n // HLC format: \"<unix_ms>-<counter>-<node>\" or just an ISO string\n const ms = Number(ts.split(\"-\")[0]);\n if (!Number.isNaN(ms) && ms > 1e12) {\n return new Date(ms).toLocaleTimeString();\n }\n return ts.slice(0, 19).replace(\"T\", \" \");\n}\n\nfunction formatPayload(raw: string): string {\n try {\n return JSON.stringify(JSON.parse(raw), null, 2);\n } catch {\n return raw;\n }\n}\n\nfunction QueryRunnerTab({\n selectedInstance,\n queryTarget,\n setQueryTarget,\n query,\n setQuery,\n queryState,\n canRunQuery,\n runQuery,\n}: {\n selectedInstance: unknown;\n queryTarget: QueryTarget;\n setQueryTarget: (t: QueryTarget) => void;\n query: string;\n setQuery: (q: string) => void;\n queryState: QueryState;\n canRunQuery: boolean;\n runQuery: () => Promise<void>;\n}) {\n return (\n <div className=\"queryRunnerLayout\">\n {/* Top toolbar */}\n <div className=\"queryToolbar\">\n <div className=\"targetToggle\">\n <button\n type=\"button\"\n className=\"targetButton\"\n data-active={queryTarget === \"memory\" ? \"true\" : undefined}\n onClick={() => setQueryTarget(\"memory\")}\n >\n Memory DB\n </button>\n <button\n type=\"button\"\n className=\"targetButton\"\n data-active={queryTarget === \"worker\" ? \"true\" : undefined}\n onClick={() => setQueryTarget(\"worker\")}\n >\n Worker DB\n </button>\n </div>\n\n <div className=\"queryToolbarRight\">\n {!selectedInstance && <span className=\"noInstanceWarning\">No instance selected</span>}\n <span className=\"shortcutHint\">⌘↵ to run</span>\n <button\n type=\"button\"\n className=\"runButton\"\n data-enabled={canRunQuery ? \"true\" : undefined}\n data-running={queryState.status === \"running\" ? \"true\" : undefined}\n disabled={!canRunQuery}\n onClick={() => void runQuery()}\n >\n {queryState.status === \"running\" ? (\n <>\n <span className=\"runningDot\" />\n Running…\n </>\n ) : (\n <>▶ Run</>\n )}\n </button>\n </div>\n </div>\n\n {/* SQL textarea */}\n <div className=\"editorWrapper\">\n <textarea\n value={query}\n onChange={(event) => setQuery(event.target.value)}\n onKeyDown={(event) => {\n if ((event.metaKey || event.ctrlKey) && event.key === \"Enter\" && canRunQuery) {\n event.preventDefault();\n void runQuery();\n }\n }}\n className=\"textarea\"\n placeholder=\"SELECT * FROM your_table LIMIT 100\"\n spellCheck={false}\n />\n </div>\n\n {/* Constraint hint */}\n <div className=\"helperText\">\n {queryTarget === \"worker\"\n ? \"Worker DB is read-only — only SELECT, PRAGMA, and EXPLAIN are allowed.\"\n : \"Memory DB allows writes only to CRDT tables.\"}\n </div>\n\n {/* Results */}\n {queryState.status === \"error\" && (\n <div className=\"errorPanel\">\n <div className=\"resultHeader\">\n <span className=\"errorBadge\">Error</span>\n <span className=\"resultMeta\">\n {queryState.error.target} · {queryState.error.sql}\n </span>\n </div>\n <pre className=\"errorMessage\">{queryState.error.message}</pre>\n </div>\n )}\n\n {queryState.status === \"success\" && (\n <div className=\"resultPanel\">\n <div className=\"resultHeader\">\n <span className=\"successBadge\">\n {queryState.output.rowCount} row{queryState.output.rowCount !== 1 ? \"s\" : \"\"}\n </span>\n <span className=\"resultMeta\">\n {queryState.output.target} · {queryState.output.durationMs}ms\n </span>\n </div>\n <ResultTable rows={queryState.output.rows} />\n </div>\n )}\n </div>\n );\n}\n\nfunction ResultTable({ rows }: { rows: unknown[] }) {\n if (rows.length === 0) {\n return <div className=\"resultEmpty\">Query returned 0 rows.</div>;\n }\n\n const firstRow = rows[0];\n if (typeof firstRow !== \"object\" || firstRow === null) {\n return <pre className=\"resultRaw\">{JSON.stringify(rows, null, 2)}</pre>;\n }\n\n const columns = Object.keys(firstRow as object);\n\n return (\n <div className=\"tableWrapper\">\n <table className=\"table\">\n <thead>\n <tr>\n <th className=\"thRowNum\">#</th>\n {columns.map((col) => (\n <th key={col} className=\"th\">\n {col}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {rows.map((row, rowIdx) => (\n <tr key={rowIdx}>\n <td className=\"tdRowNum\">{rowIdx + 1}</td>\n {columns.map((col) => {\n const val = (row as Record<string, unknown>)[col];\n return (\n <td key={col} className=\"td\">\n {val === null ? (\n <span className=\"nullValue\">NULL</span>\n ) : typeof val === \"object\" ? (\n <span className=\"jsonValue\">{JSON.stringify(val)}</span>\n ) : (\n String(val)\n )}\n </td>\n );\n })}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction formatInstanceLabel(dbId: string, instanceId: string, duplicateCount: number): string {\n if (duplicateCount < 2) {\n return dbId;\n }\n\n return `${dbId} (${instanceId.slice(0, 6)})`;\n}\n\nfunction normalizeSingleStatement(query: string): string {\n const trimmed = query.trim();\n if (!trimmed) {\n throw new Error(\"Enter a SQL statement.\");\n }\n\n const withoutTrailingSemicolons = trimmed.replace(/;+\\s*$/u, \"\");\n if (withoutTrailingSemicolons.includes(\";\")) {\n throw new Error(\"Devtools only supports a single SQL statement.\");\n }\n\n return withoutTrailingSemicolons;\n}\n\nfunction getStatementKind(query: string): string {\n const match = query.trimStart().match(/^([a-z]+)/iu);\n return match?.[1]?.toLowerCase() ?? \"\";\n}\n\nfunction isWorkerReadOnlyStatement(statementKind: string): boolean {\n return statementKind === \"select\" || statementKind === \"pragma\";\n}\n\nfunction getEmptySnapshot(): SQLiteSyncDevtoolsSnapshot {\n return emptySnapshot;\n}\n\nconst emptySnapshot: SQLiteSyncDevtoolsSnapshot = {\n instances: [],\n};\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sqlite-sync/devtools",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Embeddable devtools for @sqlite-sync",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"peerDependencies": {
|
|
33
|
-
"@sqlite-sync/core": "^0.
|
|
33
|
+
"@sqlite-sync/core": "^0.13.0",
|
|
34
34
|
"react": "^18.0.0 || ^19.0.0",
|
|
35
35
|
"react-dom": "^18.0.0 || ^19.0.0"
|
|
36
36
|
},
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"react-dom": "^19.2.7",
|
|
43
43
|
"tsdown": "0.22.14",
|
|
44
44
|
"typescript": "npm:@typescript/typescript6@6.0.2",
|
|
45
|
-
"@sqlite-sync/core": "0.
|
|
45
|
+
"@sqlite-sync/core": "0.13.0"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsdown",
|