reactoradar 1.2.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.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +366 -0
  3. package/app.js +2450 -0
  4. package/assets/icon.svg +54 -0
  5. package/bin/cli.js +79 -0
  6. package/bin/open-debugger.sh +9 -0
  7. package/bin/setup.js +473 -0
  8. package/index.html +82 -0
  9. package/main.js +528 -0
  10. package/package.json +76 -0
  11. package/preload.js +31 -0
  12. package/sdk/RNDebugSDK.js +540 -0
  13. package/src/main/main.js +396 -0
  14. package/src/main/preload.js +28 -0
  15. package/src/renderer/app.js +221 -0
  16. package/src/renderer/components/object-tree.js +245 -0
  17. package/src/renderer/index.html +111 -0
  18. package/src/renderer/panels/console.js +248 -0
  19. package/src/renderer/panels/memory.js +60 -0
  20. package/src/renderer/panels/network.js +559 -0
  21. package/src/renderer/panels/performance.js +144 -0
  22. package/src/renderer/panels/react.js +31 -0
  23. package/src/renderer/panels/redux.js +159 -0
  24. package/src/renderer/panels/settings.js +93 -0
  25. package/src/renderer/panels/sources.js +189 -0
  26. package/src/renderer/panels/storage.js +134 -0
  27. package/src/renderer/state.js +132 -0
  28. package/src/renderer/styles/components.css +145 -0
  29. package/src/renderer/styles/console.css +73 -0
  30. package/src/renderer/styles/main.css +229 -0
  31. package/src/renderer/styles/network.css +242 -0
  32. package/src/renderer/styles/performance.css +45 -0
  33. package/src/renderer/styles/redux.css +77 -0
  34. package/src/renderer/styles/settings.css +63 -0
  35. package/src/renderer/styles/sources.css +48 -0
  36. package/src/renderer/styles/storage.css +28 -0
  37. package/src/renderer/styles/theme-light.css +57 -0
  38. package/styles.css +1308 -0
