@buoy-gg/floating-tools-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.
- package/dist/index.d.mts +1779 -0
- package/dist/index.d.ts +1779 -0
- package/dist/index.js +82 -0
- package/dist/index.mjs +82 -0
- package/package.json +34 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,1779 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { FC } from 'react';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Core types for the floating tools headless system.
|
|
7
|
+
*/
|
|
8
|
+
interface Position {
|
|
9
|
+
x: number;
|
|
10
|
+
y: number;
|
|
11
|
+
}
|
|
12
|
+
interface Size {
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
}
|
|
16
|
+
interface Bounds {
|
|
17
|
+
minX: number;
|
|
18
|
+
maxX: number;
|
|
19
|
+
minY: number;
|
|
20
|
+
maxY: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Platform-agnostic storage adapter.
|
|
24
|
+
* Implement this interface for your platform (localStorage, AsyncStorage, etc.)
|
|
25
|
+
*/
|
|
26
|
+
interface StorageAdapter {
|
|
27
|
+
getItem: (key: string) => Promise<string | null> | string | null;
|
|
28
|
+
setItem: (key: string, value: string) => Promise<void> | void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* State managed by the floating tools core.
|
|
32
|
+
*/
|
|
33
|
+
interface FloatingToolsState {
|
|
34
|
+
position: Position;
|
|
35
|
+
isDragging: boolean;
|
|
36
|
+
isHidden: boolean;
|
|
37
|
+
bubbleSize: Size;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Options for creating a floating tools store.
|
|
41
|
+
*/
|
|
42
|
+
interface FloatingToolsOptions {
|
|
43
|
+
/** Screen dimensions - required for boundary calculations */
|
|
44
|
+
screenWidth: number;
|
|
45
|
+
screenHeight: number;
|
|
46
|
+
/** Initial bubble size (will be updated on layout) */
|
|
47
|
+
initialBubbleSize?: Size;
|
|
48
|
+
/** Initial position (before loading from storage) */
|
|
49
|
+
initialPosition?: Position;
|
|
50
|
+
/** Minimum position boundaries */
|
|
51
|
+
minPosition?: Position;
|
|
52
|
+
/** Whether to persist position to storage */
|
|
53
|
+
enablePositionPersistence?: boolean;
|
|
54
|
+
/** Width of visible handle when hidden (default: 32) */
|
|
55
|
+
visibleHandleWidth?: number;
|
|
56
|
+
/** Drag threshold in pixels (default: 5) */
|
|
57
|
+
dragThreshold?: number;
|
|
58
|
+
/** Animation duration in ms (default: 200) */
|
|
59
|
+
animationDuration?: number;
|
|
60
|
+
/** Edge padding in pixels (default: 10) */
|
|
61
|
+
edgePadding?: number;
|
|
62
|
+
/** Storage adapter for position persistence */
|
|
63
|
+
storage?: StorageAdapter;
|
|
64
|
+
/** Callback when position changes */
|
|
65
|
+
onPositionChange?: (position: Position) => void;
|
|
66
|
+
/** Callback when hidden state changes */
|
|
67
|
+
onHiddenChange?: (hidden: boolean) => void;
|
|
68
|
+
/** Callback when dragging state changes */
|
|
69
|
+
onDraggingChange?: (dragging: boolean) => void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Drag event data passed to handlers.
|
|
73
|
+
*/
|
|
74
|
+
interface DragEventData {
|
|
75
|
+
/** Current mouse/touch position */
|
|
76
|
+
clientX: number;
|
|
77
|
+
clientY: number;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Result of a drag end operation.
|
|
81
|
+
*/
|
|
82
|
+
interface DragEndResult {
|
|
83
|
+
/** Final clamped position */
|
|
84
|
+
position: Position;
|
|
85
|
+
/** Whether the bubble should animate to hidden state */
|
|
86
|
+
shouldHide: boolean;
|
|
87
|
+
/** Whether this was a tap (not a drag) */
|
|
88
|
+
wasTap: boolean;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Slot where a tool can appear.
|
|
92
|
+
* - 'dial': Only in the circular dial menu
|
|
93
|
+
* - 'row': Only in the floating toolbar row
|
|
94
|
+
* - 'both': Can appear in either location
|
|
95
|
+
*/
|
|
96
|
+
type ToolSlot = 'dial' | 'row' | 'both';
|
|
97
|
+
/**
|
|
98
|
+
* Base tool configuration - platform agnostic.
|
|
99
|
+
*
|
|
100
|
+
* Contains the minimum configuration needed to identify and
|
|
101
|
+
* describe a tool. Platform-specific configs extend this.
|
|
102
|
+
*
|
|
103
|
+
* Note: name, description, and color are optional because they
|
|
104
|
+
* can fall back to shared defaults from toolLabels, toolDescriptions,
|
|
105
|
+
* and toolColors in the settings module.
|
|
106
|
+
*/
|
|
107
|
+
interface BaseToolConfig {
|
|
108
|
+
/** Unique identifier for the tool */
|
|
109
|
+
id: string;
|
|
110
|
+
/** Display name (falls back to toolLabels[id]) */
|
|
111
|
+
name?: string;
|
|
112
|
+
/** Short description (falls back to toolDescriptions[id]) */
|
|
113
|
+
description?: string;
|
|
114
|
+
/** Where the tool can appear (default: 'both') */
|
|
115
|
+
slot?: ToolSlot;
|
|
116
|
+
/** Accent color (falls back to toolColors[id]) */
|
|
117
|
+
color?: string;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Web tool configuration.
|
|
121
|
+
*
|
|
122
|
+
* Extends BaseToolConfig with web-specific rendering options.
|
|
123
|
+
* Does not use React Native's ComponentType or other RN-specific types.
|
|
124
|
+
*/
|
|
125
|
+
interface WebToolConfig extends BaseToolConfig {
|
|
126
|
+
/**
|
|
127
|
+
* Icon to display.
|
|
128
|
+
* Can be:
|
|
129
|
+
* - A string (emoji or text)
|
|
130
|
+
* - A function that returns a React node given the size
|
|
131
|
+
*/
|
|
132
|
+
icon: string | ((size: number) => unknown);
|
|
133
|
+
/**
|
|
134
|
+
* React component to render when tool is activated.
|
|
135
|
+
* Optional - some tools may just have an onPress handler.
|
|
136
|
+
*/
|
|
137
|
+
component?: unknown;
|
|
138
|
+
/**
|
|
139
|
+
* Callback when tool icon is pressed.
|
|
140
|
+
* For toggle-only tools or tools with custom launch behavior.
|
|
141
|
+
*/
|
|
142
|
+
onPress?: () => void;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Environment type for the dev tools.
|
|
146
|
+
*/
|
|
147
|
+
type Environment = 'local' | 'dev' | 'qa' | 'staging' | 'prod';
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* FloatingToolsStore - Headless state management for floating tools.
|
|
151
|
+
*
|
|
152
|
+
* This class manages all the business logic for the floating tools bubble:
|
|
153
|
+
* - Position state and validation
|
|
154
|
+
* - Drag detection (tap vs drag)
|
|
155
|
+
* - Hide/show toggle
|
|
156
|
+
* - Auto-hide when dragged past edge
|
|
157
|
+
* - Position persistence
|
|
158
|
+
*
|
|
159
|
+
* Platform-specific code (animation, event handling) is NOT included here.
|
|
160
|
+
* Use this with platform-specific hooks/bindings.
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
type Listener$1 = () => void;
|
|
164
|
+
declare class FloatingToolsStore {
|
|
165
|
+
private position;
|
|
166
|
+
private isDragging;
|
|
167
|
+
private isHidden;
|
|
168
|
+
private bubbleSize;
|
|
169
|
+
private screenWidth;
|
|
170
|
+
private screenHeight;
|
|
171
|
+
private minPosition;
|
|
172
|
+
private visibleHandleWidth;
|
|
173
|
+
private dragThreshold;
|
|
174
|
+
private edgePadding;
|
|
175
|
+
private enablePositionPersistence;
|
|
176
|
+
private storage?;
|
|
177
|
+
private onPositionChange?;
|
|
178
|
+
private onHiddenChange?;
|
|
179
|
+
private onDraggingChange?;
|
|
180
|
+
private dragStartPos;
|
|
181
|
+
private dragStartMouse;
|
|
182
|
+
private hasMoved;
|
|
183
|
+
private savedPosition;
|
|
184
|
+
private saveTimeout;
|
|
185
|
+
private isInitialized;
|
|
186
|
+
private listeners;
|
|
187
|
+
private stateSnapshot;
|
|
188
|
+
constructor(options: FloatingToolsOptions);
|
|
189
|
+
subscribe: (listener: Listener$1) => (() => void);
|
|
190
|
+
getSnapshot: () => FloatingToolsState;
|
|
191
|
+
private createSnapshot;
|
|
192
|
+
private notify;
|
|
193
|
+
/**
|
|
194
|
+
* Initialize the store by loading persisted position.
|
|
195
|
+
* Call this after setting up storage adapter.
|
|
196
|
+
*/
|
|
197
|
+
initialize(): Promise<void>;
|
|
198
|
+
/**
|
|
199
|
+
* Get current bounds for position validation.
|
|
200
|
+
*/
|
|
201
|
+
getBounds(): Bounds;
|
|
202
|
+
/**
|
|
203
|
+
* Validate and clamp a position to screen boundaries.
|
|
204
|
+
*/
|
|
205
|
+
validatePosition(pos: Position): Position;
|
|
206
|
+
/**
|
|
207
|
+
* Set position directly (for animation callbacks).
|
|
208
|
+
*/
|
|
209
|
+
setPosition(pos: Position): void;
|
|
210
|
+
/**
|
|
211
|
+
* Update bubble size (call on layout).
|
|
212
|
+
* Only notifies if size actually changed.
|
|
213
|
+
*/
|
|
214
|
+
setBubbleSize(size: Size): void;
|
|
215
|
+
/**
|
|
216
|
+
* Update screen dimensions (call on resize).
|
|
217
|
+
*/
|
|
218
|
+
setScreenSize(width: number, height: number): void;
|
|
219
|
+
/**
|
|
220
|
+
* Update min position (e.g., for safe area insets).
|
|
221
|
+
*/
|
|
222
|
+
setMinPosition(minPos: Position): void;
|
|
223
|
+
private savePosition;
|
|
224
|
+
private debouncedSavePosition;
|
|
225
|
+
/**
|
|
226
|
+
* Toggle between hidden and visible states.
|
|
227
|
+
* Returns the target position for animation.
|
|
228
|
+
*/
|
|
229
|
+
toggleHideShow(): {
|
|
230
|
+
targetPosition: Position;
|
|
231
|
+
isHiding: boolean;
|
|
232
|
+
};
|
|
233
|
+
/**
|
|
234
|
+
* Force hide (for pushToSide behavior).
|
|
235
|
+
*/
|
|
236
|
+
forceHide(): {
|
|
237
|
+
targetPosition: Position;
|
|
238
|
+
};
|
|
239
|
+
/**
|
|
240
|
+
* Force show (restore from pushToSide).
|
|
241
|
+
*/
|
|
242
|
+
forceShow(): {
|
|
243
|
+
targetPosition: Position;
|
|
244
|
+
};
|
|
245
|
+
/**
|
|
246
|
+
* Start a drag operation.
|
|
247
|
+
*/
|
|
248
|
+
handleDragStart(event: DragEventData): void;
|
|
249
|
+
/**
|
|
250
|
+
* Process drag movement.
|
|
251
|
+
* Returns the new position (for animation) and whether drag threshold was exceeded.
|
|
252
|
+
*/
|
|
253
|
+
handleDragMove(event: DragEventData): {
|
|
254
|
+
position: Position;
|
|
255
|
+
isDragging: boolean;
|
|
256
|
+
};
|
|
257
|
+
/**
|
|
258
|
+
* End a drag operation.
|
|
259
|
+
* Returns the result including whether to animate to hidden state.
|
|
260
|
+
*/
|
|
261
|
+
handleDragEnd(event: DragEventData): DragEndResult;
|
|
262
|
+
/**
|
|
263
|
+
* Commit position after animation completes.
|
|
264
|
+
*/
|
|
265
|
+
commitPosition(pos: Position): void;
|
|
266
|
+
destroy(): void;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Shared constants for floating tools behavior.
|
|
271
|
+
* These values ensure consistent behavior across platforms.
|
|
272
|
+
*/
|
|
273
|
+
/** Width of the visible grip handle when bubble is hidden (pixels) */
|
|
274
|
+
declare const VISIBLE_HANDLE_WIDTH = 32;
|
|
275
|
+
/** Minimum movement to distinguish drag from tap (pixels) */
|
|
276
|
+
declare const DRAG_THRESHOLD = 5;
|
|
277
|
+
/** Animation duration for hide/show transitions (milliseconds) */
|
|
278
|
+
declare const ANIMATION_DURATION = 200;
|
|
279
|
+
/** Padding from screen edges (pixels) */
|
|
280
|
+
declare const EDGE_PADDING = 10;
|
|
281
|
+
/** Debounce delay for position persistence (milliseconds) */
|
|
282
|
+
declare const SAVE_DEBOUNCE_MS = 500;
|
|
283
|
+
/** Storage keys for position persistence */
|
|
284
|
+
declare const STORAGE_KEYS: {
|
|
285
|
+
readonly POSITION_X: "@react_buoy_bubble_position_x";
|
|
286
|
+
readonly POSITION_Y: "@react_buoy_bubble_position_y";
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Settings - Shared settings types, constants, and utilities.
|
|
291
|
+
*
|
|
292
|
+
* Pure configuration and logic functions for dev tools settings.
|
|
293
|
+
* No React or platform-specific code.
|
|
294
|
+
*
|
|
295
|
+
* This module provides:
|
|
296
|
+
* - Storage keys and constants
|
|
297
|
+
* - Tab configuration
|
|
298
|
+
* - Tool colors, labels, descriptions
|
|
299
|
+
* - Styling constants for cards and toggles
|
|
300
|
+
* - Settings logic (enforce limits, merge, etc.)
|
|
301
|
+
* - Event bus for cross-component sync
|
|
302
|
+
*/
|
|
303
|
+
/** Storage key for dev tools settings */
|
|
304
|
+
declare const SETTINGS_STORAGE_KEY = "@react_buoy_dev_tools_settings";
|
|
305
|
+
/** Maximum number of tools in the dial menu */
|
|
306
|
+
declare const MAX_SETTINGS_DIAL_SLOTS = 6;
|
|
307
|
+
type SettingsTabKey = 'dial' | 'floating' | 'settings' | 'pro';
|
|
308
|
+
interface SettingsTab {
|
|
309
|
+
key: SettingsTabKey;
|
|
310
|
+
label: string;
|
|
311
|
+
}
|
|
312
|
+
/** Tab configuration - shared across mobile and web */
|
|
313
|
+
declare const settingsTabs: SettingsTab[];
|
|
314
|
+
/**
|
|
315
|
+
* Color palette for the settings modal.
|
|
316
|
+
* Matches the mobile implementation for consistency.
|
|
317
|
+
*/
|
|
318
|
+
declare const settingsColors: {
|
|
319
|
+
readonly background: "rgba(8, 12, 21, 0.98)";
|
|
320
|
+
readonly panel: "rgba(16, 22, 35, 0.98)";
|
|
321
|
+
readonly backdrop: "rgba(0, 0, 0, 0.85)";
|
|
322
|
+
readonly cardBackground: "#0F172A";
|
|
323
|
+
readonly cardBorder: "#25324A";
|
|
324
|
+
readonly cardBorderHover: "#3b4c6b";
|
|
325
|
+
readonly text: "#E6EEFF";
|
|
326
|
+
readonly textSecondary: "#B8BFC9";
|
|
327
|
+
readonly textMuted: "#7F91B2";
|
|
328
|
+
readonly textDim: "#7A8599";
|
|
329
|
+
readonly success: "#4AFF9F";
|
|
330
|
+
readonly warning: "#FFEB3B";
|
|
331
|
+
readonly error: "#FF5252";
|
|
332
|
+
readonly info: "#00B8E6";
|
|
333
|
+
readonly toggleOnBg: (color: string) => string;
|
|
334
|
+
readonly toggleOnBorder: (color: string) => string;
|
|
335
|
+
readonly toggleOffBg: "#1b2334";
|
|
336
|
+
readonly toggleOffBorder: "#2a3550";
|
|
337
|
+
readonly toggleOffText: "#8CA2C8";
|
|
338
|
+
readonly tabActiveBg: "rgba(0, 184, 230, 0.13)";
|
|
339
|
+
readonly tabActiveBorder: "#00B8E6";
|
|
340
|
+
readonly tabInactiveBg: "transparent";
|
|
341
|
+
readonly tabInactiveText: "#7A8599";
|
|
342
|
+
};
|
|
343
|
+
type SettingsColorKey = keyof typeof settingsColors;
|
|
344
|
+
/**
|
|
345
|
+
* Color mapping for each tool type.
|
|
346
|
+
* Used for card accents, toggle states, and icons.
|
|
347
|
+
*/
|
|
348
|
+
declare const toolColors: Record<string, string>;
|
|
349
|
+
/**
|
|
350
|
+
* Get the color for a specific tool.
|
|
351
|
+
*
|
|
352
|
+
* @param toolId - Tool identifier
|
|
353
|
+
* @returns Color string for the tool
|
|
354
|
+
*/
|
|
355
|
+
declare const getToolColor: (toolId: string) => string;
|
|
356
|
+
/**
|
|
357
|
+
* Display labels for each tool.
|
|
358
|
+
* These are shown in the settings card headers.
|
|
359
|
+
*/
|
|
360
|
+
declare const toolLabels: Record<string, string>;
|
|
361
|
+
/**
|
|
362
|
+
* Get the display label for a tool.
|
|
363
|
+
*
|
|
364
|
+
* @param toolId - Tool identifier
|
|
365
|
+
* @param availableApps - Optional list of available apps to check for custom names
|
|
366
|
+
* @returns Display label for the tool
|
|
367
|
+
*/
|
|
368
|
+
declare const getToolLabel: (toolId: string, availableApps?: {
|
|
369
|
+
id: string;
|
|
370
|
+
name?: string;
|
|
371
|
+
}[]) => string;
|
|
372
|
+
/**
|
|
373
|
+
* Descriptions for each tool.
|
|
374
|
+
* These are shown in the settings card subtitles.
|
|
375
|
+
*/
|
|
376
|
+
declare const toolDescriptions: Record<string, string>;
|
|
377
|
+
/**
|
|
378
|
+
* Get the description for a tool.
|
|
379
|
+
*
|
|
380
|
+
* @param toolId - Tool identifier
|
|
381
|
+
* @param availableApps - Optional list of available apps to check for custom descriptions
|
|
382
|
+
* @returns Description for the tool
|
|
383
|
+
*/
|
|
384
|
+
declare const getToolDescription: (toolId: string, availableApps?: {
|
|
385
|
+
id: string;
|
|
386
|
+
description?: string;
|
|
387
|
+
}[]) => string;
|
|
388
|
+
/**
|
|
389
|
+
* Styling configuration for settings UI elements.
|
|
390
|
+
* All numeric values that affect appearance.
|
|
391
|
+
*/
|
|
392
|
+
declare const settingsStyles: {
|
|
393
|
+
readonly card: {
|
|
394
|
+
readonly borderRadius: 999;
|
|
395
|
+
readonly paddingVertical: 10;
|
|
396
|
+
readonly paddingHorizontal: 14;
|
|
397
|
+
readonly marginBottom: 10;
|
|
398
|
+
readonly borderWidth: 1;
|
|
399
|
+
};
|
|
400
|
+
readonly cardInner: {
|
|
401
|
+
readonly gap: 10;
|
|
402
|
+
};
|
|
403
|
+
readonly iconContainer: {
|
|
404
|
+
readonly width: 28;
|
|
405
|
+
readonly height: 28;
|
|
406
|
+
};
|
|
407
|
+
readonly toolName: {
|
|
408
|
+
readonly fontSize: 13;
|
|
409
|
+
readonly fontWeight: "800";
|
|
410
|
+
};
|
|
411
|
+
readonly toolDescription: {
|
|
412
|
+
readonly fontSize: 11;
|
|
413
|
+
};
|
|
414
|
+
readonly toggle: {
|
|
415
|
+
readonly paddingHorizontal: 12;
|
|
416
|
+
readonly paddingVertical: 6;
|
|
417
|
+
readonly borderRadius: 999;
|
|
418
|
+
readonly borderWidth: 1;
|
|
419
|
+
readonly fontSize: 11;
|
|
420
|
+
readonly fontWeight: "700";
|
|
421
|
+
};
|
|
422
|
+
readonly tab: {
|
|
423
|
+
readonly paddingHorizontal: 8;
|
|
424
|
+
readonly paddingVertical: 5;
|
|
425
|
+
readonly borderRadius: 4;
|
|
426
|
+
readonly fontSize: 12;
|
|
427
|
+
readonly fontWeight: "600";
|
|
428
|
+
readonly letterSpacing: 0.5;
|
|
429
|
+
};
|
|
430
|
+
readonly sectionHeader: {
|
|
431
|
+
readonly marginBottom: 12;
|
|
432
|
+
readonly paddingHorizontal: 4;
|
|
433
|
+
};
|
|
434
|
+
readonly sectionTitle: {
|
|
435
|
+
readonly fontSize: 10;
|
|
436
|
+
readonly fontWeight: "700";
|
|
437
|
+
readonly letterSpacing: 1;
|
|
438
|
+
readonly textTransform: "uppercase";
|
|
439
|
+
};
|
|
440
|
+
readonly scrollContent: {
|
|
441
|
+
readonly paddingTop: 16;
|
|
442
|
+
readonly paddingBottom: 24;
|
|
443
|
+
};
|
|
444
|
+
readonly section: {
|
|
445
|
+
readonly marginHorizontal: 16;
|
|
446
|
+
readonly marginBottom: 24;
|
|
447
|
+
};
|
|
448
|
+
};
|
|
449
|
+
interface GlobalSettingConfig {
|
|
450
|
+
key: keyof GlobalDevToolsSettings;
|
|
451
|
+
label: string;
|
|
452
|
+
category: string;
|
|
453
|
+
shortDescription: string;
|
|
454
|
+
fullDescription: string;
|
|
455
|
+
recommendation: string;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Configuration for global settings cards.
|
|
459
|
+
*/
|
|
460
|
+
declare const globalSettingsConfig: GlobalSettingConfig[];
|
|
461
|
+
/**
|
|
462
|
+
* Global settings that apply to all dev tools.
|
|
463
|
+
* These settings override individual tool configurations.
|
|
464
|
+
*/
|
|
465
|
+
interface GlobalDevToolsSettings {
|
|
466
|
+
/**
|
|
467
|
+
* When true, all modals share the same dimensions/position.
|
|
468
|
+
* When false (default), each modal has its own independent persistence.
|
|
469
|
+
* Priority: Settings UI > Prop override > Default (false)
|
|
470
|
+
*/
|
|
471
|
+
enableSharedModalDimensions?: boolean;
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Serialized preferences that power the floating dev tools UI.
|
|
475
|
+
* Values persist across sessions via storage so teams can tailor
|
|
476
|
+
* which tools appear in the dial or floating row.
|
|
477
|
+
*/
|
|
478
|
+
interface DevToolsSettings {
|
|
479
|
+
/** Map of dial tool ids to enabled state (max slots enforced elsewhere). */
|
|
480
|
+
dialTools: Record<string, boolean>;
|
|
481
|
+
/** Map of floating tool ids to enabled state plus the environment indicator toggle. */
|
|
482
|
+
floatingTools: Record<string, boolean> & {
|
|
483
|
+
environment: boolean;
|
|
484
|
+
};
|
|
485
|
+
/** Global settings that apply to all dev tools */
|
|
486
|
+
globalSettings?: GlobalDevToolsSettings;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Configuration for an available tool/app.
|
|
490
|
+
* Note: name and description are optional - if not provided,
|
|
491
|
+
* getToolLabel() and getToolDescription() will use shared defaults.
|
|
492
|
+
*/
|
|
493
|
+
interface AvailableToolConfig {
|
|
494
|
+
id: string;
|
|
495
|
+
name?: string;
|
|
496
|
+
description?: string;
|
|
497
|
+
slot?: 'dial' | 'row' | 'both';
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Tool metadata for display in settings.
|
|
501
|
+
*/
|
|
502
|
+
interface ToolMetadata {
|
|
503
|
+
id: string;
|
|
504
|
+
name: string;
|
|
505
|
+
description?: string;
|
|
506
|
+
category?: string;
|
|
507
|
+
color?: string;
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Enforces the dial slot limit by enabling only the first N tools.
|
|
511
|
+
* Tools are processed in order, so tools appearing first in the Record
|
|
512
|
+
* have priority when the limit is reached.
|
|
513
|
+
*
|
|
514
|
+
* @param dialTools - Map of tool ids to enabled state
|
|
515
|
+
* @param maxSlots - Maximum number of enabled tools (default: MAX_SETTINGS_DIAL_SLOTS)
|
|
516
|
+
* @returns New record with limit enforced
|
|
517
|
+
*/
|
|
518
|
+
declare const enforceDialLimit: (dialTools: Record<string, boolean>, maxSlots?: number) => Record<string, boolean>;
|
|
519
|
+
/**
|
|
520
|
+
* Sanitizes floating tools settings by removing unknown keys and ensuring
|
|
521
|
+
* the environment field is always present.
|
|
522
|
+
*
|
|
523
|
+
* @param floating - Floating tools settings object
|
|
524
|
+
* @param allowedKeys - Optional list of allowed tool keys (environment is always allowed)
|
|
525
|
+
* @returns Sanitized floating tools settings
|
|
526
|
+
*/
|
|
527
|
+
declare const sanitizeFloatingSettings: (floating: DevToolsSettings["floatingTools"], allowedKeys?: string[]) => DevToolsSettings["floatingTools"];
|
|
528
|
+
/**
|
|
529
|
+
* Options for merging settings with defaults.
|
|
530
|
+
*/
|
|
531
|
+
interface MergeSettingsOptions {
|
|
532
|
+
allowedDialKeys?: string[];
|
|
533
|
+
allowedFloatingKeys?: string[];
|
|
534
|
+
}
|
|
535
|
+
/**
|
|
536
|
+
* Merges stored settings with defaults, ensuring all required fields exist
|
|
537
|
+
* and limits are enforced.
|
|
538
|
+
*
|
|
539
|
+
* @param defaults - Default settings to use as base
|
|
540
|
+
* @param stored - Stored settings to merge (optional)
|
|
541
|
+
* @param options - Optional filtering options
|
|
542
|
+
* @returns Merged settings with all fields and limits enforced
|
|
543
|
+
*/
|
|
544
|
+
declare const mergeSettingsWithDefaults: (defaults: DevToolsSettings, stored?: Partial<DevToolsSettings> | null, options?: MergeSettingsOptions) => DevToolsSettings;
|
|
545
|
+
/**
|
|
546
|
+
* Generates default settings based on available tools and optional team defaults.
|
|
547
|
+
*
|
|
548
|
+
* @param availableTools - List of available tools from auto-discovery
|
|
549
|
+
* @param defaultFloatingTools - Optional array of tool IDs to enable by default in floating bubble
|
|
550
|
+
* @param defaultDialTools - Optional array of tool IDs to enable by default in dial menu
|
|
551
|
+
* @returns Default settings with specified tools enabled
|
|
552
|
+
*/
|
|
553
|
+
declare const generateDefaultSettings: (availableTools?: AvailableToolConfig[], defaultFloatingTools?: string[], defaultDialTools?: string[]) => DevToolsSettings;
|
|
554
|
+
/**
|
|
555
|
+
* Counts the number of enabled tools in a settings record.
|
|
556
|
+
*
|
|
557
|
+
* @param tools - Record of tool ids to enabled state
|
|
558
|
+
* @returns Count of enabled tools
|
|
559
|
+
*/
|
|
560
|
+
declare const countEnabledTools: (tools: Record<string, boolean>) => number;
|
|
561
|
+
/**
|
|
562
|
+
* Checks if a dial tool can be enabled (respects slot limit).
|
|
563
|
+
*
|
|
564
|
+
* @param dialTools - Current dial tools settings
|
|
565
|
+
* @param toolId - ID of the tool to check
|
|
566
|
+
* @param maxSlots - Maximum number of slots (default: MAX_SETTINGS_DIAL_SLOTS)
|
|
567
|
+
* @returns true if the tool can be enabled
|
|
568
|
+
*/
|
|
569
|
+
declare const canEnableDialTool: (dialTools: Record<string, boolean>, toolId: string, maxSlots?: number) => boolean;
|
|
570
|
+
/**
|
|
571
|
+
* Extracts enabled tool IDs from a settings record.
|
|
572
|
+
*
|
|
573
|
+
* @param settings - DevTools settings
|
|
574
|
+
* @returns Object with arrays of enabled floating and dial tool IDs
|
|
575
|
+
*/
|
|
576
|
+
declare const getEnabledToolIds: (settings: DevToolsSettings) => {
|
|
577
|
+
floating: string[];
|
|
578
|
+
dial: string[];
|
|
579
|
+
};
|
|
580
|
+
type SettingsListener<T> = (payload: T) => void;
|
|
581
|
+
/**
|
|
582
|
+
* Generic event bus for broadcasting settings changes.
|
|
583
|
+
* Platform-agnostic implementation for synchronizing settings
|
|
584
|
+
* across components.
|
|
585
|
+
*/
|
|
586
|
+
declare class SettingsEventBus<T = DevToolsSettings> {
|
|
587
|
+
private listeners;
|
|
588
|
+
/**
|
|
589
|
+
* Emit a settings change to all listeners.
|
|
590
|
+
*
|
|
591
|
+
* @param payload - The new settings value
|
|
592
|
+
*/
|
|
593
|
+
emit(payload: T): void;
|
|
594
|
+
/**
|
|
595
|
+
* Add a listener for settings changes.
|
|
596
|
+
*
|
|
597
|
+
* @param listener - Callback function to invoke on changes
|
|
598
|
+
* @returns Unsubscribe function
|
|
599
|
+
*/
|
|
600
|
+
addListener(listener: SettingsListener<T>): () => void;
|
|
601
|
+
/**
|
|
602
|
+
* Remove all listeners.
|
|
603
|
+
*/
|
|
604
|
+
clear(): void;
|
|
605
|
+
/**
|
|
606
|
+
* Get the number of active listeners.
|
|
607
|
+
*/
|
|
608
|
+
get listenerCount(): number;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Default settings event bus instance.
|
|
612
|
+
* Use this for broadcasting settings changes across the app.
|
|
613
|
+
*/
|
|
614
|
+
declare const settingsEventBus: SettingsEventBus<DevToolsSettings>;
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* DevToolsState - Pure state management for floating dev tools.
|
|
618
|
+
*
|
|
619
|
+
* Platform-agnostic state machine for managing:
|
|
620
|
+
* - Dial menu open/closed state
|
|
621
|
+
* - Settings modal open/closed state
|
|
622
|
+
* - Active settings tab
|
|
623
|
+
*
|
|
624
|
+
* This is a headless state manager with no React or platform dependencies.
|
|
625
|
+
* Use with useSyncExternalStore or similar subscription patterns.
|
|
626
|
+
*/
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Complete state of the floating dev tools system.
|
|
630
|
+
*/
|
|
631
|
+
interface DevToolsState {
|
|
632
|
+
/** Whether the dial menu is open */
|
|
633
|
+
isDialOpen: boolean;
|
|
634
|
+
/** Whether the settings modal is open */
|
|
635
|
+
isSettingsOpen: boolean;
|
|
636
|
+
/** Currently active settings tab */
|
|
637
|
+
activeSettingsTab: SettingsTabKey;
|
|
638
|
+
/** Whether state has been initialized (e.g., loaded from storage) */
|
|
639
|
+
isInitialized: boolean;
|
|
640
|
+
}
|
|
641
|
+
/**
|
|
642
|
+
* Actions that can be dispatched to modify state.
|
|
643
|
+
*/
|
|
644
|
+
type DevToolsAction = {
|
|
645
|
+
type: 'OPEN_DIAL';
|
|
646
|
+
} | {
|
|
647
|
+
type: 'CLOSE_DIAL';
|
|
648
|
+
} | {
|
|
649
|
+
type: 'TOGGLE_DIAL';
|
|
650
|
+
} | {
|
|
651
|
+
type: 'OPEN_SETTINGS';
|
|
652
|
+
} | {
|
|
653
|
+
type: 'CLOSE_SETTINGS';
|
|
654
|
+
} | {
|
|
655
|
+
type: 'SET_SETTINGS_TAB';
|
|
656
|
+
tab: SettingsTabKey;
|
|
657
|
+
} | {
|
|
658
|
+
type: 'INITIALIZE';
|
|
659
|
+
};
|
|
660
|
+
/**
|
|
661
|
+
* Pure reducer function for DevTools state.
|
|
662
|
+
* Can be used standalone or with any state management library.
|
|
663
|
+
*/
|
|
664
|
+
declare function devToolsReducer(state: DevToolsState, action: DevToolsAction): DevToolsState;
|
|
665
|
+
type Listener = () => void;
|
|
666
|
+
/**
|
|
667
|
+
* DevToolsStateManager - Subscribable state container.
|
|
668
|
+
*
|
|
669
|
+
* Follows the external store pattern for compatibility with
|
|
670
|
+
* React's useSyncExternalStore and similar patterns.
|
|
671
|
+
*
|
|
672
|
+
* @example
|
|
673
|
+
* ```ts
|
|
674
|
+
* const manager = new DevToolsStateManager();
|
|
675
|
+
*
|
|
676
|
+
* // Subscribe to changes
|
|
677
|
+
* const unsubscribe = manager.subscribe(() => {
|
|
678
|
+
* console.log('State changed:', manager.getState());
|
|
679
|
+
* });
|
|
680
|
+
*
|
|
681
|
+
* // Dispatch actions
|
|
682
|
+
* manager.openDial();
|
|
683
|
+
* manager.openSettings();
|
|
684
|
+
*
|
|
685
|
+
* // Clean up
|
|
686
|
+
* unsubscribe();
|
|
687
|
+
* ```
|
|
688
|
+
*/
|
|
689
|
+
declare class DevToolsStateManager {
|
|
690
|
+
private state;
|
|
691
|
+
private listeners;
|
|
692
|
+
constructor(initialStateOverride?: Partial<DevToolsState>);
|
|
693
|
+
/**
|
|
694
|
+
* Get the current state snapshot.
|
|
695
|
+
* Safe to call at any time.
|
|
696
|
+
*/
|
|
697
|
+
getState: () => DevToolsState;
|
|
698
|
+
/**
|
|
699
|
+
* Get server snapshot for SSR.
|
|
700
|
+
* Returns initial state for hydration consistency.
|
|
701
|
+
*/
|
|
702
|
+
getServerState: () => DevToolsState;
|
|
703
|
+
/**
|
|
704
|
+
* Check if dial menu is open.
|
|
705
|
+
*/
|
|
706
|
+
isDialOpen(): boolean;
|
|
707
|
+
/**
|
|
708
|
+
* Check if settings modal is open.
|
|
709
|
+
*/
|
|
710
|
+
isSettingsOpen(): boolean;
|
|
711
|
+
/**
|
|
712
|
+
* Check if state has been initialized.
|
|
713
|
+
*/
|
|
714
|
+
isInitialized(): boolean;
|
|
715
|
+
/**
|
|
716
|
+
* Get active settings tab.
|
|
717
|
+
*/
|
|
718
|
+
getActiveSettingsTab(): SettingsTabKey;
|
|
719
|
+
/**
|
|
720
|
+
* Dispatch an action to update state.
|
|
721
|
+
*/
|
|
722
|
+
dispatch(action: DevToolsAction): void;
|
|
723
|
+
/**
|
|
724
|
+
* Open the dial menu.
|
|
725
|
+
*/
|
|
726
|
+
openDial(): void;
|
|
727
|
+
/**
|
|
728
|
+
* Close the dial menu.
|
|
729
|
+
*/
|
|
730
|
+
closeDial(): void;
|
|
731
|
+
/**
|
|
732
|
+
* Toggle the dial menu open/closed.
|
|
733
|
+
*/
|
|
734
|
+
toggleDial(): void;
|
|
735
|
+
/**
|
|
736
|
+
* Open the settings modal.
|
|
737
|
+
* Also closes the dial menu if open.
|
|
738
|
+
*/
|
|
739
|
+
openSettings(): void;
|
|
740
|
+
/**
|
|
741
|
+
* Close the settings modal.
|
|
742
|
+
*/
|
|
743
|
+
closeSettings(): void;
|
|
744
|
+
/**
|
|
745
|
+
* Set the active settings tab.
|
|
746
|
+
*/
|
|
747
|
+
setSettingsTab(tab: SettingsTabKey): void;
|
|
748
|
+
/**
|
|
749
|
+
* Mark state as initialized.
|
|
750
|
+
* Call after loading persisted state.
|
|
751
|
+
*/
|
|
752
|
+
initialize(): void;
|
|
753
|
+
/**
|
|
754
|
+
* Subscribe to state changes.
|
|
755
|
+
* Returns an unsubscribe function.
|
|
756
|
+
*
|
|
757
|
+
* Compatible with React's useSyncExternalStore.
|
|
758
|
+
*/
|
|
759
|
+
subscribe: (listener: Listener) => (() => void);
|
|
760
|
+
/**
|
|
761
|
+
* Notify all listeners of state change.
|
|
762
|
+
*/
|
|
763
|
+
private notifyListeners;
|
|
764
|
+
/**
|
|
765
|
+
* Get the number of active listeners.
|
|
766
|
+
* Useful for debugging.
|
|
767
|
+
*/
|
|
768
|
+
get listenerCount(): number;
|
|
769
|
+
/**
|
|
770
|
+
* Reset state to initial values.
|
|
771
|
+
* Useful for testing.
|
|
772
|
+
*/
|
|
773
|
+
reset(): void;
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Default global DevToolsStateManager instance.
|
|
777
|
+
* Use this for app-wide state management.
|
|
778
|
+
*
|
|
779
|
+
* For isolated testing or multiple instances,
|
|
780
|
+
* create a new DevToolsStateManager instead.
|
|
781
|
+
*/
|
|
782
|
+
declare const devToolsStateManager: DevToolsStateManager;
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Shared utility functions for floating tools.
|
|
786
|
+
* Platform-agnostic - no React or DOM dependencies.
|
|
787
|
+
*/
|
|
788
|
+
type UserRole = 'admin' | 'internal' | 'user';
|
|
789
|
+
interface UserStatusConfig {
|
|
790
|
+
label: string;
|
|
791
|
+
dotColor: string;
|
|
792
|
+
textColor: string;
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Get display configuration for a user role.
|
|
796
|
+
* Used by both web and mobile renderers.
|
|
797
|
+
*/
|
|
798
|
+
declare function getUserStatusConfig(userRole: UserRole, colors: {
|
|
799
|
+
success: string;
|
|
800
|
+
optional: string;
|
|
801
|
+
muted: string;
|
|
802
|
+
secondary: string;
|
|
803
|
+
}): UserStatusConfig;
|
|
804
|
+
interface GripIconLayout {
|
|
805
|
+
dotSize: number;
|
|
806
|
+
columnGap: number;
|
|
807
|
+
rowGap: number;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Calculate grip icon layout dimensions based on size.
|
|
811
|
+
* Creates a 2x3 dot grid pattern.
|
|
812
|
+
*/
|
|
813
|
+
declare function getGripIconLayout(size: number): GripIconLayout;
|
|
814
|
+
/**
|
|
815
|
+
* Filter valid React children (removes null, undefined, false).
|
|
816
|
+
* Works with both web and React Native.
|
|
817
|
+
*/
|
|
818
|
+
declare function filterValidChildren<T>(children: T[]): T[];
|
|
819
|
+
|
|
820
|
+
/**
|
|
821
|
+
* Animation easing functions.
|
|
822
|
+
* Platform-agnostic - used by both web (RAF) and mobile (Animated).
|
|
823
|
+
*/
|
|
824
|
+
/**
|
|
825
|
+
* Easing functions for animations.
|
|
826
|
+
* All functions take progress (0-1) and return eased value (0-1).
|
|
827
|
+
*/
|
|
828
|
+
declare const easing: {
|
|
829
|
+
/**
|
|
830
|
+
* Linear - no easing.
|
|
831
|
+
*/
|
|
832
|
+
readonly linear: (t: number) => number;
|
|
833
|
+
/**
|
|
834
|
+
* Ease out cubic - decelerates towards end.
|
|
835
|
+
* Used for hide/show animations.
|
|
836
|
+
*/
|
|
837
|
+
readonly easeOutCubic: (t: number) => number;
|
|
838
|
+
/**
|
|
839
|
+
* Ease in cubic - accelerates from start.
|
|
840
|
+
*/
|
|
841
|
+
readonly easeInCubic: (t: number) => number;
|
|
842
|
+
/**
|
|
843
|
+
* Ease in-out cubic - smooth acceleration and deceleration.
|
|
844
|
+
*/
|
|
845
|
+
readonly easeInOutCubic: (t: number) => number;
|
|
846
|
+
/**
|
|
847
|
+
* Ease out quad - lighter deceleration than cubic.
|
|
848
|
+
*/
|
|
849
|
+
readonly easeOutQuad: (t: number) => number;
|
|
850
|
+
/**
|
|
851
|
+
* Ease out expo - strong deceleration (snappy feel).
|
|
852
|
+
*/
|
|
853
|
+
readonly easeOutExpo: (t: number) => number;
|
|
854
|
+
};
|
|
855
|
+
type EasingFunction = (t: number) => number;
|
|
856
|
+
type EasingName = keyof typeof easing;
|
|
857
|
+
/**
|
|
858
|
+
* Get an easing function by name.
|
|
859
|
+
*/
|
|
860
|
+
declare function getEasing(name: EasingName): EasingFunction;
|
|
861
|
+
/**
|
|
862
|
+
* Interpolate between two values using an easing function.
|
|
863
|
+
*/
|
|
864
|
+
declare function interpolate(from: number, to: number, progress: number, easingFn?: EasingFunction): number;
|
|
865
|
+
/**
|
|
866
|
+
* Interpolate a position (x, y) using an easing function.
|
|
867
|
+
*/
|
|
868
|
+
declare function interpolatePosition(from: {
|
|
869
|
+
x: number;
|
|
870
|
+
y: number;
|
|
871
|
+
}, to: {
|
|
872
|
+
x: number;
|
|
873
|
+
y: number;
|
|
874
|
+
}, progress: number, easingFn?: EasingFunction): {
|
|
875
|
+
x: number;
|
|
876
|
+
y: number;
|
|
877
|
+
};
|
|
878
|
+
|
|
879
|
+
/**
|
|
880
|
+
* Shared color palette for floating tools.
|
|
881
|
+
* Matches the gameUIColors from @buoy-gg/shared-ui.
|
|
882
|
+
*
|
|
883
|
+
* These are duplicated here to avoid requiring @buoy-gg/shared-ui
|
|
884
|
+
* as a dependency (which has React Native dependencies).
|
|
885
|
+
*
|
|
886
|
+
* TODO: Consider extracting colors to a truly platform-agnostic package
|
|
887
|
+
* that both shared-ui and floating-tools-core can depend on.
|
|
888
|
+
*/
|
|
889
|
+
/**
|
|
890
|
+
* Buoy brand colors - EXACT values from web docs site dark theme
|
|
891
|
+
*/
|
|
892
|
+
declare const floatingToolsColors: {
|
|
893
|
+
/** Dark panel background */
|
|
894
|
+
readonly panel: "#1A1A1A";
|
|
895
|
+
/** Muted gray for secondary elements */
|
|
896
|
+
readonly muted: "#888888";
|
|
897
|
+
/** Primary text color */
|
|
898
|
+
readonly secondary: "#E0E0E0";
|
|
899
|
+
/** Info/active state color (Buoy teal) */
|
|
900
|
+
readonly info: "#20C997";
|
|
901
|
+
/** Success/admin color (Buoy teal) */
|
|
902
|
+
readonly success: "#20C997";
|
|
903
|
+
/** Warning/optional color (Buoy orange) */
|
|
904
|
+
readonly optional: "#FFA94D";
|
|
905
|
+
/** Error color (Buoy red) */
|
|
906
|
+
readonly error: "#EF4444";
|
|
907
|
+
/** Primary accent color (Buoy teal) */
|
|
908
|
+
readonly primary: "#20C997";
|
|
909
|
+
/** Color used when dragging the floating tools (Buoy teal) */
|
|
910
|
+
readonly dragActive: "#20C997";
|
|
911
|
+
};
|
|
912
|
+
type FloatingToolsColorKey = keyof typeof floatingToolsColors;
|
|
913
|
+
/**
|
|
914
|
+
* Get a color with optional alpha.
|
|
915
|
+
* @param color - The base color (hex)
|
|
916
|
+
* @param alpha - Alpha value as hex string (00-FF) or number (0-1)
|
|
917
|
+
*/
|
|
918
|
+
declare function withAlpha(color: string, alpha: string | number): string;
|
|
919
|
+
|
|
920
|
+
/**
|
|
921
|
+
* Dial Menu - Shared layout calculations, colors, and styling.
|
|
922
|
+
*
|
|
923
|
+
* Pure configuration and math functions for the dial menu.
|
|
924
|
+
* No React or platform-specific code.
|
|
925
|
+
*/
|
|
926
|
+
/** Maximum number of slots in the dial */
|
|
927
|
+
declare const MAX_DIAL_SLOTS = 6;
|
|
928
|
+
/** Starting angle for first icon (top of circle, -90 degrees in radians) */
|
|
929
|
+
declare const DIAL_START_ANGLE: number;
|
|
930
|
+
/** Default button size in the center */
|
|
931
|
+
declare const DIAL_BUTTON_SIZE = 80;
|
|
932
|
+
/** Default icon view size */
|
|
933
|
+
declare const DIAL_ICON_SIZE = 60;
|
|
934
|
+
/** Padding from edge of circle to icons */
|
|
935
|
+
declare const DIAL_ICON_PADDING = 20;
|
|
936
|
+
/** Number of grid lines in the dial */
|
|
937
|
+
declare const DIAL_GRID_LINE_COUNT = 6;
|
|
938
|
+
/**
|
|
939
|
+
* Color palette for the dial menu.
|
|
940
|
+
* Derived from floatingToolsColors for consistency.
|
|
941
|
+
*
|
|
942
|
+
* Property names match existing mobile implementation for compatibility.
|
|
943
|
+
*/
|
|
944
|
+
declare const dialColors: {
|
|
945
|
+
/** Background color for the dial circle */
|
|
946
|
+
readonly dialBackground: "#000000";
|
|
947
|
+
/** Gradient layer colors (with alpha) */
|
|
948
|
+
readonly dialGradient1: string;
|
|
949
|
+
readonly dialGradient2: string;
|
|
950
|
+
readonly dialGradient3: string;
|
|
951
|
+
/** Border color for dial and buttons */
|
|
952
|
+
readonly dialBorder: string;
|
|
953
|
+
/** Shadow/glow color */
|
|
954
|
+
readonly dialShadow: "#20C997";
|
|
955
|
+
/** Grid line color */
|
|
956
|
+
readonly dialGridLine: string;
|
|
957
|
+
/** Backdrop overlay color */
|
|
958
|
+
readonly dialBackdrop: "rgba(0, 0, 0, 0.85)";
|
|
959
|
+
/** Center button text color */
|
|
960
|
+
readonly centerText: "#E0E0E0";
|
|
961
|
+
/** Center button text glow */
|
|
962
|
+
readonly centerTextGlow: "#20C997";
|
|
963
|
+
/** Icon label color */
|
|
964
|
+
readonly iconLabel: "#E0E0E0";
|
|
965
|
+
/** Empty slot dot background */
|
|
966
|
+
readonly emptyDotBackground: string;
|
|
967
|
+
/** Empty slot dot border */
|
|
968
|
+
readonly emptyDotBorder: string;
|
|
969
|
+
};
|
|
970
|
+
type DialColorKey = keyof typeof dialColors;
|
|
971
|
+
/**
|
|
972
|
+
* Styling configuration for the dial menu.
|
|
973
|
+
* All numeric values that affect appearance.
|
|
974
|
+
*/
|
|
975
|
+
declare const dialStyles: {
|
|
976
|
+
readonly backdrop: {
|
|
977
|
+
readonly opacity: 0.85;
|
|
978
|
+
};
|
|
979
|
+
readonly circle: {
|
|
980
|
+
readonly borderWidth: 1;
|
|
981
|
+
readonly shadowOpacity: 0.5;
|
|
982
|
+
readonly shadowRadius: 20;
|
|
983
|
+
};
|
|
984
|
+
readonly gradientLayers: readonly [{
|
|
985
|
+
readonly opacity: 0.6;
|
|
986
|
+
readonly offsetPercent: 0;
|
|
987
|
+
}, {
|
|
988
|
+
readonly opacity: 0.4;
|
|
989
|
+
readonly offsetPercent: 30;
|
|
990
|
+
}, {
|
|
991
|
+
readonly opacity: 0.3;
|
|
992
|
+
readonly offsetPercent: 50;
|
|
993
|
+
}];
|
|
994
|
+
readonly grid: {
|
|
995
|
+
readonly lineCount: 6;
|
|
996
|
+
readonly lineHeight: 1;
|
|
997
|
+
/** Rotation angles in degrees for each line */
|
|
998
|
+
readonly getLineRotations: () => number[];
|
|
999
|
+
};
|
|
1000
|
+
readonly centerButton: {
|
|
1001
|
+
/** Button container is this multiple of button size */
|
|
1002
|
+
readonly containerRatio: 1.5;
|
|
1003
|
+
/** Button border wrapper is this multiple of button size */
|
|
1004
|
+
readonly borderRatio: 1.2;
|
|
1005
|
+
/** Border radius ratio */
|
|
1006
|
+
readonly borderRadiusRatio: 0.6;
|
|
1007
|
+
readonly borderWidth: 2;
|
|
1008
|
+
readonly text: {
|
|
1009
|
+
readonly fontSize: 10;
|
|
1010
|
+
readonly fontWeight: "900";
|
|
1011
|
+
readonly letterSpacing: 1;
|
|
1012
|
+
readonly fontFamily: "monospace";
|
|
1013
|
+
};
|
|
1014
|
+
readonly proText: {
|
|
1015
|
+
readonly fontSize: 8;
|
|
1016
|
+
readonly letterSpacing: 2;
|
|
1017
|
+
};
|
|
1018
|
+
};
|
|
1019
|
+
readonly icon: {
|
|
1020
|
+
/** Background gradient size as percent of icon size */
|
|
1021
|
+
readonly gradientBgSizePercent: 85;
|
|
1022
|
+
readonly gradientBgBorderRadius: 12;
|
|
1023
|
+
readonly gradientBgOpacity: 0.3;
|
|
1024
|
+
/** Inner glow size as percent of icon size */
|
|
1025
|
+
readonly innerGlowSizePercent: 70;
|
|
1026
|
+
readonly innerGlowBorderRadius: 10;
|
|
1027
|
+
readonly innerGlowOpacity: 0.5;
|
|
1028
|
+
readonly label: {
|
|
1029
|
+
readonly fontSize: 8;
|
|
1030
|
+
readonly fontWeight: "900";
|
|
1031
|
+
readonly letterSpacing: 0.3;
|
|
1032
|
+
readonly fontFamily: "monospace";
|
|
1033
|
+
readonly marginTop: 2;
|
|
1034
|
+
};
|
|
1035
|
+
/** Icon wrapper margin bottom */
|
|
1036
|
+
readonly wrapperMarginBottom: 4;
|
|
1037
|
+
};
|
|
1038
|
+
readonly emptySlot: {
|
|
1039
|
+
readonly dotSize: 12;
|
|
1040
|
+
readonly borderWidth: 1;
|
|
1041
|
+
};
|
|
1042
|
+
};
|
|
1043
|
+
/**
|
|
1044
|
+
* Get rotation angles for grid lines.
|
|
1045
|
+
* @param count - Number of grid lines (default: 6)
|
|
1046
|
+
* @returns Array of rotation angles in degrees
|
|
1047
|
+
*/
|
|
1048
|
+
declare function getGridLineRotations(count?: number): number[];
|
|
1049
|
+
interface DialLayoutConfig {
|
|
1050
|
+
/** Screen width for responsive sizing */
|
|
1051
|
+
screenWidth: number;
|
|
1052
|
+
/** Maximum circle size (default: 320) */
|
|
1053
|
+
maxCircleSize?: number;
|
|
1054
|
+
/** Circle size as percentage of screen width (default: 0.75) */
|
|
1055
|
+
circleSizeRatio?: number;
|
|
1056
|
+
/** Size of each icon slot (default: 60) */
|
|
1057
|
+
iconSize?: number;
|
|
1058
|
+
/** Padding from circle edge to icons (default: 20) */
|
|
1059
|
+
iconPadding?: number;
|
|
1060
|
+
}
|
|
1061
|
+
interface DialLayout {
|
|
1062
|
+
/** Calculated circle diameter */
|
|
1063
|
+
circleSize: number;
|
|
1064
|
+
/** Circle radius */
|
|
1065
|
+
circleRadius: number;
|
|
1066
|
+
/** Radius at which icons are positioned */
|
|
1067
|
+
iconRadius: number;
|
|
1068
|
+
/** Size of each icon slot */
|
|
1069
|
+
iconSize: number;
|
|
1070
|
+
/** Center button size */
|
|
1071
|
+
buttonSize: number;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Calculate dial layout dimensions based on screen size.
|
|
1075
|
+
*/
|
|
1076
|
+
declare function getDialLayout(config: DialLayoutConfig): DialLayout;
|
|
1077
|
+
interface IconPosition {
|
|
1078
|
+
/** X offset from center */
|
|
1079
|
+
x: number;
|
|
1080
|
+
/** Y offset from center */
|
|
1081
|
+
y: number;
|
|
1082
|
+
/** Angle in radians */
|
|
1083
|
+
angle: number;
|
|
1084
|
+
}
|
|
1085
|
+
/**
|
|
1086
|
+
* Get the angle for an icon at a given index.
|
|
1087
|
+
*
|
|
1088
|
+
* @param index - Icon index (0-based)
|
|
1089
|
+
* @param totalIcons - Total number of icon slots
|
|
1090
|
+
* @param startAngle - Starting angle in radians (default: top of circle)
|
|
1091
|
+
*/
|
|
1092
|
+
declare function getIconAngle(index: number, totalIcons: number, startAngle?: number): number;
|
|
1093
|
+
/**
|
|
1094
|
+
* Get the position for an icon at a given index.
|
|
1095
|
+
*
|
|
1096
|
+
* @param index - Icon index (0-based)
|
|
1097
|
+
* @param totalIcons - Total number of icon slots
|
|
1098
|
+
* @param radius - Distance from center to icon
|
|
1099
|
+
* @param startAngle - Starting angle in radians (default: top of circle)
|
|
1100
|
+
*/
|
|
1101
|
+
declare function getIconPosition(index: number, totalIcons: number, radius: number, startAngle?: number): IconPosition;
|
|
1102
|
+
/**
|
|
1103
|
+
* Get positions for all icons in the dial.
|
|
1104
|
+
*
|
|
1105
|
+
* @param totalIcons - Total number of icon slots
|
|
1106
|
+
* @param radius - Distance from center to icons
|
|
1107
|
+
* @param startAngle - Starting angle in radians (default: top of circle)
|
|
1108
|
+
*/
|
|
1109
|
+
declare function getAllIconPositions(totalIcons: number, radius: number, startAngle?: number): IconPosition[];
|
|
1110
|
+
/**
|
|
1111
|
+
* Get the interpolation input range for staggered icon animation.
|
|
1112
|
+
* Used to create smooth entrance animations with stagger.
|
|
1113
|
+
*
|
|
1114
|
+
* @param index - Icon index (0-based)
|
|
1115
|
+
* @param totalIcons - Total number of icons
|
|
1116
|
+
* @param staggerRatio - Delay ratio per icon (default: 0.1)
|
|
1117
|
+
*/
|
|
1118
|
+
declare function getIconStaggerInputRange(index: number, totalIcons: number, staggerRatio?: number): [number, number, number, number];
|
|
1119
|
+
/**
|
|
1120
|
+
* Easing function names used in animations.
|
|
1121
|
+
*/
|
|
1122
|
+
type DialEasingName = 'linear' | 'easeOutCubic' | 'easeInCubic' | 'easeInOutCubic';
|
|
1123
|
+
/**
|
|
1124
|
+
* Spring animation configuration.
|
|
1125
|
+
*/
|
|
1126
|
+
interface SpringConfig {
|
|
1127
|
+
type: 'spring';
|
|
1128
|
+
damping: number;
|
|
1129
|
+
stiffness: number;
|
|
1130
|
+
mass?: number;
|
|
1131
|
+
}
|
|
1132
|
+
/**
|
|
1133
|
+
* Comprehensive animation configuration for the dial menu.
|
|
1134
|
+
* All timing, easing, and effect parameters in one place.
|
|
1135
|
+
*/
|
|
1136
|
+
declare const dialAnimationConfig: {
|
|
1137
|
+
/** Entrance animation sequence */
|
|
1138
|
+
readonly entrance: {
|
|
1139
|
+
/** Backdrop fade in */
|
|
1140
|
+
readonly backdrop: {
|
|
1141
|
+
readonly duration: 400;
|
|
1142
|
+
readonly easing: DialEasingName;
|
|
1143
|
+
};
|
|
1144
|
+
/** Dial circle animations */
|
|
1145
|
+
readonly dial: {
|
|
1146
|
+
/** Spring scale from 0 to 1 */
|
|
1147
|
+
readonly scale: {
|
|
1148
|
+
readonly type: "spring";
|
|
1149
|
+
readonly damping: 15;
|
|
1150
|
+
readonly stiffness: 150;
|
|
1151
|
+
readonly mass: 1;
|
|
1152
|
+
};
|
|
1153
|
+
/** 360 degree rotation on entrance */
|
|
1154
|
+
readonly rotation: {
|
|
1155
|
+
readonly duration: 800;
|
|
1156
|
+
readonly degrees: 360;
|
|
1157
|
+
readonly easing: DialEasingName;
|
|
1158
|
+
};
|
|
1159
|
+
};
|
|
1160
|
+
/** Center button spring scale with delay */
|
|
1161
|
+
readonly centerButton: {
|
|
1162
|
+
readonly delay: 300;
|
|
1163
|
+
readonly type: "spring";
|
|
1164
|
+
readonly damping: 10;
|
|
1165
|
+
readonly stiffness: 200;
|
|
1166
|
+
};
|
|
1167
|
+
/** Icons stagger entrance */
|
|
1168
|
+
readonly icons: {
|
|
1169
|
+
readonly delay: 500;
|
|
1170
|
+
readonly duration: 600;
|
|
1171
|
+
readonly easing: DialEasingName;
|
|
1172
|
+
};
|
|
1173
|
+
/** Circuit traces fade in */
|
|
1174
|
+
readonly circuitTraces: {
|
|
1175
|
+
readonly delay: 600;
|
|
1176
|
+
readonly duration: 1000;
|
|
1177
|
+
};
|
|
1178
|
+
};
|
|
1179
|
+
/** Exit animation sequence */
|
|
1180
|
+
readonly exit: {
|
|
1181
|
+
/** Icons collapse back to center */
|
|
1182
|
+
readonly icons: {
|
|
1183
|
+
readonly duration: 300;
|
|
1184
|
+
readonly easing: DialEasingName;
|
|
1185
|
+
};
|
|
1186
|
+
/** Center button scale down */
|
|
1187
|
+
readonly centerButton: {
|
|
1188
|
+
readonly duration: 200;
|
|
1189
|
+
readonly easing: DialEasingName;
|
|
1190
|
+
};
|
|
1191
|
+
/** Dial scale down */
|
|
1192
|
+
readonly dialScale: {
|
|
1193
|
+
readonly duration: 250;
|
|
1194
|
+
readonly easing: DialEasingName;
|
|
1195
|
+
};
|
|
1196
|
+
/** Backdrop fade out */
|
|
1197
|
+
readonly backdrop: {
|
|
1198
|
+
readonly duration: 200;
|
|
1199
|
+
};
|
|
1200
|
+
};
|
|
1201
|
+
/** Continuous looping effects */
|
|
1202
|
+
readonly continuous: {
|
|
1203
|
+
/** Glitch effect - horizontal jitter */
|
|
1204
|
+
readonly glitch: {
|
|
1205
|
+
readonly interval: 3000;
|
|
1206
|
+
readonly offset: 2;
|
|
1207
|
+
readonly stepDuration: 50;
|
|
1208
|
+
};
|
|
1209
|
+
/** Pulse effect - subtle scale oscillation */
|
|
1210
|
+
readonly pulse: {
|
|
1211
|
+
readonly minScale: 0.98;
|
|
1212
|
+
readonly maxScale: 1.02;
|
|
1213
|
+
readonly duration: 1000;
|
|
1214
|
+
readonly easing: DialEasingName;
|
|
1215
|
+
};
|
|
1216
|
+
/** Floating effect - vertical bobbing */
|
|
1217
|
+
readonly floating: {
|
|
1218
|
+
readonly minY: 0;
|
|
1219
|
+
readonly maxY: -8;
|
|
1220
|
+
readonly duration: 3000;
|
|
1221
|
+
readonly easing: DialEasingName;
|
|
1222
|
+
};
|
|
1223
|
+
/** Breathing effect - scale on center button */
|
|
1224
|
+
readonly breathing: {
|
|
1225
|
+
readonly minScale: 0.98;
|
|
1226
|
+
readonly maxScale: 1.05;
|
|
1227
|
+
readonly duration: 2500;
|
|
1228
|
+
readonly easing: DialEasingName;
|
|
1229
|
+
};
|
|
1230
|
+
};
|
|
1231
|
+
/** Icon-specific animations */
|
|
1232
|
+
readonly icons: {
|
|
1233
|
+
/** Stagger ratio for entrance (0-1 per icon) */
|
|
1234
|
+
readonly staggerRatio: 0.1;
|
|
1235
|
+
/** Spiral effect parameters */
|
|
1236
|
+
readonly spiral: {
|
|
1237
|
+
/** Start rotation in radians (2π = full rotation) */
|
|
1238
|
+
readonly startRotation: number;
|
|
1239
|
+
/** End rotation in radians */
|
|
1240
|
+
readonly endRotation: 0;
|
|
1241
|
+
};
|
|
1242
|
+
/** Opacity interpolation during entrance */
|
|
1243
|
+
readonly opacity: {
|
|
1244
|
+
readonly inputRange: readonly [number, number, number];
|
|
1245
|
+
readonly outputRange: readonly [number, number, number];
|
|
1246
|
+
};
|
|
1247
|
+
/** Press in animation */
|
|
1248
|
+
readonly pressIn: {
|
|
1249
|
+
readonly scale: 0.95;
|
|
1250
|
+
readonly type: "spring";
|
|
1251
|
+
readonly damping: 15;
|
|
1252
|
+
readonly stiffness: 400;
|
|
1253
|
+
};
|
|
1254
|
+
/** Press out animation */
|
|
1255
|
+
readonly pressOut: {
|
|
1256
|
+
readonly scale: 1;
|
|
1257
|
+
readonly type: "spring";
|
|
1258
|
+
readonly damping: 15;
|
|
1259
|
+
readonly stiffness: 400;
|
|
1260
|
+
};
|
|
1261
|
+
};
|
|
1262
|
+
/** User interaction animations */
|
|
1263
|
+
readonly interaction: {
|
|
1264
|
+
/** Icon selection pulse effect */
|
|
1265
|
+
readonly iconSelect: {
|
|
1266
|
+
readonly pulse: readonly [{
|
|
1267
|
+
readonly scale: 0.9;
|
|
1268
|
+
readonly damping: 15;
|
|
1269
|
+
readonly stiffness: 500;
|
|
1270
|
+
}, {
|
|
1271
|
+
readonly scale: 1;
|
|
1272
|
+
readonly damping: 10;
|
|
1273
|
+
readonly stiffness: 200;
|
|
1274
|
+
}];
|
|
1275
|
+
readonly actionDelay: 50;
|
|
1276
|
+
};
|
|
1277
|
+
/** Center button hover effect */
|
|
1278
|
+
readonly centerHover: {
|
|
1279
|
+
readonly scale: 1.05;
|
|
1280
|
+
readonly duration: 150;
|
|
1281
|
+
};
|
|
1282
|
+
};
|
|
1283
|
+
};
|
|
1284
|
+
type DialAnimationConfigType = typeof dialAnimationConfig;
|
|
1285
|
+
/**
|
|
1286
|
+
* CSS cubic-bezier approximations for React Native springs.
|
|
1287
|
+
* These provide similar visual feel in CSS transitions/animations.
|
|
1288
|
+
*/
|
|
1289
|
+
declare const dialCSSBeziers: {
|
|
1290
|
+
/** Spring: damping 15, stiffness 150 (dial scale) */
|
|
1291
|
+
readonly dialScale: "cubic-bezier(0.34, 1.56, 0.64, 1)";
|
|
1292
|
+
/** Spring: damping 10, stiffness 200 (center button) */
|
|
1293
|
+
readonly centerButton: "cubic-bezier(0.25, 1.7, 0.55, 1)";
|
|
1294
|
+
/** Spring: damping 15, stiffness 400 (icon press) */
|
|
1295
|
+
readonly iconPress: "cubic-bezier(0.22, 1.2, 0.36, 1)";
|
|
1296
|
+
/** Spring: damping 15, stiffness 500 (icon select pulse) */
|
|
1297
|
+
readonly iconSelectPulse: "cubic-bezier(0.18, 1.15, 0.32, 1)";
|
|
1298
|
+
/** Decelerate - for entrance animations */
|
|
1299
|
+
readonly easeOutCubic: "cubic-bezier(0.33, 1, 0.68, 1)";
|
|
1300
|
+
/** Accelerate - for exit animations */
|
|
1301
|
+
readonly easeInCubic: "cubic-bezier(0.32, 0, 0.67, 0)";
|
|
1302
|
+
/** Smooth in-out - for continuous effects */
|
|
1303
|
+
readonly easeInOutCubic: "cubic-bezier(0.65, 0, 0.35, 1)";
|
|
1304
|
+
/** Linear */
|
|
1305
|
+
readonly linear: "linear";
|
|
1306
|
+
};
|
|
1307
|
+
type DialCSSBezierKey = keyof typeof dialCSSBeziers;
|
|
1308
|
+
/**
|
|
1309
|
+
* Generate CSS @keyframes definitions for dial animations.
|
|
1310
|
+
* Can be injected into a <style> tag or used with CSS-in-JS.
|
|
1311
|
+
*/
|
|
1312
|
+
declare function generateDialCSSKeyframes(): Record<string, string>;
|
|
1313
|
+
/**
|
|
1314
|
+
* Get CSS animation shorthand values for continuous effects.
|
|
1315
|
+
* Use these in the `animation` CSS property.
|
|
1316
|
+
*/
|
|
1317
|
+
declare function getDialCSSAnimationStyles(): Record<string, string>;
|
|
1318
|
+
/**
|
|
1319
|
+
* Get all keyframes as a single CSS string for injection.
|
|
1320
|
+
*/
|
|
1321
|
+
declare function getDialCSSKeyframesString(): string;
|
|
1322
|
+
/**
|
|
1323
|
+
* Position and visual state during spiral animation.
|
|
1324
|
+
*/
|
|
1325
|
+
interface SpiralPosition {
|
|
1326
|
+
/** X offset from center */
|
|
1327
|
+
x: number;
|
|
1328
|
+
/** Y offset from center */
|
|
1329
|
+
y: number;
|
|
1330
|
+
/** Current rotation in radians */
|
|
1331
|
+
rotation: number;
|
|
1332
|
+
/** Scale factor (0 to 1) */
|
|
1333
|
+
scale: number;
|
|
1334
|
+
/** Opacity (0 to 1) */
|
|
1335
|
+
opacity: number;
|
|
1336
|
+
}
|
|
1337
|
+
/**
|
|
1338
|
+
* Calculate icon position during spiral entrance animation.
|
|
1339
|
+
*
|
|
1340
|
+
* @param progress - Animation progress (0 = start at center, 1 = final position)
|
|
1341
|
+
* @param index - Icon index (0-based)
|
|
1342
|
+
* @param totalIcons - Total number of icons
|
|
1343
|
+
* @param radius - Final radius from center
|
|
1344
|
+
* @param startAngle - Starting angle for icon layout (default: top of circle)
|
|
1345
|
+
*/
|
|
1346
|
+
declare function getSpiralAnimationPosition(progress: number, index: number, totalIcons: number, radius: number, startAngle?: number): SpiralPosition;
|
|
1347
|
+
/**
|
|
1348
|
+
* Calculate staggered progress for an icon based on master progress.
|
|
1349
|
+
* Applies the stagger delay so icons animate in sequence.
|
|
1350
|
+
*
|
|
1351
|
+
* @param masterProgress - Overall animation progress (0-1)
|
|
1352
|
+
* @param index - Icon index (0-based)
|
|
1353
|
+
* @param totalIcons - Total number of icons
|
|
1354
|
+
*/
|
|
1355
|
+
declare function getStaggeredIconProgress(masterProgress: number, index: number, totalIcons: number): number;
|
|
1356
|
+
|
|
1357
|
+
interface CircleElement$1 {
|
|
1358
|
+
type: 'circle';
|
|
1359
|
+
cx: number;
|
|
1360
|
+
cy: number;
|
|
1361
|
+
r: number;
|
|
1362
|
+
fill?: 'color' | 'bg' | string;
|
|
1363
|
+
border?: boolean;
|
|
1364
|
+
borderWidth?: number;
|
|
1365
|
+
opacity?: number;
|
|
1366
|
+
scaleX?: number;
|
|
1367
|
+
scaleY?: number;
|
|
1368
|
+
glow?: boolean;
|
|
1369
|
+
glowRadius?: number;
|
|
1370
|
+
rotation?: number;
|
|
1371
|
+
}
|
|
1372
|
+
interface RectElement$1 {
|
|
1373
|
+
type: 'rect';
|
|
1374
|
+
x: number;
|
|
1375
|
+
y: number;
|
|
1376
|
+
width: number;
|
|
1377
|
+
height: number;
|
|
1378
|
+
fill?: 'color' | 'bg' | string;
|
|
1379
|
+
border?: boolean;
|
|
1380
|
+
borderWidth?: number;
|
|
1381
|
+
borderRadius?: number;
|
|
1382
|
+
opacity?: number;
|
|
1383
|
+
glow?: boolean;
|
|
1384
|
+
glowRadius?: number;
|
|
1385
|
+
rotation?: number;
|
|
1386
|
+
rotateFromCenter?: boolean;
|
|
1387
|
+
}
|
|
1388
|
+
/**
|
|
1389
|
+
* Line element - draws a line between two points
|
|
1390
|
+
* Much cleaner than using rotated rectangles!
|
|
1391
|
+
*/
|
|
1392
|
+
interface LineElement$1 {
|
|
1393
|
+
type: 'line';
|
|
1394
|
+
x1: number;
|
|
1395
|
+
y1: number;
|
|
1396
|
+
x2: number;
|
|
1397
|
+
y2: number;
|
|
1398
|
+
stroke?: 'color' | 'bg' | string;
|
|
1399
|
+
strokeWidth?: number;
|
|
1400
|
+
opacity?: number;
|
|
1401
|
+
glow?: boolean;
|
|
1402
|
+
glowRadius?: number;
|
|
1403
|
+
rotation?: number;
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Triangle element - creates arrows/chevrons using CSS border trick
|
|
1407
|
+
* Works in pure React Native!
|
|
1408
|
+
*/
|
|
1409
|
+
interface TriangleElement$1 {
|
|
1410
|
+
type: 'triangle';
|
|
1411
|
+
x: number;
|
|
1412
|
+
y: number;
|
|
1413
|
+
size: number;
|
|
1414
|
+
direction: 'up' | 'down' | 'left' | 'right';
|
|
1415
|
+
fill?: 'color' | 'bg' | string;
|
|
1416
|
+
opacity?: number;
|
|
1417
|
+
rotation?: number;
|
|
1418
|
+
}
|
|
1419
|
+
/**
|
|
1420
|
+
* Arc element - creates curved segments (WiFi bars, circular progress)
|
|
1421
|
+
* Rendered as multiple line segments approximating a curve.
|
|
1422
|
+
*/
|
|
1423
|
+
interface ArcElement {
|
|
1424
|
+
type: 'arc';
|
|
1425
|
+
cx: number;
|
|
1426
|
+
cy: number;
|
|
1427
|
+
r: number;
|
|
1428
|
+
startAngle: number;
|
|
1429
|
+
endAngle: number;
|
|
1430
|
+
stroke?: 'color' | 'bg' | string;
|
|
1431
|
+
strokeWidth?: number;
|
|
1432
|
+
opacity?: number;
|
|
1433
|
+
segments?: number;
|
|
1434
|
+
}
|
|
1435
|
+
/**
|
|
1436
|
+
* Semicircle element - creates a half circle (filled)
|
|
1437
|
+
* Perfect for pokeball-style split designs!
|
|
1438
|
+
*/
|
|
1439
|
+
interface SemicircleElement {
|
|
1440
|
+
type: 'semicircle';
|
|
1441
|
+
cx: number;
|
|
1442
|
+
cy: number;
|
|
1443
|
+
r: number;
|
|
1444
|
+
half: 'top' | 'bottom' | 'left' | 'right';
|
|
1445
|
+
fill?: 'color' | 'bg' | string;
|
|
1446
|
+
border?: boolean;
|
|
1447
|
+
borderWidth?: number;
|
|
1448
|
+
opacity?: number;
|
|
1449
|
+
glow?: boolean;
|
|
1450
|
+
glowRadius?: number;
|
|
1451
|
+
}
|
|
1452
|
+
/**
|
|
1453
|
+
* SmoothArc element - creates a smooth arc using the border trick
|
|
1454
|
+
* Uses bordered circles with partial borders hidden - gives perfect anti-aliased curves!
|
|
1455
|
+
* This is the "clever trick" for WiFi-style arcs.
|
|
1456
|
+
*/
|
|
1457
|
+
interface SmoothArcElement {
|
|
1458
|
+
type: 'smootharc';
|
|
1459
|
+
cx: number;
|
|
1460
|
+
cy: number;
|
|
1461
|
+
r: number;
|
|
1462
|
+
stroke?: 'color' | 'bg' | string;
|
|
1463
|
+
strokeWidth?: number;
|
|
1464
|
+
opacity?: number;
|
|
1465
|
+
/** Which portion to show: 'bottom' shows bottom half (like WiFi), 'top' shows top half */
|
|
1466
|
+
portion?: 'bottom' | 'top' | 'left' | 'right';
|
|
1467
|
+
}
|
|
1468
|
+
type IconElement = CircleElement$1 | RectElement$1 | LineElement$1 | TriangleElement$1 | ArcElement | SemicircleElement | SmoothArcElement;
|
|
1469
|
+
interface IconData {
|
|
1470
|
+
color: string;
|
|
1471
|
+
bgColor: string;
|
|
1472
|
+
elements: IconElement[];
|
|
1473
|
+
}
|
|
1474
|
+
declare function renderIconData(data: IconData, size: number, colorOverride?: string): react_jsx_runtime.JSX.Element;
|
|
1475
|
+
declare function createIcon(data: IconData): FC<{
|
|
1476
|
+
size?: number;
|
|
1477
|
+
color?: string;
|
|
1478
|
+
}>;
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Icon Data Definitions - PURE DATA, NO JSX
|
|
1482
|
+
*
|
|
1483
|
+
* Each icon is just data. The renderer transforms it to components.
|
|
1484
|
+
* Change colors here = changes everywhere.
|
|
1485
|
+
*
|
|
1486
|
+
* Coordinates are relative to center (0,0 = center of icon)
|
|
1487
|
+
* Sizes are based on 24x24 base size, scaled automatically.
|
|
1488
|
+
*/
|
|
1489
|
+
|
|
1490
|
+
declare const NETWORK_ICON_COLOR = "#00D4FF";
|
|
1491
|
+
declare const ENV_ICON_COLOR = "#4AFF9F";
|
|
1492
|
+
declare const STORAGE_ICON_COLOR = "#FFB800";
|
|
1493
|
+
declare const ROUTES_ICON_COLOR = "#FF9F1C";
|
|
1494
|
+
declare const QUERY_ICON_COLOR = "#FF3366";
|
|
1495
|
+
declare const HIGHLIGHTER_ICON_COLOR = "#10B981";
|
|
1496
|
+
declare const RENDERS_ICON_COLOR = "#10B981";
|
|
1497
|
+
declare const BENCHMARK_ICON_COLOR = "#F59E0B";
|
|
1498
|
+
declare const SENTRY_ICON_COLOR = "#FF3366";
|
|
1499
|
+
declare const WIFI_ICON_COLOR = "#00D4FF";
|
|
1500
|
+
declare const HIGHLIGHT_ICON_COLOR = "#10B981";
|
|
1501
|
+
|
|
1502
|
+
declare const NetworkIcon: react.FC<{
|
|
1503
|
+
size?: number;
|
|
1504
|
+
color?: string;
|
|
1505
|
+
}>;
|
|
1506
|
+
|
|
1507
|
+
declare const EnvIcon: react.FC<{
|
|
1508
|
+
size?: number;
|
|
1509
|
+
color?: string;
|
|
1510
|
+
}>;
|
|
1511
|
+
|
|
1512
|
+
declare const StorageIcon: react.FC<{
|
|
1513
|
+
size?: number;
|
|
1514
|
+
color?: string;
|
|
1515
|
+
}>;
|
|
1516
|
+
|
|
1517
|
+
declare const RoutesIcon: react.FC<{
|
|
1518
|
+
size?: number;
|
|
1519
|
+
color?: string;
|
|
1520
|
+
}>;
|
|
1521
|
+
declare const RoutePinIcon: react.FC<{
|
|
1522
|
+
size?: number;
|
|
1523
|
+
color?: string;
|
|
1524
|
+
}>;
|
|
1525
|
+
declare const RoutePathIcon: react.FC<{
|
|
1526
|
+
size?: number;
|
|
1527
|
+
color?: string;
|
|
1528
|
+
}>;
|
|
1529
|
+
declare const RouteDotIcon: react.FC<{
|
|
1530
|
+
size?: number;
|
|
1531
|
+
color?: string;
|
|
1532
|
+
}>;
|
|
1533
|
+
declare const RouteTwoPinsIcon: react.FC<{
|
|
1534
|
+
size?: number;
|
|
1535
|
+
color?: string;
|
|
1536
|
+
}>;
|
|
1537
|
+
declare const CurveTestA: react.FC<{
|
|
1538
|
+
size?: number;
|
|
1539
|
+
color?: string;
|
|
1540
|
+
}>;
|
|
1541
|
+
declare const CurveTestB: react.FC<{
|
|
1542
|
+
size?: number;
|
|
1543
|
+
color?: string;
|
|
1544
|
+
}>;
|
|
1545
|
+
declare const CurveTestC: react.FC<{
|
|
1546
|
+
size?: number;
|
|
1547
|
+
color?: string;
|
|
1548
|
+
}>;
|
|
1549
|
+
declare const CurveTestD: react.FC<{
|
|
1550
|
+
size?: number;
|
|
1551
|
+
color?: string;
|
|
1552
|
+
}>;
|
|
1553
|
+
declare const CurveTestE: react.FC<{
|
|
1554
|
+
size?: number;
|
|
1555
|
+
color?: string;
|
|
1556
|
+
}>;
|
|
1557
|
+
declare const CurveTestF: react.FC<{
|
|
1558
|
+
size?: number;
|
|
1559
|
+
color?: string;
|
|
1560
|
+
}>;
|
|
1561
|
+
declare const CurveTestG: react.FC<{
|
|
1562
|
+
size?: number;
|
|
1563
|
+
color?: string;
|
|
1564
|
+
}>;
|
|
1565
|
+
declare const CurveTestH: react.FC<{
|
|
1566
|
+
size?: number;
|
|
1567
|
+
color?: string;
|
|
1568
|
+
}>;
|
|
1569
|
+
declare const CurveTestI: react.FC<{
|
|
1570
|
+
size?: number;
|
|
1571
|
+
color?: string;
|
|
1572
|
+
}>;
|
|
1573
|
+
declare const CurveTestJ: react.FC<{
|
|
1574
|
+
size?: number;
|
|
1575
|
+
color?: string;
|
|
1576
|
+
}>;
|
|
1577
|
+
declare const CurveTestK: react.FC<{
|
|
1578
|
+
size?: number;
|
|
1579
|
+
color?: string;
|
|
1580
|
+
}>;
|
|
1581
|
+
declare const CurveTestL: react.FC<{
|
|
1582
|
+
size?: number;
|
|
1583
|
+
color?: string;
|
|
1584
|
+
}>;
|
|
1585
|
+
declare const CurveTestM: react.FC<{
|
|
1586
|
+
size?: number;
|
|
1587
|
+
color?: string;
|
|
1588
|
+
}>;
|
|
1589
|
+
declare const CurveTestN: react.FC<{
|
|
1590
|
+
size?: number;
|
|
1591
|
+
color?: string;
|
|
1592
|
+
}>;
|
|
1593
|
+
declare const CurveTestO: react.FC<{
|
|
1594
|
+
size?: number;
|
|
1595
|
+
color?: string;
|
|
1596
|
+
}>;
|
|
1597
|
+
declare const CurveTestP: react.FC<{
|
|
1598
|
+
size?: number;
|
|
1599
|
+
color?: string;
|
|
1600
|
+
}>;
|
|
1601
|
+
|
|
1602
|
+
declare const QueryIcon: react.FC<{
|
|
1603
|
+
size?: number;
|
|
1604
|
+
color?: string;
|
|
1605
|
+
}>;
|
|
1606
|
+
|
|
1607
|
+
declare const HighlighterIcon: react.FC<{
|
|
1608
|
+
size?: number;
|
|
1609
|
+
color?: string;
|
|
1610
|
+
}>;
|
|
1611
|
+
declare const RendersIcon: react.FC<{
|
|
1612
|
+
size?: number;
|
|
1613
|
+
color?: string;
|
|
1614
|
+
}>;
|
|
1615
|
+
|
|
1616
|
+
declare const BenchmarkIcon: react.FC<{
|
|
1617
|
+
size?: number;
|
|
1618
|
+
color?: string;
|
|
1619
|
+
}>;
|
|
1620
|
+
|
|
1621
|
+
declare const SentryIcon: react.FC<{
|
|
1622
|
+
size?: number;
|
|
1623
|
+
color?: string;
|
|
1624
|
+
}>;
|
|
1625
|
+
|
|
1626
|
+
declare const WifiIcon: react.FC<{
|
|
1627
|
+
size?: number;
|
|
1628
|
+
color?: string;
|
|
1629
|
+
}>;
|
|
1630
|
+
|
|
1631
|
+
declare const HighlightIcon: react.FC<{
|
|
1632
|
+
size?: number;
|
|
1633
|
+
color?: string;
|
|
1634
|
+
}>;
|
|
1635
|
+
|
|
1636
|
+
/**
|
|
1637
|
+
* Icon Factories - Helper functions to create icon elements
|
|
1638
|
+
*
|
|
1639
|
+
* These factories reduce verbosity and provide sensible defaults
|
|
1640
|
+
* for common icon patterns.
|
|
1641
|
+
*/
|
|
1642
|
+
interface CircleElement {
|
|
1643
|
+
type: 'circle';
|
|
1644
|
+
cx: number;
|
|
1645
|
+
cy: number;
|
|
1646
|
+
r: number;
|
|
1647
|
+
fill?: 'color' | 'bg' | string;
|
|
1648
|
+
border?: boolean;
|
|
1649
|
+
borderWidth?: number;
|
|
1650
|
+
opacity?: number;
|
|
1651
|
+
scaleX?: number;
|
|
1652
|
+
scaleY?: number;
|
|
1653
|
+
glow?: boolean;
|
|
1654
|
+
glowRadius?: number;
|
|
1655
|
+
}
|
|
1656
|
+
interface LineElement {
|
|
1657
|
+
type: 'line';
|
|
1658
|
+
x1: number;
|
|
1659
|
+
y1: number;
|
|
1660
|
+
x2: number;
|
|
1661
|
+
y2: number;
|
|
1662
|
+
stroke?: 'color' | 'bg' | string;
|
|
1663
|
+
strokeWidth?: number;
|
|
1664
|
+
opacity?: number;
|
|
1665
|
+
glow?: boolean;
|
|
1666
|
+
glowRadius?: number;
|
|
1667
|
+
}
|
|
1668
|
+
interface RectElement {
|
|
1669
|
+
type: 'rect';
|
|
1670
|
+
x: number;
|
|
1671
|
+
y: number;
|
|
1672
|
+
width: number;
|
|
1673
|
+
height: number;
|
|
1674
|
+
fill?: 'color' | 'bg' | string;
|
|
1675
|
+
border?: boolean;
|
|
1676
|
+
borderWidth?: number;
|
|
1677
|
+
borderRadius?: number;
|
|
1678
|
+
opacity?: number;
|
|
1679
|
+
glow?: boolean;
|
|
1680
|
+
glowRadius?: number;
|
|
1681
|
+
rotation?: number;
|
|
1682
|
+
rotateFromCenter?: boolean;
|
|
1683
|
+
}
|
|
1684
|
+
interface TriangleElement {
|
|
1685
|
+
type: 'triangle';
|
|
1686
|
+
x: number;
|
|
1687
|
+
y: number;
|
|
1688
|
+
size: number;
|
|
1689
|
+
direction: 'up' | 'down' | 'left' | 'right';
|
|
1690
|
+
fill?: 'color' | 'bg' | string;
|
|
1691
|
+
opacity?: number;
|
|
1692
|
+
rotation?: number;
|
|
1693
|
+
}
|
|
1694
|
+
interface NodeOptions {
|
|
1695
|
+
fill?: 'color' | 'bg' | string;
|
|
1696
|
+
glow?: boolean;
|
|
1697
|
+
glowRadius?: number;
|
|
1698
|
+
opacity?: number;
|
|
1699
|
+
scaleX?: number;
|
|
1700
|
+
scaleY?: number;
|
|
1701
|
+
}
|
|
1702
|
+
interface LineOptions {
|
|
1703
|
+
stroke?: 'color' | 'bg' | string;
|
|
1704
|
+
strokeWidth?: number;
|
|
1705
|
+
glow?: boolean;
|
|
1706
|
+
glowRadius?: number;
|
|
1707
|
+
opacity?: number;
|
|
1708
|
+
}
|
|
1709
|
+
interface RingOptions {
|
|
1710
|
+
borderWidth?: number;
|
|
1711
|
+
opacity?: number;
|
|
1712
|
+
scaleX?: number;
|
|
1713
|
+
scaleY?: number;
|
|
1714
|
+
}
|
|
1715
|
+
/**
|
|
1716
|
+
* Creates a filled circle node (common pattern: glowing center point)
|
|
1717
|
+
*
|
|
1718
|
+
* @example
|
|
1719
|
+
* createNode(0, -4, 3) // Simple 3px radius node at center-top
|
|
1720
|
+
* createNode(0, 0, 4, { glow: true }) // Glowing center node
|
|
1721
|
+
*/
|
|
1722
|
+
declare function createNode(cx: number, cy: number, r: number, options?: NodeOptions): CircleElement;
|
|
1723
|
+
/**
|
|
1724
|
+
* Creates a line connection between two points
|
|
1725
|
+
*
|
|
1726
|
+
* @example
|
|
1727
|
+
* createLine(0, -4, -6, 4) // Simple connection line
|
|
1728
|
+
* createLine(0, 0, 5, 5, { opacity: 0.6, strokeWidth: 1.5 })
|
|
1729
|
+
*/
|
|
1730
|
+
declare function createLine(x1: number, y1: number, x2: number, y2: number, options?: LineOptions): LineElement;
|
|
1731
|
+
/**
|
|
1732
|
+
* Creates a ring (circle with border only, no fill)
|
|
1733
|
+
*
|
|
1734
|
+
* @example
|
|
1735
|
+
* createRing(0, 0, 8) // Simple ring
|
|
1736
|
+
* createRing(0, 0, 6, { borderWidth: 2, opacity: 0.5 })
|
|
1737
|
+
*/
|
|
1738
|
+
declare function createRing(cx: number, cy: number, r: number, options?: RingOptions): CircleElement;
|
|
1739
|
+
/**
|
|
1740
|
+
* Creates a small indicator dot
|
|
1741
|
+
*
|
|
1742
|
+
* @example
|
|
1743
|
+
* createDot(5, 5) // Default 2px dot
|
|
1744
|
+
* createDot(5, 5, 1.5) // Custom size
|
|
1745
|
+
*/
|
|
1746
|
+
declare function createDot(cx: number, cy: number, r?: number): CircleElement;
|
|
1747
|
+
/**
|
|
1748
|
+
* Creates a glow effect circle (background element)
|
|
1749
|
+
*
|
|
1750
|
+
* @example
|
|
1751
|
+
* createGlow(0, 0, 6) // Subtle glow behind other elements
|
|
1752
|
+
*/
|
|
1753
|
+
declare function createGlow(cx: number, cy: number, r: number, opacity?: number): CircleElement;
|
|
1754
|
+
/**
|
|
1755
|
+
* Creates an arrow/chevron triangle
|
|
1756
|
+
*
|
|
1757
|
+
* @example
|
|
1758
|
+
* createArrow(0, 5, 4, 'down') // Downward arrow
|
|
1759
|
+
* createArrow(3, 0, 3, 'right') // Right-pointing chevron
|
|
1760
|
+
*/
|
|
1761
|
+
declare function createArrow(x: number, y: number, size: number, direction: 'up' | 'down' | 'left' | 'right', options?: {
|
|
1762
|
+
fill?: 'color' | 'bg' | string;
|
|
1763
|
+
opacity?: number;
|
|
1764
|
+
rotation?: number;
|
|
1765
|
+
}): TriangleElement;
|
|
1766
|
+
/**
|
|
1767
|
+
* Creates a rectangle bar (useful for charts, progress indicators)
|
|
1768
|
+
*
|
|
1769
|
+
* @example
|
|
1770
|
+
* createBar(-4, 2, 8, 2) // Horizontal bar
|
|
1771
|
+
* createBar(0, -3, 2, 6) // Vertical bar
|
|
1772
|
+
*/
|
|
1773
|
+
declare function createBar(x: number, y: number, width: number, height: number, options?: {
|
|
1774
|
+
fill?: 'color' | 'bg' | string;
|
|
1775
|
+
opacity?: number;
|
|
1776
|
+
borderRadius?: number;
|
|
1777
|
+
}): RectElement;
|
|
1778
|
+
|
|
1779
|
+
export { ANIMATION_DURATION, type AvailableToolConfig, BENCHMARK_ICON_COLOR, type BaseToolConfig, BenchmarkIcon, type Bounds, CurveTestA, CurveTestB, CurveTestC, CurveTestD, CurveTestE, CurveTestF, CurveTestG, CurveTestH, CurveTestI, CurveTestJ, CurveTestK, CurveTestL, CurveTestM, CurveTestN, CurveTestO, CurveTestP, DIAL_BUTTON_SIZE, DIAL_GRID_LINE_COUNT, DIAL_ICON_PADDING, DIAL_ICON_SIZE, DIAL_START_ANGLE, DRAG_THRESHOLD, type DevToolsAction, type DevToolsSettings, type DevToolsState, DevToolsStateManager, type DialAnimationConfigType, type DialCSSBezierKey, type DialColorKey, type DialEasingName, type DialLayout, type DialLayoutConfig, type DragEndResult, type DragEventData, EDGE_PADDING, ENV_ICON_COLOR, type EasingFunction, type EasingName, EnvIcon, type Environment, type FloatingToolsColorKey, type FloatingToolsOptions, type FloatingToolsState, FloatingToolsStore, type GlobalDevToolsSettings, type GlobalSettingConfig, type GripIconLayout, HIGHLIGHTER_ICON_COLOR, HIGHLIGHT_ICON_COLOR, HighlightIcon, HighlighterIcon, type IconData, type IconPosition, type LineOptions, MAX_DIAL_SLOTS, MAX_SETTINGS_DIAL_SLOTS, type MergeSettingsOptions, NETWORK_ICON_COLOR, NetworkIcon, type NodeOptions, type Position, QUERY_ICON_COLOR, QueryIcon, RENDERS_ICON_COLOR, ROUTES_ICON_COLOR, RendersIcon, type RingOptions, RouteDotIcon, RoutePathIcon, RoutePinIcon, RouteTwoPinsIcon, RoutesIcon, SAVE_DEBOUNCE_MS, SENTRY_ICON_COLOR, SETTINGS_STORAGE_KEY, STORAGE_ICON_COLOR, STORAGE_KEYS, SentryIcon, type SettingsColorKey, SettingsEventBus, type SettingsTab, type SettingsTabKey, type Size, type SpiralPosition, type SpringConfig, type StorageAdapter, StorageIcon, type ToolMetadata, type ToolSlot, type UserRole, type UserStatusConfig, VISIBLE_HANDLE_WIDTH, WIFI_ICON_COLOR, type WebToolConfig, WifiIcon, canEnableDialTool, countEnabledTools, createArrow, createBar, createDot, createGlow, createIcon, createLine, createNode, createRing, devToolsReducer, devToolsStateManager, dialAnimationConfig, dialCSSBeziers, dialColors, dialStyles, easing, enforceDialLimit, filterValidChildren, floatingToolsColors, generateDefaultSettings, generateDialCSSKeyframes, getAllIconPositions, getDialCSSAnimationStyles, getDialCSSKeyframesString, getDialLayout, getEasing, getEnabledToolIds, getGridLineRotations, getGripIconLayout, getIconAngle, getIconPosition, getIconStaggerInputRange, getSpiralAnimationPosition, getStaggeredIconProgress, getToolColor, getToolDescription, getToolLabel, getUserStatusConfig, globalSettingsConfig, interpolate, interpolatePosition, mergeSettingsWithDefaults, renderIconData, sanitizeFloatingSettings, settingsColors, settingsEventBus, settingsStyles, settingsTabs, toolColors, toolDescriptions, toolLabels, withAlpha };
|