### Manage Editor Instance and Pack Assets Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Demonstrates how to initialize the Editor class, handle file imports, sync data structures, and listen to editor events for UI updates. ```typescript const buddy = new Buddy('#app', { isEditor: true }); const editor = buddy.editor; const imageFiles = document.getElementById('file-input').files; await editor.handleFiles(imageFiles); const selectedLayers = editor.getSelectedLayers(); console.log(selectedLayers); editor.syncData(true, true); editor.reset(newLoadPackPromise, newLoadDataPromise); editor.on('refresh', () => { console.log('Editor data refreshed'); }); editor.on('composite', (refreshLayers, selectedLayers) => { console.log('Composite requested', { refreshLayers, selectedLayers }); }); ``` -------------------------------- ### Initialize Buddy Class for Paper Doll Creation Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Demonstrates how to create and configure a Buddy instance, which serves as the main entry point for the paper doll system. It covers loading avatar packs, enabling editor functionalities, and handling custom open/save operations. ```typescript import Buddy from 'paperbuddy'; // Create a new Buddy instance attached to a DOM element const container = document.getElementById('paper-doll-container'); const buddy = new Buddy(container, { // Load an existing pack file src: fetch('/assets/avatar.pack').then(r => r.blob()), // Enable editor mode for content creation isEditor: true, // Enable reset button to clear all data canReset: true, // Enable open button to load pack files canOpen: true, // Enable save button to export pack files canSave: true, // Update document title based on pack metadata controlDocumentTitle: true }); // Or with a custom open/save handler const buddyCustom = new Buddy('#app', { isEditor: true, canOpen: async () => { // Custom file loading logic (e.g., from cloud storage) const response = await fetch('/api/load-avatar'); return response.blob(); }, canSave: async () => { // Custom save logic const blob = await buddyCustom.repack('blob'); await fetch('/api/save-avatar', { method: 'POST', body: blob }); } }); ``` -------------------------------- ### Utilize Core Class for Compositing and Selection Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Shows how to use the Core class, the compositing engine of the paper buddy system. It covers initializing the core with pack data, loading data, accessing metadata, selecting options, triggering compositing, generating previews, and exporting configurations. ```typescript import { Core } from 'paperbuddy/core'; // Create a Core instance with a pack source const core = new Core(packBlob); // Wait for data to load await core.loadDataPromise; // Access metadata console.log(core.title); // Pack title console.log(core.description); // Pack description console.log(core.canvasWidth); // Canvas dimensions console.log(core.canvasHeight); // Select an option (index = category index, value = option index) core.select(0, 2); // Select 3rd option in first category // Manually trigger compositing core.composite(true); // refreshLayers = true to recalculate enabled layers // Generate a preview blob for a specific selection const previewBlob = await core.getSelectionPreview(0, 1); if (previewBlob) { const url = URL.createObjectURL(previewBlob); document.getElementById('preview').src = url; } // Get a full preview with custom selection state const fullPreview = await core.getPreview([0, 2, 1]); // [category0=0, category1=2, category2=1] // Export the current configuration as a new pack const exportedBlob = await core.repack('blob'); saveAs(exportedBlob, 'my-avatar.pack'); ``` -------------------------------- ### Using PaperBuddy Utility Functions Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Demonstrates the usage of core utilities such as UUID generation, asynchronous delays, object cloning, and the @Bind decorator for class methods. These utilities help manage state, timing, and object manipulation within the PaperBuddy framework. ```typescript import { generateUniqueId, delay, delayFrame, mapClone, Bind } from 'paperbuddy/utils'; const id = generateUniqueId(); await delay(1000); await delayFrame(); const original = { a: 1, b: 2 }; const cloned = mapClone(original); class MyClass { value = 42; @Bind handleClick() { console.log(this.value); } } const instance = new MyClass(); document.addEventListener('click', instance.handleClick); ``` -------------------------------- ### Implement Tab Navigation System Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Shows how to create and manage a tabbed interface using the Tabs class, including adding tabs, programmatically selecting them, and handling lifecycle events. ```typescript import { Tabs } from 'paperbuddy/tabs'; const tabs = new Tabs('#tabs-container'); const tab1 = tabs.addTab('Hair Options'); const tab2 = tabs.addTab('Clothing'); const tab3 = tabs.addTab('Accessories'); const hairContent = tabs.contentOf(tab1); hairContent.innerHTML = '
'; tabs.selectTab(1); tabs.selectTab(tab2); tabs.hide(2); tabs.show(2); console.log(tabs.selectedIndex); tabs.on('select', (index) => { console.log(`Tab ${index} selected`); }); tabs.destroyTab(tab3); ``` -------------------------------- ### File Helper Functions: Open and Save Files Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Utility functions for interacting with the browser's file picker API to open and save files. `openFile` allows users to select files, supporting MIME type filtering and multiple selections. `saveFile` enables saving data (Blobs or strings) as downloadable files with customizable names and types. It can also handle line ending transformations. ```typescript import { openFile, saveFile } from 'paperbuddy/file-helper'; // Open a file picker dialog const files = await openFile({ accept: 'image/*', multiple: true // Allow multiple file selection }); // Process selected files for (const file of files) { console.log(file.name, file.size, file.type); const arrayBuffer = await file.arrayBuffer(); // Process file data... } // Open a single pack file const [packFile] = await openFile({ accept: '*.pack' }); if (packFile) { const buddy = new Buddy('#app', { src: packFile }); } // Save a blob as a downloadable file const blob = await buddy.repack('blob'); saveFile(blob, { fileName: 'my-avatar.pack', type: 'application/octet-stream' }); // Save with custom options saveFile(['Hello, World!'], { fileName: 'hello.txt', type: 'text/plain', endings: 'native' // Line ending transformation }); ``` -------------------------------- ### Choose Class: Visual Option Selector Source: https://context7.com/jlchntoz/paperbuddy/llms.txt The Choose class provides a component for creating interactive option selectors with visual previews. It supports lazy loading of images and emits events when selections are made. Dependencies include a tabs instance and a core function for fetching preview data. It manages UI state for selection and visibility. ```typescript import { Choose } from 'paperbuddy/choose'; // Create a Choose instance (typically managed by Buddy automatically) const choose = new Choose( tabsInstance, async (index, value) => { // Preview generator function return await core.getSelectionPreview(index, value); } ); // Update the selector with entry data choose.update( { label: "Hair Color", entries: [ { label: "Black", parts: [{ layer: "hair_black.png" }] }, { label: "Brown", parts: [{ layer: "hair_brown.png" }] }, { label: "Blonde", parts: [{ layer: "hair_blonde.png" }] } ] }, 0 // Category index ); // Get/set current value console.log(choose.value); // Currently selected option index choose.value = 2; // Set to third option // Show/hide the selector choose.show(true); // Visible choose.show(false); // Hidden // Listen for selection changes choose.on('select', (categoryIndex, optionIndex) => { console.log(`Category ${categoryIndex}: selected option ${optionIndex}`); }); // Clean up choose.dispose(); ``` -------------------------------- ### Canvas Utilities: OffscreenCanvas and Blob Conversion Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Helper functions for efficient canvas manipulation, including creating regular and OffscreenCanvas elements, and converting canvas content to Blobs asynchronously. `getOffscreenCanvas` utilizes a pooling mechanism for performance. `canvasToBlobAsync` supports both standard and OffscreenCanvas objects, allowing for flexible image export with format and quality options. ```typescript import { getCanvas, getOffscreenCanvas, returnOffscreenCanvas, canvasToBlobAsync } from 'paperbuddy/offscreen-canvas'; // Create a regular canvas element const canvas = getCanvas(512, 512); const ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; ctx.fillRect(0, 0, 512, 512); // Get an offscreen canvas (pooled for reuse) const offscreen = getOffscreenCanvas(256, 256); const offscreenCtx = offscreen.getContext('2d'); offscreenCtx.drawImage(sourceImage, 0, 0); // Convert canvas to blob (works with both regular and OffscreenCanvas) const blob = await canvasToBlobAsync(offscreen, 'image/png', 1.0); const jpegBlob = await canvasToBlobAsync(canvas, 'image/jpeg', 0.8); // Return offscreen canvas to pool when done returnOffscreenCanvas(offscreen); // Example: Create a thumbnail async function createThumbnail(sourceCanvas, size) { const thumb = getOffscreenCanvas(size, size); const ctx = thumb.getContext('2d'); ctx.drawImage(sourceCanvas, 0, 0, size, size); const blob = await canvasToBlobAsync(thumb); returnOffscreenCanvas(thumb); return blob; } ``` -------------------------------- ### Gaia Class: Internationalization System Source: https://context7.com/jlchntoz/paperbuddy/llms.txt The Gaia class is a lightweight internationalization (i18n) system for translating UI strings. It supports multiple locales, fallback mechanisms, and can automatically bind translations to DOM elements. Initialization requires supported locales and optionally a fallback and default locale. It provides functions for translation, locale checking, and dynamic locale switching. ```typescript import { Gaia } from 'paperbuddy/gaia'; // Initialize with supported locales await Gaia.init({ supportedLocales: [ 'en', ['zh-TW', { title: '標題', save: '儲存', open: '開啟', reset: '重設' }], ['ja', fetch('/locales/ja.json').then(r => r.json())] ], fallbackLocale: 'en', locale: 'zh-TW' // Optional: override auto-detection }); // Get current locale console.log(Gaia.locale); // "zh-TW" // Check if a locale is supported console.log(Gaia.isSupported('ja')); // true // Translate a string const saveText = Gaia.t('save'); // "儲存" (Chinese) or "save" (fallback) // Change locale at runtime await Gaia.setLocale('en'); // Bind translation to DOM elements (auto-updates on locale change) const button = document.createElement('button'); Gaia.bind(button, 'textContent', 'save'); Gaia.bind(button, 'title', 'save'); // Also bind title attribute // Unbind when no longer needed Gaia.unBind(button, 'textContent'); // Unbind specific property Gaia.unBind(button); // Unbind all properties from element // Set language via Buddy static method Buddy.setLang('ja', { title: 'タイトル', save: '保存' }); ``` -------------------------------- ### Define PaperBuddy Pack Data Structures Source: https://context7.com/jlchntoz/paperbuddy/llms.txt Defines the hierarchical interfaces required for paper doll configurations, including layers, categories, and entries. It also demonstrates how to instantiate a pack data object programmatically. ```typescript interface Data { title?: string; description?: string; width: number; height: number; layers: LayerData[]; categories: CategoryData[]; } interface LayerData { fileName: string; } interface CategoryData { label: string; entries?: EntryData[]; } interface EntryData extends CategoryData { parts?: PartData[]; entries?: EntryData[]; } interface PartData { layer: string; } const packData: Data = { title: "My Avatar", description: "A customizable character with **hair** and *outfit* options.", width: 512, height: 512, layers: [ { fileName: "base_body.png" }, { fileName: "hair_black.png" }, { fileName: "hair_blonde.png" }, { fileName: "outfit_casual.png" }, { fileName: "outfit_formal.png" } ], categories: [ { label: "Hair Style", entries: [ { label: "Black Hair", parts: [{ layer: "hair_black.png" }] }, { label: "Blonde Hair", parts: [{ layer: "hair_blonde.png" }] } ] }, { label: "Outfit", entries: [ { label: "Casual", parts: [{ layer: "outfit_casual.png" }] }, { label: "Formal", parts: [{ layer: "outfit_formal.png" }] } ] } ] }; ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.