import React$1 from 'react'; /** * @fileoverview Type Helper Utilities for MockFrame * * This module provides advanced TypeScript utility types that power MockFrame's * type-safe API. These utilities enable discriminated union types that provide * compile-time safety for device-specific props without any runtime overhead. * * @example How these types work together in MockFrame: * ```ts * // The DeviceFramesetProps type uses these helpers to ensure: * // - `color` prop is only required for devices that have color options * // - `landscape` prop is only available for devices that support rotation * // - Props display cleanly in IDE tooltips * * // Valid: iPhone 17 requires a color * * * // Valid: iPhone X has no colors, so color prop is omitted * * * // TypeScript Error: iPhone X doesn't accept color * * ``` * * @module helper */ /** * Extracts keys from type `T` where the value type exactly matches type `F`. * * Uses bidirectional extends check to ensure exact type matching: * - `[F] extends [T[key]]` checks if F is assignable to the value * - `[T[key]] extends [F]` checks if the value is assignable to F * Both must be true for an exact match. * * The tuple wrapper `[X]` prevents TypeScript from distributing over unions, * ensuring we match the complete type rather than individual union members. * * @template T - The object type to extract keys from * @template F - The value type to match exactly * @returns Union of keys whose values exactly match type F * * @example * ```ts * type Device = { name: string; colors: never; width: number } * * type NeverKeys = KeysOfType * // Result: 'colors' * * type StringKeys = KeysOfType * // Result: 'name' * ``` */ type KeysOfType = { [key in keyof T]: [F] extends [T[key]] ? [T[key]] extends [F] ? key : never : never; }[keyof T]; /** * Extracts keys from type `T` where type `F` is assignable to the value type. * * Unlike `KeysOfType`, this only checks one direction: whether F can be * assigned to the value. This is useful for finding keys that accept * a specific type as part of a union. * * @template T - The object type to extract keys from * @template F - The type that should be assignable to the value * @returns Union of keys whose values accept type F * * @example * ```ts * type Props = { * required: string; * optional: string | undefined; * alsoOptional: number | undefined; * } * * type UndefinedKeys = KeysOfSubType * // Result: 'optional' | 'alsoOptional' * ``` */ type KeysOfSubType = { [key in keyof T]: [F] extends [T[key]] ? key : never; }[keyof T]; /** * Creates a new type by omitting fields from `T` whose value type exactly matches `F`. * * Primary use case: Remove fields typed as `never` from discriminated unions. * When building conditional prop types, some device configurations result in * `never` typed fields that should be excluded from the final type. * * @template T - The object type to transform * @template F - The value type to filter out * @returns New type with matching fields removed * * @example * ```ts * // Internal type before cleanup * type RawProps = { * device: 'iPhone X'; * color: never; // iPhone X has no color options * landscape: boolean; * } * * type CleanProps = OmitFieldByType * // Result: { device: 'iPhone X'; landscape: boolean } * // The `color` field is removed since it's typed as `never` * ``` */ type OmitFieldByType = Omit>; /** * Makes fields optional if their type includes `undefined`. * * TypeScript distinguishes between optional fields (`key?: T`) and fields that * accept undefined (`key: T | undefined`). This utility converts the latter * to the former, allowing callers to omit the prop entirely rather than * passing an explicit `undefined`. * * Implementation: * 1. `Omit>` - Remove all undefined-accepting keys * 2. `Partial>>` - Add them back as optional * 3. Intersection combines both parts * * @template T - The object type to transform * @returns New type with undefined-accepting fields made optional * * @example * ```ts * type BeforeTransform = { * device: 'iPad Pro'; * color: 'silver' | 'space-gray'; * landscape: boolean | undefined; // Accepts undefined but is required * } * * type AfterTransform = OptionField * // Result: { * // device: 'iPad Pro'; * // color: 'silver' | 'space-gray'; * // landscape?: boolean | undefined; // Now truly optional * // } * ``` */ type OptionField = Omit> & Partial>>; /** * Flattens a type for cleaner IDE display and better autocomplete. * * Complex types built from intersections (`A & B`) and mapped types can * display as unwieldy expressions in IDE tooltips. This utility forces * TypeScript to eagerly compute the final object shape, resulting in * cleaner, more readable type hints. * * The `& unknown` is a TypeScript trick that triggers type simplification * without affecting the resulting type (since `T & unknown = T`). * * @template A - The type to flatten * @returns Simplified type with identical structure but cleaner display * * @example * ```ts * // Without Compute - IDE shows: * // Omit<{ device: string; color: never }, 'color'> & { landscape?: boolean } * * // With Compute - IDE shows: * // { device: string; landscape?: boolean } * * type Complex = { a: string } & { b: number } & { c: boolean } * type Simple = Compute * // Hover shows: { a: string; b: number; c: boolean } * ``` */ type Compute = { [K in keyof A]: A[K]; } & unknown; /** * Internal type representing a device configuration */ type DeviceType = { /** CSS class name for the device frame */ device: Device; /** Available color variants */ colors: Colors; /** Whether the device supports landscape orientation */ hasLandscape: boolean; /** Default content width in pixels */ width?: number; /** Default content height in pixels */ height?: number; }; declare const DeviceOptions: { "iPhone X": { device: "iphone-x"; colors: readonly []; hasLandscape: true; width: number; height: number; }; "iPhone 8": { device: "iphone8"; colors: readonly ["black", "silver", "gold"]; hasLandscape: true; width: number; height: number; }; "iPhone 8 Plus": { device: "iphone8plus"; colors: readonly ["black", "silver", "gold"]; hasLandscape: true; width: number; height: number; }; "iPhone 17": { device: "iphone17"; colors: readonly ["black", "white", "mist-blue", "sage", "lavender", "cosmic-orange", "deep-blue"]; hasLandscape: true; width: number; height: number; }; "Pixel 10": { device: "pixel10"; colors: readonly ["obsidian", "porcelain", "mint", "rose"]; hasLandscape: true; width: number; height: number; }; "Galaxy S25": { device: "galaxy-s25"; colors: readonly ["phantom-black", "icy-blue", "navy", "silver", "mint"]; hasLandscape: true; width: number; height: number; }; "iPad Mini": { device: "ipad"; colors: readonly ["black", "silver"]; hasLandscape: true; width: number; height: number; }; "iPad Pro": { device: "ipad-pro"; colors: readonly ["space-gray", "silver"]; hasLandscape: true; width: number; height: number; }; "MacBook Pro 2020": { device: "macbook"; colors: readonly []; hasLandscape: false; width: number; height: number; }; "MacBook Pro": { device: "macbook-pro"; colors: readonly ["space-gray", "silver"]; hasLandscape: false; width: number; height: number; }; }; /** * Union type of all available device names * @example 'iPhone X' | 'iPhone 8' | 'iPhone 17' | 'Pixel 10' | ... */ type DeviceName = keyof typeof DeviceOptions; /** * Array of all available device names */ declare const DeviceNames: DeviceName[]; /** * Get the device configuration for a specific device */ type DeviceConfig = typeof DeviceOptions[D]; /** * Get the available colors for a specific device * @example DeviceColor<'iPhone 8'> = 'black' | 'silver' | 'gold' */ type DeviceColor = typeof DeviceOptions[D]['colors'][number]; /** * Check if a device supports landscape orientation */ type DeviceHasLandscape = typeof DeviceOptions[D]['hasLandscape']; /** * Internal type for generating discriminated union props */ type DevicesType>> = { [key in keyof R]: Compute>>; }[keyof R]; /** * Props for the MockFrame component * * This is a discriminated union type that provides type-safe props based on the selected device. * The `color` prop is only required for devices that have color variants. * The `landscape` prop is only available for devices that support landscape orientation. * * @example * // iPhone X - no color required, landscape supported * * * @example * // iPhone 8 - color required, landscape supported * * * @example * // MacBook Pro - color required, no landscape support * */ type MockFrameProps = DevicesType & Omit, 'color'>; /** * @fileoverview MockFrame Components * * This module exports two main components: * - `MockFrame` - Renders predefined device frames (iPhone, Android, iPad, MacBook) * - `CustomMockFrame` - Creates custom device frames with configurable bezels * * @example Basic usage * ```tsx * import { MockFrame } from 'react-mockframe' * import 'react-mockframe/styles/mockframe.css' * * * * * ``` * * @module MockFrame */ /** * Props for the CustomMockFrame component. */ interface CustomMockFrameProps extends React$1.HTMLAttributes { /** Content to render inside the device screen */ children?: React$1.ReactNode; /** Width of the screen area in pixels (required) */ width: number; /** Height of the screen area in pixels (required) */ height: number; /** * Bezel thickness around the screen. * Can be a uniform number or per-side object. * @default 12 * * @example Uniform bezel * bezelWidth={16} * * @example Per-side bezel (like older iPhones with chin) * bezelWidth={{ top: 20, right: 8, bottom: 40, left: 8 }} */ bezelWidth?: number | { top?: number; right?: number; bottom?: number; left?: number; }; /** * Border radius of the outer device frame. * @default 44 */ borderRadius?: number; /** * Border radius of the screen area. * If not specified, calculated as `borderRadius - bezelWidth`. */ screenBorderRadius?: number; /** * Background color of the device bezel. * @default '#1a1a1a' */ bezelColor?: string; /** * Background color of the screen area. * @default '#ffffff' */ screenColor?: string; /** * Scale factor for the entire device frame. * Values less than 1 shrink, greater than 1 enlarge. * @example zoom={0.75} // 75% size */ zoom?: number; /** * Enable smooth CSS transitions for zoom and color changes. * Useful when zoom is controlled by user interaction. */ animated?: boolean; /** * Display the device in landscape orientation. * Swaps width and height dimensions. */ landscape?: boolean; /** Additional CSS class for the outer frame element */ frameClassName?: string; /** Additional CSS class for the screen area element */ screenClassName?: string; } /** * Creates a custom device frame with configurable bezel, colors, and dimensions. * * Use this component when you need a device frame that doesn't match any * predefined device, or when you want full control over the frame appearance. * * @example Basic usage * ```tsx * * * * ``` * * @example With asymmetric bezels (like older phones with chin) * ```tsx * * * * ``` */ declare const CustomMockFrame: React$1.NamedExoticComponent; /** * Renders a realistic device frame around your content. * * This is the primary component for displaying content inside predefined * device mockups. The component is fully type-safe - TypeScript will only * allow valid color options for each device. * * @example iPhone with color * ```tsx * * * * ``` * * @example iPhone X (no color options) * ```tsx * * * * ``` * * @example With zoom and animation * ```tsx * * * * ``` * * @see {@link DeviceOptions} for available devices and their configurations */ declare const MockFrame: React$1.NamedExoticComponent; export { CustomMockFrame, type CustomMockFrameProps, type DeviceColor, type DeviceConfig, type DeviceHasLandscape, type DeviceName, DeviceNames, DeviceOptions, MockFrame, type MockFrameProps };