@sqlite-sync/devtools 0.12.1 → 0.12.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
- const maxX = window.innerWidth - button.offsetWidth - VIEWPORT_MARGIN_PX;
113
- const maxY = window.innerHeight - button.offsetHeight - VIEWPORT_MARGIN_PX;
114
- setPosition({
115
- x: Math.max(VIEWPORT_MARGIN_PX, Math.min(event.clientX - drag.offsetX, maxX)),
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
- }, [isControlled, onHiddenChange]);
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 SQLiteSyncDevtools({ className, hidden: hiddenProp, onHiddenChange }) {
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") setIsOpen(false);
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: () => setIsOpen(false),
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: () => setIsOpen(false),
411
+ onClick: closeDialog,
370
412
  "aria-label": "Close",
371
413
  children: "✕"
372
414
  })
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 &amp; 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 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 &amp; 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.12.1",
3
+ "version": "0.12.3",
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.12.1",
33
+ "@sqlite-sync/core": "^0.12.3",
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.12.1"
45
+ "@sqlite-sync/core": "0.12.3"
46
46
  },
47
47
  "scripts": {
48
48
  "build": "tsdown",