@buoy-gg/core 7.0.26 → 7.0.27

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 (40) hide show
  1. package/bin/buoy.js +6 -0
  2. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +524 -1520
  3. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +541 -566
  4. package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +5 -1
  5. package/lib/commonjs/floatingMenu/ToolHost.js +2 -1
  6. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +50 -21
  7. package/lib/commonjs/floatingMenu/dial/DialHyperspace.js +177 -0
  8. package/lib/commonjs/floatingMenu/dial/DialSnow.js +92 -0
  9. package/lib/commonjs/version.js +1 -1
  10. package/lib/module/floatingMenu/DevToolsSettingsModal.js +525 -1524
  11. package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +542 -569
  12. package/lib/module/floatingMenu/FloatingDevTools.web.js +5 -1
  13. package/lib/module/floatingMenu/ToolHost.js +2 -1
  14. package/lib/module/floatingMenu/dial/DialDevTools.js +52 -23
  15. package/lib/module/floatingMenu/dial/DialHyperspace.js +173 -0
  16. package/lib/module/floatingMenu/dial/DialSnow.js +90 -0
  17. package/lib/module/version.js +1 -1
  18. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +19 -13
  19. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  20. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -3
  21. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  22. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  23. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  24. package/lib/typescript/commonjs/floatingMenu/dial/DialHyperspace.d.ts +24 -0
  25. package/lib/typescript/commonjs/floatingMenu/dial/DialHyperspace.d.ts.map +1 -0
  26. package/lib/typescript/commonjs/floatingMenu/dial/DialSnow.d.ts +23 -0
  27. package/lib/typescript/commonjs/floatingMenu/dial/DialSnow.d.ts.map +1 -0
  28. package/lib/typescript/commonjs/version.d.ts +1 -1
  29. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +19 -13
  30. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
  31. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts +3 -3
  32. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +1 -1
  33. package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
  34. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -1
  35. package/lib/typescript/module/floatingMenu/dial/DialHyperspace.d.ts +24 -0
  36. package/lib/typescript/module/floatingMenu/dial/DialHyperspace.d.ts.map +1 -0
  37. package/lib/typescript/module/floatingMenu/dial/DialSnow.d.ts +23 -0
  38. package/lib/typescript/module/floatingMenu/dial/DialSnow.d.ts.map +1 -0
  39. package/lib/typescript/module/version.d.ts +1 -1
  40. package/package.json +5 -5
@@ -8,9 +8,9 @@
8
8
  *
9
9
  * VISUAL PARITY: styled 1:1 against the native reference
10
10
  * (devtools-floating-menu/src/floatingMenu/DevToolsSettingsModal.tsx, which
11
- * renders inside JsModal + ModalHeader + TabSelector from @buoy-gg/shared-ui).
12
- * shared-ui is RN-only, so its buoyColors palette and the native-only style
13
- * values are inlined below with provenance comments.
11
+ * renders in the "night" language — shared-ui's ui/night Everlights port —
12
+ * inside JsModal variant="night"). shared-ui is RN-only, so the night tokens
13
+ * and primitive styles are inlined below with provenance comments.
14
14
  *
15
15
  * @platform React DOM Web (Vite, CRA, Next.js, Electron)
16
16
  */
@@ -21,8 +21,6 @@ import {
21
21
  useSettings,
22
22
  // Tab configuration
23
23
  settingsTabs,
24
- // Shared style tokens (used where they match the native reference)
25
- settingsStyles,
26
24
  // Tool metadata
27
25
  getToolLabel, getToolDescription,
28
26
  // Global settings config
@@ -31,8 +29,10 @@ globalSettingsConfig
31
29
  } from '@buoy-gg/floating-tools-react';
32
30
  import { QueryIcon, EnvIcon, StorageIcon, NetworkIcon, RoutesIcon, HighlighterIcon, ReduxIcon, EventsIcon, WifiIcon, ImageOverlayIcon, ZustandIcon, JotaiIcon } from '@buoy-gg/floating-tools-core';
33
31
  // JsModal.web + storage keys via the consumer's shared-ui web shim — the
34
- // settings sheet is a real JsModal on web now, same as native.
35
- import { JsModal, devToolsStorageKeys } from '@buoy-gg/shared-ui';
32
+ // settings sheet is a real JsModal on web now, same as native. The
33
+ // BackgroundSwitcher is the same RN component native mounts: it renders under
34
+ // the consumer's RNW lane exactly like the ToolBackground JsModal.web draws.
35
+ import { JsModal, devToolsStorageKeys, BackgroundSwitcher } from '@buoy-gg/shared-ui';
36
36
 
37
37
  /** env(safe-area-inset-top) via a one-shot probe (native: useSafeAreaInsets). */
38
38
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
@@ -47,29 +47,39 @@ function readTopSafeAreaInset() {
47
47
  }
48
48
 
49
49
  // =============================
50
- // Native palette (provenance)
50
+ // Night tokens (provenance)
51
51
  // =============================
52
52
 
53
53
  /**
54
- * buoyColors from @buoy-gg/shared-ui (gameUIColors.ts) — the palette the
55
- * native settings modal is styled with. shared-ui cannot be imported on web,
56
- * so the values are inlined verbatim.
54
+ * `night` from @buoy-gg/shared-ui (ui/night/nightTheme.ts) — the Everlights
55
+ * palette the native settings modal is styled with. shared-ui cannot be
56
+ * imported on web, so the values are inlined verbatim.
57
57
  */
58
- const buoy = {
59
- base: '#121212',
60
- card: '#1A1A1A',
61
- hover: '#242424',
62
- input: '#2A2A2A',
63
- border: '#333333',
64
- borderStrong: '#444444',
65
- text: '#E0E0E0',
66
- textSecondary: '#A0A0A0',
67
- textMuted: '#888888',
68
- primary: '#20C997',
69
- success: '#20C997',
70
- warning: '#FFA94D',
71
- error: '#EF4444',
72
- info: '#00B8E6'
58
+ const night = {
59
+ bg: '#050505',
60
+ surface: '#0C0C0C',
61
+ surfaceElevated: '#161618',
62
+ border: '#1A1A1C',
63
+ separator: 'rgba(255, 255, 255, 0.08)',
64
+ fillTertiary: 'rgba(255, 255, 255, 0.12)',
65
+ buttonSurface: 'rgba(8, 10, 14, 0.85)',
66
+ button: '#1C1C1C',
67
+ buttonPressed: '#2C2C2E',
68
+ text: '#ECEDEE',
69
+ textSecondary: '#9BA1A6',
70
+ textTertiary: '#636366',
71
+ placeholder: 'rgba(255, 255, 255, 0.30)',
72
+ accent: '#20C997',
73
+ accentSoft: 'rgba(32, 201, 151, 0.12)',
74
+ accentFill: 'rgba(32, 201, 151, 0.18)',
75
+ accentBorderStrong: 'rgba(32, 201, 151, 0.35)',
76
+ onAccent: '#000000',
77
+ danger: '#FF3B30',
78
+ dangerSoft: 'rgba(255, 59, 48, 0.10)',
79
+ warning: '#FF8329',
80
+ warningSoft: 'rgba(255, 131, 41, 0.12)',
81
+ fillSecondary: 'rgba(255, 255, 255, 0.08)',
82
+ knob: '#D4D8DC'
73
83
  };
74
84
 
75
85
  // =============================
@@ -89,7 +99,7 @@ const webStorageAdapter = {
89
99
  // Icon Components (Web SVGs)
90
100
  // =============================
91
101
 
92
- /** Fallback for shared-ui Layers icon (native debug-borders card icon). */
102
+ /** Fallback for shared-ui Layers icon (native debug-borders row icon). */
93
103
  const Layers = ({
94
104
  size = 24,
95
105
  color = 'currentColor'
@@ -111,7 +121,7 @@ const Layers = ({
111
121
  })]
112
122
  });
113
123
 
114
- /** Fallback for shared-ui RenderCountIcon (native highlight-updates card icon). */
124
+ /** Fallback for shared-ui RenderCountIcon (native highlight-updates row icon). */
115
125
  const Sparkles = ({
116
126
  size = 24,
117
127
  color = 'currentColor'
@@ -137,7 +147,7 @@ const Sparkles = ({
137
147
  })]
138
148
  });
