(
setExtraCols(ec => { const c = [...ec]; c[idx] = e.target.value; return c })}
@@ -521,7 +521,7 @@ export default function Mappings({ source, onNeedsReprocess }) {
setExtraCols(ec => [...ec, ''])}
- className="text-gray-400 hover:text-gray-700 font-medium"
+ className="text-muted hover:text-ink-soft font-medium"
title="Add column"
>+
@@ -536,7 +536,7 @@ export default function Mappings({ source, onNeedsReprocess }) {
const isSaving = saving[k]
const isSelected = selected.has(k)
const hasDraft = !!(drafts[k] && Object.keys(drafts[k]).length > 0)
- const rowBg = isSelected ? 'bg-blue-50' : hasDraft ? 'bg-blue-50' : row.is_mapped ? '' : 'bg-yellow-50'
+ const rowBg = isSelected ? 'bg-accent-soft' : hasDraft ? 'bg-accent-soft' : row.is_mapped ? '' : 'bg-warn-soft'
function handleRowClick(e) {
if (e.target.closest('input,button,a,select')) return
@@ -571,7 +571,7 @@ export default function Mappings({ source, onNeedsReprocess }) {
key={k}
ref={el => rowRefs.current[k] = el}
tabIndex={0}
- className={`border-t border-gray-50 hover:bg-gray-50 cursor-pointer outline-none ${rowBg}`}
+ className={`border-t border-line-soft hover:bg-raised cursor-pointer outline-none ${rowBg}`}
onClick={handleRowClick}
onKeyDown={handleRowKeyDown}
>
@@ -586,13 +586,13 @@ export default function Mappings({ source, onNeedsReprocess }) {
}}
/>
- {displayValue(row.extracted_value)}
- {row.record_count}
+ {displayValue(row.extracted_value)}
+ {row.record_count}
{cols.map(col => (
setCellValue(row.extracted_value, col, v)}
@@ -605,7 +605,7 @@ export default function Mappings({ source, onNeedsReprocess }) {
{samples.length > 0 && (
setSampleOpen(s => ({ ...s, [k]: !s[k] }))}
>
{sampleOpen[k] ? 'hide' : 'show'}
@@ -624,7 +624,7 @@ export default function Mappings({ source, onNeedsReprocess }) {
{row.is_mapped && (
deleteRow(row)}
- className="text-red-400 hover:text-red-600 text-base leading-none"
+ className="text-danger hover:text-danger text-base leading-none"
title="Remove mapping"
>×
)}
@@ -634,21 +634,21 @@ export default function Mappings({ source, onNeedsReprocess }) {
{sampleOpen[k] && (() => {
const sampleCols = [...new Set(samples.flatMap(r => Object.keys(r)))]
return (
-
+
-
+
-
+
{sampleCols.map(c => (
- {c}
+ {c}
))}
{samples.map((rec, i) => (
-
+
{sampleCols.map(c => (
-
+
{rec[c] != null ? String(rec[c]) : ''}
))}
diff --git a/ui/src/pages/Pivot.jsx b/ui/src/pages/Pivot.jsx
index 6054a9e..5bc7fa9 100644
--- a/ui/src/pages/Pivot.jsx
+++ b/ui/src/pages/Pivot.jsx
@@ -370,7 +370,7 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
viewer.restore({ table: selectedView, settings: true, plugin_config: DEFAULT_PLUGIN_CONFIG })
}
- if (!source) return Select a source first.
+ if (!source) return Select a source first.
const cols = inspectedRows?.length ? Object.keys(inspectedRows[0]) : []
@@ -416,24 +416,24 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
{/* Layouts sub-bar */}
-
+
{layouts.map(l => (
applyLayout(l)}
className={`flex items-center gap-1 rounded px-2 py-0.5 cursor-pointer border transition-colors
${activeLayoutId === l.id
- ? 'bg-blue-50 border-blue-300 text-blue-700'
- : 'bg-white border-gray-200 text-gray-600 hover:border-gray-400'}`}>
+ ? 'bg-accent-soft border-accent-line text-accent'
+ : 'bg-surface border-line text-ink-soft hover:border-line'}`}>
{l.layout_name}
handleDelete(l, e)}
- className="text-gray-300 hover:text-red-400 leading-none ml-0.5 text-sm">×
+ className="text-muted hover:text-danger leading-none ml-0.5 text-sm">×
))}
{activeLayoutId !== null && !showSaveAs && (
+ className="text-accent hover:text-accent border border-accent-line rounded px-2 py-0.5">
Save
)}
@@ -446,27 +446,27 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
onChange={e => setSaveAsName(e.target.value)}
onKeyDown={e => { if (e.key === 'Enter') handleSaveAs(); if (e.key === 'Escape') { setShowSaveAs(false); setSaveAsName('') } }}
placeholder="Layout name…"
- className="border border-gray-300 rounded px-2 py-0.5 w-36 focus:outline-none focus:border-blue-400"
+ className="border border-line rounded px-2 py-0.5 w-36 focus:outline-none focus:border-accent"
/>
-
Save
-
{ setShowSaveAs(false); setSaveAsName('') }} className="text-gray-400 hover:text-gray-600 px-1">Cancel
+
Save
+
{ setShowSaveAs(false); setSaveAsName('') }} className="text-muted hover:text-ink-soft px-1">Cancel
) : (
setShowSaveAs(true)}
- className="text-gray-400 hover:text-gray-600 border border-dashed border-gray-200 rounded px-2 py-0.5">
+ className="text-muted hover:text-ink-soft border border-dashed border-line rounded px-2 py-0.5">
+ Save as…
)}
{activeLayoutId !== null && (
-
reset
+
reset
)}
- {layoutMsg &&
{layoutMsg} }
+ {layoutMsg &&
{layoutMsg} }
-
depth:
+
depth:
{[0, 1, 2, 3].map(d => (
{
const v = viewerRef.current; if (!v) return
@@ -475,7 +475,7 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
const p = await v.getPlugin()
await p.draw(view)
expandDepthRef.current = d
- }} className="border border-gray-200 rounded px-1.5 py-0.5 text-gray-500 hover:border-gray-400">
+ }} className="border border-line rounded px-1.5 py-0.5 text-muted hover:border-line">
{d}
))}
@@ -486,18 +486,18 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
{status === 'loading' && (
-
-
Loading…
+
)}
{status === 'error' && (
-
-
Error: {error}
+
)}
{status === 'noview' && (
-
-
No view data — generate a view and transform records first.
+
+
No view data — generate a view and transform records first.
)}
{/* Drag-to-resize handle on left edge */}
{/* Header: breadcrumb + row count + controls */}
-
+
{cellCoords.length > 0 && (
-
+
{cellCoords.join(' › ')}
)}
-
+
{inspectedRows.length} row{inspectedRows.length !== 1 ? 's' : ''}
setDecimals(d => Math.max(0, d - 1))}
- className="text-xs text-gray-400 hover:text-gray-600 w-4 text-center">−
- {decimals}
+ className="text-xs text-muted hover:text-ink-soft w-4 text-center">−
+ {decimals}
setDecimals(d => Math.min(8, d + 1))}
- className="text-xs text-gray-400 hover:text-gray-600 w-4 text-center">+
+ className="text-xs text-muted hover:text-ink-soft w-4 text-center">+
{ setInspectedRows(null); setClickDetail(null); lastClickKeyRef.current = null }}
- className="text-gray-300 hover:text-gray-500 leading-none text-lg">×
+ className="text-muted hover:text-muted leading-none text-lg">×
@@ -558,10 +558,10 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
{(() => {
const userFilters = (clickDetail.eventFilters || []).filter(([f]) => !coordFields.has(f))
return userFilters.length > 0 ? (
-
-
Filters
+
+
Filters
{userFilters.map((f, i) => (
-
{f.join(' ')}
+
{f.join(' ')}
))}
) : null
@@ -572,13 +572,13 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
-
+
{cols.map(c => {
const active = sortCol === c
return (
{ if (active) setSortDir(d => d === 'asc' ? 'desc' : 'asc'); else { setSortCol(c); setSortDir('asc') } }}
- className="px-2 py-1 font-medium whitespace-nowrap cursor-pointer select-none hover:text-gray-600">
+ className="px-2 py-1 font-medium whitespace-nowrap cursor-pointer select-none hover:text-ink-soft">
{c}{active ? (sortDir === 'asc' ? ' ▲' : ' ▼') : ''}
)
@@ -587,12 +587,12 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
{sortedRows.map((row, i) => (
-
+
{cols.map(c => {
const f = formatVal(row[c], decimals)
return (
-
- {f == null ? — : f}
+
+ {f == null ? — : f}
)
})}
@@ -601,7 +601,7 @@ export default function Pivot({ source, selectedStack, setSelectedStack }) {
{Object.keys(totals).length > 0 && (
-
+
{cols.map(c => (
{totals[c] != null ? formatVal(totals[c], decimals) : ''}
diff --git a/ui/src/pages/Records.jsx b/ui/src/pages/Records.jsx
index c1be1f9..4915e81 100644
--- a/ui/src/pages/Records.jsx
+++ b/ui/src/pages/Records.jsx
@@ -49,10 +49,10 @@ function AutocompleteInput({ value, onChange, onEnter, suggestions = [], classNa
{open && filtered.length > 0 && dropPos && (
+ className="bg-surface border border-line rounded shadow-lg max-h-40 overflow-y-auto">
{filtered.map((s, i) => (
{ e.preventDefault(); select(s) }}>{s}
))}
@@ -283,7 +283,7 @@ export default function Records({ source }) {
}
}
- if (!source) return Select a source first.
+ if (!source) return Select a source first.
const displayCols = gridCols(rows.length > 0 ? Object.keys(rows[0]) : cols)
const visCols = gridCols(cols)
@@ -300,42 +300,42 @@ export default function Records({ source }) {
-
Records — {source}
+ Records — {source}
{exists && rows.length > 0 && (
- dfv.{source}
+ dfv.{source}
)}
{/* Filter bar */}
{exists !== false && visCols.length > 0 && (
-
DB query:
+
DB query:
{filters.map((f, i) => (
-
+
updateFilter(i, 'col', e.target.value)}
>
{visCols.map(c => {c} )}
- ~*
+ ~*
updateFilter(i, 'pattern', e.target.value)}
/>
- removeFilter(i)} className="text-gray-300 hover:text-gray-500 ml-1 leading-none">×
+ removeFilter(i)} className="text-muted hover:text-muted ml-1 leading-none">×
))}
+ className="text-xs text-muted hover:text-ink-soft border border-dashed border-line rounded px-2 py-1">
+ filter
{filters.length > 0 && (
{ setFilters([]); setOffset(0); load(0, sort.col, sort.dir, []) }}
- className="text-xs text-gray-400 hover:text-red-500">clear
+ className="text-xs text-muted hover:text-danger">clear
)}
)}
@@ -343,24 +343,24 @@ export default function Records({ source }) {
{/* Bulk select + override bar */}
{exists && visCols.length > 0 && (
-
Bulk select:
+
Bulk select:
setRowFilter(e.target.value)}
/>
{rowFilter && (
-
{selected.size} of {rows.length} rows selected
+
{selected.size} of {rows.length} rows selected
)}
{selected.size > 0 && (
-
+
{allOverrideCols.map(col => (
setBulkDraft(d => ({ ...d, [col]: v }))}
@@ -395,7 +395,7 @@ export default function Records({ source }) {
{ setSelected(new Set()); setBulkDraft({}); setRowFilter('') }}
- className="text-xs text-blue-400 hover:text-blue-600"
+ className="text-xs text-accent hover:text-accent"
>
cancel
@@ -404,25 +404,25 @@ export default function Records({ source }) {
)}
- {loading &&
Loading…
}
- {!loading && viewError &&
View error: {viewError} — check field types in Sources.
}
+ {loading &&
Loading…
}
+ {!loading && viewError &&
View error: {viewError} — check field types in Sources.
}
{!loading && exists === false && (
-
- No view generated yet. Go to Sources , check fields as In view , then click Generate view .
+
+ No view generated yet. Go to Sources , check fields as In view , then click Generate view .
)}
{!loading && exists && rows.length === 0 && (
-
+
{filters.some(f => f.col && f.pattern) ? 'No records match the current filters.' : 'View exists but no transformed records yet. Import data and run a transform first.'}
)}
{!loading && exists && rows.length > 0 && (
<>
-
+
-
+
← Prev
+ className="px-3 py-1 border border-line rounded hover:bg-raised disabled:opacity-40">← Prev
{offset + 1}–{offset + rows.length}
Next →
+ className="px-3 py-1 border border-line rounded hover:bg-raised disabled:opacity-40">Next →
>
)}
@@ -494,58 +494,58 @@ export default function Records({ source }) {
{/* Panel */}
{panelOpen && (
-
-
-
Record
-
×
+
+
+ Record
+ ×
- {panelLoading &&
Loading…
}
+ {panelLoading &&
Loading…
}
{selectedRecord && !panelLoading && (
{panelMsg && (
-
+
{panelMsg.text}
)}
{/* Raw fields — read only */}
-
-
-
Raw
+
+
+ Raw
{Object.entries(selectedRecord.data || {}).map(([field, val]) => (
-
-
{field}
-
{formatVal(val) ?? — }
+
+ {field}
+ {formatVal(val) ?? — }
))}
{/* Transformed fields — read only delta */}
-
-
-
Transformed
+
+
+ Transformed
{Object.entries(selectedRecord.transformed || {}).filter(([k]) => !HIDDEN_COLS.has(k)).length === 0
- ?
No rule output yet.
+ ?
No rule output yet.
: Object.entries(selectedRecord.transformed || {}).filter(([k]) => !HIDDEN_COLS.has(k)).map(([field, val]) => (
-
-
{field}
-
{formatVal(val) ?? — }
+
+ {field}
+ {formatVal(val) ?? — }
))
}
{/* Overrides — editable */}
-
-
-
Overrides
+
+
+ Overrides
setExtraCols(ec => [...ec, ''])}
- className="text-gray-400 hover:text-gray-700 font-medium text-sm leading-none"
+ className="text-muted hover:text-ink-soft font-medium text-sm leading-none"
title="Add field">+
@@ -559,14 +559,14 @@ export default function Records({ source }) {
const placeholder = formatVal(selectedRecord.transformed?.[col]) ?? ''
const suggestions = [...(globalValues[col] || [])].sort()
return (
-
+
- {col}
+ {col}
setOverrideDraft(d => { const n = { ...d }; delete n[col]; return n })}
- className="text-gray-300 hover:text-red-400 leading-none text-base">×
+ className="text-muted hover:text-danger leading-none text-base">×
)}
@@ -589,10 +589,10 @@ export default function Records({ source }) {
const val = overrideDraft[col] ?? ''
const suggestions = [...(globalValues[col] || [])].sort()
return (
-
+
{
@@ -610,7 +610,7 @@ export default function Records({ source }) {
setOverrideDraft(d => ({ ...d, [col]: v }))}
@@ -622,7 +622,7 @@ export default function Records({ source }) {
{val && (
setOverrideDraft(d => { const n = { ...d }; delete n[col]; return n })}
- className="text-gray-300 hover:text-red-400 leading-none text-base">×
+ className="text-muted hover:text-danger leading-none text-base">×
)}
@@ -632,7 +632,7 @@ export default function Records({ source }) {
-
+
+ className="text-xs border border-line rounded px-3 py-1.5 text-muted hover:border-danger-line hover:text-danger disabled:opacity-40">
Clear
)}
diff --git a/ui/src/pages/Remap.jsx b/ui/src/pages/Remap.jsx
index 599a8e1..3e47f37 100644
--- a/ui/src/pages/Remap.jsx
+++ b/ui/src/pages/Remap.jsx
@@ -74,7 +74,7 @@ export default function Remap() {
return (
-
Remap Output Values
+
Remap Output Values
{/* Search */}