@buoy-gg/core 7.0.26 → 7.0.28

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