139
149
 
140
- /** Fallback for shared-ui SentryBugIcon (native sentry card icon, red). */
150
+ /** Fallback for shared-ui SentryBugIcon (native sentry row icon, red). */
141
151
  const AlertTriangle = ({
142
152
  size = 24,
143
153
  color = 'currentColor'
@@ -183,32 +193,7 @@ const Info = ({
183
193
  })]
184
194
  });
185
195
 
186
- /** shared-ui Database icon (native storage status card icon). */
187
- const Database = ({
188
- size = 24,
189
- color = 'currentColor'
190
- }) => /*#__PURE__*/_jsxs("svg", {
191
- width: size,
192
- height: size,
193
- viewBox: "0 0 24 24",
194
- fill: "none",
195
- stroke: color,
196
- strokeWidth: "2",
197
- strokeLinecap: "round",
198
- strokeLinejoin: "round",
199
- children: [/*#__PURE__*/_jsx("ellipse", {
200
- cx: "12",
201
- cy: "5",
202
- rx: "9",
203
- ry: "3"
204
- }), /*#__PURE__*/_jsx("path", {
205
- d: "M3 5V19A9 3 0 0 0 21 19V5"
206
- }), /*#__PURE__*/_jsx("path", {
207
- d: "M3 12A9 3 0 0 0 21 12"
208
- })]
209
- });
210
-
211
- /** shared-ui CheckCircle2 icon (native storage badge check). */
196
+ /** shared-ui CheckCircle2 icon (clear-success feedback). */
212
197
  const CheckCircle2 = ({
213
198
  size = 24,
214
199
  color = 'currentColor'
@@ -230,33 +215,7 @@ const CheckCircle2 = ({
230
215
  })]
231
216
  });
232
217
 
233
- /** shared-ui FileText icon (native SAVED SETTINGS header icon). */
234
- const FileText = ({
235
- size = 24,
236
- color = 'currentColor'
237
- }) => /*#__PURE__*/_jsxs("svg", {
238
- width: size,
239
- height: size,
240
- viewBox: "0 0 24 24",
241
- fill: "none",
242
- stroke: color,
243
- strokeWidth: "2",
244
- strokeLinecap: "round",
245
- strokeLinejoin: "round",
246
- children: [/*#__PURE__*/_jsx("path", {
247
- d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"
248
- }), /*#__PURE__*/_jsx("path", {
249
- d: "M14 2v4a2 2 0 0 0 2 2h4"
250
- }), /*#__PURE__*/_jsx("path", {
251
- d: "M10 9H8"
252
- }), /*#__PURE__*/_jsx("path", {
253
- d: "M16 13H8"
254
- }), /*#__PURE__*/_jsx("path", {
255
- d: "M16 17H8"
256
- })]
257
- });
258
-
259
- /** shared-ui Trash2 icon (native CLEAR ALL SETTINGS button icon). */
218
+ /** shared-ui Trash2 icon (native Clear All Settings button icon). */
260
219
  const Trash2 = ({
261
220
  size = 24,
262
221
  color = 'currentColor'
@@ -288,7 +247,7 @@ const Trash2 = ({
288
247
  })]
289
248
  });