@@ -0,0 +1,229 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@300;400;500;600&family=Syne:wght@700;800&display=swap');
2
+
3
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
4
+
5
+ :root, [data-theme="dark"] {
6
+ --bg: #0d0e11;
7
+ --bg2: #13151a;
8
+ --bg3: #1a1d24;
9
+ --bg4: #20242e;
10
+ --border: #1e2230;
11
+ --border2: #2a2f40;
12
+ --text: #c0c8dc;
13
+ --text-dim: #4a5068;
14
+ --text-mid: #7a8299;
15
+ --text-bright: #e4e9f6;
16
+ --accent: #4facff;
17
+ --accent2: #9b7fff;
18
+ --green: #3dd68c;
19
+ --yellow: #f5c842;
20
+ --red: #ff5e72;
21
+ --orange: #ff8c42;
22
+ --sidebar-w: 56px;
23
+ --titlebar-h: 44px;
24
+ }
25
+
26
+ html, body, #app { height: 100%; overflow: hidden; }
27
+ body {
28
+ background: var(--bg);
29
+ color: var(--text);
30
+ font-family: 'JetBrains Mono', monospace;
31
+ font-size: 12px;
32
+ -webkit-font-smoothing: antialiased;
33
+ user-select: text;
34
+ -webkit-user-select: text;
35
+ }
36
+
37
+ /* ── LAYOUT ─────────────────────────────────────────────────────────────────── */
38
+ #app {
39
+ display: grid;
40
+ grid-template-areas: "tb tb" "nav main";
41
+ grid-template-rows: var(--titlebar-h) 1fr;
42
+ grid-template-columns: var(--sidebar-w) 1fr;
43
+ height: 100vh;
44
+ }
45
+
46
+ /* ── INLINE DEVICE STATUS (inside titlebar) ───────────────────────────────── */
47
+ .title-sep { color: var(--text-dim); font-size: 13px; -webkit-app-region: no-drag; }
48
+ .device-status {
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 6px;
52
+ font-size: 11px;
53
+ font-weight: 500;
54
+ transition: color 0.2s;
55
+ -webkit-app-region: no-drag;
56
+ white-space: nowrap;
57
+ }
58
+ .device-status.waiting { color: var(--text-dim); }
59
+ .device-status.connected { color: var(--green); }
60
+ .device-dot {
61
+ width: 7px;
62
+ height: 7px;
63
+ border-radius: 50%;
64
+ flex-shrink: 0;
65
+ }
66
+ .device-status.waiting .device-dot {
67
+ background: var(--text-dim);
68
+ animation: pulse 2s infinite;
69
+ }
70
+ .device-status.connected .device-dot {
71
+ background: var(--green);
72
+ animation: none;
73
+ }
74
+ @keyframes pulse {
75
+ 0%, 100% { opacity: 1; }
76
+ 50% { opacity: 0.3; }
77
+ }
78
+
79
+ /* ── TITLE BAR ───────────────────────────────────────────────────────────────── */
80
+ #titlebar {
81
+ grid-area: tb;
82
+ display: flex;
83
+ align-items: center;
84
+ gap: 12px;
85
+ padding: 0 12px 0 0;
86
+ background: var(--bg2);
87
+ border-bottom: 1px solid var(--border);
88
+ -webkit-app-region: drag;
89
+ user-select: none;
90
+ }
91
+ .titlebar-drag { width: 76px; flex-shrink: 0; -webkit-app-region: drag; }
92
+ .logo {
93
+ font-family: 'Syne', sans-serif;
94
+ font-weight: 800;
95
+ font-size: 15px;
96
+ letter-spacing: -0.5px;
97
+ color: var(--accent);
98
+ -webkit-app-region: no-drag;
99
+ }
100
+ .logo span { color: var(--text-dim); font-weight: 700; }
101
+
102
+ .titlebar-actions {
103
+ margin-left: auto;
104
+ display: flex;
105
+ align-items: center;
106
+ gap: 8px;
107
+ -webkit-app-region: no-drag;
108
+ }
109
+ .filter-input {
110
+ width: 180px;
111
+ padding: 5px 10px;
112
+ border-radius: 6px;
113
+ border: 1px solid var(--border2);
114
+ background: var(--bg3);
115
+ color: var(--text);
116
+ font-family: inherit;
117
+ font-size: 11px;
118
+ outline: none;
119
+ transition: border 0.15s, box-shadow 0.15s;
120
+ user-select: text;
121
+ -webkit-user-select: text;
122
+ -webkit-app-region: no-drag;
123
+ }
124
+ .filter-input:focus { border-color: var(--accent); box-shadow: 0 0 0 2px rgba(79,172,255,.12); }
125
+ .filter-input::placeholder { color: var(--text-dim); }
126
+
127
+ .tb-btn {
128
+ padding: 5px 12px;
129
+ border-radius: 6px;
130
+ border: 1px solid var(--border2);
131
+ background: transparent;
132
+ color: var(--text-mid);
133
+ font-family: inherit;
134
+ font-size: 11px;
135
+ font-weight: 500;
136
+ cursor: pointer;
137
+ transition: all 0.15s;
138
+ white-space: nowrap;
139
+ }
140
+ .tb-btn:hover { border-color: var(--accent); color: var(--accent); }
141
+ .tb-btn.primary { border-color: var(--accent); color: var(--accent); background: rgba(79,172,255,.08); }
142
+ .tb-btn.primary:hover { background: rgba(79,172,255,.18); }
143
+
144
+ /* ── SIDEBAR ─────────────────────────────────────────────────────────────────── */
145
+ #sidebar {
146
+ grid-area: nav;
147
+ display: flex;
148
+ flex-direction: column;
149
+ align-items: center;
150
+ padding: 8px 0;
151
+ gap: 2px;
152
+ background: var(--bg2);
153
+ border-right: 1px solid var(--border);
154
+ }
155
+ .nav-btn {
156
+ display: flex;
157
+ flex-direction: column;
158
+ align-items: center;
159
+ gap: 3px;
160
+ width: 48px;
161
+ padding: 8px 4px;
162
+ border-radius: 8px;
163
+ border: none;
164
+ background: transparent;
165
+ color: var(--text-dim);
166
+ font-family: inherit;
167
+ font-size: 9px;
168
+ font-weight: 600;
169
+ letter-spacing: 0.3px;
170
+ text-transform: uppercase;
171
+ cursor: pointer;
172
+ transition: all 0.15s;
173
+ }
174
+ .nav-btn svg { width: 18px; height: 18px; }
175
+ .nav-btn:hover { background: var(--bg3); color: var(--text-mid); }
176
+ .nav-btn.active { background: var(--bg4); color: var(--accent); }
177
+
178
+ /* ── NAV SPACER ──────────────────────────────────────────────────────────────── */
179
+ .nav-spacer { flex: 1; }
180
+
181
+ /* ── PANELS ──────────────────────────────────────────────────────────────────── */
182
+ #content { grid-area: main; overflow: hidden; position: relative; }
183
+ .panel { display: none; height: 100%; flex-direction: column; overflow: hidden; }
184
+ .panel.active { display: flex; }
185
+
186
+ /* ── PANEL TOOLBAR ─────────────────────────────────────────────────────────── */
187
+ .panel-toolbar {
188
+ display: flex;
189
+ align-items: center;
190
+ gap: 6px;
191
+ padding: 6px 14px;
192
+ border-bottom: 1px solid var(--border);
193
+ background: var(--bg2);
194
+ flex-shrink: 0;
195
+ height: 36px;
196
+ }
197
+ .panel-label { font-family: 'Syne', sans-serif; font-size: 10px; font-weight: 700; letter-spacing: 1.5px; text-transform: uppercase; color: var(--text-dim); }
198
+ .badge { padding: 1px 6px; border-radius: 8px; font-size: 10px; background: var(--bg4); color: var(--text-dim); border: 1px solid var(--border2); min-width: 24px; text-align: center; }
199
+ .tab-row { display: flex; gap: 3px; }
200
+ .tab { padding: 2px 9px; border-radius: 4px; border: 1px solid transparent; background: transparent; color: var(--text-dim); font-family: inherit; font-size: 10px; font-weight: 500; cursor: pointer; transition: all 0.12s; text-transform: uppercase; letter-spacing: 0.5px; }
201
+ .tab.active { background: var(--bg4); border-color: var(--border2); color: var(--text-bright); }
202
+ .tab:hover:not(.active) { color: var(--text); }
203
+ .ml-auto { margin-left: auto; }
204
+
205
+ /* ── SCROLL AREA ─────────────────────────────────────────────────────────────── */
206
+ .scroll-area { flex: 1; overflow-y: auto; overflow-x: hidden; user-select: text; -webkit-user-select: text; }
207
+ .scroll-area::-webkit-scrollbar { width: 4px; }
208
+ .scroll-area::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
209
+
210
+ /* ── EMPTY STATE ─────────────────────────────────────────────────────────────── */
211
+ .empty-state {
212
+ display: flex;
213
+ flex-direction: column;
214
+ align-items: center;
215
+ justify-content: center;
216
+ height: 100%;
217
+ gap: 10px;
218
+ color: var(--text-dim);
219
+ }
220
+ .empty-state .icon { font-size: 36px; opacity: 0.25; }
221
+ .empty-state .label { font-size: 12px; }
222
+ .empty-state .hint { font-size: 10px; color: var(--text-dim); opacity: 0.7; }
223
+
224
+ /* ── ANIMATIONS ──────────────────────────────────────────────────────────────── */
225
+ @keyframes fadeSlide {
226
+ from { opacity: 0; transform: translateY(-3px); }
227
+ to { opacity: 1; transform: none; }
228
+ }
229
+ .entry { animation: fadeSlide 0.15s ease; }
@@ -0,0 +1,242 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ NETWORK PANEL (Chrome DevTools-style)
3
+ ───────────────────────────────────────────────────────────────────────────── */
4
+ /* Filter bar: search + type filters + throttle */
5
+ .net-filter-bar {
6
+ display: flex;
7
+ align-items: center;
8
+ gap: 8px;
9
+ padding: 4px 10px;
10
+ border-bottom: 1px solid var(--border);
11
+ background: var(--bg2);
12
+ flex-shrink: 0;
13
+ }
14
+ .net-search-input {
15
+ width: 160px;
16
+ padding: 3px 8px;
17
+ border-radius: 4px;
18
+ border: 1px solid var(--border2);
19
+ background: var(--bg3);
20
+ color: var(--text);
21
+ font-family: inherit;
22
+ font-size: 10px;
23
+ outline: none;
24
+ user-select: text;
25
+ -webkit-user-select: text;
26
+ }
27
+ .net-search-input:focus { border-color: var(--accent); }
28
+ .net-search-input::placeholder { color: var(--text-dim); }
29
+ .net-type-filters {
30
+ display: flex;
31
+ align-items: center;
32
+ gap: 1px;
33
+ }
34
+ .net-type-btn {
35
+ padding: 2px 8px;
36
+ border: none;
37
+ border-right: 1px solid var(--border);
38
+ background: transparent;
39
+ color: var(--text-dim);
40
+ font-family: inherit;
41
+ font-size: 10px;
42
+ font-weight: 500;
43
+ cursor: pointer;
44
+ transition: all 0.12s;
45
+ }
46
+ .net-type-btn:last-child { border-right: none; }
47
+ .net-type-btn:hover { color: var(--text); background: var(--bg3); }
48
+ .net-type-btn.active { color: var(--accent); background: rgba(79,172,255,.1); }
49
+ .net-throttle { margin-left: auto; }
50
+ .net-throttle-select {
51
+ padding: 2px 6px;
52
+ border-radius: 4px;
53
+ border: 1px solid var(--border2);
54
+ background: var(--bg3);
55
+ color: var(--text-dim);
56
+ font-family: inherit;
57
+ font-size: 10px;
58
+ outline: none;
59
+ cursor: pointer;
60
+ }
61
+ .net-throttle-select:focus { border-color: var(--accent); }
62
+
63
+ .net-layout { display: flex; flex-direction: row; height: 100%; overflow: hidden; }
64
+ .net-table-wrap { flex: 1; min-width: 0; overflow: hidden; display: flex; flex-direction: column; }
65
+
66
+ /* Column header row */
67
+ .net-header {
68
+ display: flex;
69
+ align-items: center;
70
+ background: var(--bg2);
71
+ border-bottom: 1px solid var(--border);
72
+ flex-shrink: 0;
73
+ font-size: 10px;
74
+ font-weight: 600;
75
+ color: var(--text-dim);
76
+ text-transform: uppercase;
77
+ letter-spacing: 0.5px;
78
+ user-select: none;
79
+ }
80
+ .net-hcell {
81
+ padding: 5px 8px;
82
+ position: relative;
83
+ overflow: hidden;
84
+ text-overflow: ellipsis;
85
+ white-space: nowrap;
86
+ flex-shrink: 0;
87
+ border-right: 1px solid var(--border2);
88
+ }
89
+ .net-hcell:last-child { border-right: none; }
90
+ .net-hcell-label { pointer-events: none; }
91
+ .net-sort-icon { font-size: 8px; color: var(--text-dim); opacity: 0.3; pointer-events: none; }
92
+ .net-sort-icon.active { opacity: 1; color: var(--accent); }
93
+ /* Resize handle — aligned on the border line */
94
+ .net-hcell-resize {
95
+ position: absolute;
96
+ top: 0; right: -3px; bottom: 0;
97
+ width: 6px;
98
+ cursor: col-resize;
99
+ z-index: 2;
100
+ }
101
+ .net-hcell-resize:hover { background: var(--accent); opacity: 0.25; }
102
+ .net-hcell-resize.active { background: var(--accent); opacity: 0.5; }
103
+
104
+ /* Data rows */
105
+ .net-rows { flex: 1; overflow-y: auto; overflow-x: hidden; }
106
+ .net-rows::-webkit-scrollbar { width: 4px; }
107
+ .net-rows::-webkit-scrollbar-thumb { background: var(--border2); border-radius: 2px; }
108
+
109
+ .net-row {
110
+ display: flex;
111
+ align-items: center;
112
+ border-bottom: 1px solid var(--border);
113
+ cursor: pointer;
114
+ transition: background 0.08s;
115
+ font-size: 11px;
116
+ }
117
+ .net-row:hover { background: var(--bg3); }
118
+ .net-row.selected { background: var(--bg4); }
119
+ .net-row.error { background: rgba(255,94,114,.04); }
120
+ .net-cell {
121
+ padding: 6px 8px;
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ white-space: nowrap;
125
+ flex-shrink: 0;
126
+ border-right: 1px solid var(--border2);
127
+ }
128
+ .net-cell:last-child { border-right: none; }
129
+ .net-cell-name { color: var(--text-bright); white-space: normal; word-break: break-all; line-height: 1.4; }
130
+ .net-cell-name .net-path { font-weight: 500; word-break: break-all; }
131
+ .net-cell-name .net-host { color: var(--text-dim); font-size: 10px; display: block; margin-top: 1px; }
132
+ .net-cell-name .method-badge { flex-shrink: 0; vertical-align: middle; }
133
+
134
+ .net-status { font-weight: 700; }
135
+ .s-2 { color: var(--green); }
136
+ .s-3 { color: var(--yellow); }
137
+ .s-4 { color: var(--orange); }
138
+ .s-5 { color: var(--red); }
139
+ .s-pending { color: var(--text-dim); }
140
+ .s-err { color: var(--red); }
141
+
142
+ .net-type { color: var(--text-dim); font-size: 10px; }
143
+ .net-initiator { color: var(--text-dim); font-size: 10px; }
144
+ .net-size { color: var(--text-dim); font-size: 10px; text-align: right; }
145
+ .net-time { color: var(--text-dim); font-size: 10px; text-align: right; }
146
+ .net-time.slow { color: var(--orange); }
147
+
148
+ /* Waterfall bar */
149
+ .net-waterfall { position: relative; height: 14px; }
150
+ .wf-bar {
151
+ position: absolute;
152
+ top: 3px;
153
+ height: 8px;
154
+ border-radius: 2px;
155
+ min-width: 2px;
156
+ }
157
+ .wf-bar.s2 { background: var(--green); opacity: 0.6; }
158
+ .wf-bar.s3 { background: var(--yellow); opacity: 0.6; }
159
+ .wf-bar.s4 { background: var(--orange); opacity: 0.6; }
160
+ .wf-bar.s5 { background: var(--red); opacity: 0.6; }
161
+ .wf-bar.pending { background: var(--text-dim); opacity: 0.3; }
162
+ .wf-bar.err { background: var(--red); opacity: 0.5; }
163
+
164
+ .method-badge { font-size: 9px; font-weight: 700; padding: 1px 4px; border-radius: 3px; letter-spacing: 0.3px; }
165
+ .m-GET { background: rgba(61,214,140,.12); color: var(--green); }
166
+ .m-POST { background: rgba(79,172,255,.12); color: var(--accent); }
167
+ .m-PUT { background: rgba(155,127,255,.12); color: var(--accent2); }
168
+ .m-PATCH { background: rgba(255,140,66,.12); color: var(--orange); }
169
+ .m-DELETE { background: rgba(255,94,114,.12); color: var(--red); }
170
+ .m-other { background: var(--bg4); color: var(--text-dim); }
171
+
172
+ /* Detail pane (right side of the table) */
173
+ .net-detail-pane {
174
+ display: none;
175
+ border-left: 1px solid var(--border2);
176
+ width: 45%;
177
+ min-width: 300px;
178
+ max-width: 60%;
179
+ flex-shrink: 0;
180
+ flex-direction: column;
181
+ background: var(--bg2);
182
+ overflow: hidden;
183
+ }
184
+ .net-detail-pane.open { display: flex; }
185
+ .net-detail-bar {
186
+ display: flex;
187
+ align-items: center;
188
+ background: var(--bg2);
189
+ border-bottom: 1px solid var(--border);
190
+ flex-shrink: 0;
191
+ }
192
+ .detail-tabs { display: flex; gap: 0; flex: 1; }
193
+ .detail-tab {
194
+ padding: 7px 14px;
195
+ border: none;
196
+ border-bottom: 2px solid transparent;
197
+ background: transparent;
198
+ color: var(--text-dim);
199
+ font-family: inherit;
200
+ font-size: 10px;
201
+ font-weight: 600;
202
+ cursor: pointer;
203
+ transition: all 0.12s;
204
+ text-transform: uppercase;
205
+ letter-spacing: 0.5px;
206
+ }
207
+ .detail-tab:hover { color: var(--text); }
208
+ .detail-tab.active { color: var(--accent); border-bottom-color: var(--accent); }
209
+ .detail-close {
210
+ padding: 4px 10px;
211
+ border: none;
212
+ background: transparent;
213
+ color: var(--text-dim);
214
+ font-size: 16px;
215
+ cursor: pointer;
216
+ flex-shrink: 0;
217
+ line-height: 1;
218
+ transition: color 0.1s;
219
+ }
220
+ .detail-close:hover { color: var(--red); }
221
+ .detail-content {
222
+ flex: 1;
223
+ overflow-y: auto;
224
+ padding: 10px 14px;
225
+ white-space: pre-wrap;
226
+ word-break: break-all;
227
+ font-size: 11px;
228
+ line-height: 1.6;
229
+ color: var(--text);
230
+ user-select: text;
231
+ -webkit-user-select: text;
232
+ cursor: text;
233
+ }
234
+ .detail-content::-webkit-scrollbar { width: 3px; }
235
+ .detail-content::-webkit-scrollbar-thumb { background: var(--border2); }
236
+
237
+
238
+ .kv-grid { display: grid; grid-template-columns: auto 1fr; gap: 2px 12px; }
239
+ .kv-key { color: var(--accent); font-size: 11px; }
240
+ .kv-val { color: var(--text); word-break: break-all; font-size: 11px; }
241
+ .section-label { font-size: 10px; text-transform: uppercase; letter-spacing: 1px; color: var(--text-dim); margin-bottom: 6px; margin-top: 10px; }
242
+ .section-label:first-child { margin-top: 0; }
@@ -0,0 +1,45 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ PERFORMANCE PANEL
3
+ ───────────────────────────────────────────────────────────────────────────── */
4
+ .perf-layout { display: flex; flex-direction: column; height: 100%; }
5
+ .perf-meters {
6
+ display: flex;
7
+ gap: 12px;
8
+ padding: 14px;
9
+ border-bottom: 1px solid var(--border);
10
+ flex-shrink: 0;
11
+ flex-wrap: wrap;
12
+ }
13
+ .perf-meter {
14
+ flex: 1;
15
+ min-width: 150px;
16
+ background: var(--bg3);
17
+ border-radius: 8px;
18
+ padding: 10px 14px;
19
+ border: 1px solid var(--border);
20
+ }
21
+ .perf-meter-label {
22
+ font-size: 10px;
23
+ text-transform: uppercase;
24
+ letter-spacing: 0.5px;
25
+ color: var(--text-dim);
26
+ margin-bottom: 4px;
27
+ }
28
+ .perf-meter-value {
29
+ font-size: 20px;
30
+ font-weight: 600;
31
+ color: var(--text-bright);
32
+ margin-bottom: 8px;
33
+ }
34
+ .perf-canvas {
35
+ width: 100%;
36
+ height: 60px;
37
+ border-radius: 4px;
38
+ background: var(--bg);
39
+ }
40
+ .perf-timeline { flex: 1; }
41
+
42
+ /* ─────────────────────────────────────────────────────────────────────────────
43
+ MEMORY PANEL
44
+ ───────────────────────────────────────────────────────────────────────────── */
45
+ .memory-layout { display: flex; flex-direction: column; height: 100%; }
@@ -0,0 +1,77 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ REDUX PANEL
3
+ ───────────────────────────────────────────────────────────────────────────── */
4
+ .redux-layout { display: grid; grid-template-columns: 280px 1fr; height: 100%; }
5
+ .redux-actions { display: flex; flex-direction: column; border-right: 1px solid var(--border); overflow: hidden; }
6
+ .redux-actions-list { flex: 1; overflow-y: auto; }
7
+ .redux-actions-list::-webkit-scrollbar { width: 3px; }
8
+ .redux-actions-list::-webkit-scrollbar-thumb { background: var(--border2); }
9
+
10
+ .action-row {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: 8px;
14
+ padding: 8px 12px;
15
+ border-bottom: 1px solid var(--border);
16
+ cursor: pointer;
17
+ transition: background 0.08s;
18
+ }
19
+ .action-row:hover { background: var(--bg3); }
20
+ .action-row.selected { background: var(--bg4); border-left: 2px solid var(--accent); }
21
+ .action-type { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 11px; color: var(--text-bright); }
22
+ .action-index { font-size: 10px; color: var(--text-dim); min-width: 24px; text-align: right; }
23
+ .action-time-badge { font-size: 9px; color: var(--text-dim); }
24
+
25
+ .redux-state-view { display: flex; flex-direction: column; overflow: hidden; }
26
+ .redux-state-tabs { display: flex; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--border); background: var(--bg2); }
27
+ .redux-state-body { flex: 1; overflow-y: auto; padding: 12px; font-size: 11px; line-height: 1.6; white-space: pre-wrap; word-break: break-all; user-select: text; -webkit-user-select: text; cursor: text; }
28
+ .redux-state-body::-webkit-scrollbar { width: 3px; }
29
+ .redux-state-body::-webkit-scrollbar-thumb { background: var(--border2); }
30
+
31
+ /* Redux action context (prev/current/next) */
32
+ .redux-action-ctx {
33
+ display: flex;
34
+ align-items: center;
35
+ gap: 8px;
36
+ padding: 6px 0 4px;
37
+ border-bottom: 1px solid var(--border);
38
+ margin-bottom: 6px;
39
+ }
40
+ .redux-ctx-label {
41
+ font-size: 9px;
42
+ font-weight: 700;
43
+ padding: 2px 6px;
44
+ border-radius: 3px;
45
+ text-transform: uppercase;
46
+ letter-spacing: 0.5px;
47
+ }
48
+ .redux-ctx-label.prev { background: var(--bg4); color: var(--text-dim); }
49
+ .redux-ctx-label.current { background: rgba(79,172,255,.15); color: var(--accent); }
50
+ .redux-ctx-label.next { background: var(--bg4); color: var(--text-dim); }
51
+ .redux-ctx-type { font-size: 11px; color: var(--text-bright); font-weight: 500; }
52
+ .redux-action-detail { margin-bottom: 14px; }
53
+ .redux-action-detail.prev, .redux-action-detail.next { opacity: 0.5; }
54
+ .redux-action-detail.current { opacity: 1; }
55
+
56
+ /* time travel toolbar */
57
+ .time-travel-bar {
58
+ display: flex;
59
+ align-items: center;
60
+ gap: 6px;
61
+ padding: 6px 12px;
62
+ border-top: 1px solid var(--border);
63
+ background: var(--bg2);
64
+ }
65
+ .tt-btn {
66
+ padding: 3px 10px;
67
+ border-radius: 4px;
68
+ border: 1px solid var(--border2);
69
+ background: transparent;
70
+ color: var(--text-mid);
71
+ font-family: inherit;
72
+ font-size: 10px;
73
+ cursor: pointer;
74
+ transition: all 0.12s;
75
+ }
76
+ .tt-btn:hover { border-color: var(--accent2); color: var(--accent2); }
77
+ .tt-label { font-size: 10px; color: var(--text-dim); margin-left: auto; }
@@ -0,0 +1,63 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ SETTINGS PANEL
3
+ ───────────────────────────────────────────────────────────────────────────── */
4
+ .settings-content {
5
+ padding: 24px;
6
+ max-width: 480px;
7
+ }
8
+ .settings-section {
9
+ margin-bottom: 28px;
10
+ }
11
+ .settings-section-title {
12
+ font-family: 'Syne', sans-serif;
13
+ font-size: 11px;
14
+ font-weight: 700;
15
+ letter-spacing: 1.5px;
16
+ text-transform: uppercase;
17
+ color: var(--text-dim);
18
+ margin-bottom: 14px;
19
+ }
20
+ .settings-row {
21
+ display: flex;
22
+ align-items: center;
23
+ justify-content: space-between;
24
+ padding: 10px 0;
25
+ border-bottom: 1px solid var(--border);
26
+ }
27
+ .settings-row:last-child { border-bottom: none; }
28
+ .settings-label {
29
+ font-size: 12px;
30
+ color: var(--text);
31
+ }
32
+ .settings-hint {
33
+ font-size: 10px;
34
+ color: var(--text-dim);
35
+ margin-top: 3px;
36
+ }
37
+
38
+ /* Theme switcher — 3-way segmented control */
39
+ .theme-switcher {
40
+ display: flex;
41
+ gap: 0;
42
+ border: 1px solid var(--border2);
43
+ border-radius: 6px;
44
+ overflow: hidden;
45
+ }
46
+ .theme-option {
47
+ padding: 5px 14px;
48
+ border: none;
49
+ background: transparent;
50
+ color: var(--text-dim);
51
+ font-family: inherit;
52
+ font-size: 11px;
53
+ font-weight: 500;
54
+ cursor: pointer;
55
+ transition: all 0.15s;
56
+ border-right: 1px solid var(--border2);
57
+ }
58
+ .theme-option:last-child { border-right: none; }
59
+ .theme-option:hover { color: var(--text); background: var(--bg3); }
60
+ .theme-option.active {
61
+ background: var(--accent);
62
+ color: #fff;
63
+ }
@@ -0,0 +1,48 @@
1
+ /* ─────────────────────────────────────────────────────────────────────────────
2
+ SOURCES PANEL
3
+ ───────────────────────────────────────────────────────────────────────────── */
4
+ .sources-layout { display: grid; grid-template-columns: 240px 1fr; height: 100%; }
5
+ .sources-sidebar { display: flex; flex-direction: column; border-right: 1px solid var(--border); overflow: hidden; }
6
+ .sources-file-list { flex: 1; overflow-y: auto; }
7
+ .sources-file-list::-webkit-scrollbar { width: 3px; }
8
+ .sources-file-list::-webkit-scrollbar-thumb { background: var(--border2); }
9
+ .source-file-row {
10
+ padding: 8px 12px;
11
+ border-bottom: 1px solid var(--border);
12
+ cursor: pointer;
13
+ transition: background 0.08s;
14
+ }
15
+ .source-file-row:hover { background: var(--bg3); }
16
+ .source-file-row.selected { background: var(--bg4); border-left: 2px solid var(--accent); }
17
+ .sources-editor { display: flex; flex-direction: column; overflow: hidden; }
18
+ .sources-code {
19
+ flex: 1;
20
+ overflow: auto;
21
+ font-size: 11px;
22
+ line-height: 1.6;
23
+ user-select: text;
24
+ -webkit-user-select: text;
25
+ }
26
+ .source-pre { margin: 0; padding: 0; }
27
+ .source-line {
28
+ display: flex;
29
+ padding: 0 8px;
30
+ min-height: 18px;
31
+ }
32
+ .source-line:hover { background: var(--bg3); }
33
+ .source-line-num {
34
+ display: inline-block;
35
+ width: 44px;
36
+ flex-shrink: 0;
37
+ text-align: right;
38
+ padding-right: 12px;
39
+ color: var(--text-dim);
40
+ opacity: 0.5;
41
+ user-select: none;
42
+ -webkit-user-select: none;
43
+ }
44
+ .source-line-code {
45
+ flex: 1;
46
+ white-space: pre;
47
+ tab-size: 2;
48
+ }