@biela.dev/core 1.7.13 → 1.7.14

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/lite.d.ts CHANGED
@@ -1,4 +1,518 @@
1
- export { AdaptiveScaleResult, ButtonName, CustomSVGStore, DeviceCompare, DeviceCompareProps, DeviceErrorBoundary, DeviceFrame, DeviceFrameProps, DynamicStatusBar, HardwareButtons, SCALE_STEPS, SVGCropArea, SVGOverrideEntry, SVGScreenRect, SafeAreaOverlay, SafeAreaView, ScaleBar, ScreenPowerState, StatusBarIndicators, UseAdaptiveScaleOptions, UseOrientationResult, VolumeHUD, VolumeState, computeAdaptiveScale, computeFullScale, computeHostSize, getCustomSVGStore, ptsToPercent, ptsToPx, pxToPts, registerCustomDeviceSVG, registerDeviceSVG, scaleValue, snapToStep, useAdaptiveScale, useContainerSize, useDeviceContract, useOrientation, useScreenPower, useVolumeControl } from './index.js';
2
- import 'react';
3
- import '@biela.dev/devices';
4
- import 'react/jsx-runtime';
1
+ import { RefObject, ReactNode, Component, ErrorInfo, CSSProperties, ReactElement } from 'react';
2
+ import { DeviceMeta, DeviceLayoutContract } from '@biela.dev/devices';
3
+ import * as react_jsx_runtime from 'react/jsx-runtime';
4
+
5
+ /**
6
+ * Design token dimension math — conversion utilities.
7
+ * All device dimensions are in logical points (CSS pixels at 1x).
8
+ */
9
+ /** Convert logical points to physical pixels */
10
+ declare function ptsToPx(pts: number, dpr: number): number;
11
+ /** Convert physical pixels to logical points */
12
+ declare function pxToPts(px: number, dpr: number): number;
13
+ /** Convert points to percentage of a total dimension */
14
+ declare function ptsToPercent(pts: number, total: number): number;
15
+ /** Apply uniform scale factor to any dimension value */
16
+ declare function scaleValue(value: number, scaleFactor: number): number;
17
+
18
+ /**
19
+ * Scale Engine Math — mirrors Xcode Simulator "fit to screen" behavior.
20
+ *
21
+ * Rules:
22
+ * 1. Inner content ALWAYS at 1:1 logical point size
23
+ * 2. Scale derived from available container space, never hardcoded
24
+ * 3. SVG frame chrome scales WITH content as one atomic unit
25
+ * 4. Host layout reserves SCALED dimensions
26
+ * 5. Maximum scale always 1.0 — never larger than the real device
27
+ */
28
+ /** Discrete scale steps matching Xcode Simulator presets */
29
+ declare const SCALE_STEPS: readonly [0.25, 0.33, 0.5, 0.75, 1];
30
+ /**
31
+ * Compute the adaptive scale factor for a device in a given container.
32
+ * Mirrors Xcode "fit to screen" exactly.
33
+ *
34
+ * @param deviceWidth - Logical points width of the device screen
35
+ * @param deviceHeight - Logical points height of the device screen
36
+ * @param containerWidth - Available CSS px width of the host container
37
+ * @param containerHeight - Available CSS px height of the host container
38
+ * @param padding - Breathing room in px (subtracted from each side)
39
+ * @param maxScale - Upper cap — never exceed 1.0 (real device size)
40
+ * @param minScale - Lower floor — prevent invisibly small render
41
+ */
42
+ declare function computeAdaptiveScale(deviceWidth: number, deviceHeight: number, containerWidth: number, containerHeight: number, padding?: number, maxScale?: number, minScale?: number): number;
43
+ /**
44
+ * Snap a raw scale to the nearest discrete step that does not exceed it.
45
+ * Fixed version: filters steps to only those <= raw, takes max.
46
+ * Falls back to raw if no step qualifies.
47
+ */
48
+ declare function snapToStep(raw: number): number;
49
+ /**
50
+ * Derive host container size from device dimensions + scale.
51
+ * The host div occupies these dimensions in normal document flow.
52
+ */
53
+ declare function computeHostSize(deviceWidth: number, deviceHeight: number, scale: number): {
54
+ width: number;
55
+ height: number;
56
+ };
57
+ /** Result returned by the scale computation */
58
+ interface AdaptiveScaleResult {
59
+ /** Computed scale factor e.g. 0.735 */
60
+ scale: number;
61
+ /** Host container width = deviceWidth * scale */
62
+ scaledWidth: number;
63
+ /** Host container height = deviceHeight * scale */
64
+ scaledHeight: number;
65
+ /** Raw logical pts — scaler div width */
66
+ deviceWidth: number;
67
+ /** Raw logical pts — scaler div height */
68
+ deviceHeight: number;
69
+ /** True when scale === maxScale (showing at real size) */
70
+ isAtMaxScale: boolean;
71
+ /** True when scale < maxScale (container is limiting) */
72
+ isConstrained: boolean;
73
+ /** Display string e.g. "73%" */
74
+ scalePercent: string;
75
+ }
76
+ /**
77
+ * Full scale computation returning all derived values.
78
+ */
79
+ declare function computeFullScale(deviceWidth: number, deviceHeight: number, containerWidth: number, containerHeight: number, options?: {
80
+ padding?: number;
81
+ maxScale?: number;
82
+ minScale?: number;
83
+ snapToSteps?: boolean;
84
+ }): AdaptiveScaleResult;
85
+
86
+ interface ContainerSize {
87
+ width: number;
88
+ height: number;
89
+ }
90
+ /**
91
+ * Observes an element's content box dimensions via ResizeObserver.
92
+ * Foundation of adaptive scaling — same mechanism as Xcode's window resize detection.
93
+ *
94
+ * Safety features:
95
+ * 1. Clamps reported size to the visual viewport so a mis-sized parent
96
+ * can never cause the device frame to render larger than the screen.
97
+ * 2. When the element has 0 height (common AI-generated code mistake:
98
+ * height: auto or height: 100% without explicit ancestor height),
99
+ * uses a viewport-based fallback so the device still renders.
100
+ * 3. Listens for window resize to stay in sync.
101
+ */
102
+ declare function useContainerSize(ref: RefObject<HTMLElement | null>): ContainerSize;
103
+
104
+ interface UseAdaptiveScaleOptions {
105
+ /** Device metadata (screen dimensions) */
106
+ device: DeviceMeta;
107
+ /** Container width from useContainerSize */
108
+ containerWidth: number;
109
+ /** Container height from useContainerSize */
110
+ containerHeight: number;
111
+ /** Breathing room in px (default: 24) */
112
+ padding?: number;
113
+ /** Upper cap — never exceed 1.0 (default: 1.0) */
114
+ maxScale?: number;
115
+ /** Lower floor (default: 0.1) */
116
+ minScale?: number;
117
+ /** Snap to discrete 25/33/50/75/100% steps (default: false) */
118
+ snapToSteps?: boolean;
119
+ }
120
+ /**
121
+ * Full adaptive scale hook — mirrors Xcode "fit to screen".
122
+ * Recalculates live as container resizes via ResizeObserver.
123
+ */
124
+ declare function useAdaptiveScale(options: UseAdaptiveScaleOptions): AdaptiveScaleResult;
125
+
126
+ interface UseDeviceContractResult {
127
+ contract: DeviceLayoutContract;
128
+ cssVariables: DeviceLayoutContract["cssVariables"];
129
+ contentZone: DeviceLayoutContract["contentZone"]["portrait"];
130
+ }
131
+ /**
132
+ * Hook to access the Device Layout Contract for a given device.
133
+ * Returns the contract, CSS variables, and content zone for the current orientation.
134
+ */
135
+ declare function useDeviceContract(deviceId: string, orientation?: "portrait" | "landscape"): UseDeviceContractResult;
136
+
137
+ interface VolumeState {
138
+ /** Current volume level 0–1 (16 steps, each = 1/16) */
139
+ level: number;
140
+ /** Is audio muted? */
141
+ muted: boolean;
142
+ /** Should the HUD be visible? */
143
+ hudVisible: boolean;
144
+ /** Increase volume by one step */
145
+ volumeUp: () => void;
146
+ /** Decrease volume by one step */
147
+ volumeDown: () => void;
148
+ /** Toggle mute */
149
+ toggleMute: () => void;
150
+ }
151
+ /**
152
+ * Volume control hook — 16-step volume with auto-hiding HUD.
153
+ * Applies volume to all <audio> and <video> elements inside `.bielaframe-content`.
154
+ */
155
+ declare function useVolumeControl(initialVolume?: number): VolumeState;
156
+
157
+ interface ScreenPowerState {
158
+ /** Is the screen off? */
159
+ isOff: boolean;
160
+ /** Toggle screen on/off */
161
+ toggle: () => void;
162
+ }
163
+ /**
164
+ * Screen power hook — manages on/off state for the power button.
165
+ */
166
+ declare function useScreenPower(): ScreenPowerState;
167
+
168
+ interface UseOrientationResult {
169
+ /** Current orientation */
170
+ orientation: "portrait" | "landscape";
171
+ /** Convenience boolean */
172
+ isLandscape: boolean;
173
+ /** Toggle between portrait and landscape */
174
+ toggle: () => void;
175
+ /** Set orientation directly */
176
+ setOrientation: (o: "portrait" | "landscape") => void;
177
+ }
178
+ /**
179
+ * Hook for managing device orientation state with a toggle function.
180
+ *
181
+ * ```tsx
182
+ * const { orientation, toggle } = useOrientation();
183
+ * <button onClick={toggle}>Rotate</button>
184
+ * <DeviceFrame deviceId="iphone-17-pro" orientation={orientation} />
185
+ * ```
186
+ */
187
+ declare function useOrientation(initial?: "portrait" | "landscape"): UseOrientationResult;
188
+
189
+ /**
190
+ * Resolve device SVG component by ID.
191
+ * This is a lookup registry — devices register their SVG components here.
192
+ */
193
+ type DeviceSVGComponent = React.ComponentType<{
194
+ colorScheme?: "light" | "dark";
195
+ style?: React.CSSProperties;
196
+ }>;
197
+ interface FrameInfo {
198
+ bezelTop: number;
199
+ bezelBottom: number;
200
+ bezelLeft: number;
201
+ bezelRight: number;
202
+ totalWidth: number;
203
+ totalHeight: number;
204
+ screenWidth: number;
205
+ screenHeight: number;
206
+ screenRadius: number;
207
+ }
208
+ /** Register a device SVG component for use with DeviceFrame */
209
+ declare function registerDeviceSVG(deviceId: string, component: DeviceSVGComponent, frame: FrameInfo): void;
210
+ /** Optional crop area to rewrite the SVG viewBox (e.g., to exclude side buttons) */
211
+ interface SVGCropArea {
212
+ x: number;
213
+ y: number;
214
+ width: number;
215
+ height: number;
216
+ }
217
+ /** Screen rectangle in SVG native coordinates — used to punch a transparent hole */
218
+ interface SVGScreenRect {
219
+ x: number;
220
+ y: number;
221
+ width: number;
222
+ height: number;
223
+ rx?: number;
224
+ }
225
+ /**
226
+ * Register a custom device SVG from a raw SVG string.
227
+ *
228
+ * Creates a React component that renders the SVG with scoped IDs
229
+ * and registers it in the SVG_REGISTRY.
230
+ *
231
+ * The inner <svg> element is rewritten to use width="100%" height="100%"
232
+ * so it fills the parent container (which is sized by the frame info).
233
+ *
234
+ * If `cropViewBox` is provided, the SVG viewBox is set to that area,
235
+ * cropping out external elements like side buttons.
236
+ *
237
+ * If `screenRect` is provided, a mask is injected to punch a transparent
238
+ * hole where the screen is, so content underneath shows through.
239
+ */
240
+ declare function registerCustomDeviceSVG(deviceId: string, svgString: string, frame: FrameInfo, cropViewBox?: SVGCropArea, screenRect?: SVGScreenRect): void;
241
+ interface DeviceFrameProps {
242
+ /** Device ID e.g. "iphone-16-pro" */
243
+ device?: string;
244
+ /** Alias for device — accepts either prop name */
245
+ deviceId?: string;
246
+ /** Orientation */
247
+ orientation?: "portrait" | "landscape";
248
+ /** Scale mode: "fit" auto-scales, "manual" uses manualScale value */
249
+ scaleMode?: "fit" | "manual" | "steps";
250
+ /** Manual scale override (0.1–1.0), only when scaleMode="manual" */
251
+ manualScale?: number;
252
+ /** Show safe zone overlay (dev tool) */
253
+ showSafeAreaOverlay?: boolean;
254
+ /** Show DLC JSON panel */
255
+ showDLCPanel?: boolean;
256
+ /** Show scale bar (default: true) */
257
+ showScaleBar?: boolean;
258
+ /** Frame color scheme */
259
+ colorScheme?: "light" | "dark";
260
+ /** Callback when DLC is ready */
261
+ onContractReady?: (dlc: DeviceLayoutContract) => void;
262
+ /** Callback when scale changes */
263
+ onScaleChange?: (scale: number) => void;
264
+ /** Content rendered inside the device screen at real resolution */
265
+ children?: ReactNode;
266
+ }
267
+ /**
268
+ * DeviceFrame — the main BielaFrame component.
269
+ *
270
+ * Implements the Two-World Rendering Model:
271
+ * - Inner content renders at 1:1 device resolution (e.g. 402×874px)
272
+ * - Visual presentation scales via CSS transform: scale()
273
+ * - The AI component always thinks it's on a real device
274
+ *
275
+ * DOM structure:
276
+ * bielaframe-sentinel (fills parent, ResizeObserver target)
277
+ * └── bielaframe-host (scaled dimensions in flow)
278
+ * └── bielaframe-scaler (real device dims, transform: scale(N))
279
+ * ├── bielaframe-content (clipped to screen, CSS vars injected)
280
+ * │ └── children (AI-generated component)
281
+ * ├── SVG frame overlay (pointer-events: none)
282
+ * └── SafeAreaOverlay (optional dev tool)
283
+ * └── ScaleBar (outside scaler, in normal flow)
284
+ */
285
+ declare function DeviceFrame({ device: deviceProp, deviceId, orientation, scaleMode, manualScale, showSafeAreaOverlay, showScaleBar, colorScheme, onContractReady, onScaleChange, children, }: DeviceFrameProps): react_jsx_runtime.JSX.Element;
286
+
287
+ interface DeviceCompareProps {
288
+ /** First device ID */
289
+ deviceA: string;
290
+ /** Second device ID */
291
+ deviceB: string;
292
+ /** Orientation for both devices */
293
+ orientation?: "portrait" | "landscape";
294
+ /** Frame color scheme */
295
+ colorScheme?: "light" | "dark";
296
+ /** Show safe area overlays */
297
+ showSafeAreaOverlay?: boolean;
298
+ /** Show scale bars */
299
+ showScaleBar?: boolean;
300
+ /** Layout direction — "auto" picks row for portrait, column for landscape */
301
+ layout?: "horizontal" | "vertical" | "auto";
302
+ /** Gap between the two frames in px (default: 24) */
303
+ gap?: number;
304
+ /** Content rendered inside BOTH device frames */
305
+ children?: ReactNode;
306
+ /** Content for device A only (overrides children for A) */
307
+ childrenA?: ReactNode;
308
+ /** Content for device B only (overrides children for B) */
309
+ childrenB?: ReactNode;
310
+ /** Callback when device A contract is ready */
311
+ onContractReadyA?: (dlc: DeviceLayoutContract) => void;
312
+ /** Callback when device B contract is ready */
313
+ onContractReadyB?: (dlc: DeviceLayoutContract) => void;
314
+ }
315
+ /**
316
+ * DeviceCompare — renders two device frames side-by-side for comparison.
317
+ *
318
+ * Layout defaults to "auto": horizontal (row) in portrait, vertical (column) in landscape.
319
+ * Each frame auto-scales independently to fit its half of the container.
320
+ *
321
+ * Must be placed inside a container with explicit width and height.
322
+ */
323
+ declare function DeviceCompare({ deviceA, deviceB, orientation, colorScheme, showSafeAreaOverlay, showScaleBar, layout, gap, children, childrenA, childrenB, onContractReadyA, onContractReadyB, }: DeviceCompareProps): react_jsx_runtime.JSX.Element;
324
+
325
+ interface Props {
326
+ children: ReactNode;
327
+ fallback?: ReactNode;
328
+ }
329
+ interface State {
330
+ hasError: boolean;
331
+ error: Error | null;
332
+ }
333
+ /**
334
+ * Error Boundary wrapping the children slot in DeviceFrame.
335
+ * AI-generated components will crash — this catches them gracefully
336
+ * and renders a fallback inside the device screen area.
337
+ */
338
+ declare class DeviceErrorBoundary extends Component<Props, State> {
339
+ constructor(props: Props);
340
+ static getDerivedStateFromError(error: Error): State;
341
+ componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
342
+ render(): ReactNode;
343
+ }
344
+
345
+ interface SafeAreaViewProps {
346
+ /** Which edges to apply safe area padding to (default: all) */
347
+ edges?: Array<"top" | "bottom" | "left" | "right">;
348
+ children: ReactNode;
349
+ style?: CSSProperties;
350
+ }
351
+ /**
352
+ * Convenience wrapper that applies safe area padding via CSS variables.
353
+ * Uses var(--safe-top), var(--safe-bottom), etc. — injected by DeviceFrame.
354
+ *
355
+ * Usage inside a generated app:
356
+ * <SafeAreaView edges={["top", "bottom"]}>
357
+ * {content that never overlaps hardware elements}
358
+ * </SafeAreaView>
359
+ */
360
+ declare function SafeAreaView({ edges, children, style }: SafeAreaViewProps): react_jsx_runtime.JSX.Element;
361
+
362
+ interface SafeAreaOverlayProps {
363
+ contract: DeviceLayoutContract;
364
+ orientation: "portrait" | "landscape";
365
+ }
366
+ /**
367
+ * Dev overlay showing safe zones when showSafeAreaOverlay={true}.
368
+ * Does NOT affect layout — position: absolute, pointerEvents: none.
369
+ *
370
+ * Colors:
371
+ * - Red: status bar zone + home indicator zone (restricted)
372
+ * - Orange: hardware overlay (Dynamic Island / punch-hole)
373
+ * - Green: content zone (usable area)
374
+ * - White dimension labels at each edge
375
+ */
376
+ declare function SafeAreaOverlay({ contract, orientation }: SafeAreaOverlayProps): react_jsx_runtime.JSX.Element;
377
+
378
+ interface ScaleBarProps {
379
+ deviceName: string;
380
+ deviceWidth: number;
381
+ deviceHeight: number;
382
+ scale: number;
383
+ scalePercent: string;
384
+ isAtMaxScale: boolean;
385
+ isConstrained: boolean;
386
+ onScaleChange?: (scale: number) => void;
387
+ onFit?: () => void;
388
+ onRealSize?: () => void;
389
+ }
390
+ /**
391
+ * Persistent footer below device showing scale state:
392
+ * [ iPhone 16 Pro · 402×874pt | ━━━●━━━━━ 66% | Fit ↗ | 1:1 ]
393
+ *
394
+ * Accessibility:
395
+ * - role="slider" with aria-valuenow on scrubber
396
+ * - aria-label on the component
397
+ * - aria-live="polite" on scale announcements
398
+ */
399
+ declare function ScaleBar({ deviceName, deviceWidth, deviceHeight, scale, scalePercent, isAtMaxScale, isConstrained, onScaleChange, onFit, onRealSize, }: ScaleBarProps): react_jsx_runtime.JSX.Element;
400
+
401
+ interface VolumeHUDProps {
402
+ level: number;
403
+ muted: boolean;
404
+ visible: boolean;
405
+ platform: "ios" | "android";
406
+ }
407
+ /**
408
+ * Volume HUD overlay — iOS-style vertical pill or Android-style horizontal bar.
409
+ */
410
+ declare function VolumeHUD({ level, muted, visible, platform }: VolumeHUDProps): react_jsx_runtime.JSX.Element;
411
+
412
+ type ButtonName = "volumeUp" | "volumeDown" | "power" | "actionButton" | "cameraControl";
413
+ interface HardwareButtonsProps {
414
+ /** The container element that holds the SVG frame overlay */
415
+ frameContainerRef: React.RefObject<HTMLDivElement | null>;
416
+ /** Callbacks for button actions */
417
+ onButtonPress?: (button: ButtonName) => void;
418
+ /** Whether interactive buttons are enabled */
419
+ enabled?: boolean;
420
+ /** Current orientation — triggers button position re-discovery */
421
+ orientation?: "portrait" | "landscape";
422
+ }
423
+ /**
424
+ * HardwareButtons — creates invisible click-target overlays positioned
425
+ * over the SVG button elements.
426
+ *
427
+ * Because the SVG frame overlay has pointer-events: none (so content
428
+ * underneath remains interactive), we can't attach event listeners directly
429
+ * to SVG elements. Instead, we:
430
+ * 1. Find all [data-button] elements in the SVG
431
+ * 2. Read their bounding rects relative to the scaler container
432
+ * 3. Render transparent absolutely-positioned divs at those positions
433
+ * 4. Handle mouse/touch events on those divs
434
+ * 5. Apply press animation to the original SVG elements
435
+ */
436
+ declare function HardwareButtons({ frameContainerRef, onButtonPress, enabled, orientation, }: HardwareButtonsProps): ReactElement | null;
437
+
438
+ interface DynamicStatusBarProps {
439
+ contract: DeviceLayoutContract;
440
+ orientation: "portrait" | "landscape";
441
+ colorScheme: "light" | "dark";
442
+ /** Show a live updating clock (default: true) */
443
+ showLiveClock?: boolean;
444
+ /** Fixed time string override (e.g. "9:41") — disables live clock */
445
+ fixedTime?: string;
446
+ }
447
+ /**
448
+ * DynamicStatusBar — renders ONLY a live clock overlay.
449
+ *
450
+ * The SVG frame already provides all decorative status bar elements
451
+ * (signal bars, wifi, battery). This component only replaces the
452
+ * static time text (e.g. "9:41") with a live-updating clock.
453
+ *
454
+ * It renders a small opaque patch behind the clock text so the
455
+ * SVG's baked-in static time is fully covered, then draws the
456
+ * live time on top.
457
+ *
458
+ * Platform-specific clock positions:
459
+ * - iOS Dynamic Island: left side, paddingLeft ~20
460
+ * - iOS Notch: left side, paddingLeft ~20
461
+ * - iOS SE: centered
462
+ * - Android: left side, paddingLeft ~16
463
+ */
464
+ declare function DynamicStatusBar({ contract, orientation, colorScheme, showLiveClock, fixedTime, }: DynamicStatusBarProps): react_jsx_runtime.JSX.Element | null;
465
+
466
+ interface StatusBarIndicatorsProps {
467
+ platform: "ios" | "android";
468
+ colorScheme: "light" | "dark";
469
+ }
470
+ /**
471
+ * Static decorative status bar indicators — signal, wifi, battery.
472
+ * Rendered as small inline SVGs, platform-specific styling.
473
+ */
474
+ declare function StatusBarIndicators({ platform, colorScheme }: StatusBarIndicatorsProps): react_jsx_runtime.JSX.Element;
475
+
476
+ interface SVGOverrideEntry {
477
+ deviceId: string;
478
+ svgString: string;
479
+ bezelTop: number;
480
+ bezelBottom: number;
481
+ bezelLeft: number;
482
+ bezelRight: number;
483
+ screenRect?: SVGScreenRect;
484
+ updatedAt: string;
485
+ }
486
+ /**
487
+ * Persistent storage for custom SVG overrides.
488
+ *
489
+ * When a user uploads a custom SVG frame for a device, it's stored in
490
+ * localStorage and automatically applied on subsequent imports.
491
+ *
492
+ * SSR-safe: falls back to no-op storage when localStorage is unavailable.
493
+ */
494
+ declare class CustomSVGStore {
495
+ private storage;
496
+ constructor(storage?: Storage | null);
497
+ /** Load all stored overrides */
498
+ getAll(): Record<string, SVGOverrideEntry>;
499
+ /** Save an override and register it in the SVG registry */
500
+ save(entry: SVGOverrideEntry): void;
501
+ /** Remove an override (revert to built-in) */
502
+ remove(deviceId: string): void;
503
+ /** Check if a device has a custom override */
504
+ has(deviceId: string): boolean;
505
+ /** Get a single override by device ID */
506
+ get(deviceId: string): SVGOverrideEntry | undefined;
507
+ /**
508
+ * Apply all stored overrides to the SVG registry.
509
+ * Called during auto-registration to restore user customizations.
510
+ */
511
+ applyAll(): void;
512
+ private applyEntry;
513
+ private persist;
514
+ }
515
+ /** Get the default CustomSVGStore instance (singleton, uses localStorage) */
516
+ declare function getCustomSVGStore(): CustomSVGStore;
517
+
518
+ export { type AdaptiveScaleResult, type ButtonName, CustomSVGStore, DeviceCompare, type DeviceCompareProps, DeviceErrorBoundary, DeviceFrame, type DeviceFrameProps, DynamicStatusBar, HardwareButtons, SCALE_STEPS, type SVGCropArea, type SVGOverrideEntry, type SVGScreenRect, SafeAreaOverlay, SafeAreaView, ScaleBar, type ScreenPowerState, StatusBarIndicators, type UseAdaptiveScaleOptions, type UseOrientationResult, VolumeHUD, type VolumeState, computeAdaptiveScale, computeFullScale, computeHostSize, getCustomSVGStore, ptsToPercent, ptsToPx, pxToPts, registerCustomDeviceSVG, registerDeviceSVG, scaleValue, snapToStep, useAdaptiveScale, useContainerSize, useDeviceContract, useOrientation, useScreenPower, useVolumeControl };
package/dist/lite.js CHANGED
@@ -818,6 +818,7 @@ function DeviceFrame({
818
818
  overflow: "hidden",
819
819
  backfaceVisibility: "hidden",
820
820
  transform: "translateZ(0)",
821
+ zIndex: 12,
821
822
  ...cssVarStyle
822
823
  },
823
824
  children: /* @__PURE__ */ jsx(DeviceErrorBoundary, { children })