290
249
  function ChevronRightIcon({
291
- size = 18,
250
+ size = 16,
292
251
  color = 'currentColor'
293
252
  }) {
294
253
  return /*#__PURE__*/_jsx("svg", {
@@ -306,7 +265,7 @@ function ChevronRightIcon({
306
265
  });
307
266
  }
308
267
  function ChevronDownIcon({
309
- size = 18,
268
+ size = 16,
310
269
  color = 'currentColor'
311
270
  }) {
312
271
  return /*#__PURE__*/_jsx("svg", {
@@ -326,14 +285,15 @@ function ChevronDownIcon({
326
285
 
327
286
  /**
328
287
  * Tool icon mapping — mirrors the native getToolIcon() switch in
329
- * DevToolsSettingsModal.tsx. Real tool icons come from floating-tools-core
330
- * (web-compatible); shared-ui-only icons (SentryBugIcon, WifiCircuitIcon,
331
- * Layers, RenderCountIcon) use the closest web SVG fallback.
288
+ * DevToolsSettingsModal.tsx (size 18 in the night rows). Real tool icons come
289
+ * from floating-tools-core (web-compatible); shared-ui-only icons use the
290
+ * closest web SVG fallback.
332
291
  */
333
292
  function ToolIcon({
334
- toolId
293
+ toolId,
294
+ tool
335
295
  }) {
336
- const size = 16; // native: getToolIcon renders all icons at size 16
296
+ const size = 18; // native: getToolIcon renders all icons at size 18
337
297
  switch (toolId) {
338
298
  case 'query':
339
299
  return /*#__PURE__*/_jsx(QueryIcon, {
@@ -348,11 +308,13 @@ function ToolIcon({
348
308
  // native: SentryBugIcon colorPreset="red" noBackground
349
309
  return /*#__PURE__*/_jsx(AlertTriangle, {
350
310
  size: size,
351
- color: buoy.error
311
+ color: night.danger
352
312
  });
353
313
  case 'storage':
314
+ // native passes bgColor=night surface for the BIF knock-out parts
354
315
  return /*#__PURE__*/_jsx(StorageIcon, {
355
- size: size
316
+ size: size,
317
+ bgColor: night.surface
356
318
  });
357
319
  case 'wifi':
358
320
  case 'query-wifi-toggle':
@@ -364,23 +326,24 @@ function ToolIcon({
364
326
  case 'routes':
365
327
  // web alias for the same tool
366
328
  return /*#__PURE__*/_jsx(RoutesIcon, {
367
- size: size
329
+ size: size,
330
+ bgColor: night.surface
368
331
  });
369
332
  case 'network':
370
333
  return /*#__PURE__*/_jsx(NetworkIcon, {
371
334
  size: size
372
335
  });
373
336
  case 'debug-borders':
374
- // native: Layers size 16 color buoyColors.primary
337
+ // native: Layers size 18 color night accent
375
338
  return /*#__PURE__*/_jsx(Layers, {
376
339
  size: size,
377
- color: buoy.primary
340
+ color: night.accent
378
341
  });
379
342
  case 'highlight-updates':
380
- // native: RenderCountIcon size 16 color buoyColors.primary
343
+ // native: RenderCountIcon size 18 color night accent
381
344
  return /*#__PURE__*/_jsx(Sparkles, {
382
345
  size: size,
383
- color: buoy.primary
346
+ color: night.accent
384
347
  });
385
348
  case 'highlight-updates-modal':
386
349
  return /*#__PURE__*/_jsx(HighlighterIcon, {
@@ -407,60 +370,236 @@ function ToolIcon({
407
370
  size: size
408
371
  });
409
372
  default:
410
- // native: Info size 16 color buoyColors.textSecondary
411
- return /*#__PURE__*/_jsx(Info, {
412
- size: size,
413
- color: buoy.textSecondary
414
- });
373
+ {
374
+ // Tools without a hardcoded glyph (console, images, time machine,
375
+ // perf monitor, custom toolkit tools, …) render their own icon —
376
+ // mirrors the native getToolIcon() renderAppIcon fallback.
377
+ if (typeof tool?.icon === 'function') {
378
+ return /*#__PURE__*/_jsx(_Fragment, {
379
+ children: tool.icon(size)
380
+ });
381
+ }
382
+ if (typeof tool?.icon === 'string') {
383
+ // Web twin of native AppTextIcon: short labels/emoji auto-fit the slot.
384
+ return /*#__PURE__*/_jsx("span", {
385
+ style: {
386
+ maxWidth: size * 1.6,
387
+ overflow: 'hidden',
388
+ whiteSpace: 'nowrap',
389
+ fontSize: tool.icon.length <= 2 ? size * 0.7 : 10,
390
+ fontWeight: 800,
391
+ letterSpacing: 0.5,
392
+ textAlign: 'center',
393
+ color: tool.color ?? night.textSecondary
394
+ },
395
+ children: tool.icon
396
+ });
397
+ }
398
+ // native: Info size 18 color night textSecondary
399
+ return /*#__PURE__*/_jsx(Info, {
400
+ size: size,
401
+ color: night.textSecondary
402
+ });
403
+ }
415
404
  }
416
405
  }
417
406
 
418
407
  // =============================
419
- // Toggle Pill (shared by cards)
408
+ // Night primitives (DOM twins of shared-ui ui/night/primitives.tsx)
420
409
  // =============================
421
410
 
422
- /**
423
- * Native styles.pillToggle / pillToggleOn / pillToggleOff.
424
- * onColor lets the global-settings cards use the success color like native.
425
- */
426
- function togglePillStyle(on, onColor, onStrongBorder) {
427
- return {
428
- paddingLeft: 14,
429
- // native DevToolsSettingsModal.tsx pillToggle: paddingHorizontal 14
430
- paddingRight: 14,
431
- paddingTop: settingsStyles.toggle.paddingVertical,
432
- paddingBottom: settingsStyles.toggle.paddingVertical,
433
- borderRadius: 6,
434
- // native pillToggle: borderRadius 6
435
- borderWidth: settingsStyles.toggle.borderWidth,
436
- borderStyle: 'solid',
437
- minWidth: 48,
438
- // native pillToggle: minWidth 48
439
- boxSizing: 'border-box',
440
- display: 'inline-flex',
441
- alignItems: 'center',
442
- justifyContent: 'center',
443
- backgroundColor: on ? `${onColor}${onStrongBorder ? '33' : '20'}` : buoy.hover,
444
- borderColor: on ? onStrongBorder ? `${onColor}88` : onColor : buoy.border,
445
- color: on ? onColor : buoy.textMuted,
446
- fontSize: settingsStyles.toggle.fontSize,
447
- fontWeight: 600,
448
- // native pillToggleText: fontWeight 600
449
- letterSpacing: 0.5,
450
- // native pillToggleText: letterSpacing 0.5
451
- fontFamily: 'inherit',
452
- cursor: 'pointer',
453
- transition: 'all 150ms ease',
454
- // native global-settings toggle: teal glow when ON (shadowRadius 8 / opacity 0.4)
455
- boxShadow: on && onStrongBorder ? `0 0 8px ${onColor}66` : 'none'
456
- };
411
+ /** native NightSectionLabel: 12/600/ls0.8 uppercase, mb 8, ml 4 */
412
+ function SectionLabel({
413
+ children
414
+ }) {
415
+ return /*#__PURE__*/_jsx("div", {
416
+ style: {
417
+ color: night.textSecondary,
418
+ fontSize: 12,
419
+ fontWeight: 600,
420
+ letterSpacing: 0.8,
421
+ textTransform: 'uppercase',
422
+ marginBottom: 8,
423
+ marginLeft: 4
424
+ },
425
+ children: children
426
+ });
427
+ }
428
+
429
+ /** native NightFootnote: 13/500 textTertiary, mt 8, ml 4 */
430
+ function Footnote({
431
+ children,
432
+ tone = 'tertiary'
433
+ }) {
434
+ return /*#__PURE__*/_jsx("div", {
435
+ style: {
436
+ color: tone === 'warning' ? night.warning : tone === 'danger' ? night.danger : night.textTertiary,
437
+ fontSize: 13,
438
+ fontWeight: 500,
439
+ lineHeight: '18px',
440
+ marginTop: 8,
441
+ marginLeft: 4
442
+ },
443
+ children: children
444
+ });
445
+ }
446
+
447
+ /** native NightCard: #0C0C0C, radius 14, 1px #1A1A1C, clipped */
448
+ const cardStyle = {
449
+ backgroundColor: night.surface,
450
+ borderRadius: 14,
451
+ border: `1px solid ${night.border}`,
452
+ overflow: 'hidden'
453
+ };
454
+
455
+ /** native NightSeparator: hairline inset 16 */
456
+ function Separator({
457
+ inset = 16
458
+ }) {
459
+ return /*#__PURE__*/_jsx("div", {
460
+ style: {
461
+ height: 1,
462
+ transform: 'scaleY(0.5)',
463
+ // hairline
464
+ marginLeft: inset,
465
+ backgroundColor: night.separator
466
+ }
467
+ });
468
+ }
469
+
470
+ /** native NightSwitch: 56×32 track, 22px thumb, 24px travel, 200ms */
471
+ function NightSwitch({
472
+ value,
473
+ onChange,
474
+ disabled
475
+ }) {
476
+ return /*#__PURE__*/_jsx("button", {
477
+ role: "switch",
478
+ "aria-checked": value,
479
+ disabled: disabled,
480
+ onClick: e => {
481
+ e.stopPropagation();
482
+ if (!disabled) onChange();
483
+ },
484
+ style: {
485
+ width: 56,
486
+ height: 32,
487
+ borderRadius: 16,
488
+ border: `1px solid ${value ? night.accentBorderStrong : night.fillTertiary}`,
489
+ backgroundColor: value ? night.accentFill : night.surfaceElevated,
490
+ padding: 0,
491
+ position: 'relative',
492
+ cursor: disabled ? 'not-allowed' : 'pointer',
493
+ opacity: disabled ? 0.4 : 1,
494
+ flexShrink: 0,
495
+ boxSizing: 'border-box',
496
+ transition: 'background-color 200ms ease, border-color 200ms ease'
497
+ },
498
+ children: /*#__PURE__*/_jsx("span", {
499
+ style: {
500
+ position: 'absolute',
501
+ top: 4,
502
+ left: 4,
503
+ width: 22,
504
+ height: 22,
505
+ borderRadius: 11,
506
+ backgroundColor: value ? night.accent : night.knob,
507
+ transform: value ? 'translateX(24px)' : 'translateX(0)',
508
+ transition: 'transform 200ms ease, background-color 200ms ease'
509
+ }
510
+ })
511
+ });
512
+ }
513
+
514
+ /** native NightBadge: uppercase 11/600 cap on a soft tint */
515
+ function Badge({
516
+ label,
517
+ tone = 'neutral'
518
+ }) {
519
+ const bg = tone === 'accent' ? night.accentSoft : tone === 'warning' ? night.warningSoft : tone === 'danger' ? night.dangerSoft : night.fillSecondary;
520
+ const color = tone === 'accent' ? night.accent : tone === 'warning' ? night.warning : tone === 'danger' ? night.danger : night.textSecondary;
521
+ return /*#__PURE__*/_jsx("span", {
522
+ style: {
523
+ padding: '4px 8px',
524
+ borderRadius: 6,
525
+ backgroundColor: bg,
526
+ color,
527
+ fontSize: 11,
528
+ fontWeight: 600,
529
+ letterSpacing: 0.5,
530
+ textTransform: 'uppercase',
531
+ flexShrink: 0
532
+ },
533
+ children: label
534
+ });
535
+ }
536
+
537
+ /** native NightButton size md: 34pt, radius 17, plate or accent fill */
538
+ function NightButton({
539
+ label,
540
+ onClick,
541
+ variant = 'secondary',
542
+ icon,
543
+ disabled
544
+ }) {
545
+ const color = variant === 'primary' ? night.onAccent : variant === 'destructive' ? night.danger : night.accent;
546
+ return /*#__PURE__*/_jsxs("button", {
547
+ onClick: onClick,
548
+ disabled: disabled,
549
+ style: {
550
+ width: '100%',
551
+ height: 34,
552
+ borderRadius: 17,
553
+ border: 'none',
554
+ display: 'flex',
555
+ alignItems: 'center',
556
+ justifyContent: 'center',
557
+ gap: 8,
558
+ backgroundColor: variant === 'primary' ? night.accent : night.button,
559
+ color,
560
+ fontSize: 15,
561
+ fontWeight: 600,
562
+ fontFamily: 'inherit',
563
+ cursor: disabled ? 'not-allowed' : 'pointer',
564
+ opacity: disabled ? 0.4 : 1,
565
+ transition: 'background-color 150ms ease, opacity 150ms ease'
566
+ },
567
+ children: [icon, label]
568
+ });
457
569
  }
458
570
 
459
571
  // =============================
460
- // Tool Card Component
572
+ // Row styles (native styles.settingRow / toolRow / rowLabel / rowCaption)
461
573
  // =============================
462
574
 
463
- function ToolCard({
575
+ const settingRowStyle = {
576
+ display: 'flex',
577
+ flexDirection: 'row',
578
+ alignItems: 'center',
579
+ gap: 10,
580
+ padding: '14px 16px',
581
+ minHeight: 52,
582
+ boxSizing: 'border-box',
583
+ cursor: 'pointer'
584
+ };
585
+ const rowLabelStyle = {
586
+ color: night.text,
587
+ fontSize: 15,
588
+ fontWeight: 500
589
+ };
590
+ const rowCaptionStyle = {
591
+ color: night.textTertiary,
592
+ fontSize: 12,
593
+ overflow: 'hidden',
594
+ textOverflow: 'ellipsis',
595
+ whiteSpace: 'nowrap'
596
+ };
597
+
598
+ // =============================
599
+ // Tool Row (native renderToolRow)
600
+ // =============================
601
+
602
+ function ToolRow({
464
603
  toolId,
465
604
  enabled,
466
605
  disabled,
@@ -469,101 +608,59 @@ function ToolCard({
469
608
  }) {
470
609
  const label = getToolLabel(toolId, availableTools);
471
610
  const description = getToolDescription(toolId, availableTools);
472
-
473
- // native styles.glassCard / glassCardActive
474
- const cardStyle = {
475
- display: 'flex',
476
- flexDirection: 'row',
477
- alignItems: 'center',
478
- gap: 12,
479
- // native glassCardInner: gap 12
480
- paddingTop: 12,
481
- // native glassCard: paddingVertical 12
482
- paddingBottom: 12,
483
- paddingLeft: settingsStyles.card.paddingHorizontal,
484
- paddingRight: settingsStyles.card.paddingHorizontal,
485
- backgroundColor: enabled ? `${buoy.primary}08` : buoy.card,
486
- // native glassCardActive bg
487
- borderRadius: 12,
488
- // native glassCard: borderRadius 12
489
- borderWidth: settingsStyles.card.borderWidth,
490
- borderStyle: 'solid',
491
- borderColor: enabled ? `${buoy.primary}50` : buoy.border,
492
- // native glassCardActive border
493
- marginBottom: 8,
494
- // native renderToolCard wrapper: marginBottom 8
495
- cursor: disabled ? 'not-allowed' : 'pointer',
496
- opacity: disabled ? 0.5 : 1,
497
- // native wrapper: opacity 0.5 when disabled
498
- transition: 'all 150ms ease'
499
- };
500
611
  return /*#__PURE__*/_jsxs("div", {
501
612
  onClick: disabled ? undefined : onToggle,
502
- style: cardStyle,
613
+ style: {
614
+ // native styles.toolRow: gap 12, px 16, py 12
615
+ display: 'flex',
616
+ flexDirection: 'row',
617
+ alignItems: 'center',
618
+ gap: 12,
619
+ padding: '12px 16px',
620
+ cursor: disabled ? 'not-allowed' : 'pointer',
621
+ opacity: disabled ? 0.4 : 1
622
+ },
503
623
  children: [/*#__PURE__*/_jsx("div", {
504
624
  style: {
505
- width: 32,
506
- // native iconContainer: 32x32
507
- height: 32,
508
- borderRadius: 8,
509
- // native iconContainer: borderRadius 8
510
- backgroundColor: enabled ? `${buoy.primary}20` : buoy.hover,
625
+ width: 24,
511
626
  display: 'flex',
512
627
  alignItems: 'center',
513
628
  justifyContent: 'center',
514
629
  flexShrink: 0
515
630
  },
516
631
  children: /*#__PURE__*/_jsx(ToolIcon, {
517
- toolId: toolId
632
+ toolId: toolId,
633
+ tool: availableTools?.find(t => t.id === toolId)
518
634
  })
519
635
  }), /*#__PURE__*/_jsxs("div", {
520
636
  style: {
521
637
  flex: 1,
522
- minWidth: 0
638
+ minWidth: 0,
639
+ display: 'flex',
640
+ flexDirection: 'column',
641
+ gap: 2
523
642
  },
524
643
  children: [/*#__PURE__*/_jsxs("div", {
525
- style: {
526
- color: buoy.text,
527
- fontWeight: 600,
528
- // native toolName: fontWeight 600
529
- fontSize: settingsStyles.toolName.fontSize
530
- },
531
- children: [label, disabled && ' (MAX 6)']
532
- }), /*#__PURE__*/_jsx("div", {
533
- style: {
534
- color: buoy.textMuted,
535
- fontSize: settingsStyles.toolDescription.fontSize,
536
- marginTop: 2,
537
- // native toolDescription: marginTop 2
538
- overflow: 'hidden',
539
- textOverflow: 'ellipsis',
540
- whiteSpace: 'nowrap'
541
- },
644
+ style: rowLabelStyle,
645
+ children: [label, disabled && ' · max 6']
646
+ }), description ? /*#__PURE__*/_jsx("div", {
647
+ style: rowCaptionStyle,
542
648
  children: description
543
- })]
544
- }), /*#__PURE__*/_jsx("button", {
545
- onClick: e => {
546
- e.stopPropagation();
547
- if (!disabled) onToggle();
548
- },
649
+ }) : null]
650
+ }), /*#__PURE__*/_jsx(NightSwitch, {
651
+ value: enabled,
549
652
  disabled: disabled,
550
- style: {
551
- ...togglePillStyle(enabled, buoy.primary, false),
552
- cursor: disabled ? 'not-allowed' : 'pointer'
553
- },
554
- children: enabled ? 'ON' : 'OFF'
653
+ onChange: onToggle
555
654
  })]
556
655
  });
557
656
  }
558
657
 
559
658
  // =============================
560
- // Global Setting Card (expandable, native renderGlobalSettingCard)
659
+ // Global Setting Row (native renderGlobalSettingRow)
561
660
  // =============================
562
661
 
563
- function GlobalSettingCard({
564
- configKey,
662
+ function GlobalSettingRow({
565
663
  label,
566
- category,
567
664
  shortDescription,
568
665
  fullDescription,
569
666
  recommendation,
@@ -571,155 +668,57 @@ function GlobalSettingCard({
571
668
  onToggle
572
669
  }) {
573
670
  const [isExpanded, setIsExpanded] = useState(false);
574
-
575
- // native styles.expandableCard (+ expanded teal ring/glow/scale)
576
- const cardStyle = {
577
- backgroundColor: buoy.card,
578
- borderRadius: 8,
579
- borderWidth: isExpanded ? 2 : 1,
580
- // native expanded: borderWidth 2
581
- borderStyle: 'solid',
582
- borderColor: isExpanded ? buoy.primary : buoy.border,
583
- padding: 12,
584
- cursor: 'pointer',
585
- transition: 'all 150ms ease',
586
- // native expanded: shadowColor primary, opacity 0.8, radius 20
587
- boxShadow: isExpanded ? `0 0 20px ${buoy.primary}CC` : 'none',
588
- transform: isExpanded ? 'scale(1.01)' : 'scale(1)' // native expanded: scale 1.01
589
- };
590
- return /*#__PURE__*/_jsx("div", {
591
- style: {
592
- marginBottom: 10
593
- },
594
- children: /*#__PURE__*/_jsxs("div", {
671
+ return /*#__PURE__*/_jsxs("div", {
672
+ children: [/*#__PURE__*/_jsxs("div", {
595
673
  onClick: () => setIsExpanded(v => !v),
596
- style: cardStyle,
674
+ style: settingRowStyle,
597
675
  children: [/*#__PURE__*/_jsxs("div", {
598
676
  style: {
677
+ flex: 1,
678
+ minWidth: 0,
599
679
  display: 'flex',
600
- alignItems: 'center',
601
- gap: 12
680
+ flexDirection: 'column',
681
+ gap: 2
602
682
  },
603
683
  children: [/*#__PURE__*/_jsx("div", {
604
- style: {
605
- backgroundColor: `${buoy.primary}20`,
606
- border: `1px solid ${buoy.primary}40`,
607
- borderRadius: 4,
608
- padding: '4px 8px',
609
- flexShrink: 0
610
- },
611
- children: /*#__PURE__*/_jsx("span", {
612
- style: {
613
- fontSize: 10,
614
- fontWeight: 700,
615
- color: buoy.primary,
616
- letterSpacing: 0.5
617
- },
618
- children: category
619
- })
620
- }), /*#__PURE__*/_jsxs("div", {
621
- style: {
622
- flex: 1,
623
- minWidth: 0,
624
- paddingLeft: 4,
625
- paddingRight: 4
626
- },
627
- children: [/*#__PURE__*/_jsx("div", {
628
- style: {
629
- fontFamily: 'monospace',
630
- fontSize: 12,
631
- fontWeight: 700,
632
- color: buoy.text
633
- },
634
- children: label
635
- }), !isExpanded && /*#__PURE__*/_jsx("div", {
636
- style: {
637
- fontSize: 10,
638
- color: buoy.textMuted,
639
- marginTop: 2,
640
- overflow: 'hidden',
641
- textOverflow: 'ellipsis',
642
- whiteSpace: 'nowrap'
643
- },
644
- children: shortDescription
645
- })]
646
- }), /*#__PURE__*/_jsxs("div", {
647
- style: {
648
- display: 'flex',
649
- alignItems: 'center',
650
- gap: 8,
651
- flexShrink: 0
652
- },
653
- children: [/*#__PURE__*/_jsx("button", {
654
- onClick: e => {
655
- e.stopPropagation();
656
- onToggle();
657
- },
658
- style: togglePillStyle(value, buoy.success, true),
659
- children: value ? 'ON' : 'OFF'
660
- }), isExpanded ?
661
- /*#__PURE__*/
662
- // native: ChevronDown size 18 color #7F91B2
663
- _jsx(ChevronDownIcon, {
664
- size: 18,
665
- color: "#7F91B2"
666
- }) : /*#__PURE__*/_jsx(ChevronRightIcon, {
667
- size: 18,
668
- color: "#7F91B2"
669
- })]
684
+ style: rowLabelStyle,
685
+ children: label
686
+ }), /*#__PURE__*/_jsx("div", {
687
+ style: isExpanded ? {
688
+ ...rowCaptionStyle,
689
+ whiteSpace: 'normal'
690
+ } : rowCaptionStyle,
691
+ children: shortDescription
670
692
  })]
671
- }), isExpanded && /*#__PURE__*/_jsxs("div", {
693
+ }), /*#__PURE__*/_jsx(NightSwitch, {
694
+ value: value,
695
+ onChange: onToggle
696
+ })]
697
+ }), isExpanded && /*#__PURE__*/_jsxs("div", {
698
+ style: {
699
+ // native settingRowBody: px 16, pb 14, gap 6
700
+ padding: '0 16px 14px',
701
+ display: 'flex',
702
+ flexDirection: 'column',
703
+ gap: 6
704
+ },
705
+ children: [/*#__PURE__*/_jsx("div", {
672
706
  style: {
673
- marginTop: 12,
674
- paddingTop: 12,
675
- borderTop: `1px solid ${buoy.border}50`
707
+ color: night.textSecondary,
708
+ fontSize: 13,
709
+ lineHeight: '19px'
676
710
  },
677
- children: [/*#__PURE__*/_jsxs("div", {
678
- style: {
679
- marginBottom: 12
680
- },
681
- children: [/*#__PURE__*/_jsx("div", {
682
- style: {
683
- fontSize: 10,
684
- fontWeight: 700,
685
- color: buoy.primary,
686
- letterSpacing: 1,
687
- marginBottom: 6
688
- },
689
- children: "DESCRIPTION"
690
- }), /*#__PURE__*/_jsx("div", {
691
- style: {
692
- fontSize: 12,
693
- color: buoy.textSecondary,
694
- lineHeight: '18px'
695
- },
696
- children: fullDescription
697
- })]
698
- }), /*#__PURE__*/_jsxs("div", {
699
- style: {
700
- marginBottom: 12
701
- },
702
- children: [/*#__PURE__*/_jsx("div", {
703
- style: {
704
- fontSize: 10,
705
- fontWeight: 700,
706
- color: buoy.primary,
707
- letterSpacing: 1,
708
- marginBottom: 6
709
- },
710
- children: "RECOMMENDATION"
711
- }), /*#__PURE__*/_jsx("div", {
712
- style: {
713
- fontSize: 12,
714
- color: buoy.textSecondary,
715
- lineHeight: '18px'
716
- },
717
- children: recommendation
718
- })]
719
- })]
711
+ children: fullDescription
712
+ }), /*#__PURE__*/_jsx("div", {
713
+ style: {
714
+ color: night.textTertiary,
715
+ fontSize: 13,
716
+ lineHeight: '19px'
717
+ },
718
+ children: recommendation
720
719
  })]
721
- })
722
- }, configKey);
720
+ })]
721
+ });
723
722
  }
724
723
 
725
724
  // =============================
@@ -782,7 +781,7 @@ export function SettingsModal({
782
781
  }
783
782
  }, [visible, isStorageExpanded, clearSuccess, settings]);
784
783
  const handleClearAll = useCallback(() => {
785
- // Same behavior as before (reset via the shared hook); the 2s "CLEARED"
784
+ // Same behavior as before (reset via the shared hook); the 2s "Cleared"
786
785
  // flash mirrors the native clear button feedback.
787
786
  actions.resetToDefaults();
788
787
  setClearSuccess(true);
@@ -793,61 +792,67 @@ export function SettingsModal({
793
792
  // Filter tabs - exclude 'pro' for now on web
794
793
  const displayTabs = settingsTabs.filter(tab => tab.key !== 'pro');
795
794
 
796
- // Tab pill row rendered inside the JsModal header — native passes
797
- // ModalHeader + TabSelector as header.customContent the same way.
795
+ // Segmented control rendered inside the JsModal header — native passes a
796
+ // NightSegmented as header.customContent the same way. Track = night bg at
797
+ // radius 10 / padding 3; active thumb = surfaceElevated at radius 8 with
798
+ // the accent underline glow (the Everlights All/Day tabs).
798
799
  const tabHeader = /*#__PURE__*/_jsx("div", {
799
800
  style: {
800
801
  display: 'flex',
801
802
  alignItems: 'center',
802
- paddingLeft: 4,
803
- paddingRight: 28,
803
+ paddingLeft: 16,
804
+ paddingRight: 64,
804
805
  // clears JsModal's absolutely-positioned window controls
805
- paddingBottom: 6
806
+ paddingBottom: 8
806
807
  },
807
808
  children: /*#__PURE__*/_jsx("div", {
808
809
  style: {
809
810
  flex: 1,
810
811
  display: 'flex',
811
- backgroundColor: buoy.hover,
812
- borderRadius: 6,
813
- padding: 2,
814
- border: `1px solid ${buoy.border}`,
815
- height: 28,
812
+ backgroundColor: night.bg,
813
+ borderRadius: 10,
814
+ border: `1px solid ${night.border}`,
815
+ padding: 3,
816
816
  boxSizing: 'border-box'
817
817
  },
818
818
  children: displayTabs.map(tab => {
819
819
  const isActive = activeTab === tab.key;
820
- return /*#__PURE__*/_jsx("button", {
820
+ // native settingsTabs labels are uppercase ids; night shows title case
821
+ const label = tab.label.charAt(0).toUpperCase() + tab.label.slice(1).toLowerCase();
822
+ return /*#__PURE__*/_jsxs("button", {
821
823
  onClick: () => setActiveTab(tab.key),
824
+ role: "tab",
825
+ "aria-selected": isActive,
822
826
  style: {
823
827
  flex: 1,
824
- marginLeft: 1,
825
- // native TabSelector tabButton: marginHorizontal 1
826
- marginRight: 1,
827
- paddingLeft: settingsStyles.tab.paddingHorizontal,
828
- paddingRight: settingsStyles.tab.paddingHorizontal,
829
- paddingTop: 3,
830
- // native TabSelector tabButton: paddingVertical 3
831
- paddingBottom: 3,
832
- borderRadius: settingsStyles.tab.borderRadius,
833
- // native tabButtonActive: bg primary+20, 1px primary border
834
- backgroundColor: isActive ? `${buoy.primary}20` : 'transparent',
835
- border: isActive ? `1px solid ${buoy.primary}` : '1px solid transparent',
836
- color: isActive ? buoy.primary : buoy.textMuted,
837
- fontSize: settingsStyles.tab.fontSize,
838
- fontWeight: settingsStyles.tab.fontWeight,
839
- letterSpacing: settingsStyles.tab.letterSpacing,
828
+ position: 'relative',
829
+ padding: '8px 0',
830
+ borderRadius: 8,
831
+ border: 'none',
832
+ backgroundColor: isActive ? night.surfaceElevated : 'transparent',
833
+ color: isActive ? night.text : night.textSecondary,
834
+ fontSize: 13,
835
+ fontWeight: isActive ? 600 : 500,
836
+ fontFamily: 'inherit',
840
837
  cursor: 'pointer',
841
838
  transition: 'all 150ms ease',
842
- textTransform: 'uppercase',
843
- fontFamily: 'inherit',
844
- // native TabSelector uses the system font
845
- boxSizing: 'border-box',
846
839
  display: 'flex',
847
840
  alignItems: 'center',
848
841
  justifyContent: 'center'
849
842
  },
850
- children: tab.label
843
+ children: [label, isActive && /*#__PURE__*/_jsx("span", {
844
+ style: {
845
+ position: 'absolute',
846
+ bottom: 2,
847
+ left: '50%',
848
+ transform: 'translateX(-50%)',
849
+ width: 24,
850
+ height: 2.5,
851
+ borderRadius: 1.25,
852
+ backgroundColor: night.accent,
853
+ boxShadow: `0 0 6px ${night.accent}99`
854
+ }
855
+ })]
851
856
  }, tab.key);
852
857
  })
853
858
  })
@@ -860,6 +865,7 @@ export function SettingsModal({
860
865
  return /*#__PURE__*/_jsx(JsModal, {
861
866
  visible: visible,
862
867
  onClose: handleClose,
868
+ variant: "night",
863
869
  header: {
864
870
  showToggleButton: false,
865
871
  customContent: tabHeader
@@ -880,11 +886,11 @@ export function SettingsModal({
880
886
  flex: 1,
881
887
  minHeight: 0,
882
888
  overflow: 'auto',
883
- backgroundColor: buoy.base,
884
- paddingTop: settingsStyles.scrollContent.paddingTop,
885
- paddingBottom: settingsStyles.scrollContent.paddingBottom,
886
- paddingLeft: settingsStyles.section.marginHorizontal,
887
- paddingRight: settingsStyles.section.marginHorizontal
889
+ backgroundColor: 'transparent',
890
+ padding: '8px 16px 24px',
891
+ display: 'flex',
892
+ flexDirection: 'column',
893
+ gap: 24
888
894
  },
889
895
  children: isLoading ? /*#__PURE__*/_jsx("div", {
890
896
  style: {
@@ -892,209 +898,176 @@ export function SettingsModal({
892
898
  alignItems: 'center',
893
899
  justifyContent: 'center',
894
900
  padding: 40,
895
- color: buoy.textMuted,
896
- fontSize: 12
901
+ color: night.textTertiary,
902
+ fontSize: 13
897
903
  },
898
- children: "Loading settings..."
904
+ children: "Loading settings\u2026"
899
905
  }) : /*#__PURE__*/_jsxs(_Fragment, {
900
- children: [activeTab === 'floating' && /*#__PURE__*/_jsx("div", {
901
- children: Object.entries(settings.floatingTools).map(([id, enabled]) => /*#__PURE__*/_jsx(ToolCard, {
902
- toolId: id,
903
- enabled: enabled,
904
- availableTools: availableTools,
905
- onToggle: () => id === 'environment' ? actions.toggleEnvironment() : actions.toggleFloatingTool(id)
906
- }, id))
907
- }), activeTab === 'settings' && /*#__PURE__*/_jsxs("div", {
906
+ children: [activeTab === 'floating' && /*#__PURE__*/_jsxs("div", {
907
+ children: [/*#__PURE__*/_jsx(SectionLabel, {
908
+ children: "Floating Tools"
909
+ }), /*#__PURE__*/_jsx("div", {
910
+ style: cardStyle,
911
+ children: Object.entries(settings.floatingTools).map(([id, enabled], index) => /*#__PURE__*/_jsxs("div", {
912
+ children: [index > 0 && /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsx(ToolRow, {
913
+ toolId: id,
914
+ enabled: enabled,
915
+ availableTools: availableTools,
916
+ onToggle: () => id === 'environment' ? actions.toggleEnvironment() : actions.toggleFloatingTool(id)
917
+ })]
918
+ }, id))
919
+ }), /*#__PURE__*/_jsx(Footnote, {
920
+ children: "Tools switched on here appear in the floating bubble row."
921
+ })]
922
+ }), activeTab === 'settings' && /*#__PURE__*/_jsxs(_Fragment, {
908
923
  children: [/*#__PURE__*/_jsxs("div", {
909
- style: {
910
- backgroundColor: buoy.card,
911
- borderRadius: 8,
912
- border: `1px solid ${isStorageExpanded ? `${buoy.success}60` : buoy.border}`,
913
- padding: 12,
914
- marginBottom: 10,
915
- transition: 'border-color 150ms ease'
916
- },
917
- children: [/*#__PURE__*/_jsxs("div", {
918
- onClick: () => setIsStorageExpanded(v => !v),
924
+ children: [/*#__PURE__*/_jsx(SectionLabel, {
925
+ children: "Background"
926
+ }), /*#__PURE__*/_jsx("div", {
919
927
  style: {
920
- display: 'flex',
921
- alignItems: 'center',
922
- gap: 12,
923
- marginBottom: 8,
924
- cursor: 'pointer'
928
+ ...cardStyle,
929
+ padding: 14
925
930
  },
926
- children: [/*#__PURE__*/_jsx("div", {
927
- style: {
928
- width: 36,
929
- height: 36,
930
- borderRadius: 8,
931
- backgroundColor: `${buoy.success}15`,
932
- display: 'flex',
933
- alignItems: 'center',
934
- justifyContent: 'center',
935
- flexShrink: 0
936
- },
937
- children: /*#__PURE__*/_jsx(Database, {
938
- size: 18,
939
- color: buoy.success
940
- })
941
- }), /*#__PURE__*/_jsxs("div", {
942
- style: {
943
- flex: 1,
944
- minWidth: 0
945
- },
931
+ children: /*#__PURE__*/_jsx(BackgroundSwitcher, {
932
+ embedded: true
933
+ })
934
+ })]
935
+ }), /*#__PURE__*/_jsxs("div", {
936
+ children: [/*#__PURE__*/_jsx(SectionLabel, {
937
+ children: "Storage"
938
+ }), /*#__PURE__*/_jsxs("div", {
939
+ style: cardStyle,
940
+ children: [/*#__PURE__*/_jsxs("div", {
941
+ onClick: () => setIsStorageExpanded(v => !v),
942
+ style: settingRowStyle,
946
943
  children: [/*#__PURE__*/_jsx("div", {
947
944
  style: {
948
- fontSize: 10,
949
- fontWeight: 700,
950
- color: buoy.textMuted,
951
- letterSpacing: 1,
952
- marginBottom: 4
945
+ flex: 1,
946
+ minWidth: 0
953
947
  },
954
- children: "STORAGE TYPE"
955
- }), /*#__PURE__*/_jsxs("div", {
948
+ children: /*#__PURE__*/_jsx("div", {
949
+ style: rowLabelStyle,
950
+ children: "Storage Type"
951
+ })
952
+ }), /*#__PURE__*/_jsx(Badge, {
953
+ label: "Local Storage",
954
+ tone: "accent"
955
+ }), isStorageExpanded ? /*#__PURE__*/_jsx(ChevronDownIcon, {
956
+ size: 16,
957
+ color: night.textTertiary
958
+ }) : /*#__PURE__*/_jsx(ChevronRightIcon, {
959
+ size: 16,
960
+ color: night.textTertiary
961
+ })]
962
+ }), isStorageExpanded && /*#__PURE__*/_jsxs(_Fragment, {
963
+ children: [/*#__PURE__*/_jsx("div", {
956
964
  style: {
957
- display: 'flex',
958
- alignItems: 'center',
959
- gap: 6
965
+ padding: '0 16px 14px'
960
966
  },
961
- children: [/*#__PURE__*/_jsx("span", {
967
+ children: /*#__PURE__*/_jsx("div", {
962
968
  style: {
963
- padding: '4px 8px',
964
- borderRadius: 4,
965
- border: `1px solid ${buoy.success}60`,
966
- backgroundColor: `${buoy.success}20`,
967
- color: buoy.success,
968
- fontSize: 11,
969
- fontWeight: 700,
970
- letterSpacing: 0.5
969
+ color: night.textSecondary,
970
+ fontSize: 13,
971
+ lineHeight: '19px'
971
972
  },
972
- children: "LOCAL STORAGE"
973
- }), /*#__PURE__*/_jsx(CheckCircle2, {
974
- size: 14,
975
- color: buoy.success
976
- })]
977
- })]
978
- }), isStorageExpanded ? /*#__PURE__*/_jsx(ChevronDownIcon, {
979
- size: 18,
980
- color: buoy.textMuted
981
- }) : /*#__PURE__*/_jsx(ChevronRightIcon, {
982
- size: 18,
983
- color: buoy.textMuted
984
- })]
985
- }), /*#__PURE__*/_jsx("div", {
986
- style: {
987
- fontSize: 11,
988
- color: buoy.textMuted,
989
- lineHeight: '16px',
990
- marginBottom: 12
991
- },
992
- children: "Settings persist in the browser's localStorage and survive page reloads."
993
- }), isStorageExpanded && /*#__PURE__*/_jsxs("div", {
994
- style: {
995
- marginTop: 12,
996
- paddingTop: 12,
997
- borderTop: `1px solid ${buoy.border}50`,
998
- marginBottom: 12
999
- },
1000
- children: [/*#__PURE__*/_jsxs("div", {
1001
- style: {
1002
- display: 'flex',
1003
- alignItems: 'center',
1004
- gap: 8,
1005
- marginBottom: 10
1006
- },
1007
- children: [/*#__PURE__*/_jsx(FileText, {
1008
- size: 14,
1009
- color: buoy.primary
1010
- }), /*#__PURE__*/_jsx("span", {
1011
- style: {
1012
- fontSize: 10,
1013
- fontWeight: 700,
1014
- color: buoy.primary,
1015
- letterSpacing: 1,
1016
- flex: 1
1017
- },
1018
- children: "SAVED SETTINGS"
1019
- }), /*#__PURE__*/_jsxs("span", {
1020
- style: {
1021
- fontSize: 10,
1022
- color: buoy.textMuted
1023
- },
1024
- children: [savedKeys.length, " keys"]
1025
- })]
1026
- }), savedKeys.length === 0 ? /*#__PURE__*/_jsx("div", {
1027
- style: {
1028
- fontSize: 11,
1029
- color: buoy.textMuted,
1030
- fontStyle: 'italic',
1031
- padding: '8px 0'
1032
- },
1033
- children: "No settings saved yet"
1034
- }) : /*#__PURE__*/_jsx("div", {
1035
- style: {
1036
- maxHeight: 150,
1037
- overflow: 'auto'
1038
- },
1039
- children: savedKeys.map(key => /*#__PURE__*/_jsx("div", {
973
+ children: "Settings persist in the browser's localStorage and survive page reloads."
974
+ })
975
+ }), /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsxs("div", {
1040
976
  style: {
1041
- backgroundColor: buoy.hover,
1042
- borderRadius: 4,
1043
- padding: '6px 8px',
1044
- border: `1px solid ${buoy.border}50`,
1045
- marginBottom: 4
977
+ padding: '12px 16px',
978
+ display: 'flex',
979
+ flexDirection: 'column',
980
+ gap: 8
1046
981
  },
1047
- children: /*#__PURE__*/_jsx("div", {
982
+ children: [/*#__PURE__*/_jsxs("div", {
1048
983
  style: {
1049
- fontSize: 11,
1050
- color: buoy.textSecondary,
1051
- fontFamily: 'monospace',
1052
- overflow: 'hidden',
1053
- textOverflow: 'ellipsis',
1054
- whiteSpace: 'nowrap'
984
+ display: 'flex',
985
+ alignItems: 'center'
1055
986
  },
1056
- children: key.replace('@react_buoy_', '')
987
+ children: [/*#__PURE__*/_jsx("span", {
988
+ style: {
989
+ flex: 1,
990
+ color: night.textSecondary,
991
+ fontSize: 11,
992
+ fontWeight: 600,
993
+ letterSpacing: 0.5
994
+ },
995
+ children: "SAVED SETTINGS"
996
+ }), /*#__PURE__*/_jsxs("span", {
997
+ style: {
998
+ color: night.textTertiary,
999
+ fontSize: 11
1000
+ },
1001
+ children: [savedKeys.length, " keys"]
1002
+ })]
1003
+ }), savedKeys.length === 0 ? /*#__PURE__*/_jsx("div", {
1004
+ style: {
1005
+ color: night.textTertiary,
1006
+ fontSize: 13,
1007
+ fontStyle: 'italic'
1008
+ },
1009
+ children: "No settings saved yet"
1010
+ }) : /*#__PURE__*/_jsx("div", {
1011
+ style: {
1012
+ maxHeight: 150,
1013
+ overflow: 'auto'
1014
+ },
1015
+ children: savedKeys.map(key => /*#__PURE__*/_jsx("div", {
1016
+ style: {
1017
+ backgroundColor: night.surfaceElevated,
1018
+ borderRadius: 8,
1019
+ padding: '7px 10px',
1020
+ marginBottom: 4
1021
+ },
1022
+ children: /*#__PURE__*/_jsx("div", {
1023
+ style: {
1024
+ color: night.textSecondary,
1025
+ fontSize: 11,
1026
+ fontFamily: 'monospace',
1027
+ overflow: 'hidden',
1028
+ textOverflow: 'ellipsis',
1029
+ whiteSpace: 'nowrap'
1030
+ },
1031
+ children: key.replace('@react_buoy_', '')
1032
+ })
1033
+ }, key))
1034
+ })]
1035
+ }), /*#__PURE__*/_jsx("div", {
1036
+ style: {
1037
+ padding: '10px 14px 14px'
1038
+ },
1039
+ children: /*#__PURE__*/_jsx(NightButton, {
1040
+ label: clearSuccess ? 'Cleared' : 'Clear All Settings',
1041
+ variant: clearSuccess ? 'secondary' : 'destructive',
1042
+ onClick: handleClearAll,
1043
+ icon: clearSuccess ? /*#__PURE__*/_jsx(CheckCircle2, {
1044
+ size: 15,
1045
+ color: night.accent
1046
+ }) : /*#__PURE__*/_jsx(Trash2, {
1047
+ size: 15,
1048
+ color: night.danger
1049
+ })
1057
1050
  })
1058
- }, key))
1051
+ })]
1059
1052
  })]
1060
- }), /*#__PURE__*/_jsxs("button", {
1061
- onClick: handleClearAll,
1062
- style: {
1063
- width: '100%',
1064
- display: 'flex',
1065
- alignItems: 'center',
1066
- justifyContent: 'center',
1067
- gap: 8,
1068
- padding: '10px 16px',
1069
- borderRadius: 6,
1070
- border: `1px solid ${clearSuccess ? `${buoy.success}40` : `${buoy.error}40`}`,
1071
- backgroundColor: clearSuccess ? `${buoy.success}15` : `${buoy.error}15`,
1072
- color: clearSuccess ? buoy.success : buoy.error,
1073
- fontSize: 12,
1074
- fontWeight: 700,
1075
- letterSpacing: 0.5,
1076
- fontFamily: 'inherit',
1077
- cursor: 'pointer',
1078
- transition: 'all 150ms ease'
1079
- },
1080
- children: [clearSuccess ? /*#__PURE__*/_jsx(CheckCircle2, {
1081
- size: 14,
1082
- color: buoy.success
1083
- }) : /*#__PURE__*/_jsx(Trash2, {
1084
- size: 14,
1085
- color: buoy.error
1086
- }), clearSuccess ? 'CLEARED' : 'CLEAR ALL SETTINGS']
1087
1053
  })]
1088
- }), globalSettingsConfig.map(config => /*#__PURE__*/_jsx(GlobalSettingCard, {
1089
- configKey: config.key,
1090
- label: config.label,
1091
- category: config.category,
1092
- shortDescription: config.shortDescription,
1093
- fullDescription: config.fullDescription,
1094
- recommendation: config.recommendation,
1095
- value: settings.globalSettings?.[config.key] ?? false,
1096
- onToggle: () => actions.toggleGlobalSetting(config.key)
1097
- }, config.key))]
1054
+ }), /*#__PURE__*/_jsxs("div", {
1055
+ children: [/*#__PURE__*/_jsx(SectionLabel, {
1056
+ children: "Modal Behavior"
1057
+ }), /*#__PURE__*/_jsx("div", {
1058
+ style: cardStyle,
1059
+ children: globalSettingsConfig.map((config, index) => /*#__PURE__*/_jsxs("div", {
1060
+ children: [index > 0 && /*#__PURE__*/_jsx(Separator, {}), /*#__PURE__*/_jsx(GlobalSettingRow, {
1061
+ label: config.label,
1062
+ shortDescription: config.shortDescription,
1063
+ fullDescription: config.fullDescription,
1064
+ recommendation: config.recommendation,
1065
+ value: settings.globalSettings?.[config.key] ?? false,
1066
+ onToggle: () => actions.toggleGlobalSetting(config.key)
1067
+ })]
1068
+ }, config.key))
1069
+ })]
1070
+ })]
1098
1071
  })]
1099
1072
  })
1100
1073
  })