@buoy-gg/core 1.7.2

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 (132) hide show
  1. package/README.md +43 -0
  2. package/lib/commonjs/floatingMenu/AppHost.js +410 -0
  3. package/lib/commonjs/floatingMenu/AppHostLogic.js +44 -0
  4. package/lib/commonjs/floatingMenu/DefaultConfigContext.js +45 -0
  5. package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +2274 -0
  6. package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +49 -0
  7. package/lib/commonjs/floatingMenu/DraggableHeader.js +114 -0
  8. package/lib/commonjs/floatingMenu/FloatingDevTools.js +254 -0
  9. package/lib/commonjs/floatingMenu/FloatingMenu.js +364 -0
  10. package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +247 -0
  11. package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +206 -0
  12. package/lib/commonjs/floatingMenu/ToggleStateManager.js +36 -0
  13. package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +241 -0
  14. package/lib/commonjs/floatingMenu/defaultConfig.js +160 -0
  15. package/lib/commonjs/floatingMenu/dial/DialDevTools.js +835 -0
  16. package/lib/commonjs/floatingMenu/dial/DialIcon.js +246 -0
  17. package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +249 -0
  18. package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +70 -0
  19. package/lib/commonjs/floatingMenu/floatingTools.js +771 -0
  20. package/lib/commonjs/floatingMenu/settingsBus.js +23 -0
  21. package/lib/commonjs/floatingMenu/types.js +5 -0
  22. package/lib/commonjs/index.js +240 -0
  23. package/lib/commonjs/package.json +1 -0
  24. package/lib/module/floatingMenu/AppHost.js +402 -0
  25. package/lib/module/floatingMenu/AppHostLogic.js +39 -0
  26. package/lib/module/floatingMenu/DefaultConfigContext.js +39 -0
  27. package/lib/module/floatingMenu/DevToolsSettingsModal.js +2273 -0
  28. package/lib/module/floatingMenu/DevToolsVisibilityContext.js +44 -0
  29. package/lib/module/floatingMenu/DraggableHeader.js +110 -0
  30. package/lib/module/floatingMenu/FloatingDevTools.js +249 -0
  31. package/lib/module/floatingMenu/FloatingMenu.js +358 -0
  32. package/lib/module/floatingMenu/MinimizedToolsContext.js +239 -0
  33. package/lib/module/floatingMenu/MinimizedToolsStack.js +202 -0
  34. package/lib/module/floatingMenu/ToggleStateManager.js +32 -0
  35. package/lib/module/floatingMenu/autoDiscoverPresets.js +236 -0
  36. package/lib/module/floatingMenu/defaultConfig.js +151 -0
  37. package/lib/module/floatingMenu/dial/DialDevTools.js +829 -0
  38. package/lib/module/floatingMenu/dial/DialIcon.js +241 -0
  39. package/lib/module/floatingMenu/dial/OnboardingTooltip.js +244 -0
  40. package/lib/module/floatingMenu/dial/onboardingConstants.js +64 -0
  41. package/lib/module/floatingMenu/floatingTools.js +767 -0
  42. package/lib/module/floatingMenu/settingsBus.js +19 -0
  43. package/lib/module/floatingMenu/types.js +3 -0
  44. package/lib/module/index.js +29 -0
  45. package/lib/module/package.json +1 -0
  46. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts +39 -0
  47. package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +1 -0
  48. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts +37 -0
  49. package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +1 -0
  50. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts +27 -0
  51. package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  52. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  53. package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  54. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  55. package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  56. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts +30 -0
  57. package/lib/typescript/commonjs/floatingMenu/DraggableHeader.d.ts.map +1 -0
  58. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +226 -0
  59. package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  60. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts +39 -0
  61. package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +1 -0
  62. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  63. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  64. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  65. package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  66. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts +21 -0
  67. package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  68. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  69. package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  70. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +120 -0
  71. package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +1 -0
  72. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts +35 -0
  73. package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  74. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts +14 -0
  75. package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  76. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  77. package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  78. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  79. package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  80. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts +56 -0
  81. package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +1 -0
  82. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts +10 -0
  83. package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +1 -0
  84. package/lib/typescript/commonjs/floatingMenu/types.d.ts +56 -0
  85. package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +1 -0
  86. package/lib/typescript/commonjs/index.d.ts +18 -0
  87. package/lib/typescript/commonjs/index.d.ts.map +1 -0
  88. package/lib/typescript/commonjs/package.json +1 -0
  89. package/lib/typescript/module/floatingMenu/AppHost.d.ts +39 -0
  90. package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +1 -0
  91. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts +37 -0
  92. package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +1 -0
  93. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts +27 -0
  94. package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +1 -0
  95. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts +57 -0
  96. package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -0
  97. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts +25 -0
  98. package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +1 -0
  99. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts +30 -0
  100. package/lib/typescript/module/floatingMenu/DraggableHeader.d.ts.map +1 -0
  101. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +226 -0
  102. package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -0
  103. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts +39 -0
  104. package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +1 -0
  105. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts +95 -0
  106. package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +1 -0
  107. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts +10 -0
  108. package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +1 -0
  109. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts +21 -0
  110. package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +1 -0
  111. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts +75 -0
  112. package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -0
  113. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +120 -0
  114. package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +1 -0
  115. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts +35 -0
  116. package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +1 -0
  117. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts +14 -0
  118. package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +1 -0
  119. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts +12 -0
  120. package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +1 -0
  121. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts +30 -0
  122. package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +1 -0
  123. package/lib/typescript/module/floatingMenu/floatingTools.d.ts +56 -0
  124. package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +1 -0
  125. package/lib/typescript/module/floatingMenu/settingsBus.d.ts +10 -0
  126. package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +1 -0
  127. package/lib/typescript/module/floatingMenu/types.d.ts +56 -0
  128. package/lib/typescript/module/floatingMenu/types.d.ts.map +1 -0
  129. package/lib/typescript/module/index.d.ts +18 -0
  130. package/lib/typescript/module/index.d.ts.map +1 -0
  131. package/lib/typescript/module/package.json +1 -0
  132. package/package.json +79 -0
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+
3
+ import React, { useCallback, useEffect, useRef } from "react";
4
+ import { Animated, TouchableOpacity, StyleSheet, Easing } from "react-native";
5
+ import { ExpandablePopover } from "@buoy-gg/shared-ui";
6
+ import { useMinimizedTools } from "./MinimizedToolsContext.js";
7
+
8
+ // ============================================================================
9
+ // Constants
10
+ // ============================================================================
11
+ import { jsx as _jsx } from "react/jsx-runtime";
12
+ const PEEK_HEIGHT = 28;
13
+ const TOOLBAR_WIDTH = 44;
14
+ const TOOL_ITEM_SIZE = 32;
15
+ const ICON_GAP = 6;
16
+ const TOOLBAR_PADDING = 8;
17
+ const COLLAPSE_BUTTON_SIZE = 24;
18
+ const STORAGE_KEY_EXPANDED = "@react_buoy_minimized_stack_expanded";
19
+
20
+ // Glitch effect constants
21
+ const GLITCH_DURATION_MS = 80;
22
+ const MIN_GLITCH_DELAY = 2000;
23
+ const MAX_GLITCH_DELAY = 6000;
24
+
25
+ // ============================================================================
26
+ // Glitch Tool Button Component
27
+ // ============================================================================
28
+
29
+ function GlitchToolButton({
30
+ tool,
31
+ onPress,
32
+ index
33
+ }) {
34
+ const glitchX = useRef(new Animated.Value(0)).current;
35
+ const glitchOpacity = useRef(new Animated.Value(1)).current;
36
+ const glitchScale = useRef(new Animated.Value(1)).current;
37
+ useEffect(() => {
38
+ let isMounted = true;
39
+ const runGlitch = () => {
40
+ if (!isMounted) return;
41
+ const d = GLITCH_DURATION_MS;
42
+ Animated.parallel([
43
+ // X displacement - quick shake
44
+ Animated.sequence([Animated.timing(glitchX, {
45
+ toValue: 3,
46
+ duration: d * 0.2,
47
+ easing: Easing.linear,
48
+ useNativeDriver: true
49
+ }), Animated.timing(glitchX, {
50
+ toValue: -3,
51
+ duration: d * 0.2,
52
+ easing: Easing.linear,
53
+ useNativeDriver: true
54
+ }), Animated.timing(glitchX, {
55
+ toValue: 2,
56
+ duration: d * 0.2,
57
+ easing: Easing.linear,
58
+ useNativeDriver: true
59
+ }), Animated.timing(glitchX, {
60
+ toValue: -1,
61
+ duration: d * 0.2,
62
+ easing: Easing.linear,
63
+ useNativeDriver: true
64
+ }), Animated.timing(glitchX, {
65
+ toValue: 0,
66
+ duration: d * 0.2,
67
+ easing: Easing.linear,
68
+ useNativeDriver: true
69
+ })]),
70
+ // Opacity flicker
71
+ Animated.sequence([Animated.timing(glitchOpacity, {
72
+ toValue: 0.4,
73
+ duration: d * 0.25,
74
+ useNativeDriver: true
75
+ }), Animated.timing(glitchOpacity, {
76
+ toValue: 1,
77
+ duration: d * 0.25,
78
+ useNativeDriver: true
79
+ }), Animated.timing(glitchOpacity, {
80
+ toValue: 0.6,
81
+ duration: d * 0.25,
82
+ useNativeDriver: true
83
+ }), Animated.timing(glitchOpacity, {
84
+ toValue: 1,
85
+ duration: d * 0.25,
86
+ useNativeDriver: true
87
+ })]),
88
+ // Scale pulse
89
+ Animated.sequence([Animated.timing(glitchScale, {
90
+ toValue: 1.1,
91
+ duration: d * 0.3,
92
+ useNativeDriver: true
93
+ }), Animated.timing(glitchScale, {
94
+ toValue: 0.95,
95
+ duration: d * 0.4,
96
+ useNativeDriver: true
97
+ }), Animated.timing(glitchScale, {
98
+ toValue: 1,
99
+ duration: d * 0.3,
100
+ useNativeDriver: true
101
+ })])]).start();
102
+ };
103
+ const scheduleNextGlitch = () => {
104
+ if (!isMounted) return;
105
+ const delay = MIN_GLITCH_DELAY + Math.random() * (MAX_GLITCH_DELAY - MIN_GLITCH_DELAY) + index * 300;
106
+ setTimeout(() => {
107
+ if (isMounted) {
108
+ runGlitch();
109
+ scheduleNextGlitch();
110
+ }
111
+ }, delay);
112
+ };
113
+ const initialDelay = 500 + Math.random() * 1500 + index * 200;
114
+ const timeoutId = setTimeout(() => {
115
+ if (isMounted) {
116
+ runGlitch();
117
+ scheduleNextGlitch();
118
+ }
119
+ }, initialDelay);
120
+ return () => {
121
+ isMounted = false;
122
+ clearTimeout(timeoutId);
123
+ };
124
+ }, [glitchX, glitchOpacity, glitchScale, index]);
125
+ return /*#__PURE__*/_jsx(TouchableOpacity, {
126
+ onPress: () => onPress(tool),
127
+ activeOpacity: 0.7,
128
+ style: styles.toolButton,
129
+ accessibilityLabel: `Restore ${tool.title}`,
130
+ accessibilityRole: "button",
131
+ children: /*#__PURE__*/_jsx(Animated.View, {
132
+ style: {
133
+ opacity: glitchOpacity,
134
+ transform: [{
135
+ translateX: glitchX
136
+ }, {
137
+ scale: glitchScale
138
+ }]
139
+ },
140
+ children: tool.icon
141
+ })
142
+ });
143
+ }
144
+
145
+ // ============================================================================
146
+ // Types
147
+ // ============================================================================
148
+
149
+ // ============================================================================
150
+ // Main Component
151
+ // ============================================================================
152
+
153
+ export function MinimizedToolsStack({
154
+ onRestore,
155
+ containerWidth = TOOLBAR_WIDTH
156
+ }) {
157
+ const {
158
+ minimizedTools,
159
+ restore
160
+ } = useMinimizedTools();
161
+
162
+ // Calculate expanded height based on number of tools
163
+ const expandedHeight = TOOLBAR_PADDING + minimizedTools.length * TOOL_ITEM_SIZE + (minimizedTools.length - 1) * ICON_GAP + ICON_GAP + COLLAPSE_BUTTON_SIZE + 4;
164
+
165
+ // Handle tool press (restore)
166
+ const handleToolPress = useCallback(tool => {
167
+ const restored = restore(tool.instanceId);
168
+ if (restored && onRestore) {
169
+ onRestore(restored);
170
+ }
171
+ }, [restore, onRestore]);
172
+ return /*#__PURE__*/_jsx(ExpandablePopover, {
173
+ hasItems: minimizedTools.length > 0,
174
+ itemCount: minimizedTools.length,
175
+ showCount: true,
176
+ width: containerWidth,
177
+ expandedHeight: expandedHeight,
178
+ persistState: true,
179
+ storageKey: STORAGE_KEY_EXPANDED,
180
+ peekHeight: PEEK_HEIGHT,
181
+ collapsedLabel: `Show ${minimizedTools.length} minimized tools`,
182
+ children: [...minimizedTools].reverse().map((tool, index) => /*#__PURE__*/_jsx(GlitchToolButton, {
183
+ tool: tool,
184
+ onPress: handleToolPress,
185
+ index: index
186
+ }, tool.instanceId))
187
+ });
188
+ }
189
+
190
+ // ============================================================================
191
+ // Styles
192
+ // ============================================================================
193
+
194
+ const styles = StyleSheet.create({
195
+ toolButton: {
196
+ width: TOOL_ITEM_SIZE,
197
+ height: TOOL_ITEM_SIZE,
198
+ alignItems: "center",
199
+ justifyContent: "center",
200
+ backgroundColor: "transparent"
201
+ }
202
+ });
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * ToggleStateManager
5
+ *
6
+ * Global event emitter for toggle-only dev tools to notify when their state changes.
7
+ * This allows FloatingMenu to re-render and update icon colors.
8
+ */
9
+
10
+ class ToggleStateManager {
11
+ listeners = new Set();
12
+
13
+ /**
14
+ * Subscribe to any toggle state change
15
+ */
16
+ subscribe(listener) {
17
+ this.listeners.add(listener);
18
+ return () => {
19
+ this.listeners.delete(listener);
20
+ };
21
+ }
22
+
23
+ /**
24
+ * Notify all subscribers that a toggle state changed
25
+ */
26
+ notify() {
27
+ this.listeners.forEach(listener => listener());
28
+ }
29
+ }
30
+
31
+ // Singleton instance
32
+ export const toggleStateManager = new ToggleStateManager();
@@ -0,0 +1,236 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Automatically discovers and loads dev tool presets from installed packages.
5
+ *
6
+ * This function attempts to import presets from known dev tool packages.
7
+ * If a package is installed, its preset will be automatically loaded.
8
+ * If a package is not installed, it will be silently skipped.
9
+ *
10
+ * This enables zero-config setup - just install the packages you want
11
+ * and they'll automatically appear in your dev tools!
12
+ *
13
+ * @returns Array of automatically discovered preset configurations
14
+ *
15
+ * @example
16
+ * ```tsx
17
+ * import { FloatingDevTools, autoDiscoverPresets } from '@buoy-gg/core';
18
+ *
19
+ * // Automatically discover and load all installed dev tool presets
20
+ * const autoPresets = autoDiscoverPresets();
21
+ *
22
+ * function App() {
23
+ * return (
24
+ * <FloatingDevTools
25
+ * apps={autoPresets} // That's it! All installed tools load automatically
26
+ * environment="local"
27
+ * userRole="admin"
28
+ * />
29
+ * );
30
+ * }
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```tsx
35
+ * // Combine auto-discovery with custom tools
36
+ * const autoPresets = autoDiscoverPresets();
37
+ * const customTools = [
38
+ * {
39
+ * id: "my-custom-tool",
40
+ * name: "CUSTOM",
41
+ * // ... custom config
42
+ * },
43
+ * ];
44
+ *
45
+ * const allTools = [...autoPresets, ...customTools];
46
+ *
47
+ * <FloatingDevTools apps={allTools} />
48
+ * ```
49
+ */
50
+ export function autoDiscoverPresets() {
51
+ const discoveredPresets = [];
52
+
53
+ // Try to load each known preset
54
+ // These will only succeed if the package is actually installed
55
+ const presetLoaders = [
56
+ // ENV Tools
57
+ {
58
+ name: "@buoy-gg/env",
59
+ loader: () => {
60
+ try {
61
+ // @ts-ignore - Dynamic import that may not exist
62
+ const {
63
+ envToolPreset
64
+ } = require("@buoy-gg/env");
65
+ return envToolPreset;
66
+ } catch {
67
+ return null;
68
+ }
69
+ }
70
+ },
71
+ // Network Tools
72
+ {
73
+ name: "@buoy-gg/network",
74
+ loader: () => {
75
+ try {
76
+ // @ts-ignore - Dynamic import that may not exist
77
+ const {
78
+ networkToolPreset
79
+ } = require("@buoy-gg/network");
80
+ return networkToolPreset;
81
+ } catch {
82
+ return null;
83
+ }
84
+ }
85
+ },
86
+ // Storage Tools
87
+ {
88
+ name: "@buoy-gg/storage",
89
+ loader: () => {
90
+ try {
91
+ // @ts-ignore - Dynamic import that may not exist
92
+ const {
93
+ storageToolPreset
94
+ } = require("@buoy-gg/storage");
95
+ return storageToolPreset;
96
+ } catch {
97
+ return null;
98
+ }
99
+ }
100
+ },
101
+ // React Query Tools
102
+ {
103
+ name: "@buoy-gg/react-query",
104
+ loader: () => {
105
+ try {
106
+ // @ts-ignore - Dynamic import that may not exist
107
+ const {
108
+ reactQueryToolPreset,
109
+ wifiTogglePreset
110
+ } = require("@buoy-gg/react-query");
111
+ return [reactQueryToolPreset, wifiTogglePreset];
112
+ } catch {
113
+ return null;
114
+ }
115
+ }
116
+ },
117
+ // Route Events
118
+ {
119
+ name: "@buoy-gg/route-events",
120
+ loader: () => {
121
+ try {
122
+ // @ts-ignore - Dynamic import that may not exist
123
+ const {
124
+ routeEventsToolPreset
125
+ } = require("@buoy-gg/route-events");
126
+ return routeEventsToolPreset;
127
+ } catch {
128
+ return null;
129
+ }
130
+ }
131
+ },
132
+ // Debug Borders
133
+ {
134
+ name: "@buoy-gg/debug-borders",
135
+ loader: () => {
136
+ try {
137
+ // @ts-ignore - Dynamic import that may not exist
138
+ const {
139
+ debugBordersToolPreset
140
+ } = require("@buoy-gg/debug-borders");
141
+ return debugBordersToolPreset;
142
+ } catch {
143
+ return null;
144
+ }
145
+ }
146
+ },
147
+ // Highlight Updates (both toggle and modal presets)
148
+ {
149
+ name: "@buoy-gg/highlight-updates",
150
+ loader: () => {
151
+ try {
152
+ // @ts-ignore - Dynamic import that may not exist
153
+ const {
154
+ highlightUpdatesPreset,
155
+ highlightUpdatesModalPreset
156
+ } = require("@buoy-gg/highlight-updates");
157
+ return [highlightUpdatesModalPreset, highlightUpdatesPreset];
158
+ } catch {
159
+ return null;
160
+ }
161
+ }
162
+ },
163
+ // Benchmark Tools
164
+ {
165
+ name: "@buoy-gg/benchmark",
166
+ loader: () => {
167
+ try {
168
+ // @ts-ignore - Dynamic import that may not exist
169
+ const {
170
+ benchmarkPreset
171
+ } = require("@buoy-gg/benchmark");
172
+ return benchmarkPreset;
173
+ } catch {
174
+ return null;
175
+ }
176
+ }
177
+ }];
178
+
179
+ // Attempt to load each preset
180
+ for (const {
181
+ name,
182
+ loader
183
+ } of presetLoaders) {
184
+ try {
185
+ const preset = loader();
186
+ if (preset) {
187
+ if (Array.isArray(preset)) {
188
+ discoveredPresets.push(...preset);
189
+ } else {
190
+ discoveredPresets.push(preset);
191
+ }
192
+ }
193
+ } catch (error) {
194
+ // Silently skip packages that aren't installed
195
+ // This is expected behavior - not all packages will be installed
196
+ }
197
+ }
198
+ return discoveredPresets;
199
+ }
200
+
201
+ /**
202
+ * Merges auto-discovered presets with custom tools, ensuring no duplicates.
203
+ * Custom tools take precedence over auto-discovered ones with the same ID.
204
+ *
205
+ * @param customTools - Array of custom tool configurations
206
+ * @returns Combined array of tools with custom tools taking precedence
207
+ *
208
+ * @example
209
+ * ```tsx
210
+ * import { FloatingDevTools, autoDiscoverPresetsWithCustom } from '@buoy-gg/core';
211
+ * import { createEnvTool } from '@buoy-gg/env';
212
+ *
213
+ * const customTools = [
214
+ * // Override the env preset with custom config
215
+ * createEnvTool({
216
+ * requiredEnvVars: myRequiredVars,
217
+ * }),
218
+ * ];
219
+ *
220
+ * const allTools = autoDiscoverPresetsWithCustom(customTools);
221
+ *
222
+ * <FloatingDevTools apps={allTools} />
223
+ * ```
224
+ */
225
+ export function autoDiscoverPresetsWithCustom(customTools) {
226
+ const autoPresets = autoDiscoverPresets();
227
+
228
+ // Create a map of custom tool IDs for quick lookup
229
+ const customToolIds = new Set(customTools.map(tool => tool.id));
230
+
231
+ // Filter out auto-discovered presets that have custom overrides
232
+ const filteredAutoPresets = autoPresets.filter(preset => !customToolIds.has(preset.id));
233
+
234
+ // Custom tools first (higher priority), then auto-discovered
235
+ return [...customTools, ...filteredAutoPresets];
236
+ }
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Type-safe default configuration for React Buoy DevTools.
5
+ *
6
+ * This module provides a simple, type-safe way for teams to configure
7
+ * which tools are enabled by default in the floating menu and dial menu.
8
+ *
9
+ * @example
10
+ * ```tsx
11
+ * import { FloatingDevTools } from '@buoy-gg/core';
12
+ *
13
+ * // Simple: Enable specific tools by default
14
+ * <FloatingDevTools
15
+ * defaultFloatingTools={['env', 'environment', 'network']}
16
+ * defaultDialTools={['env', 'network', 'storage', 'query']}
17
+ * />
18
+ * ```
19
+ */
20
+
21
+ /**
22
+ * All known tool IDs that can appear in the floating menu or dial menu.
23
+ * This is a union type of all auto-discovered tool IDs.
24
+ */
25
+
26
+ // Performance benchmarking (@buoy-gg/benchmark)
27
+
28
+ /**
29
+ * Special floating-only tool IDs that only appear in the floating bubble row.
30
+ */
31
+ // Environment badge indicator
32
+
33
+ /**
34
+ * All tool IDs that can appear in the floating menu (bubble row).
35
+ * Includes all built-in tools plus floating-only tools.
36
+ */
37
+
38
+ /**
39
+ * Tool IDs that can appear in the dial menu.
40
+ * Same as BuiltInToolId (environment badge is floating-only).
41
+ */
42
+
43
+ /**
44
+ * Maximum number of tools allowed in the dial menu.
45
+ */
46
+ export const MAX_DIAL_TOOLS = 6;
47
+
48
+ /**
49
+ * Configuration for default floating menu tools.
50
+ * Pass an array of tool IDs to enable by default.
51
+ *
52
+ * @example
53
+ * ```tsx
54
+ * const floatingDefaults: DefaultFloatingConfig = ['env', 'environment', 'network'];
55
+ * ```
56
+ */
57
+
58
+ /**
59
+ * Configuration for default dial menu tools.
60
+ * Pass an array of 1-6 tool IDs to enable by default.
61
+ *
62
+ * @example
63
+ * ```tsx
64
+ * const dialDefaults: DefaultDialConfig = ['env', 'network', 'storage', 'query'];
65
+ * ```
66
+ */
67
+
68
+ /**
69
+ * Validates that a dial configuration doesn't exceed the maximum allowed tools.
70
+ * Throws an error with helpful message if validation fails.
71
+ *
72
+ * @param tools - Array of dial tool IDs to validate
73
+ * @throws Error if more than MAX_DIAL_TOOLS are provided
74
+ *
75
+ * @example
76
+ * ```tsx
77
+ * // This is valid
78
+ * validateDialConfig(['env', 'network', 'storage']);
79
+ *
80
+ * // This throws an error
81
+ * validateDialConfig(['env', 'network', 'storage', 'query', 'route-events', 'debug-borders', 'benchmark']);
82
+ * // Error: "Dial menu default configuration has 7 tools, but maximum is 6..."
83
+ * ```
84
+ */
85
+ export function validateDialConfig(tools) {
86
+ if (tools.length > MAX_DIAL_TOOLS) {
87
+ const toolList = tools.map(t => `"${t}"`).join(', ');
88
+ throw new Error(`Dial menu default configuration has ${tools.length} tools, but maximum is ${MAX_DIAL_TOOLS}. ` + `Tools provided: [${toolList}]. ` + `Please remove ${tools.length - MAX_DIAL_TOOLS} tool(s) from defaultDialTools.`);
89
+ }
90
+ }
91
+
92
+ /**
93
+ * Helper to create a type-safe default configuration.
94
+ * Provides autocomplete and validation at compile time.
95
+ *
96
+ * @example
97
+ * ```tsx
98
+ * import { createDefaultConfig } from '@buoy-gg/core';
99
+ *
100
+ * const config = createDefaultConfig({
101
+ * floating: ['env', 'environment', 'network', 'query-wifi-toggle'],
102
+ * dial: ['env', 'network', 'storage', 'query', 'route-events', 'debug-borders'],
103
+ * });
104
+ *
105
+ * <FloatingDevTools
106
+ * defaultFloatingTools={config.floating}
107
+ * defaultDialTools={config.dial}
108
+ * />
109
+ * ```
110
+ */
111
+ export function createDefaultConfig(config) {
112
+ // Runtime validation for dial tools
113
+ if (config.dial) {
114
+ validateDialConfig(config.dial);
115
+ }
116
+ return {
117
+ floating: config.floating,
118
+ dial: config.dial
119
+ };
120
+ }
121
+
122
+ /**
123
+ * Type guard to check if a string is a valid FloatingToolId.
124
+ */
125
+ export function isFloatingToolId(id) {
126
+ const validIds = ['env', 'network', 'storage', 'query', 'query-wifi-toggle', 'route-events', 'debug-borders', 'highlight-updates', 'highlight-updates-modal', 'benchmark', 'environment'];
127
+ return validIds.includes(id);
128
+ }
129
+
130
+ /**
131
+ * Type guard to check if a string is a valid DialToolId.
132
+ */
133
+ export function isDialToolId(id) {
134
+ const validIds = ['env', 'network', 'storage', 'query', 'query-wifi-toggle', 'route-events', 'debug-borders', 'highlight-updates', 'highlight-updates-modal', 'benchmark'];
135
+ return validIds.includes(id);
136
+ }
137
+
138
+ /**
139
+ * Converts an array of tool IDs into a settings record.
140
+ * Used internally to convert default config to DevToolsSettings format.
141
+ *
142
+ * @internal
143
+ */
144
+ export function toolIdsToRecord(ids, allPossibleIds) {
145
+ const record = {};
146
+ const enabledSet = new Set(ids);
147
+ for (const id of allPossibleIds) {
148
+ record[id] = enabledSet.has(id);
149
+ }
150
+ return record;
151
+ }