### Install live-photo with npm, pnpm, or yarn Source: https://github.com/iceywu/live-photo/blob/main/README.md Install the library using your preferred package manager. ```bash npm install live-photo # pnpm add live-photo # yarn add live-photo ``` -------------------------------- ### Example Usage of PreferencesStore Subscription Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Demonstrates how to subscribe to preference changes, update preferences, and unsubscribe. The subscription callback logs changes to the console. ```typescript const store = createMemoryStore(); const unsubscribe = store.subscribe((prefs) => { console.log('Preferences changed:', prefs); }); store.set({ muted: true }); // Logs: Preferences changed: { muted: true } unsubscribe(); // Stop listening store.set({ muted: false }); // No log output ``` -------------------------------- ### Using a New Locale Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/i18n.md Example of initializing the LivePhotoViewer with a newly added locale, 'es' (Spanish). ```typescript const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), locale: 'es', }); ``` -------------------------------- ### Initialize and Play LivePhotoViewer Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/LivePhotoViewer.md Initializes a new LivePhotoViewer instance and starts video playback. Ensure the container element exists and video/photo sources are correctly provided. ```typescript const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), }); await viewer.play(); ``` -------------------------------- ### ElementCustomization Example Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/types.md An example demonstrating how to use the ElementCustomization interface to apply styles and attributes to an element. This includes setting CSS filters, border-radius, and custom data attributes. ```typescript const customization: ElementCustomization = { styles: { filter: 'brightness(1.1)', borderRadius: '8px', }, attributes: { 'data-testid': 'my-element', 'data-custom': 'value', }, }; ``` -------------------------------- ### play() Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/LivePhotoViewer.md Starts playback of the video. It resets the video to the start, applies the muted state, triggers haptic feedback if enabled, and hides the photo. If the video is not yet loaded, it will be loaded first. Playback waits until the video is ready. ```APIDOC ## play() ### Description Starts playback of the video. Resets the video to the start, applies the muted state, triggers haptic feedback if enabled, and hides the photo. Loads the video if not already loaded and waits for it to be ready. ### Method `async play(): Promise` ### Returns `Promise` - Resolves when playback begins or immediately if video is already playing. ### Throws Rejects on playback errors (caught and passed to `onError` callback). ### Behavior - Loads video if not yet loaded. - Waits for video to be ready (`canplay` event) before playing. - Stops immediately if `videoError` state is true. - Applies optional haptic vibration (200ms) if `enableVibration` is true and `navigator.vibrate` is available. - Adds `playing` class to container and sets photo opacity to 0. ### Example ```typescript const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), }); await viewer.play(); ``` ``` -------------------------------- ### Monitor Live Photo Load Progress Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/errors.md This example shows how to use onLoadStart, onLoadProgress, and onProgress callbacks to monitor video loading status. It also includes handling for 'VIDEO_LOAD_ERROR' to display loading indicators and error messages. ```typescript const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), lazyLoadVideo: true, onLoadStart: () => { console.log('Video download started'); showLoadingIndicator(); }, onLoadProgress: (loaded, total) => { const percent = (loaded / total) * 100; console.log(`Downloaded: ${percent.toFixed(1)}%`); updateProgressBar(percent); }, onProgress: (buffered, event, video) => { console.log(`Buffered: ${buffered}%`); }, onError: (error) => { if (error.type === 'VIDEO_LOAD_ERROR') { hideLoadingIndicator(); showErrorMessage('Download failed'); } }, }); ``` -------------------------------- ### Configure High-Performance Setup Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/configuration.md Optimize for high performance by disabling vibration, using a static badge icon, and setting a specific long press delay. Preloads only metadata. ```typescript new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), lazyLoadVideo: true, enableVibration: false, staticBadgeIcon: true, longPressDelay: 200, preload: 'none', }); ``` -------------------------------- ### Download Extracted Live Photo Components Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/extractFromLivePhoto.md This example shows how to extract photo and video components from a Live Photo and trigger downloads for each. Ensure to revoke the resources after initiating the downloads. ```typescript async function downloadLivePhotoComponents(file) { const result = await extractFromLivePhoto(file); if (!result) { console.error('Invalid Live Photo'); return; } // Download photo const photoLink = document.createElement('a'); photoLink.href = result.photoUrl; photoLink.download = `${file.name.replace(/\.\w+$/, '')}.jpg`; photoLink.click(); // Download video const videoLink = document.createElement('a'); videoLink.href = result.videoUrl; videoLink.download = `${file.name.replace(/\.\w+$/, '')}.mp4`; videoLink.click(); // Cleanup result.revoke(); } ``` -------------------------------- ### get() Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Retrieves a snapshot of the current live photo preferences. This method returns an object containing the current settings without making any changes. ```APIDOC ## get() ### Description Returns a snapshot of the current preferences. ### Method GET (conceptual) ### Endpoint N/A (SDK method) ### Parameters None ### Response #### Success Response - **prefs** (`LivePhotoPrefs`) - Object with `autoplay?: boolean` and `muted?: boolean` fields ### Response Example ```json { "autoplay": true, "muted": false } ``` ``` -------------------------------- ### Auto-initialize Live Photo with CDN Source: https://github.com/iceywu/live-photo/blob/main/README.md Elements with the `data-live-photo` attribute will automatically initialize once the DOM is ready. This method is convenient for quick setup via CDN. ```html
``` -------------------------------- ### Example Usage of extractFromLivePhoto and revoke Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/extractFromLivePhoto.md Demonstrates how to use extractFromLivePhoto, display the extracted photo and video, and then revoke the object URLs to free memory. ```typescript const result = await extractFromLivePhoto(file); if (result) { // Create image and video elements const img = document.createElement('img'); img.src = result.photoUrl; document.body.appendChild(img); const video = document.createElement('video'); video.src = result.videoUrl; document.body.appendChild(video); // When done (after a timeout, user navigation, etc.) setTimeout(() => { result.revoke(); // Frees the object URLs }, 5000); } ``` -------------------------------- ### Initialize LivePhotoViewer with Fully Custom Locale Labels Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/i18n.md Provides an example of setting entirely custom labels for a specific locale, such as Japanese ('ja'), for full internationalization control. ```typescript import { LivePhotoViewer } from 'live-photo'; const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), labels: { live: 'ライブ', enableAutoplay: '自動再生を有効にする', disableAutoplay: '自動再生を無効にする', mute: 'ミュート', unmute: 'ミュート解除', }, }); ``` -------------------------------- ### Fully Customized Live Photo Viewer Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/configuration.md A comprehensive example showing extensive customization options including dimensions, styling, autoplay, mute controls, theming, custom labels, and event handlers. ```typescript new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), width: 400, height: 300, borderRadius: 12, autoplay: true, muted: true, showMuteButton: true, theme: 'dark', locale: 'en', labels: { live: 'ACTIVE', enableAutoplay: 'Play on hover', disableAutoplay: 'Stop autoplay', mute: 'Mute', unmute: 'Unmute', }, storageKey: 'my-viewer', retryAttempts: 3, enableVibration: true, imageCustomization: { styles: { filter: 'brightness(1.1)' }, }, videoCustomization: { styles: { filter: 'saturate(1.1)' }, }, onPhotoLoad: (event, photo) => console.log('Photo loaded'), onVideoLoad: (duration) => console.log(`Video: ${duration}s`), onProgress: (progress) => console.log(`Buffered: ${progress}%`), onError: (error) => console.error(error), }); ``` -------------------------------- ### Handle Autoplay Policy with Muted Playback Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/errors.md Demonstrates how to handle browser autoplay policies by starting the video muted. If playback fails due to autoplay restrictions, it prompts the user to enable sound, which is necessary for unmuted playback. ```typescript const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), muted: true, // Start muted to allow autoplay onError: (error) => { if (error.type === 'PLAYBACK_ERROR') { // User gesture required for unmuted playback showMessage('Please click to enable sound'); } }, }); ``` -------------------------------- ### autoInit System Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/FILE_MANIFEST.md System for declarative initialization of Live Photo elements using data attributes. ```APIDOC ## autoInit System ### Description Enables declarative initialization of Live Photo elements on a page using `data-live-photo` attributes. ### Functions Documented - **autoInit(root, selector)**: Initializes Live Photo elements within a specified root and selector. - **AUTO_INIT_SELECTOR**: Constant defining the default selector for auto-initialization. ### Data Attributes - **data-photo-src, data-video-src**: Required attributes for specifying media sources. - Additional optional attributes for customization and behavior control. - Rules for boolean, dimension, and sync group parsing. ### Format - Function signature and behavior description. - Reference table for data attributes. - Explanation of attribute parsing rules. - Usage examples covering various scenarios like sync, persistence, and lazy-loading. - Guidance on accessing instances after initialization and comparing declarative vs. imperative approaches. ``` -------------------------------- ### autoInit() Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/autoInit.md Scans the DOM for elements with `[data-live-photo]` attribute and initializes LivePhotoViewer instances for each one. It is SSR safe and idempotent. ```APIDOC ## autoInit() ### Description Scans the DOM for elements with `[data-live-photo]` attribute and initializes LivePhotoViewer instances for each one. It is SSR safe and idempotent. ### Method ```typescript export function autoInit( root?: ParentNode, selector?: string ): LivePhotoViewer[] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | root | `ParentNode` | No | `document` | DOM subtree to scan | | selector | `string` | No | `'[data-live-photo]'` | CSS selector for elements to initialize | ### Returns `LivePhotoViewer[]` - Array of newly created viewer instances ### Behavior 1. Scans the provided root (or entire document) for elements matching the selector 2. Skips elements already initialized (have `data-live-photo-initialized` attribute) 3. Parses `data-*` attributes into `LivePhotoOptions` 4. Creates a new `LivePhotoViewer` for each valid element 5. Marks initialized elements with `data-live-photo-initialized="true"` 6. Stores the instance reference on the element (internal key `__livePhotoViewer`) 7. Returns array of newly created instances ### Error Handling If an element is missing required attributes or has invalid values: - Logs a warning to console - Skips that element - Continues with other elements ### Example ```typescript // Initialize all [data-live-photo] elements on the page const viewers = autoInit(); console.log(`Initialized ${viewers.length} viewers`); // Initialize only within a specific container const viewers = autoInit(document.getElementById('gallery')); // Custom selector const viewers = autoInit(document, '.my-live-photos'); ``` ``` -------------------------------- ### onLoadStart Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/configuration.md Fired when the video load begins, particularly relevant in lazy loading scenarios. ```APIDOC ## onLoadStart ### Description Fired when video load begins (in lazy mode). ### Parameters None ``` -------------------------------- ### Basic Declarative Viewer Initialization Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/autoInit.md Initializes a single Live Photo viewer using data attributes for photo and video sources. Ensure the live-photo script is included. ```html
``` -------------------------------- ### Enable Haptic Vibration Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/configuration.md Enables haptic vibration feedback on supported devices when playback starts. Defaults to true. ```typescript enableVibration?: boolean ``` ```typescript enableVibration: true // Haptic feedback on play (default) enableVibration: false // Disable vibration ``` -------------------------------- ### pause() Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/LivePhotoViewer.md Pauses video playback without resetting to the start or hiding the video. The current video position is preserved. ```APIDOC ## pause() ### Description Pauses video playback without resetting to the start or hiding the video. The video position is preserved. ### Method `pause(): void` ### Returns `void` ### Behavior - Stops the internal playback state. - Calls `video.pause()` on the underlying video element. - Removes the `playing` class from the container. - Keeps the photo hidden. ### Example ```typescript viewer.pause(); ``` ``` -------------------------------- ### Example Usage of IS_MOBILE Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/helpers.md Demonstrates how to import and use the IS_MOBILE constant to conditionally log messages based on device type. ```typescript import { IS_MOBILE } from 'live-photo/utils/helpers'; if (IS_MOBILE) { console.log('Device has touch input'); } else { console.log('Desktop device'); } ``` -------------------------------- ### MP4 Extraction Algorithm Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/extractFromLivePhoto.md The algorithm locates the 'ftyp' atom to determine the start of the MP4 data, treating all preceding data as JPEG. ```text 1. Searches backward from the end of the file for the `ftyp` atom (bytes: `0x66 0x74 0x79 0x70`) 2. The 4 bytes before `ftyp` contain the box size, so the actual MP4 start is `ftypPos - 4` 3. Data from 0 to the MP4 start is treated as JPEG 4. Data from MP4 start to end is treated as MP4 ``` -------------------------------- ### Accessing Live Photo Viewer Instances After Auto-Init Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/autoInit.md Demonstrates how to retrieve an array of all initialized Live Photo viewer instances after calling autoInit, and how to access individual viewer states or control them programmatically. ```javascript import { autoInit } from 'live-photo'; const viewers = autoInit(); // Get the state of each viewer viewers.forEach(viewer => { const state = viewer.getState(); console.log('Autoplay:', state.autoplay); }); // Or retrieve a specific element's viewer instance const element = document.querySelector('[data-live-photo]'); const viewer = element.__livePhotoViewer; // Internal property viewer.play(); ``` -------------------------------- ### LivePhotoViewer with Explicit PreferencesStore Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Demonstrates initializing LivePhotoViewer with an explicitly provided PreferencesStore instance, which takes the highest priority. ```typescript // Priority 1: Explicit store const customStore = createMemoryStore(); const viewer1 = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container1'), preferencesStore: customStore, }); ``` -------------------------------- ### Auto-initialize Live Photo Viewers Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/autoInit.md Demonstrates how to automatically initialize Live Photo viewers using the `autoInit` function. You can either call it without arguments to use the default selector or provide a specific document and selector. ```typescript import { autoInit, AUTO_INIT_SELECTOR } from 'live-photo'; // Both are equivalent: const viewers1 = autoInit(); const viewers2 = autoInit(document, AUTO_INIT_SELECTOR); ``` -------------------------------- ### Debounce Resize Handler Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/debounce.md Debounces a resize event handler to limit expensive layout calculations. Includes an example of how to cancel the debounced function. ```typescript import { debounce } from 'live-photo/utils/debounce'; const handleResize = debounce(() => { console.log('Window resized'); // Expensive layout calculation }, 300); window.addEventListener('resize', handleResize); // Cleanup window.addEventListener('resize', () => { handleResize.cancel(); }); ``` -------------------------------- ### LivePhotoViewer Constructor Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/LivePhotoViewer.md Initializes a new LivePhotoViewer instance with the provided configuration options. This constructor validates options, sets up internal components, and prepares the viewer for displaying Live Photos. ```APIDOC ## LivePhotoViewer Constructor ### Description Creates a new LivePhotoViewer instance. Validates options, initializes internal managers, assembles DOM elements, sets up event listeners, and configures preference persistence. ### Method constructor ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **options** (`LivePhotoOptions`) - Required - Configuration object for the viewer ### Request Example ```typescript const viewer = new LivePhotoViewer({ photoSrc: "path/to/photo.jpg", videoSrc: "path/to/video.mp4", container: document.getElementById("viewer-container") }); ``` ### Response #### Success Response None (constructor) #### Response Example None ### Throws - `Error` if `photoSrc`, `videoSrc`, or `container` are missing - `Error` if `container` is not a valid `HTMLElement` - `Error` if `longPressDelay` or `retryAttempts` are negative - `Error` if `width` or `height` are non-positive values - `Error` if `storageKey` is an empty string ``` -------------------------------- ### Manual `autoInit()` Call in Bundled Projects Source: https://github.com/iceywu/live-photo/blob/main/docs/auto-init.md In bundled projects using `import`, you must manually call `autoInit()` once to scan for `data-live-photo` elements. This function can scan the entire document or a specific container. ```javascript import { autoInit } from 'live-photo'; autoInit(); // Scan the entire document for data-live-photo elements autoInit(myContainer); // Scan only a specific subtree ``` -------------------------------- ### Get Current Preferences Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Retrieves a snapshot of the current preferences. The returned object may contain optional `autoplay` and `muted` boolean fields. ```typescript get(): LivePhotoPrefs ``` -------------------------------- ### Declarative HTML Initialization for Live Photo Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/INDEX.md Set up Live Photo Viewer directly in HTML using data attributes and the autoInit function for automatic initialization. ```html
``` -------------------------------- ### Example Usage of createLivePhotoError Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/helpers.md Shows how to import and use createLivePhotoError to generate a structured error object for video load failures, including an original error. ```typescript import { createLivePhotoError } from 'live-photo/utils/helpers'; const error = createLivePhotoError( 'VIDEO_LOAD_ERROR', 'Failed to fetch video from CDN', new Error('Network timeout') ); console.log(error.type); // 'VIDEO_LOAD_ERROR' console.log(error.message); // 'Failed to fetch video from CDN' console.log(error.originalError); // Error: Network timeout ``` -------------------------------- ### Get LivePhotoViewer State Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/LivePhotoViewer.md Retrieves a frozen snapshot of the current playback and preference state, including playing status, autoplay, mute, and error states. ```typescript const state = viewer.getState(); console.log(state.isPlaying); // true or false console.log(state.muted); // true or false ``` -------------------------------- ### onLoadStart Callback Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/configuration.md Fired when the video load begins, specifically in lazy loading mode. This callback takes no arguments. ```typescript onLoadStart?: () => void ``` -------------------------------- ### Cancel Pending Execution Example Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/debounce.md Shows how to use the `cancel` method on a debounced function to prevent a pending execution from occurring. This is useful for aborting scheduled operations. ```typescript const debounced = debounce(() => console.log('Done'), 1000); debounced(); // Scheduled for 1000ms // Cancel before execution debounced.cancel(); // "Done" is never logged ``` -------------------------------- ### LivePhotoViewer with Shared Memory and Persistent Storage Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Demonstrates initializing LivePhotoViewer with both syncGroup and storageKey for a combined shared memory and persistent store. ```typescript // Priority 2: Both syncGroup and storageKey const viewer4 = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container4'), syncGroup: 'gallery', storageKey: 'gallery-prefs', }); ``` -------------------------------- ### Initialize LivePhotoViewer with ES Module Source: https://github.com/iceywu/live-photo/blob/main/README.md Import and initialize the LivePhotoViewer when using ES Modules. Make sure the container element is available in the DOM. ```javascript import { LivePhotoViewer } from 'live-photo'; const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), }); ``` -------------------------------- ### Resolve Labels with Default Locale Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/i18n.md Uses the resolveLabels function to get UI labels for a specified locale, defaulting to English. Demonstrates accessing standard labels. ```typescript import { resolveLabels } from 'live-photo'; // Use English locale const labels = resolveLabels('en'); console.log(labels.live); // "LIVE" console.log(labels.enableAutoplay); // "Enable autoplay" ``` -------------------------------- ### LivePhotoViewer with Shared Memory Store Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Shows how to initialize LivePhotoViewer using only a syncGroup, resulting in a shared memory store. ```typescript // Priority 3: Only syncGroup const viewer2 = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container2'), syncGroup: 'default', }); ``` -------------------------------- ### LivePhotoViewer with Persistent Storage Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/PreferencesStore.md Illustrates initializing LivePhotoViewer with only a storageKey, enabling persistent storage for preferences. ```typescript // Priority 4: Only storageKey const viewer3 = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container3'), storageKey: 'my-prefs', }); ``` -------------------------------- ### Manual Preference Management with LivePhotoViewer Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/storage.md Demonstrates how to manually load preferences from localStorage before initializing a LivePhotoViewer and how to save updated preferences when a setting like mute changes. Ensure preferences are loaded using `loadPrefs` and saved using `savePrefs`. ```typescript import { loadPrefs, savePrefs } from 'live-photo'; // Load saved preferences const saved = loadPrefs('gallery'); // Create viewer with loaded preferences const viewer = new LivePhotoViewer({ photoSrc: 'photo.jpg', videoSrc: 'video.mp4', container: document.getElementById('container'), autoplay: saved.autoplay ?? true, muted: saved.muted ?? true, onMutedChange: (muted) => { savePrefs('gallery', { muted }); }, }); ``` -------------------------------- ### Fallback to Default Locale Example Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/i18n.md Illustrates how to use the DEFAULT_LOCALE to provide a fallback set of labels when a user's requested locale is not available in LOCALE_LABELS. This ensures UI consistency. ```typescript import { DEFAULT_LOCALE, LOCALE_LABELS } from 'live-photo'; // If user's locale is not in LOCALE_LABELS, fall back to default const labels = LOCALE_LABELS[userLocale] || LOCALE_LABELS[DEFAULT_LOCALE]; ``` -------------------------------- ### Debounce Usage Example Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/debounce.md Demonstrates how to use the debounce function to limit the execution of an expensive operation. Only the last invocation within the wait period triggers the actual function call. ```typescript import { debounce } from 'live-photo/utils/debounce'; const expensiveOperation = (value) => { console.log('Processing:', value); }; const debouncedOp = debounce(expensiveOperation, 500); // Call multiple times debouncedOp('a'); debouncedOp('b'); debouncedOp('c'); // Only 'c' is logged, 500ms after the last call // Output (after 500ms): Processing: c ``` -------------------------------- ### createVideo() Source: https://github.com/iceywu/live-photo/blob/main/_autodocs/api-reference/UIComponents.md Creates the video element with player configuration, allowing customization of styles, muted state, and preload strategy. ```APIDOC ## createVideo() ### Description Creates the video element with player configuration. ### Method createVideo ### Parameters #### Function Parameters - **customization** (ElementCustomization) - Optional - Custom styles and attributes - **muted** (boolean) - Optional - Default: `true` - Initial muted state - **preload** ('auto' | 'metadata' | 'none') - Optional - Default: `'metadata'` - Preload strategy ### Returns - **element** (HTMLVideoElement) - The `